diff options
Diffstat (limited to 'phpBB/includes')
207 files changed, 151202 insertions, 0 deletions
diff --git a/phpBB/includes/acm/acm_apc.php b/phpBB/includes/acm/acm_apc.php new file mode 100644 index 0000000000..1a487f94ad --- /dev/null +++ b/phpBB/includes/acm/acm_apc.php @@ -0,0 +1,84 @@ +<?php +/** +* +* @package acm +* @version $Id$ +* @copyright (c) 2005, 2009 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +// Include the abstract base +if (!class_exists('acm_memory')) +{ + require("{$phpbb_root_path}includes/acm/acm_memory.$phpEx"); +} + +/** +* ACM for APC +* @package acm +*/ +class acm extends acm_memory +{ + var $extension = 'apc'; + + /** + * Purge cache data + * + * @return void + */ + function purge() + { + apc_clear_cache('user'); + + parent::purge(); + } + + /** + * Fetch an item from the cache + * + * @access protected + * @param string $var Cache key + * @return mixed Cached data + */ + function _read($var) + { + return apc_fetch($this->key_prefix . $var); + } + + /** + * Store data in the cache + * + * @access protected + * @param string $var Cache key + * @param mixed $data Data to store + * @param int $ttl Time-to-live of cached data + * @return bool True if the operation succeeded + */ + function _write($var, $data, $ttl = 2592000) + { + return apc_store($this->key_prefix . $var, $data, $ttl); + } + + /** + * Remove an item from the cache + * + * @access protected + * @param string $var Cache key + * @return bool True if the operation succeeded + */ + function _delete($var) + { + return apc_delete($this->key_prefix . $var); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acm/acm_eaccelerator.php b/phpBB/includes/acm/acm_eaccelerator.php new file mode 100644 index 0000000000..1a3cf3c0f7 --- /dev/null +++ b/phpBB/includes/acm/acm_eaccelerator.php @@ -0,0 +1,120 @@ +<?php +/** +* +* @package acm +* @version $Id$ +* @copyright (c) 2005, 2009 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +// Include the abstract base +if (!class_exists('acm_memory')) +{ + require("{$phpbb_root_path}includes/acm/acm_memory.$phpEx"); +} + +/** +* ACM for eAccelerator +* @package acm +* @todo Missing locks from destroy() talk with David +*/ +class acm extends acm_memory +{ + var $extension = 'eaccelerator'; + + var $serialize_header = '#phpbb-serialized#'; + + /** + * Purge cache data + * + * @return void + */ + function purge() + { + foreach (eaccelerator_list_keys() as $var) + { + // @todo Check why the substr() + // @todo Only unset vars matching $this->key_prefix + eaccelerator_rm(substr($var['name'], 1)); + } + + parent::purge(); + } + + /** + * Perform cache garbage collection + * + * @return void + */ + function tidy() + { + eaccelerator_gc(); + + set_config('cache_last_gc', time(), true); + } + + /** + * Fetch an item from the cache + * + * @access protected + * @param string $var Cache key + * @return mixed Cached data + */ + function _read($var) + { + $result = eaccelerator_get($this->key_prefix . $var); + + if ($result === null) + { + return false; + } + + // Handle serialized objects + if (is_string($result) && strpos($result, $this->serialize_header . 'O:') === 0) + { + $result = unserialize(substr($result, strlen($this->serialize_header))); + } + + return $result; + } + + /** + * Store data in the cache + * + * @access protected + * @param string $var Cache key + * @param mixed $data Data to store + * @param int $ttl Time-to-live of cached data + * @return bool True if the operation succeeded + */ + function _write($var, $data, $ttl = 2592000) + { + // Serialize objects and make them easy to detect + $data = (is_object($data)) ? $this->serialize_header . serialize($data) : $data; + + return eaccelerator_put($this->key_prefix . $var, $data, $ttl); + } + + /** + * Remove an item from the cache + * + * @access protected + * @param string $var Cache key + * @return bool True if the operation succeeded + */ + function _delete($var) + { + return eaccelerator_rm($this->key_prefix . $var); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acm/acm_file.php b/phpBB/includes/acm/acm_file.php new file mode 100644 index 0000000000..234be5c5d1 --- /dev/null +++ b/phpBB/includes/acm/acm_file.php @@ -0,0 +1,720 @@ +<?php +/** +* +* @package acm +* @version $Id$ +* @copyright (c) 2005, 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 $var_expires = array(); + var $is_modified = false; + + var $sql_rowset = array(); + var $sql_row_pointer = array(); + var $cache_dir = ''; + + /** + * Set cache path + */ + function acm() + { + global $phpbb_root_path; + $this->cache_dir = $phpbb_root_path . 'cache/'; + } + + /** + * Load global cache + */ + function load() + { + return $this->_read('data_global'); + } + + /** + * Unload cache object + */ + function unload() + { + $this->save(); + unset($this->vars); + unset($this->var_expires); + unset($this->sql_rowset); + unset($this->sql_row_pointer); + + $this->vars = array(); + $this->var_expires = array(); + $this->sql_rowset = array(); + $this->sql_row_pointer = array(); + } + + /** + * Save modified objects + */ + function save() + { + if (!$this->is_modified) + { + return; + } + + global $phpEx; + + if (!$this->_write('data_global')) + { + // 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 ' . $this->cache_dir . 'data_global.' . $phpEx); + exit; + } + + $this->is_modified = false; + } + + /** + * Tidy cache + */ + function tidy() + { + global $phpEx; + + $dir = @opendir($this->cache_dir); + + if (!$dir) + { + return; + } + + $time = time(); + + while (($entry = readdir($dir)) !== false) + { + if (!preg_match('/^(sql_|data_(?!global))/', $entry)) + { + continue; + } + + if (!($handle = @fopen($this->cache_dir . $entry, 'rb'))) + { + continue; + } + + // Skip the PHP header + fgets($handle); + + // Skip expiration + $expires = (int) fgets($handle); + + fclose($handle); + + if ($time >= $expires) + { + $this->remove_file($this->cache_dir . $entry); + } + } + closedir($dir); + + if (file_exists($this->cache_dir . 'data_global.' . $phpEx)) + { + if (!sizeof($this->vars)) + { + $this->load(); + } + + foreach ($this->var_expires as $var_name => $expires) + { + if ($time >= $expires) + { + $this->destroy($var_name); + } + } + } + + set_config('cache_last_gc', time(), true); + } + + /** + * Get saved cache object + */ + function get($var_name) + { + if ($var_name[0] == '_') + { + global $phpEx; + + if (!$this->_exists($var_name)) + { + return false; + } + + return $this->_read('data' . $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] == '_') + { + $this->_write('data' . $var_name, $var, time() + $ttl); + } + else + { + $this->vars[$var_name] = $var; + $this->var_expires[$var_name] = time() + $ttl; + $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); + + unset($this->vars); + unset($this->var_expires); + unset($this->sql_rowset); + unset($this->sql_row_pointer); + + $this->vars = array(); + $this->var_expires = array(); + $this->sql_rowset = array(); + $this->sql_row_pointer = array(); + + $this->is_modified = false; + } + + /** + * Destroy cache data + */ + function destroy($var_name, $table = '') + { + global $phpEx; + + if ($var_name == 'sql' && !empty($table)) + { + if (!is_array($table)) + { + $table = array($table); + } + + $dir = @opendir($this->cache_dir); + + if (!$dir) + { + return; + } + + while (($entry = readdir($dir)) !== false) + { + if (strpos($entry, 'sql_') !== 0) + { + continue; + } + + if (!($handle = @fopen($this->cache_dir . $entry, 'rb'))) + { + continue; + } + + // Skip the PHP header + fgets($handle); + + // Skip expiration + fgets($handle); + + // Grab the query, remove the LF + $query = substr(fgets($handle), 0, -1); + + fclose($handle); + + foreach ($table as $check_table) + { + // Better catch partial table names than no table names. ;) + if (strpos($query, $check_table) !== false) + { + $this->remove_file($this->cache_dir . $entry); + break; + } + } + } + closedir($dir); + + return; + } + + if (!$this->_exists($var_name)) + { + return; + } + + if ($var_name[0] == '_') + { + $this->remove_file($this->cache_dir . 'data' . $var_name . ".$phpEx", true); + } + else if (isset($this->vars[$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->save(); + } + } + + /** + * Check if a given cache entry exist + */ + function _exists($var_name) + { + if ($var_name[0] == '_') + { + global $phpEx; + return file_exists($this->cache_dir . 'data' . $var_name . ".$phpEx"); + } + else + { + if (!sizeof($this->vars)) + { + $this->load(); + } + + if (!isset($this->var_expires[$var_name])) + { + return false; + } + + return (time() > $this->var_expires[$var_name]) ? false : 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); + + if (($rowset = $this->_read('sql_' . md5($query))) === false) + { + return false; + } + + $query_id = sizeof($this->sql_rowset); + $this->sql_rowset[$query_id] = $rowset; + $this->sql_row_pointer[$query_id] = 0; + + return $query_id; + } + + /** + * Save sql query + */ + function sql_save($query, &$query_result, $ttl) + { + global $db; + + // Remove extra spaces and tabs + $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); + + $query_id = sizeof($this->sql_rowset); + $this->sql_rowset[$query_id] = array(); + $this->sql_row_pointer[$query_id] = 0; + + while ($row = $db->sql_fetchrow($query_result)) + { + $this->sql_rowset[$query_id][] = $row; + } + $db->sql_freeresult($query_result); + + if ($this->_write('sql_' . md5($query), $this->sql_rowset[$query_id], $ttl + time(), $query)) + { + $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; + } + + /** + * Read cached data from a specified file + * + * @access private + * @param string $filename Filename to write + * @return mixed False if an error was encountered, otherwise the data type of the cached data + */ + function _read($filename) + { + global $phpEx; + + $file = "{$this->cache_dir}$filename.$phpEx"; + + $type = substr($filename, 0, strpos($filename, '_')); + + if (!file_exists($file)) + { + return false; + } + + if (!($handle = @fopen($file, 'rb'))) + { + return false; + } + + // Skip the PHP header + fgets($handle); + + if ($filename == 'data_global') + { + $this->vars = $this->var_expires = array(); + + $time = time(); + + while (($expires = (int) fgets($handle)) && !feof($handle)) + { + // Number of bytes of data + $bytes = substr(fgets($handle), 0, -1); + + if (!is_numeric($bytes) || ($bytes = (int) $bytes) === 0) + { + // We cannot process the file without a valid number of bytes + // so we discard it + fclose($handle); + + $this->vars = $this->var_expires = array(); + $this->is_modified = false; + + $this->remove_file($file); + + return false; + } + + if ($time >= $expires) + { + fseek($handle, $bytes, SEEK_CUR); + + continue; + } + + $var_name = substr(fgets($handle), 0, -1); + + // Read the length of bytes that consists of data. + $data = fread($handle, $bytes - strlen($var_name)); + $data = @unserialize($data); + + // Don't use the data if it was invalid + if ($data !== false) + { + $this->vars[$var_name] = $data; + $this->var_expires[$var_name] = $expires; + } + + // Absorb the LF + fgets($handle); + } + + fclose($handle); + + $this->is_modified = false; + + return true; + } + else + { + $data = false; + $line = 0; + + while (($buffer = fgets($handle)) && !feof($handle)) + { + $buffer = substr($buffer, 0, -1); // Remove the LF + + // $buffer is only used to read integers + // if it is non numeric we have an invalid + // cache file, which we will now remove. + if (!is_numeric($buffer)) + { + break; + } + + if ($line == 0) + { + $expires = (int) $buffer; + + if (time() >= $expires) + { + break; + } + + if ($type == 'sql') + { + // Skip the query + fgets($handle); + } + } + else if ($line == 1) + { + $bytes = (int) $buffer; + + // Never should have 0 bytes + if (!$bytes) + { + break; + } + + // Grab the serialized data + $data = fread($handle, $bytes); + + // Read 1 byte, to trigger EOF + fread($handle, 1); + + if (!feof($handle)) + { + // Somebody tampered with our data + $data = false; + } + break; + } + else + { + // Something went wrong + break; + } + $line++; + } + fclose($handle); + + // unserialize if we got some data + $data = ($data !== false) ? @unserialize($data) : $data; + + if ($data === false) + { + $this->remove_file($file); + return false; + } + + return $data; + } + } + + /** + * Write cache data to a specified file + * + * 'data_global' is a special case and the generated format is different for this file: + * <code> + * <?php exit; ?> + * (expiration) + * (length of var and serialised data) + * (var) + * (serialised data) + * ... (repeat) + * </code> + * + * The other files have a similar format: + * <code> + * <?php exit; ?> + * (expiration) + * (query) [SQL files only] + * (length of serialised data) + * (serialised data) + * </code> + * + * @access private + * @param string $filename Filename to write + * @param mixed $data Data to store + * @param int $expires Timestamp when the data expires + * @param string $query Query when caching SQL queries + * @return bool True if the file was successfully created, otherwise false + */ + function _write($filename, $data = null, $expires = 0, $query = '') + { + global $phpEx; + + $file = "{$this->cache_dir}$filename.$phpEx"; + + if ($handle = @fopen($file, 'wb')) + { + @flock($handle, LOCK_EX); + + // File header + fwrite($handle, '<' . '?php exit; ?' . '>'); + + if ($filename == 'data_global') + { + // Global data is a different format + foreach ($this->vars as $var => $data) + { + if (strpos($var, "\r") !== false || strpos($var, "\n") !== false) + { + // CR/LF would cause fgets() to read the cache file incorrectly + // do not cache test entries, they probably won't be read back + // the cache keys should really be alphanumeric with a few symbols. + continue; + } + $data = serialize($data); + + // Write out the expiration time + fwrite($handle, "\n" . $this->var_expires[$var] . "\n"); + + // Length of the remaining data for this var (ignoring two LF's) + fwrite($handle, strlen($data . $var) . "\n"); + fwrite($handle, $var . "\n"); + fwrite($handle, $data); + } + } + else + { + fwrite($handle, "\n" . $expires . "\n"); + + if (strpos($filename, 'sql_') === 0) + { + fwrite($handle, $query . "\n"); + } + $data = serialize($data); + + fwrite($handle, strlen($data) . "\n"); + fwrite($handle, $data); + } + + @flock($handle, LOCK_UN); + fclose($handle); + + if (!function_exists('phpbb_chmod')) + { + global $phpbb_root_path; + include($phpbb_root_path . 'includes/functions.' . $phpEx); + } + + phpbb_chmod($file, CHMOD_READ | CHMOD_WRITE); + + return true; + } + + return false; + } + + /** + * 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_memcache.php b/phpBB/includes/acm/acm_memcache.php new file mode 100644 index 0000000000..3077ee9615 --- /dev/null +++ b/phpBB/includes/acm/acm_memcache.php @@ -0,0 +1,124 @@ +<?php +/** +* +* @package acm +* @version $Id$ +* @copyright (c) 2005, 2009 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +// Include the abstract base +if (!class_exists('acm_memory')) +{ + require("{$phpbb_root_path}includes/acm/acm_memory.$phpEx"); +} + +if (!defined('PHPBB_ACM_MEMCACHE_PORT')) +{ + define('PHPBB_ACM_MEMCACHE_PORT', 11211); +} + +if (!defined('PHPBB_ACM_MEMCACHE_COMPRESS')) +{ + define('PHPBB_ACM_MEMCACHE_COMPRESS', false); +} + +if (!defined('PHPBB_ACM_MEMCACHE_HOST')) +{ + define('PHPBB_ACM_MEMCACHE_HOST', 'localhost'); +} + +/** +* ACM for Memcached +* @package acm +*/ +class acm extends acm_memory +{ + var $extension = 'memcache'; + + var $memcache; + var $flags = 0; + + function acm() + { + // Call the parent constructor + parent::acm_memory(); + + $this->memcache = new Memcache; + $this->memcache->connect(PHPBB_ACM_MEMCACHE_HOST, PHPBB_ACM_MEMCACHE_PORT); + $this->flags = (PHPBB_ACM_MEMCACHE_COMPRESS) ? MEMCACHE_COMPRESSED : 0; + } + + /** + * Unload the cache resources + * + * @return void + */ + function unload() + { + parent::unload(); + + $this->memcache->close(); + } + + /** + * Purge cache data + * + * @return void + */ + function purge() + { + $this->memcache->flush(); + + parent::purge(); + } + + /** + * Fetch an item from the cache + * + * @access protected + * @param string $var Cache key + * @return mixed Cached data + */ + function _read($var) + { + return $this->memcache->get($this->key_prefix . $var); + } + + /** + * Store data in the cache + * + * @access protected + * @param string $var Cache key + * @param mixed $data Data to store + * @param int $ttl Time-to-live of cached data + * @return bool True if the operation succeeded + */ + function _write($var, $data, $ttl = 2592000) + { + return $this->memcache->set($this->key_prefix . $var, $data, $this->flags, $ttl); + } + + /** + * Remove an item from the cache + * + * @access protected + * @param string $var Cache key + * @return bool True if the operation succeeded + */ + function _delete($var) + { + return $this->memcache->delete($this->key_prefix . $var); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acm/acm_memory.php b/phpBB/includes/acm/acm_memory.php new file mode 100644 index 0000000000..1ed4fb0d55 --- /dev/null +++ b/phpBB/includes/acm/acm_memory.php @@ -0,0 +1,426 @@ +<?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 Abstract Memory Class +* @package acm +*/ +class acm_memory +{ + var $key_prefix; + + var $vars = array(); + var $is_modified = false; + + var $sql_rowset = array(); + var $sql_row_pointer = array(); + var $cache_dir = ''; + + /** + * Set cache path + */ + function acm_memory() + { + global $phpbb_root_path, $dbname, $table_prefix; + + $this->cache_dir = $phpbb_root_path . 'cache/'; + $this->key_prefix = substr(md5($dbname . $table_prefix), 0, 8) . '_'; + + if (!isset($this->extension) || !extension_loaded($this->extension)) + { + global $acm_type; + + trigger_error("Could not find required extension [{$this->extension}] for the ACM module $acm_type.", E_USER_ERROR); + } + } + + /** + * Load global cache + */ + function load() + { + // grab the global cache + $this->vars = $this->_read('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; + } + + $this->_write('global', $this->vars, 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 $this->_read($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] == '_') + { + $this->_write($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); + + 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 = $this->_read('sql_' . $table_name); + + if ($temp === false) + { + continue; + } + + // delete each query ref + foreach ($temp as $md5_id => $void) + { + $this->_delete('sql_' . $md5_id); + } + + // delete the table ref + $this->_delete('sql_' . $table_name); + } + + return; + } + + if (!$this->_exists($var_name)) + { + return; + } + + if ($var_name[0] == '_') + { + $this->_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 $this->_isset($var_name); + } + 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); + + if (($result = $this->_read('sql_' . md5($query))) === false) + { + return false; + } + + $this->sql_rowset[$query_id] = $result; + $this->sql_row_pointer[$query_id] = 0; + + return $query_id; + } + + /** + * Save sql query + */ + function sql_save($query, &$query_result, $ttl) + { + global $db; + + // Remove extra spaces and tabs + $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); + $hash = md5($query); + + // determine which tables this query belongs to + // Some queries use backticks, namely the get_database_size() query + // don't check for conformity, the SQL would error and not reach here. + if (!preg_match('/FROM \\(?(`?\\w+`?(?: \\w+)?(?:, ?`?\\w+`?(?: \\w+)?)*)\\)?/', $query, $regs)) + { + // Bail out if the match fails. + return; + } + $tables = array_map('trim', explode(',', $regs[1])); + + foreach ($tables as $table_name) + { + // Remove backticks + $table_name = ($table_name[0] == '`') ? substr($table_name, 1, -1) : $table_name; + + if (($pos = strpos($table_name, ' ')) !== false) + { + $table_name = substr($table_name, 0, $pos); + } + + $temp = $this->_read('sql_' . $table_name); + + if ($temp === false) + { + $temp = array(); + } + + $temp[$hash] = true; + + // This must never expire + $this->_write('sql_' . $table_name, $temp, 0); + } + + // 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 = $db->sql_fetchrow($query_result)) + { + $this->sql_rowset[$query_id][] = $row; + } + $db->sql_freeresult($query_result); + + $this->_write('sql_' . $hash, $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); + } + + /** + * Check if a cache var exists + * + * @access protected + * @param string $var Cache key + * @return bool True if it exists, otherwise false + */ + function _isset($var) + { + // Most caches don't need to check + return true; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acm/acm_null.php b/phpBB/includes/acm/acm_null.php new file mode 100644 index 0000000000..fca67115a7 --- /dev/null +++ b/phpBB/includes/acm/acm_null.php @@ -0,0 +1,156 @@ +<?php +/** +* +* @package acm +* @version $Id$ +* @copyright (c) 2005, 2009 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ACM Null Caching +* @package acm +*/ +class acm +{ + /** + * Set cache path + */ + function acm() + { + } + + /** + * Load global cache + */ + function load() + { + return true; + } + + /** + * Unload cache object + */ + function unload() + { + } + + /** + * Save modified objects + */ + function save() + { + } + + /** + * Tidy cache + */ + function tidy() + { + // This cache always has a tidy room. + set_config('cache_last_gc', time(), true); + } + + /** + * Get saved cache object + */ + function get($var_name) + { + return false; + } + + /** + * Put data into cache + */ + function put($var_name, $var, $ttl = 0) + { + } + + /** + * Purge cache data + */ + function purge() + { + } + + /** + * Destroy cache data + */ + function destroy($var_name, $table = '') + { + } + + /** + * Check if a given cache entry exist + */ + function _exists($var_name) + { + return false; + } + + /** + * Load cached sql query + */ + function sql_load($query) + { + return false; + } + + /** + * Save sql query + */ + function sql_save($query, &$query_result, $ttl) + { + } + + /** + * Ceck if a given sql query exist in cache + */ + function sql_exists($query_id) + { + return false; + } + + /** + * Fetch row from cache (database) + */ + function sql_fetchrow($query_id) + { + return false; + } + + /** + * Fetch a field from the current row of a cached database result (database) + */ + function sql_fetchfield($query_id, $field) + { + return false; + } + + /** + * Seek a specific row in an a cached database result (database) + */ + function sql_rowseek($rownum, $query_id) + { + return false; + } + + /** + * Free memory used for a cached database result (database) + */ + function sql_freeresult($query_id) + { + return false; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acm/acm_xcache.php b/phpBB/includes/acm/acm_xcache.php new file mode 100644 index 0000000000..d0a614660c --- /dev/null +++ b/phpBB/includes/acm/acm_xcache.php @@ -0,0 +1,121 @@ +<?php +/** +* +* @package acm +* @version $Id$ +* @copyright (c) 2005, 2009 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +// Include the abstract base +if (!class_exists('acm_memory')) +{ + require("{$phpbb_root_path}includes/acm/acm_memory.$phpEx"); +} + +/** +* ACM for XCache +* @package acm +* +* To use this module you need ini_get() enabled and the following INI settings configured as follows: +* - xcache.var_size > 0 +* - xcache.admin.enable_auth = off (or xcache.admin.user and xcache.admin.password set) +* +*/ +class acm extends acm_memory +{ + var $extension = 'XCache'; + + function acm() + { + parent::acm_memory(); + + if (!function_exists('ini_get') || (int) ini_get('xcache.var_size') <= 0) + { + trigger_error('Increase xcache.var_size setting above 0 or enable ini_get() to use this ACM module.', E_USER_ERROR); + } + } + + /** + * Purge cache data + * + * @return void + */ + function purge() + { + // Run before for XCache, if admin functions are disabled it will terminate execution + parent::purge(); + + // If the admin authentication is enabled but not set up, this will cause a nasty error. + // Not much we can do about it though. + $n = xcache_count(XC_TYPE_VAR); + + for ($i = 0; $i < $n; $i++) + { + xcache_clear_cache(XC_TYPE_VAR, $i); + } + } + + /** + * Fetch an item from the cache + * + * @access protected + * @param string $var Cache key + * @return mixed Cached data + */ + function _read($var) + { + $result = xcache_get($this->key_prefix . $var); + + return ($result !== null) ? $result : false; + } + + /** + * Store data in the cache + * + * @access protected + * @param string $var Cache key + * @param mixed $data Data to store + * @param int $ttl Time-to-live of cached data + * @return bool True if the operation succeeded + */ + function _write($var, $data, $ttl = 2592000) + { + return xcache_set($this->key_prefix . $var, $data, $ttl); + } + + /** + * Remove an item from the cache + * + * @access protected + * @param string $var Cache key + * @return bool True if the operation succeeded + */ + function _delete($var) + { + return xcache_unset($this->key_prefix . $var); + } + + /** + * Check if a cache var exists + * + * @access protected + * @param string $var Cache key + * @return bool True if it exists, otherwise false + */ + function _isset($var) + { + return xcache_isset($this->key_prefix . $var); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_attachments.php b/phpBB/includes/acp/acp_attachments.php new file mode 100644 index 0000000000..849c076f0e --- /dev/null +++ b/phpBB/includes/acp/acp_attachments.php @@ -0,0 +1,1452 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_attachments +{ + var $u_action; + var $new_config; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache; + global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx; + + $user->add_lang(array('posting', 'viewtopic', 'acp/attachments')); + + $error = $notify = array(); + $submit = (isset($_POST['submit'])) ? true : false; + $action = request_var('action', ''); + + $form_key = 'acp_attach'; + add_form_key($form_key); + + if ($submit && !check_form_key($form_key)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + switch ($mode) + { + case 'attach': + $l_title = 'ACP_ATTACHMENT_SETTINGS'; + break; + + case 'extensions': + $l_title = 'ACP_MANAGE_EXTENSIONS'; + break; + + case 'ext_groups': + $l_title = 'ACP_EXTENSION_GROUPS'; + break; + + case 'orphan': + $l_title = 'ACP_ORPHAN_ATTACHMENTS'; + break; + + default: + trigger_error('NO_MODE', E_USER_ERROR); + break; + } + + $this->tpl_name = 'acp_attachments'; + $this->page_title = $l_title; + + $template->assign_vars(array( + 'L_TITLE' => $user->lang[$l_title], + 'L_TITLE_EXPLAIN' => $user->lang[$l_title . '_EXPLAIN'], + 'U_ACTION' => $this->u_action) + ); + + switch ($mode) + { + case 'attach': + + include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); + + $sql = 'SELECT group_name, cat_id + FROM ' . EXTENSION_GROUPS_TABLE . ' + WHERE cat_id > 0 + ORDER BY cat_id'; + $result = $db->sql_query($sql); + + $s_assigned_groups = array(); + while ($row = $db->sql_fetchrow($result)) + { + $s_assigned_groups[$row['cat_id']][] = $row['group_name']; + } + $db->sql_freeresult($result); + + $l_legend_cat_images = $user->lang['SETTINGS_CAT_IMAGES'] . ' [' . $user->lang['ASSIGNED_GROUP'] . ': ' . ((!empty($s_assigned_groups[ATTACHMENT_CATEGORY_IMAGE])) ? implode(', ', $s_assigned_groups[ATTACHMENT_CATEGORY_IMAGE]) : $user->lang['NO_EXT_GROUP']) . ']'; + + $display_vars = array( + 'title' => 'ACP_ATTACHMENT_SETTINGS', + 'vars' => array( + 'legend1' => 'ACP_ATTACHMENT_SETTINGS', + + 'img_max_width' => array('lang' => 'MAX_IMAGE_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false,), + 'img_max_height' => array('lang' => 'MAX_IMAGE_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false,), + 'img_link_width' => array('lang' => 'IMAGE_LINK_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false,), + 'img_link_height' => array('lang' => 'IMAGE_LINK_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false,), + + 'allow_attachments' => array('lang' => 'ALLOW_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_pm_attach' => array('lang' => 'ALLOW_PM_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'upload_path' => array('lang' => 'UPLOAD_DIR', 'validate' => 'wpath', 'type' => 'text:25:100', 'explain' => true), + 'display_order' => array('lang' => 'DISPLAY_ORDER', 'validate' => 'bool', 'type' => 'custom', 'method' => 'display_order', 'explain' => true), + 'attachment_quota' => array('lang' => 'ATTACH_QUOTA', 'validate' => 'string', 'type' => 'custom', 'method' => 'max_filesize', 'explain' => true), + 'max_filesize' => array('lang' => 'ATTACH_MAX_FILESIZE', 'validate' => 'string', 'type' => 'custom', 'method' => 'max_filesize', 'explain' => true), + 'max_filesize_pm' => array('lang' => 'ATTACH_MAX_PM_FILESIZE','validate' => 'string', 'type' => 'custom', 'method' => 'max_filesize', 'explain' => true), + 'max_attachments' => array('lang' => 'MAX_ATTACHMENTS', 'validate' => 'int', 'type' => 'text:3:3', 'explain' => false), + 'max_attachments_pm' => array('lang' => 'MAX_ATTACHMENTS_PM', 'validate' => 'int', 'type' => 'text:3:3', 'explain' => false), + 'secure_downloads' => array('lang' => 'SECURE_DOWNLOADS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'secure_allow_deny' => array('lang' => 'SECURE_ALLOW_DENY', 'validate' => 'int', 'type' => 'custom', 'method' => 'select_allow_deny', 'explain' => true), + 'secure_allow_empty_referer' => array('lang' => 'SECURE_EMPTY_REFERRER', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'check_attachment_content' => array('lang' => 'CHECK_CONTENT', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + + + 'legend2' => $l_legend_cat_images, + 'img_display_inlined' => array('lang' => 'DISPLAY_INLINED', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'img_create_thumbnail' => array('lang' => 'CREATE_THUMBNAIL', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'img_max_thumb_width' => array('lang' => 'MAX_THUMB_WIDTH', 'validate' => 'int', 'type' => 'text:7:15', 'explain' => true, 'append' => ' px'), + 'img_min_thumb_filesize' => array('lang' => 'MIN_THUMB_FILESIZE', 'validate' => 'int', 'type' => 'text:7:15', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']), + 'img_imagick' => array('lang' => 'IMAGICK_PATH', 'validate' => 'string', 'type' => 'text:20:200', 'explain' => true, 'append' => ' <span>[ <a href="' . $this->u_action . '&action=imgmagick">' . $user->lang['SEARCH_IMAGICK'] . '</a> ]</span>'), + 'img_max' => array('lang' => 'MAX_IMAGE_SIZE', 'validate' => 'int', 'type' => 'dimension:3:4', 'explain' => true, 'append' => ' px'), + 'img_link' => array('lang' => 'IMAGE_LINK_SIZE', 'validate' => 'int', 'type' => 'dimension:3:4', 'explain' => true, 'append' => ' px'), + ) + ); + + $this->new_config = $config; + $cfg_array = (isset($_REQUEST['config'])) ? request_var('config', array('' => '')) : $this->new_config; + $error = array(); + + // We validate the complete config if whished + validate_config_vars($display_vars['vars'], $cfg_array, $error); + + // Do not write values if there is an error + if (sizeof($error)) + { + $submit = false; + } + + // We go through the display_vars to make sure no one is trying to set variables he/she is not allowed to... + foreach ($display_vars['vars'] as $config_name => $null) + { + if (!isset($cfg_array[$config_name]) || strpos($config_name, 'legend') !== false) + { + continue; + } + + $this->new_config[$config_name] = $config_value = $cfg_array[$config_name]; + + if (in_array($config_name, array('attachment_quota', 'max_filesize', 'max_filesize_pm'))) + { + $size_var = request_var($config_name, ''); + $this->new_config[$config_name] = $config_value = ($size_var == 'kb') ? round($config_value * 1024) : (($size_var == 'mb') ? round($config_value * 1048576) : $config_value); + } + + if ($submit) + { + set_config($config_name, $config_value); + } + } + + $this->perform_site_list(); + + if ($submit) + { + add_log('admin', 'LOG_CONFIG_ATTACH'); + + // Check Settings + $this->test_upload($error, $this->new_config['upload_path'], false); + + if (!sizeof($error)) + { + trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); + } + } + + $template->assign_var('S_ATTACHMENT_SETTINGS', true); + + if ($action == 'imgmagick') + { + $this->new_config['img_imagick'] = $this->search_imagemagick(); + } + + // We strip eventually manual added convert program, we only want the patch + if ($this->new_config['img_imagick']) + { + // Change path separator + $this->new_config['img_imagick'] = str_replace('\\', '/', $this->new_config['img_imagick']); + $this->new_config['img_imagick'] = str_replace(array('convert', '.exe'), array('', ''), $this->new_config['img_imagick']); + + // Check for trailing slash + if (substr($this->new_config['img_imagick'], -1) !== '/') + { + $this->new_config['img_imagick'] .= '/'; + } + } + + $supported_types = get_supported_image_types(); + + // Check Thumbnail Support + if (!$this->new_config['img_imagick'] && (!isset($supported_types['format']) || !sizeof($supported_types['format']))) + { + $this->new_config['img_create_thumbnail'] = 0; + } + + $template->assign_vars(array( + 'U_SEARCH_IMAGICK' => $this->u_action . '&action=imgmagick', + 'S_THUMBNAIL_SUPPORT' => (!$this->new_config['img_imagick'] && (!isset($supported_types['format']) || !sizeof($supported_types['format']))) ? false : true) + ); + + // Secure Download Options - Same procedure as with banning + $allow_deny = ($this->new_config['secure_allow_deny']) ? 'ALLOWED' : 'DISALLOWED'; + + $sql = 'SELECT * + FROM ' . SITELIST_TABLE; + $result = $db->sql_query($sql); + + $defined_ips = ''; + $ips = array(); + + while ($row = $db->sql_fetchrow($result)) + { + $value = ($row['site_ip']) ? $row['site_ip'] : $row['site_hostname']; + if ($value) + { + $defined_ips .= '<option' . (($row['ip_exclude']) ? ' class="sep"' : '') . ' value="' . $row['site_id'] . '">' . $value . '</option>'; + $ips[$row['site_id']] = $value; + } + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'S_SECURE_DOWNLOADS' => $this->new_config['secure_downloads'], + 'S_DEFINED_IPS' => ($defined_ips != '') ? true : false, + 'S_WARNING' => (sizeof($error)) ? true : false, + + 'WARNING_MSG' => implode('<br />', $error), + 'DEFINED_IPS' => $defined_ips, + + 'L_SECURE_TITLE' => $user->lang['DEFINE_' . $allow_deny . '_IPS'], + 'L_IP_EXCLUDE' => $user->lang['EXCLUDE_FROM_' . $allow_deny . '_IP'], + 'L_REMOVE_IPS' => $user->lang['REMOVE_' . $allow_deny . '_IPS']) + ); + + // Output relevant options + foreach ($display_vars['vars'] as $config_key => $vars) + { + if (!is_array($vars) && strpos($config_key, 'legend') === false) + { + continue; + } + + if (strpos($config_key, 'legend') !== false) + { + $template->assign_block_vars('options', array( + 'S_LEGEND' => true, + 'LEGEND' => (isset($user->lang[$vars])) ? $user->lang[$vars] : $vars) + ); + + continue; + } + + $type = explode(':', $vars['type']); + + $l_explain = ''; + if ($vars['explain'] && isset($vars['lang_explain'])) + { + $l_explain = (isset($user->lang[$vars['lang_explain']])) ? $user->lang[$vars['lang_explain']] : $vars['lang_explain']; + } + else if ($vars['explain']) + { + $l_explain = (isset($user->lang[$vars['lang'] . '_EXPLAIN'])) ? $user->lang[$vars['lang'] . '_EXPLAIN'] : ''; + } + + $content = build_cfg_template($type, $config_key, $this->new_config, $config_key, $vars); + if (empty($content)) + { + continue; + } + + $template->assign_block_vars('options', array( + 'KEY' => $config_key, + 'TITLE' => $user->lang[$vars['lang']], + 'S_EXPLAIN' => $vars['explain'], + 'TITLE_EXPLAIN' => $l_explain, + 'CONTENT' => $content, + ) + ); + + unset($display_vars['vars'][$config_key]); + } + + break; + + case 'extensions': + + if ($submit || isset($_POST['add_extension_check'])) + { + if ($submit) + { + // Change Extensions ? + $extension_change_list = request_var('extension_change_list', array(0)); + $group_select_list = request_var('group_select', array(0)); + + // Generate correct Change List + $extensions = array(); + + for ($i = 0, $size = sizeof($extension_change_list); $i < $size; $i++) + { + $extensions[$extension_change_list[$i]]['group_id'] = $group_select_list[$i]; + } + + $sql = 'SELECT * + FROM ' . EXTENSIONS_TABLE . ' + ORDER BY extension_id'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if ($row['group_id'] != $extensions[$row['extension_id']]['group_id']) + { + $sql = 'UPDATE ' . EXTENSIONS_TABLE . ' + SET group_id = ' . (int) $extensions[$row['extension_id']]['group_id'] . ' + WHERE extension_id = ' . $row['extension_id']; + $db->sql_query($sql); + + add_log('admin', 'LOG_ATTACH_EXT_UPDATE', $row['extension']); + } + } + $db->sql_freeresult($result); + + // Delete Extension? + $extension_id_list = request_var('extension_id_list', array(0)); + + if (sizeof($extension_id_list)) + { + $sql = 'SELECT extension + FROM ' . EXTENSIONS_TABLE . ' + WHERE ' . $db->sql_in_set('extension_id', $extension_id_list); + $result = $db->sql_query($sql); + + $extension_list = ''; + while ($row = $db->sql_fetchrow($result)) + { + $extension_list .= ($extension_list == '') ? $row['extension'] : ', ' . $row['extension']; + } + $db->sql_freeresult($result); + + $sql = 'DELETE + FROM ' . EXTENSIONS_TABLE . ' + WHERE ' . $db->sql_in_set('extension_id', $extension_id_list); + $db->sql_query($sql); + + add_log('admin', 'LOG_ATTACH_EXT_DEL', $extension_list); + } + } + + // Add Extension? + $add_extension = strtolower(request_var('add_extension', '')); + $add_extension_group = request_var('add_group_select', 0); + $add = (isset($_POST['add_extension_check'])) ? true : false; + + if ($add_extension && $add) + { + if (!sizeof($error)) + { + $sql = 'SELECT extension_id + FROM ' . EXTENSIONS_TABLE . " + WHERE extension = '" . $db->sql_escape($add_extension) . "'"; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + $error[] = sprintf($user->lang['EXTENSION_EXIST'], $add_extension); + } + $db->sql_freeresult($result); + + if (!sizeof($error)) + { + $sql_ary = array( + 'group_id' => $add_extension_group, + 'extension' => $add_extension + ); + + $db->sql_query('INSERT INTO ' . EXTENSIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + add_log('admin', 'LOG_ATTACH_EXT_ADD', $add_extension); + } + } + } + + if (!sizeof($error)) + { + $notify[] = $user->lang['EXTENSIONS_UPDATED']; + } + + $cache->destroy('_extensions'); + } + + $template->assign_vars(array( + 'S_EXTENSIONS' => true, + 'ADD_EXTENSION' => (isset($add_extension)) ? $add_extension : '', + 'GROUP_SELECT_OPTIONS' => (isset($_POST['add_extension_check'])) ? $this->group_select('add_group_select', $add_extension_group, 'extension_group') : $this->group_select('add_group_select', false, 'extension_group')) + ); + + $sql = 'SELECT * + FROM ' . EXTENSIONS_TABLE . ' + ORDER BY group_id, extension'; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + $old_group_id = $row['group_id']; + do + { + $s_spacer = false; + + $current_group_id = $row['group_id']; + if ($old_group_id != $current_group_id) + { + $s_spacer = true; + $old_group_id = $current_group_id; + } + + $template->assign_block_vars('extensions', array( + 'S_SPACER' => $s_spacer, + 'EXTENSION_ID' => $row['extension_id'], + 'EXTENSION' => $row['extension'], + 'GROUP_OPTIONS' => $this->group_select('group_select[]', $row['group_id'])) + ); + } + while ($row = $db->sql_fetchrow($result)); + } + $db->sql_freeresult($result); + + break; + + case 'ext_groups': + + $template->assign_var('S_EXTENSION_GROUPS', true); + + if ($submit) + { + $action = request_var('action', ''); + $group_id = request_var('g', 0); + + if ($action != 'add' && $action != 'edit') + { + trigger_error('NO_MODE', E_USER_ERROR); + } + + if (!$group_id && $action == 'edit') + { + trigger_error($user->lang['NO_EXT_GROUP_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if ($group_id) + { + $sql = 'SELECT * + FROM ' . EXTENSION_GROUPS_TABLE . " + WHERE group_id = $group_id"; + $result = $db->sql_query($sql); + $ext_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$ext_row) + { + trigger_error($user->lang['NO_EXT_GROUP_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + else + { + $ext_row = array(); + } + + $group_name = utf8_normalize_nfc(request_var('group_name', '', true)); + $new_group_name = ($action == 'add') ? $group_name : (($ext_row['group_name'] != $group_name) ? $group_name : ''); + + if (!$group_name) + { + $error[] = $user->lang['NO_EXT_GROUP_NAME']; + } + + // Check New Group Name + if ($new_group_name) + { + $sql = 'SELECT group_id + FROM ' . EXTENSION_GROUPS_TABLE . " + WHERE LOWER(group_name) = '" . $db->sql_escape(utf8_strtolower($new_group_name)) . "'"; + $result = $db->sql_query($sql); + + if ($db->sql_fetchrow($result)) + { + $error[] = sprintf($user->lang['EXTENSION_GROUP_EXIST'], $new_group_name); + } + $db->sql_freeresult($result); + } + + if (!sizeof($error)) + { + // Ok, build the update/insert array + $upload_icon = request_var('upload_icon', 'no_image'); + $size_select = request_var('size_select', 'b'); + $forum_select = request_var('forum_select', false); + $allowed_forums = request_var('allowed_forums', array(0)); + $allow_in_pm = (isset($_POST['allow_in_pm'])) ? true : false; + $max_filesize = request_var('max_filesize', 0); + $max_filesize = ($size_select == 'kb') ? round($max_filesize * 1024) : (($size_select == 'mb') ? round($max_filesize * 1048576) : $max_filesize); + $allow_group = (isset($_POST['allow_group'])) ? true : false; + + if ($max_filesize == $config['max_filesize']) + { + $max_filesize = 0; + } + + if (!sizeof($allowed_forums)) + { + $forum_select = false; + } + + $group_ary = array( + 'group_name' => $group_name, + 'cat_id' => request_var('special_category', ATTACHMENT_CATEGORY_NONE), + 'allow_group' => ($allow_group) ? 1 : 0, + 'upload_icon' => ($upload_icon == 'no_image') ? '' : $upload_icon, + 'max_filesize' => $max_filesize, + 'allowed_forums'=> ($forum_select) ? serialize($allowed_forums) : '', + 'allow_in_pm' => ($allow_in_pm) ? 1 : 0, + ); + + if ($action == 'add') + { + $group_ary['download_mode'] = INLINE_LINK; + } + + $sql = ($action == 'add') ? 'INSERT INTO ' . EXTENSION_GROUPS_TABLE . ' ' : 'UPDATE ' . EXTENSION_GROUPS_TABLE . ' SET '; + $sql .= $db->sql_build_array((($action == 'add') ? 'INSERT' : 'UPDATE'), $group_ary); + $sql .= ($action == 'edit') ? " WHERE group_id = $group_id" : ''; + + $db->sql_query($sql); + + if ($action == 'add') + { + $group_id = $db->sql_nextid(); + } + + add_log('admin', 'LOG_ATTACH_EXTGROUP_' . strtoupper($action), $group_name); + } + + $extension_list = request_var('extensions', array(0)); + + if ($action == 'edit' && sizeof($extension_list)) + { + $sql = 'UPDATE ' . EXTENSIONS_TABLE . " + SET group_id = 0 + WHERE group_id = $group_id"; + $db->sql_query($sql); + } + + if (sizeof($extension_list)) + { + $sql = 'UPDATE ' . EXTENSIONS_TABLE . " + SET group_id = $group_id + WHERE " . $db->sql_in_set('extension_id', $extension_list); + $db->sql_query($sql); + } + + $cache->destroy('_extensions'); + + if (!sizeof($error)) + { + $notify[] = $user->lang['SUCCESS_EXTENSION_GROUP_' . strtoupper($action)]; + } + } + + $cat_lang = array( + ATTACHMENT_CATEGORY_NONE => $user->lang['NO_FILE_CAT'], + ATTACHMENT_CATEGORY_IMAGE => $user->lang['CAT_IMAGES'], + ATTACHMENT_CATEGORY_WM => $user->lang['CAT_WM_FILES'], + ATTACHMENT_CATEGORY_RM => $user->lang['CAT_RM_FILES'], + ATTACHMENT_CATEGORY_FLASH => $user->lang['CAT_FLASH_FILES'], + ATTACHMENT_CATEGORY_QUICKTIME => $user->lang['CAT_QUICKTIME_FILES'], + ); + + $group_id = request_var('g', 0); + $action = (isset($_POST['add'])) ? 'add' : $action; + + switch ($action) + { + case 'delete': + + if (confirm_box(true)) + { + $sql = 'SELECT group_name + FROM ' . EXTENSION_GROUPS_TABLE . " + WHERE group_id = $group_id"; + $result = $db->sql_query($sql); + $group_name = (string) $db->sql_fetchfield('group_name'); + $db->sql_freeresult($result); + + $sql = 'DELETE + FROM ' . EXTENSION_GROUPS_TABLE . " + WHERE group_id = $group_id"; + $db->sql_query($sql); + + // Set corresponding Extensions to a pending Group + $sql = 'UPDATE ' . EXTENSIONS_TABLE . " + SET group_id = 0 + WHERE group_id = $group_id"; + $db->sql_query($sql); + + add_log('admin', 'LOG_ATTACH_EXTGROUP_DEL', $group_name); + + $cache->destroy('_extensions'); + + trigger_error($user->lang['EXTENSION_GROUP_DELETED'] . adm_back_link($this->u_action)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'group_id' => $group_id, + 'action' => 'delete', + ))); + } + + break; + + case 'edit': + + if (!$group_id) + { + trigger_error($user->lang['NO_EXT_GROUP_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT * + FROM ' . EXTENSION_GROUPS_TABLE . " + WHERE group_id = $group_id"; + $result = $db->sql_query($sql); + $ext_group_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $forum_ids = (!$ext_group_row['allowed_forums']) ? array() : unserialize(trim($ext_group_row['allowed_forums'])); + + // no break; + + case 'add': + + if ($action == 'add') + { + $ext_group_row = array( + 'group_name' => utf8_normalize_nfc(request_var('group_name', '', true)), + 'cat_id' => 0, + 'allow_group' => 1, + 'allow_in_pm' => 1, + 'upload_icon' => '', + 'max_filesize' => 0, + ); + + $forum_ids = array(); + } + + $extensions = array(); + + $sql = 'SELECT * + FROM ' . EXTENSIONS_TABLE . " + WHERE group_id = $group_id + OR group_id = 0 + ORDER BY extension"; + $result = $db->sql_query($sql); + $extensions = $db->sql_fetchrowset($result); + $db->sql_freeresult($result); + + if ($ext_group_row['max_filesize'] == 0) + { + $ext_group_row['max_filesize'] = (int) $config['max_filesize']; + } + + $max_filesize = get_formatted_filesize($ext_group_row['max_filesize'], false, array('mb', 'kb', 'b')); + $size_format = $max_filesize['si_identifier']; + $ext_group_row['max_filesize'] = $max_filesize['value']; + + $img_path = $config['upload_icons_path']; + + $filename_list = ''; + $no_image_select = false; + + $imglist = filelist($phpbb_root_path . $img_path); + + if (!empty($imglist[''])) + { + $imglist = array_values($imglist); + $imglist = $imglist[0]; + + foreach ($imglist as $key => $img) + { + if (!$ext_group_row['upload_icon']) + { + $no_image_select = true; + $selected = ''; + } + else + { + $selected = ($ext_group_row['upload_icon'] == $img) ? ' selected="selected"' : ''; + } + + if (strlen($img) > 255) + { + continue; + } + + $filename_list .= '<option value="' . htmlspecialchars($img) . '"' . $selected . '>' . htmlspecialchars($img) . '</option>'; + } + } + + $i = 0; + $assigned_extensions = ''; + foreach ($extensions as $num => $row) + { + if ($row['group_id'] == $group_id && $group_id) + { + $assigned_extensions .= ($i) ? ', ' . $row['extension'] : $row['extension']; + $i++; + } + } + + $s_extension_options = ''; + foreach ($extensions as $row) + { + $s_extension_options .= '<option' . ((!$row['group_id']) ? ' class="disabled"' : '') . ' value="' . $row['extension_id'] . '"' . (($row['group_id'] == $group_id && $group_id) ? ' selected="selected"' : '') . '>' . $row['extension'] . '</option>'; + } + + $template->assign_vars(array( + 'PHPBB_ROOT_PATH' => $phpbb_root_path, + 'IMG_PATH' => $img_path, + 'ACTION' => $action, + 'GROUP_ID' => $group_id, + 'GROUP_NAME' => $ext_group_row['group_name'], + 'ALLOW_GROUP' => $ext_group_row['allow_group'], + 'ALLOW_IN_PM' => $ext_group_row['allow_in_pm'], + 'UPLOAD_ICON_SRC' => $phpbb_root_path . $img_path . '/' . $ext_group_row['upload_icon'], + 'EXTGROUP_FILESIZE' => $ext_group_row['max_filesize'], + 'ASSIGNED_EXTENSIONS' => $assigned_extensions, + + 'S_CATEGORY_SELECT' => $this->category_select('special_category', $group_id, 'category'), + 'S_EXT_GROUP_SIZE_OPTIONS' => size_select_options($size_format), + 'S_EXTENSION_OPTIONS' => $s_extension_options, + 'S_FILENAME_LIST' => $filename_list, + 'S_EDIT_GROUP' => true, + 'S_NO_IMAGE' => $no_image_select, + 'S_FORUM_IDS' => (sizeof($forum_ids)) ? true : false, + + 'U_EXTENSIONS' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=extensions"), + 'U_BACK' => $this->u_action, + + 'L_LEGEND' => $user->lang[strtoupper($action) . '_EXTENSION_GROUP']) + ); + + $s_forum_id_options = ''; + + /** @todo use in-built function **/ + + $sql = 'SELECT forum_id, forum_name, parent_id, forum_type, left_id, right_id + FROM ' . FORUMS_TABLE . ' + ORDER BY left_id ASC'; + $result = $db->sql_query($sql, 600); + + $right = $cat_right = $padding_inc = 0; + $padding = $forum_list = $holding = ''; + $padding_store = array('0' => ''); + + while ($row = $db->sql_fetchrow($result)) + { + if ($row['forum_type'] == FORUM_CAT && ($row['left_id'] + 1 == $row['right_id'])) + { + // Non-postable forum with no subforums, don't display + continue; + } + + if (!$auth->acl_get('f_list', $row['forum_id'])) + { + // if the user does not have permissions to list this forum skip + continue; + } + + if ($row['left_id'] < $right) + { + $padding .= ' '; + $padding_store[$row['parent_id']] = $padding; + } + else if ($row['left_id'] > $right + 1) + { + $padding = empty($padding_store[$row['parent_id']]) ? '' : $padding_store[$row['parent_id']]; + } + + $right = $row['right_id']; + + $selected = (in_array($row['forum_id'], $forum_ids)) ? ' selected="selected"' : ''; + + if ($row['left_id'] > $cat_right) + { + // make sure we don't forget anything + $s_forum_id_options .= $holding; + $holding = ''; + } + + if ($row['right_id'] - $row['left_id'] > 1) + { + $cat_right = max($cat_right, $row['right_id']); + + $holding .= '<option value="' . $row['forum_id'] . '"' . (($row['forum_type'] == FORUM_POST) ? ' class="sep"' : '') . $selected . '>' . $padding . $row['forum_name'] . '</option>'; + } + else + { + $s_forum_id_options .= $holding . '<option value="' . $row['forum_id'] . '"' . (($row['forum_type'] == FORUM_POST) ? ' class="sep"' : '') . $selected . '>' . $padding . $row['forum_name'] . '</option>'; + $holding = ''; + } + } + + if ($holding) + { + $s_forum_id_options .= $holding; + } + + $db->sql_freeresult($result); + unset($padding_store); + + $template->assign_vars(array( + 'S_FORUM_ID_OPTIONS' => $s_forum_id_options) + ); + + break; + } + + $sql = 'SELECT * + FROM ' . EXTENSION_GROUPS_TABLE . ' + ORDER BY allow_group DESC, allow_in_pm DESC, group_name'; + $result = $db->sql_query($sql); + + $old_allow_group = $old_allow_pm = 1; + while ($row = $db->sql_fetchrow($result)) + { + $s_add_spacer = ($old_allow_group != $row['allow_group'] || $old_allow_pm != $row['allow_in_pm']) ? true : false; + + $template->assign_block_vars('groups', array( + 'S_ADD_SPACER' => $s_add_spacer, + 'S_ALLOWED_IN_PM' => ($row['allow_in_pm']) ? true : false, + 'S_GROUP_ALLOWED' => ($row['allow_group']) ? true : false, + + 'U_EDIT' => $this->u_action . "&action=edit&g={$row['group_id']}", + 'U_DELETE' => $this->u_action . "&action=delete&g={$row['group_id']}", + + 'GROUP_NAME' => $row['group_name'], + 'CATEGORY' => $cat_lang[$row['cat_id']], + ) + ); + + $old_allow_group = $row['allow_group']; + $old_allow_pm = $row['allow_in_pm']; + } + $db->sql_freeresult($result); + + break; + + case 'orphan': + + if ($submit) + { + $delete_files = (isset($_POST['delete'])) ? array_keys(request_var('delete', array('' => 0))) : array(); + $add_files = (isset($_POST['add'])) ? array_keys(request_var('add', array('' => 0))) : array(); + $post_ids = request_var('post_id', array('' => 0)); + + if (sizeof($delete_files)) + { + $sql = 'SELECT * + FROM ' . ATTACHMENTS_TABLE . ' + WHERE ' . $db->sql_in_set('attach_id', $delete_files) . ' + AND is_orphan = 1'; + $result = $db->sql_query($sql); + + $delete_files = array(); + while ($row = $db->sql_fetchrow($result)) + { + phpbb_unlink($row['physical_filename'], 'file'); + + if ($row['thumbnail']) + { + phpbb_unlink($row['physical_filename'], 'thumbnail'); + } + + $delete_files[$row['attach_id']] = $row['real_filename']; + } + $db->sql_freeresult($result); + } + + if (sizeof($delete_files)) + { + $sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . ' + WHERE ' . $db->sql_in_set('attach_id', array_keys($delete_files)); + $db->sql_query($sql); + + add_log('admin', 'LOG_ATTACH_ORPHAN_DEL', implode(', ', $delete_files)); + $notify[] = sprintf($user->lang['LOG_ATTACH_ORPHAN_DEL'], implode(', ', $delete_files)); + } + + $upload_list = array(); + foreach ($add_files as $attach_id) + { + if (!isset($delete_files[$attach_id]) && !empty($post_ids[$attach_id])) + { + $upload_list[$attach_id] = $post_ids[$attach_id]; + } + } + unset($add_files); + + if (sizeof($upload_list)) + { + $template->assign_var('S_UPLOADING_FILES', true); + + $sql = 'SELECT forum_id, forum_name + FROM ' . FORUMS_TABLE; + $result = $db->sql_query($sql); + + $forum_names = array(); + while ($row = $db->sql_fetchrow($result)) + { + $forum_names[$row['forum_id']] = $row['forum_name']; + } + $db->sql_freeresult($result); + + $sql = 'SELECT forum_id, topic_id, post_id, poster_id + FROM ' . POSTS_TABLE . ' + WHERE ' . $db->sql_in_set('post_id', $upload_list); + $result = $db->sql_query($sql); + + $post_info = array(); + while ($row = $db->sql_fetchrow($result)) + { + $post_info[$row['post_id']] = $row; + } + $db->sql_freeresult($result); + + // Select those attachments we want to change... + $sql = 'SELECT * + FROM ' . ATTACHMENTS_TABLE . ' + WHERE ' . $db->sql_in_set('attach_id', array_keys($upload_list)) . ' + AND is_orphan = 1'; + $result = $db->sql_query($sql); + + $files_added = $space_taken = 0; + while ($row = $db->sql_fetchrow($result)) + { + $post_row = $post_info[$upload_list[$row['attach_id']]]; + + $template->assign_block_vars('upload', array( + 'FILE_INFO' => sprintf($user->lang['UPLOADING_FILE_TO'], $row['real_filename'], $post_row['post_id']), + 'S_DENIED' => (!$auth->acl_get('f_attach', $post_row['forum_id'])) ? true : false, + 'L_DENIED' => (!$auth->acl_get('f_attach', $post_row['forum_id'])) ? sprintf($user->lang['UPLOAD_DENIED_FORUM'], $forum_names[$row['forum_id']]) : '') + ); + + if (!$auth->acl_get('f_attach', $post_row['forum_id'])) + { + continue; + } + + // Adjust attachment entry + $sql_ary = array( + 'in_message' => 0, + 'is_orphan' => 0, + 'poster_id' => $post_row['poster_id'], + 'post_msg_id' => $post_row['post_id'], + 'topic_id' => $post_row['topic_id'], + ); + + $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE attach_id = ' . $row['attach_id']; + $db->sql_query($sql); + + $sql = 'UPDATE ' . POSTS_TABLE . ' + SET post_attachment = 1 + WHERE post_id = ' . $post_row['post_id']; + $db->sql_query($sql); + + $sql = 'UPDATE ' . TOPICS_TABLE . ' + SET topic_attachment = 1 + WHERE topic_id = ' . $post_row['topic_id']; + $db->sql_query($sql); + + $space_taken += $row['filesize']; + $files_added++; + + add_log('admin', 'LOG_ATTACH_FILEUPLOAD', $post_row['post_id'], $row['real_filename']); + } + $db->sql_freeresult($result); + + if ($files_added) + { + set_config_count('upload_dir_size', $space_taken, true); + set_config_count('num_files', $files_added, true); + } + } + } + + $template->assign_vars(array( + 'S_ORPHAN' => true) + ); + + // Just get the files with is_orphan set and older than 3 hours + $sql = 'SELECT * + FROM ' . ATTACHMENTS_TABLE . ' + WHERE is_orphan = 1 + AND filetime < ' . (time() - 3*60*60) . ' + ORDER BY filetime DESC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $template->assign_block_vars('orphan', array( + 'FILESIZE' => get_formatted_filesize($row['filesize']), + 'FILETIME' => $user->format_date($row['filetime']), + 'REAL_FILENAME' => utf8_basename($row['real_filename']), + 'PHYSICAL_FILENAME' => utf8_basename($row['physical_filename']), + 'ATTACH_ID' => $row['attach_id'], + 'POST_IDS' => (!empty($post_ids[$row['attach_id']])) ? $post_ids[$row['attach_id']] : '', + 'U_FILE' => append_sid($phpbb_root_path . 'download/file.' . $phpEx, 'mode=view&id=' . $row['attach_id'])) + ); + } + $db->sql_freeresult($result); + + break; + } + + if (sizeof($error)) + { + $template->assign_vars(array( + 'S_WARNING' => true, + 'WARNING_MSG' => implode('<br />', $error)) + ); + } + + if (sizeof($notify)) + { + $template->assign_vars(array( + 'S_NOTIFY' => true, + 'NOTIFY_MSG' => implode('<br />', $notify)) + ); + } + } + + /** + * Build Select for category items + */ + function category_select($select_name, $group_id = false, $key = '') + { + global $db, $user; + + $types = array( + ATTACHMENT_CATEGORY_NONE => $user->lang['NO_FILE_CAT'], + ATTACHMENT_CATEGORY_IMAGE => $user->lang['CAT_IMAGES'], + ATTACHMENT_CATEGORY_WM => $user->lang['CAT_WM_FILES'], + ATTACHMENT_CATEGORY_RM => $user->lang['CAT_RM_FILES'], + ATTACHMENT_CATEGORY_FLASH => $user->lang['CAT_FLASH_FILES'], + ATTACHMENT_CATEGORY_QUICKTIME => $user->lang['CAT_QUICKTIME_FILES'], + ); + + if ($group_id) + { + $sql = 'SELECT cat_id + FROM ' . EXTENSION_GROUPS_TABLE . ' + WHERE group_id = ' . (int) $group_id; + $result = $db->sql_query($sql); + + $cat_type = (!($row = $db->sql_fetchrow($result))) ? ATTACHMENT_CATEGORY_NONE : $row['cat_id']; + + $db->sql_freeresult($result); + } + else + { + $cat_type = ATTACHMENT_CATEGORY_NONE; + } + + $group_select = '<select name="' . $select_name . '"' . (($key) ? ' id="' . $key . '"' : '') . '>'; + + foreach ($types as $type => $mode) + { + $selected = ($type == $cat_type) ? ' selected="selected"' : ''; + $group_select .= '<option value="' . $type . '"' . $selected . '>' . $mode . '</option>'; + } + + $group_select .= '</select>'; + + return $group_select; + } + + /** + * Extension group select + */ + function group_select($select_name, $default_group = false, $key = '') + { + global $db, $user; + + $group_select = '<select name="' . $select_name . '"' . (($key) ? ' id="' . $key . '"' : '') . '>'; + + $sql = 'SELECT group_id, group_name + FROM ' . EXTENSION_GROUPS_TABLE . ' + ORDER BY group_name'; + $result = $db->sql_query($sql); + + $group_name = array(); + while ($row = $db->sql_fetchrow($result)) + { + $group_name[] = $row; + } + $db->sql_freeresult($result); + + $row['group_id'] = 0; + $row['group_name'] = $user->lang['NOT_ASSIGNED']; + $group_name[] = $row; + + for ($i = 0; $i < sizeof($group_name); $i++) + { + if ($default_group === false) + { + $selected = ($i == 0) ? ' selected="selected"' : ''; + } + else + { + $selected = ($group_name[$i]['group_id'] == $default_group) ? ' selected="selected"' : ''; + } + + $group_select .= '<option value="' . $group_name[$i]['group_id'] . '"' . $selected . '>' . $group_name[$i]['group_name'] . '</option>'; + } + + $group_select .= '</select>'; + + return $group_select; + } + + /** + * Search Imagick + */ + function search_imagemagick() + { + $imagick = ''; + + $exe = ((defined('PHP_OS')) && (preg_match('#^win#i', PHP_OS))) ? '.exe' : ''; + + $magic_home = getenv('MAGICK_HOME'); + + if (empty($magic_home)) + { + $locations = array('C:/WINDOWS/', 'C:/WINNT/', 'C:/WINDOWS/SYSTEM/', 'C:/WINNT/SYSTEM/', 'C:/WINDOWS/SYSTEM32/', 'C:/WINNT/SYSTEM32/', '/usr/bin/', '/usr/sbin/', '/usr/local/bin/', '/usr/local/sbin/', '/opt/', '/usr/imagemagick/', '/usr/bin/imagemagick/'); + $path_locations = str_replace('\\', '/', (explode(($exe) ? ';' : ':', getenv('PATH')))); + + $locations = array_merge($path_locations, $locations); + + foreach ($locations as $location) + { + // The path might not end properly, fudge it + if (substr($location, -1) !== '/') + { + $location .= '/'; + } + + if (@file_exists($location) && @is_readable($location . 'mogrify' . $exe) && @filesize($location . 'mogrify' . $exe) > 3000) + { + $imagick = str_replace('\\', '/', $location); + continue; + } + } + } + else + { + $imagick = str_replace('\\', '/', $magic_home); + } + + return $imagick; + } + + /** + * Test Settings + */ + function test_upload(&$error, $upload_dir, $create_directory = false) + { + global $user, $phpbb_root_path; + + // Does the target directory exist, is it a directory and writable. + if ($create_directory) + { + if (!file_exists($phpbb_root_path . $upload_dir)) + { + @mkdir($phpbb_root_path . $upload_dir, 0777); + phpbb_chmod($phpbb_root_path . $upload_dir, CHMOD_READ | CHMOD_WRITE); + } + } + + if (!file_exists($phpbb_root_path . $upload_dir)) + { + $error[] = sprintf($user->lang['NO_UPLOAD_DIR'], $upload_dir); + return; + } + + if (!is_dir($phpbb_root_path . $upload_dir)) + { + $error[] = sprintf($user->lang['UPLOAD_NOT_DIR'], $upload_dir); + return; + } + + if (!is_writable($phpbb_root_path . $upload_dir)) + { + $error[] = sprintf($user->lang['NO_WRITE_UPLOAD'], $upload_dir); + return; + } + } + + /** + * Perform operations on sites for external linking + */ + function perform_site_list() + { + global $db, $user; + + if (isset($_REQUEST['securesubmit'])) + { + // Grab the list of entries + $ips = request_var('ips', ''); + $ip_list = array_unique(explode("\n", $ips)); + $ip_list_log = implode(', ', $ip_list); + + $ip_exclude = (!empty($_POST['ipexclude'])) ? 1 : 0; + + $iplist = array(); + $hostlist = array(); + + foreach ($ip_list as $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($item), $ip_range_explode)) + { + // 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; + + $iplist[] = "'$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; + + $iplist[] = "'$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; + + $iplist[] = "'$ip_1_counter.$ip_2_counter.$ip_3_counter.*'"; + } + + while ($ip_4_counter <= $ip_4_end) + { + $iplist[] = "'$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($item)) || preg_match('#^[a-f0-9:]+\*?$#i', trim($item))) + { + $iplist[] = "'" . trim($item) . "'"; + } + else if (preg_match('#^([\w\-_]\.?){2,}$#is', trim($item))) + { + $hostlist[] = "'" . trim($item) . "'"; + } + else if (preg_match("#^([a-z0-9\-\*\._/]+?)$#is", trim($item))) + { + $hostlist[] = "'" . trim($item) . "'"; + } + } + + $sql = 'SELECT site_ip, site_hostname + FROM ' . SITELIST_TABLE . " + WHERE ip_exclude = $ip_exclude"; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + $iplist_tmp = array(); + $hostlist_tmp = array(); + do + { + if ($row['site_ip']) + { + if (strlen($row['site_ip']) > 40) + { + continue; + } + + $iplist_tmp[] = "'" . $row['site_ip'] . "'"; + } + else if ($row['site_hostname']) + { + if (strlen($row['site_hostname']) > 255) + { + continue; + } + + $hostlist_tmp[] = "'" . $row['site_hostname'] . "'"; + } + // break; + } + while ($row = $db->sql_fetchrow($result)); + + $iplist = array_unique(array_diff($iplist, $iplist_tmp)); + $hostlist = array_unique(array_diff($hostlist, $hostlist_tmp)); + unset($iplist_tmp); + unset($hostlist_tmp); + } + $db->sql_freeresult($result); + + if (sizeof($iplist)) + { + foreach ($iplist as $ip_entry) + { + $sql = 'INSERT INTO ' . SITELIST_TABLE . " (site_ip, ip_exclude) + VALUES ($ip_entry, $ip_exclude)"; + $db->sql_query($sql); + } + } + + if (sizeof($hostlist)) + { + foreach ($hostlist as $host_entry) + { + $sql = 'INSERT INTO ' . SITELIST_TABLE . " (site_hostname, ip_exclude) + VALUES ($host_entry, $ip_exclude)"; + $db->sql_query($sql); + } + } + + if (!empty($ip_list_log)) + { + // Update log + $log_entry = ($ip_exclude) ? 'LOG_DOWNLOAD_EXCLUDE_IP' : 'LOG_DOWNLOAD_IP'; + add_log('admin', $log_entry, $ip_list_log); + } + + trigger_error($user->lang['SECURE_DOWNLOAD_UPDATE_SUCCESS'] . adm_back_link($this->u_action)); + } + else if (isset($_POST['unsecuresubmit'])) + { + $unip_sql = request_var('unip', array(0)); + + if (sizeof($unip_sql)) + { + $l_unip_list = ''; + + // Grab details of ips for logging information later + $sql = 'SELECT site_ip, site_hostname + FROM ' . SITELIST_TABLE . ' + WHERE ' . $db->sql_in_set('site_id', $unip_sql); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $l_unip_list .= (($l_unip_list != '') ? ', ' : '') . (($row['site_ip']) ? $row['site_ip'] : $row['site_hostname']); + } + $db->sql_freeresult($result); + + $sql = 'DELETE FROM ' . SITELIST_TABLE . ' + WHERE ' . $db->sql_in_set('site_id', $unip_sql); + $db->sql_query($sql); + + add_log('admin', 'LOG_DOWNLOAD_REMOVE_IP', $l_unip_list); + } + + trigger_error($user->lang['SECURE_DOWNLOAD_UPDATE_SUCCESS'] . adm_back_link($this->u_action)); + } + } + + /** + * Write display_order config field + */ + function display_order($value, $key = '') + { + $radio_ary = array(0 => 'DESCENDING', 1 => 'ASCENDING'); + + return h_radio('config[display_order]', $radio_ary, $value, $key); + } + + /** + * Adjust all three max_filesize config vars for display + */ + function max_filesize($value, $key = '') + { + // Determine size var and adjust the value accordingly + $filesize = get_formatted_filesize($value, false, array('mb', 'kb', 'b')); + $size_var = $filesize['si_identifier']; + $value = $filesize['value']; + + return '<input type="text" id="' . $key . '" size="8" maxlength="15" name="config[' . $key . ']" value="' . $value . '" /> <select name="' . $key . '">' . size_select_options($size_var) . '</select>'; + } + + /** + * Write secure_allow_deny config field + */ + function select_allow_deny($value, $key = '') + { + $radio_ary = array(1 => 'ORDER_ALLOW_DENY', 0 => 'ORDER_DENY_ALLOW'); + + return h_radio('config[' . $key . ']', $radio_ary, $value, $key); + } + +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_ban.php b/phpBB/includes/acp/acp_ban.php new file mode 100644 index 0000000000..3198376584 --- /dev/null +++ b/phpBB/includes/acp/acp_ban.php @@ -0,0 +1,252 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_ban +{ + var $u_action; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $cache; + global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix; + + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + + $bansubmit = (isset($_POST['bansubmit'])) ? true : false; + $unbansubmit = (isset($_POST['unbansubmit'])) ? true : false; + $current_time = time(); + + $user->add_lang(array('acp/ban', 'acp/users')); + $this->tpl_name = 'acp_ban'; + $form_key = 'acp_ban'; + add_form_key($form_key); + + if (($bansubmit || $unbansubmit) && !check_form_key($form_key)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Ban submitted? + if ($bansubmit) + { + // Grab the list of entries + $ban = utf8_normalize_nfc(request_var('ban', '', true)); + $ban_len = request_var('banlength', 0); + $ban_len_other = request_var('banlengthother', ''); + $ban_exclude = request_var('banexclude', 0); + $ban_reason = utf8_normalize_nfc(request_var('banreason', '', true)); + $ban_give_reason = utf8_normalize_nfc(request_var('bangivereason', '', true)); + + if ($ban) + { + user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reason, $ban_give_reason); + + trigger_error($user->lang['BAN_UPDATE_SUCCESSFUL'] . adm_back_link($this->u_action)); + } + } + else if ($unbansubmit) + { + $ban = request_var('unban', array('')); + + if ($ban) + { + user_unban($mode, $ban); + + trigger_error($user->lang['BAN_UPDATE_SUCCESSFUL'] . adm_back_link($this->u_action)); + } + } + + // Define language vars + $this->page_title = $user->lang[strtoupper($mode) . '_BAN']; + + $l_ban_explain = $user->lang[strtoupper($mode) . '_BAN_EXPLAIN']; + $l_ban_exclude_explain = $user->lang[strtoupper($mode) . '_BAN_EXCLUDE_EXPLAIN']; + $l_unban_title = $user->lang[strtoupper($mode) . '_UNBAN']; + $l_unban_explain = $user->lang[strtoupper($mode) . '_UNBAN_EXPLAIN']; + $l_no_ban_cell = $user->lang[strtoupper($mode) . '_NO_BANNED']; + + switch ($mode) + { + case 'user': + $l_ban_cell = $user->lang['USERNAME']; + break; + + case 'ip': + $l_ban_cell = $user->lang['IP_HOSTNAME']; + break; + + case 'email': + $l_ban_cell = $user->lang['EMAIL_ADDRESS']; + break; + } + + $this->display_ban_options($mode); + + $template->assign_vars(array( + 'L_TITLE' => $this->page_title, + 'L_EXPLAIN' => $l_ban_explain, + 'L_UNBAN_TITLE' => $l_unban_title, + 'L_UNBAN_EXPLAIN' => $l_unban_explain, + 'L_BAN_CELL' => $l_ban_cell, + 'L_BAN_EXCLUDE_EXPLAIN' => $l_ban_exclude_explain, + 'L_NO_BAN_CELL' => $l_no_ban_cell, + + 'S_USERNAME_BAN' => ($mode == 'user') ? true : false, + + 'U_ACTION' => $this->u_action, + 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=acp_ban&field=ban'), + )); + } + + /** + * Display ban options + */ + function display_ban_options($mode) + { + global $user, $db, $template; + + // Ban length options + $ban_end_text = array(0 => $user->lang['PERMANENT'], 30 => $user->lang['30_MINS'], 60 => $user->lang['1_HOUR'], 360 => $user->lang['6_HOURS'], 1440 => $user->lang['1_DAY'], 10080 => $user->lang['7_DAYS'], 20160 => $user->lang['2_WEEKS'], 40320 => $user->lang['1_MONTH'], -1 => $user->lang['UNTIL'] . ' -> '); + + $ban_end_options = ''; + foreach ($ban_end_text as $length => $text) + { + $ban_end_options .= '<option value="' . $length . '">' . $text . '</option>'; + } + + switch ($mode) + { + case 'user': + + $field = 'username'; + $l_ban_cell = $user->lang['USERNAME']; + + $sql = 'SELECT b.*, u.user_id, u.username, u.username_clean + FROM ' . BANLIST_TABLE . ' b, ' . USERS_TABLE . ' u + WHERE (b.ban_end >= ' . time() . ' + OR b.ban_end = 0) + AND u.user_id = b.ban_userid + ORDER BY u.username_clean ASC'; + break; + + case 'ip': + + $field = 'ban_ip'; + $l_ban_cell = $user->lang['IP_HOSTNAME']; + + $sql = 'SELECT * + FROM ' . BANLIST_TABLE . ' + WHERE (ban_end >= ' . time() . " + OR ban_end = 0) + AND ban_ip <> '' + ORDER BY ban_ip"; + break; + + case 'email': + + $field = 'ban_email'; + $l_ban_cell = $user->lang['EMAIL_ADDRESS']; + + $sql = 'SELECT * + FROM ' . BANLIST_TABLE . ' + WHERE (ban_end >= ' . time() . " + OR ban_end = 0) + AND ban_email <> '' + ORDER BY ban_email"; + break; + } + $result = $db->sql_query($sql); + + $banned_options = ''; + $ban_length = $ban_reasons = $ban_give_reasons = array(); + + while ($row = $db->sql_fetchrow($result)) + { + $banned_options .= '<option' . (($row['ban_exclude']) ? ' class="sep"' : '') . ' value="' . $row['ban_id'] . '">' . $row[$field] . '</option>'; + + $time_length = ($row['ban_end']) ? ($row['ban_end'] - $row['ban_start']) / 60 : 0; + + if ($time_length == 0) + { + // Banned permanently + $ban_length[$row['ban_id']] = $user->lang['PERMANENT']; + } + else if (isset($ban_end_text[$time_length])) + { + // Banned for a given duration + $ban_length[$row['ban_id']] = sprintf($user->lang['BANNED_UNTIL_DURATION'], $ban_end_text[$time_length], $user->format_date($row['ban_end'], false, true)); + } + else + { + // Banned until given date + $ban_length[$row['ban_id']] = sprintf($user->lang['BANNED_UNTIL_DATE'], $user->format_date($row['ban_end'], false, true)); + } + + $ban_reasons[$row['ban_id']] = $row['ban_reason']; + $ban_give_reasons[$row['ban_id']] = $row['ban_give_reason']; + } + $db->sql_freeresult($result); + + if (sizeof($ban_length)) + { + foreach ($ban_length as $ban_id => $length) + { + $template->assign_block_vars('ban_length', array( + 'BAN_ID' => (int) $ban_id, + 'LENGTH' => $length, + 'A_LENGTH' => addslashes($length), + )); + } + } + + if (sizeof($ban_reasons)) + { + foreach ($ban_reasons as $ban_id => $reason) + { + $template->assign_block_vars('ban_reason', array( + 'BAN_ID' => $ban_id, + 'REASON' => $reason, + 'A_REASON' => addslashes(htmlspecialchars_decode($reason)), + )); + } + } + + if (sizeof($ban_give_reasons)) + { + foreach ($ban_give_reasons as $ban_id => $reason) + { + $template->assign_block_vars('ban_give_reason', array( + 'BAN_ID' => $ban_id, + 'REASON' => $reason, + 'A_REASON' => addslashes(htmlspecialchars_decode($reason)), + )); + } + } + + $template->assign_vars(array( + 'S_BAN_END_OPTIONS' => $ban_end_options, + 'S_BANNED_OPTIONS' => ($banned_options) ? true : false, + 'BANNED_OPTIONS' => $banned_options) + ); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php new file mode 100644 index 0000000000..b827d1107e --- /dev/null +++ b/phpBB/includes/acp/acp_bbcodes.php @@ -0,0 +1,443 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_bbcodes +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + $user->add_lang('acp/posting'); + + // Set up general vars + $action = request_var('action', ''); + $bbcode_id = request_var('bbcode', 0); + + $this->tpl_name = 'acp_bbcodes'; + $this->page_title = 'ACP_BBCODES'; + $form_key = 'acp_bbcodes'; + + add_form_key($form_key); + + // Set up mode-specific vars + switch ($action) + { + case 'add': + $bbcode_match = $bbcode_tpl = $bbcode_helpline = ''; + $display_on_posting = 0; + break; + + case 'edit': + $sql = 'SELECT bbcode_match, bbcode_tpl, display_on_posting, bbcode_helpline + FROM ' . BBCODES_TABLE . ' + WHERE bbcode_id = ' . $bbcode_id; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error($user->lang['BBCODE_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $bbcode_match = $row['bbcode_match']; + $bbcode_tpl = htmlspecialchars($row['bbcode_tpl']); + $display_on_posting = $row['display_on_posting']; + $bbcode_helpline = $row['bbcode_helpline']; + break; + + case 'modify': + $sql = 'SELECT bbcode_id, bbcode_tag + FROM ' . BBCODES_TABLE . ' + WHERE bbcode_id = ' . $bbcode_id; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error($user->lang['BBCODE_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // No break here + + case 'create': + $display_on_posting = request_var('display_on_posting', 0); + + $bbcode_match = request_var('bbcode_match', ''); + $bbcode_tpl = htmlspecialchars_decode(utf8_normalize_nfc(request_var('bbcode_tpl', '', true))); + $bbcode_helpline = utf8_normalize_nfc(request_var('bbcode_helpline', '', true)); + break; + } + + // Do major work + switch ($action) + { + case 'edit': + case 'add': + + $template->assign_vars(array( + 'S_EDIT_BBCODE' => true, + 'U_BACK' => $this->u_action, + 'U_ACTION' => $this->u_action . '&action=' . (($action == 'add') ? 'create' : 'modify') . (($bbcode_id) ? "&bbcode=$bbcode_id" : ''), + + 'L_BBCODE_USAGE_EXPLAIN'=> sprintf($user->lang['BBCODE_USAGE_EXPLAIN'], '<a href="#down">', '</a>'), + 'BBCODE_MATCH' => $bbcode_match, + 'BBCODE_TPL' => $bbcode_tpl, + 'BBCODE_HELPLINE' => $bbcode_helpline, + 'DISPLAY_ON_POSTING' => $display_on_posting) + ); + + foreach ($user->lang['tokens'] as $token => $token_explain) + { + $template->assign_block_vars('token', array( + 'TOKEN' => '{' . $token . '}', + 'EXPLAIN' => $token_explain) + ); + } + + return; + + break; + + case 'modify': + case 'create': + + $data = $this->build_regexp($bbcode_match, $bbcode_tpl); + + // Make sure the user didn't pick a "bad" name for the BBCode tag. + $hard_coded = array('code', 'quote', 'quote=', 'attachment', 'attachment=', 'b', 'i', 'url', 'url=', 'img', 'size', 'size=', 'color', 'color=', 'u', 'list', 'list=', 'email', 'email=', 'flash', 'flash='); + + if (($action == 'modify' && strtolower($data['bbcode_tag']) !== strtolower($row['bbcode_tag'])) || ($action == 'create')) + { + $sql = 'SELECT 1 as test + FROM ' . BBCODES_TABLE . " + WHERE LOWER(bbcode_tag) = '" . $db->sql_escape(strtolower($data['bbcode_tag'])) . "'"; + $result = $db->sql_query($sql); + $info = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + // Grab the end, interrogate the last closing tag + if ($info['test'] === '1' || in_array(strtolower($data['bbcode_tag']), $hard_coded) || (preg_match('#\[/([^[]*)]$#', $bbcode_match, $regs) && in_array(strtolower($regs[1]), $hard_coded))) + { + trigger_error($user->lang['BBCODE_INVALID_TAG_NAME'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + + if (substr($data['bbcode_tag'], -1) === '=') + { + $test = substr($data['bbcode_tag'], 0, -1); + } + else + { + $test = $data['bbcode_tag']; + } + + if (!preg_match('%\\[' . $test . '[^]]*].*?\\[/' . $test . ']%s', $bbcode_match)) + { + trigger_error($user->lang['BBCODE_OPEN_ENDED_TAG'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (strlen($data['bbcode_tag']) > 16) + { + trigger_error($user->lang['BBCODE_TAG_TOO_LONG'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (strlen($bbcode_match) > 4000) + { + trigger_error($user->lang['BBCODE_TAG_DEF_TOO_LONG'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + + if (strlen($bbcode_helpline) > 255) + { + trigger_error($user->lang['BBCODE_HELPLINE_TOO_LONG'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql_ary = array( + 'bbcode_tag' => $data['bbcode_tag'], + 'bbcode_match' => $bbcode_match, + 'bbcode_tpl' => $bbcode_tpl, + 'display_on_posting' => $display_on_posting, + 'bbcode_helpline' => $bbcode_helpline, + 'first_pass_match' => $data['first_pass_match'], + 'first_pass_replace' => $data['first_pass_replace'], + 'second_pass_match' => $data['second_pass_match'], + 'second_pass_replace' => $data['second_pass_replace'] + ); + + if ($action == 'create') + { + $sql = 'SELECT MAX(bbcode_id) as max_bbcode_id + FROM ' . BBCODES_TABLE; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + $bbcode_id = $row['max_bbcode_id'] + 1; + + // Make sure it is greater than the core bbcode ids... + if ($bbcode_id <= NUM_CORE_BBCODES) + { + $bbcode_id = NUM_CORE_BBCODES + 1; + } + } + else + { + $bbcode_id = NUM_CORE_BBCODES + 1; + } + + if ($bbcode_id > 1511) + { + trigger_error($user->lang['TOO_MANY_BBCODES'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql_ary['bbcode_id'] = (int) $bbcode_id; + + $db->sql_query('INSERT INTO ' . BBCODES_TABLE . $db->sql_build_array('INSERT', $sql_ary)); + $cache->destroy('sql', BBCODES_TABLE); + + $lang = 'BBCODE_ADDED'; + $log_action = 'LOG_BBCODE_ADD'; + } + else + { + $sql = 'UPDATE ' . BBCODES_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE bbcode_id = ' . $bbcode_id; + $db->sql_query($sql); + $cache->destroy('sql', BBCODES_TABLE); + + $lang = 'BBCODE_EDITED'; + $log_action = 'LOG_BBCODE_EDIT'; + } + + add_log('admin', $log_action, $data['bbcode_tag']); + + trigger_error($user->lang[$lang] . adm_back_link($this->u_action)); + + break; + + case 'delete': + + $sql = 'SELECT bbcode_tag + FROM ' . BBCODES_TABLE . " + WHERE bbcode_id = $bbcode_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + if (confirm_box(true)) + { + $db->sql_query('DELETE FROM ' . BBCODES_TABLE . " WHERE bbcode_id = $bbcode_id"); + $cache->destroy('sql', BBCODES_TABLE); + add_log('admin', 'LOG_BBCODE_DELETE', $row['bbcode_tag']); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'bbcode' => $bbcode_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action)) + ); + } + } + + break; + } + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action . '&action=add') + ); + + $sql = 'SELECT * + FROM ' . BBCODES_TABLE . ' + ORDER BY bbcode_tag'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $template->assign_block_vars('bbcodes', array( + 'BBCODE_TAG' => $row['bbcode_tag'], + 'U_EDIT' => $this->u_action . '&action=edit&bbcode=' . $row['bbcode_id'], + 'U_DELETE' => $this->u_action . '&action=delete&bbcode=' . $row['bbcode_id']) + ); + } + $db->sql_freeresult($result); + } + + /* + * Build regular expression for custom bbcode + */ + function build_regexp(&$bbcode_match, &$bbcode_tpl) + { + $bbcode_match = trim($bbcode_match); + $bbcode_tpl = trim($bbcode_tpl); + + $fp_match = preg_quote($bbcode_match, '!'); + $fp_replace = preg_replace('#^\[(.*?)\]#', '[$1:$uid]', $bbcode_match); + $fp_replace = preg_replace('#\[/(.*?)\]$#', '[/$1:$uid]', $fp_replace); + + $sp_match = preg_quote($bbcode_match, '!'); + $sp_match = preg_replace('#^\\\\\[(.*?)\\\\\]#', '\[$1:$uid\]', $sp_match); + $sp_match = preg_replace('#\\\\\[/(.*?)\\\\\]$#', '\[/$1:$uid\]', $sp_match); + $sp_replace = $bbcode_tpl; + + // @todo Make sure to change this too if something changed in message parsing + $tokens = array( + 'URL' => array( + '!(?:(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('url')) . ')|(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('www_url')) . '))!ie' => "\$this->bbcode_specialchars(('\$1') ? '\$1' : 'http://\$2')" + ), + 'LOCAL_URL' => array( + '!(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('relative_url')) . ')!e' => "\$this->bbcode_specialchars('$1')" + ), + 'EMAIL' => array( + '!(' . get_preg_expression('email') . ')!ie' => "\$this->bbcode_specialchars('$1')" + ), + 'TEXT' => array( + '!(.*?)!es' => "str_replace(array(\"\\r\\n\", '\\\"', '\\'', '(', ')'), array(\"\\n\", '\"', ''', '(', ')'), trim('\$1'))" + ), + 'SIMPLETEXT' => array( + '!([a-zA-Z0-9-+.,_ ]+)!' => "$1" + ), + 'IDENTIFIER' => array( + '!([a-zA-Z0-9-_]+)!' => "$1" + ), + 'COLOR' => array( + '!([a-z]+|#[0-9abcdef]+)!i' => '$1' + ), + 'NUMBER' => array( + '!([0-9]+)!' => '$1' + ) + ); + + $sp_tokens = array( + 'URL' => '(?i)((?:' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('url')) . ')|(?:' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('www_url')) . '))(?-i)', + 'LOCAL_URL' => '(?i)(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('relative_url')) . ')(?-i)', + 'EMAIL' => '(' . get_preg_expression('email') . ')', + 'TEXT' => '(.*?)', + 'SIMPLETEXT' => '([a-zA-Z0-9-+.,_ ]+)', + 'IDENTIFIER' => '([a-zA-Z0-9-_]+)', + 'COLOR' => '([a-zA-Z]+|#[0-9abcdefABCDEF]+)', + 'NUMBER' => '([0-9]+)', + ); + + $pad = 0; + $modifiers = 'i'; + + if (preg_match_all('/\{(' . implode('|', array_keys($tokens)) . ')[0-9]*\}/i', $bbcode_match, $m)) + { + foreach ($m[0] as $n => $token) + { + $token_type = $m[1][$n]; + + reset($tokens[strtoupper($token_type)]); + list($match, $replace) = each($tokens[strtoupper($token_type)]); + + // Pad backreference numbers from tokens + if (preg_match_all('/(?<!\\\\)\$([0-9]+)/', $replace, $repad)) + { + $repad = $pad + sizeof(array_unique($repad[0])); + $replace = preg_replace('/(?<!\\\\)\$([0-9]+)/e', "'\${' . (\$1 + \$pad) . '}'", $replace); + $pad = $repad; + } + + // Obtain pattern modifiers to use and alter the regex accordingly + $regex = preg_replace('/!(.*)!([a-z]*)/', '$1', $match); + $regex_modifiers = preg_replace('/!(.*)!([a-z]*)/', '$2', $match); + + for ($i = 0, $size = strlen($regex_modifiers); $i < $size; ++$i) + { + if (strpos($modifiers, $regex_modifiers[$i]) === false) + { + $modifiers .= $regex_modifiers[$i]; + + if ($regex_modifiers[$i] == 'e') + { + $fp_replace = "'" . str_replace("'", "\\'", $fp_replace) . "'"; + } + } + + if ($regex_modifiers[$i] == 'e') + { + $replace = "'.$replace.'"; + } + } + + $fp_match = str_replace(preg_quote($token, '!'), $regex, $fp_match); + $fp_replace = str_replace($token, $replace, $fp_replace); + + $sp_match = str_replace(preg_quote($token, '!'), $sp_tokens[$token_type], $sp_match); + $sp_replace = str_replace($token, '${' . ($n + 1) . '}', $sp_replace); + } + + $fp_match = '!' . $fp_match . '!' . $modifiers; + $sp_match = '!' . $sp_match . '!s'; + + if (strpos($fp_match, 'e') !== false) + { + $fp_replace = str_replace("'.'", '', $fp_replace); + $fp_replace = str_replace(".''.", '.', $fp_replace); + } + } + else + { + // No replacement is present, no need for a second-pass pattern replacement + // A simple str_replace will suffice + $fp_match = '!' . $fp_match . '!' . $modifiers; + $sp_match = $fp_replace; + $sp_replace = ''; + } + + // Lowercase tags + $bbcode_tag = preg_replace('/.*?\[([a-z0-9_-]+=?).*/i', '$1', $bbcode_match); + $bbcode_search = preg_replace('/.*?\[([a-z0-9_-]+)=?.*/i', '$1', $bbcode_match); + + if (!preg_match('/^[a-zA-Z0-9_-]+=?$/', $bbcode_tag)) + { + global $user; + trigger_error($user->lang['BBCODE_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $fp_match = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $fp_match); + $fp_replace = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $fp_replace); + $sp_match = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $sp_match); + $sp_replace = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $sp_replace); + + return array( + 'bbcode_tag' => $bbcode_tag, + 'first_pass_match' => $fp_match, + 'first_pass_replace' => $fp_replace, + 'second_pass_match' => $sp_match, + 'second_pass_replace' => $sp_replace + ); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php new file mode 100644 index 0000000000..9f0bcf210f --- /dev/null +++ b/phpBB/includes/acp/acp_board.php @@ -0,0 +1,957 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +* @todo add cron intervals to server settings? (database_gc, queue_interval, session_gc, search_gc, cache_gc, warnings_gc) +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_board +{ + var $u_action; + var $new_config = array(); + + function main($id, $mode) + { + global $db, $user, $auth, $template; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + $user->add_lang('acp/board'); + + $action = request_var('action', ''); + $submit = (isset($_POST['submit'])) ? true : false; + + $form_key = 'acp_board'; + add_form_key($form_key); + + /** + * Validation types are: + * string, int, bool, + * script_path (absolute path in url - beginning with / and no trailing slash), + * rpath (relative), rwpath (realtive, writable), path (relative path, but able to escape the root), wpath (writable) + */ + switch ($mode) + { + case 'settings': + $display_vars = array( + 'title' => 'ACP_BOARD_SETTINGS', + 'vars' => array( + 'legend1' => 'ACP_BOARD_SETTINGS', + 'sitename' => array('lang' => 'SITE_NAME', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => false), + 'site_desc' => array('lang' => 'SITE_DESC', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => false), + 'board_disable' => array('lang' => 'DISABLE_BOARD', 'validate' => 'bool', 'type' => 'custom', 'method' => 'board_disable', 'explain' => true), + 'board_disable_msg' => false, + 'default_lang' => array('lang' => 'DEFAULT_LANGUAGE', 'validate' => 'lang', 'type' => 'select', 'function' => 'language_select', 'params' => array('{CONFIG_VALUE}'), 'explain' => false), + 'default_dateformat' => array('lang' => 'DEFAULT_DATE_FORMAT', 'validate' => 'string', 'type' => 'custom', 'method' => 'dateformat_select', 'explain' => true), + 'board_timezone' => array('lang' => 'SYSTEM_TIMEZONE', 'validate' => 'string', 'type' => 'select', 'function' => 'tz_select', 'params' => array('{CONFIG_VALUE}', 1), 'explain' => false), + 'board_dst' => array('lang' => 'SYSTEM_DST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'default_style' => array('lang' => 'DEFAULT_STYLE', 'validate' => 'int', 'type' => 'select', 'function' => 'style_select', 'params' => array('{CONFIG_VALUE}', false), 'explain' => false), + 'override_user_style' => array('lang' => 'OVERRIDE_STYLE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + + 'legend2' => 'WARNINGS', + 'warnings_expire_days' => array('lang' => 'WARNINGS_EXPIRE', 'validate' => 'int', 'type' => 'text:3:4', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']), + + 'legend3' => 'ACP_SUBMIT_CHANGES', + ) + ); + break; + + case 'features': + $display_vars = array( + 'title' => 'ACP_BOARD_FEATURES', + 'vars' => array( + 'legend1' => 'ACP_BOARD_FEATURES', + 'allow_privmsg' => array('lang' => 'BOARD_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'allow_topic_notify' => array('lang' => 'ALLOW_TOPIC_NOTIFY', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_forum_notify' => array('lang' => 'ALLOW_FORUM_NOTIFY', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_namechange' => array('lang' => 'ALLOW_NAME_CHANGE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_attachments' => array('lang' => 'ALLOW_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_pm_attach' => array('lang' => 'ALLOW_PM_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_pm_report' => array('lang' => 'ALLOW_PM_REPORT', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'allow_bbcode' => array('lang' => 'ALLOW_BBCODE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_smilies' => array('lang' => 'ALLOW_SMILIES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_sig' => array('lang' => 'ALLOW_SIG', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_nocensors' => array('lang' => 'ALLOW_NO_CENSORS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'allow_bookmarks' => array('lang' => 'ALLOW_BOOKMARKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'allow_birthdays' => array('lang' => 'ALLOW_BIRTHDAYS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'allow_quick_reply' => array('lang' => 'ALLOW_QUICK_REPLY', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + + 'legend2' => 'ACP_LOAD_SETTINGS', + 'load_birthdays' => array('lang' => 'YES_BIRTHDAYS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'load_moderators' => array('lang' => 'YES_MODERATORS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'load_jumpbox' => array('lang' => 'YES_JUMPBOX', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'load_cpf_memberlist' => array('lang' => 'LOAD_CPF_MEMBERLIST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'load_cpf_viewprofile' => array('lang' => 'LOAD_CPF_VIEWPROFILE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'load_cpf_viewtopic' => array('lang' => 'LOAD_CPF_VIEWTOPIC', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + + 'legend3' => 'ACP_SUBMIT_CHANGES', + ) + ); + break; + + case 'avatar': + $display_vars = array( + 'title' => 'ACP_AVATAR_SETTINGS', + 'vars' => array( + 'legend1' => 'ACP_AVATAR_SETTINGS', + + 'avatar_min_width' => array('lang' => 'MIN_AVATAR_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false,), + 'avatar_min_height' => array('lang' => 'MIN_AVATAR_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false,), + 'avatar_max_width' => array('lang' => 'MAX_AVATAR_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false,), + 'avatar_max_height' => array('lang' => 'MAX_AVATAR_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false,), + + 'allow_avatar' => array('lang' => 'ALLOW_AVATARS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'allow_avatar_local' => array('lang' => 'ALLOW_LOCAL', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_avatar_remote' => array('lang' => 'ALLOW_REMOTE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'allow_avatar_upload' => array('lang' => 'ALLOW_UPLOAD', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_avatar_remote_upload'=> array('lang' => 'ALLOW_REMOTE_UPLOAD', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'avatar_filesize' => array('lang' => 'MAX_FILESIZE', 'validate' => 'int:0', 'type' => 'text:4:10', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']), + 'avatar_min' => array('lang' => 'MIN_AVATAR_SIZE', 'validate' => 'int:0', 'type' => 'dimension:3:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), + 'avatar_max' => array('lang' => 'MAX_AVATAR_SIZE', 'validate' => 'int:0', 'type' => 'dimension:3:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), + 'avatar_path' => array('lang' => 'AVATAR_STORAGE_PATH', 'validate' => 'rwpath', 'type' => 'text:20:255', 'explain' => true), + 'avatar_gallery_path' => array('lang' => 'AVATAR_GALLERY_PATH', 'validate' => 'rpath', 'type' => 'text:20:255', 'explain' => true) + ) + ); + break; + + case 'message': + $display_vars = array( + 'title' => 'ACP_MESSAGE_SETTINGS', + 'lang' => 'ucp', + 'vars' => array( + 'legend1' => 'GENERAL_SETTINGS', + 'allow_privmsg' => array('lang' => 'BOARD_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'pm_max_boxes' => array('lang' => 'BOXES_MAX', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true), + 'pm_max_msgs' => array('lang' => 'BOXES_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true), + 'full_folder_action' => array('lang' => 'FULL_FOLDER_ACTION', 'validate' => 'int', 'type' => 'select', 'method' => 'full_folder_select', 'explain' => true), + 'pm_edit_time' => array('lang' => 'PM_EDIT_TIME', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']), + 'pm_max_recipients' => array('lang' => 'PM_MAX_RECIPIENTS', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true), + + 'legend2' => 'GENERAL_OPTIONS', + 'allow_mass_pm' => array('lang' => 'ALLOW_MASS_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'auth_bbcode_pm' => array('lang' => 'ALLOW_BBCODE_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'auth_smilies_pm' => array('lang' => 'ALLOW_SMILIES_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_pm_attach' => array('lang' => 'ALLOW_PM_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_sig_pm' => array('lang' => 'ALLOW_SIG_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'print_pm' => array('lang' => 'ALLOW_PRINT_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'forward_pm' => array('lang' => 'ALLOW_FORWARD_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'auth_img_pm' => array('lang' => 'ALLOW_IMG_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'auth_flash_pm' => array('lang' => 'ALLOW_FLASH_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'enable_pm_icons' => array('lang' => 'ENABLE_PM_ICONS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + + 'legend3' => 'ACP_SUBMIT_CHANGES', + ) + ); + break; + + case 'post': + $display_vars = array( + 'title' => 'ACP_POST_SETTINGS', + 'vars' => array( + 'legend1' => 'GENERAL_OPTIONS', + 'allow_topic_notify' => array('lang' => 'ALLOW_TOPIC_NOTIFY', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_forum_notify' => array('lang' => 'ALLOW_FORUM_NOTIFY', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_bbcode' => array('lang' => 'ALLOW_BBCODE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_post_flash' => array('lang' => 'ALLOW_POST_FLASH', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'allow_smilies' => array('lang' => 'ALLOW_SMILIES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_post_links' => array('lang' => 'ALLOW_POST_LINKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'allow_nocensors' => array('lang' => 'ALLOW_NO_CENSORS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'allow_bookmarks' => array('lang' => 'ALLOW_BOOKMARKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'enable_post_confirm' => array('lang' => 'VISUAL_CONFIRM_POST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'allow_quick_reply' => array('lang' => 'ALLOW_QUICK_REPLY', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + + 'legend2' => 'POSTING', + 'bump_type' => false, + 'edit_time' => array('lang' => 'EDIT_TIME', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']), + 'delete_time' => array('lang' => 'DELETE_TIME', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']), + 'display_last_edited' => array('lang' => 'DISPLAY_LAST_EDITED', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'flood_interval' => array('lang' => 'FLOOD_INTERVAL', 'validate' => 'int:0', 'type' => 'text:3:10', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']), + 'bump_interval' => array('lang' => 'BUMP_INTERVAL', 'validate' => 'int:0', 'type' => 'custom', 'method' => 'bump_interval', 'explain' => true), + 'topics_per_page' => array('lang' => 'TOPICS_PER_PAGE', 'validate' => 'int:1', 'type' => 'text:3:4', 'explain' => false), + 'posts_per_page' => array('lang' => 'POSTS_PER_PAGE', 'validate' => 'int:1', 'type' => 'text:3:4', 'explain' => false), + 'smilies_per_page' => array('lang' => 'SMILIES_PER_PAGE', 'validate' => 'int:1', 'type' => 'text:3:4', 'explain' => false), + 'hot_threshold' => array('lang' => 'HOT_THRESHOLD', 'validate' => 'int:0', 'type' => 'text:3:4', 'explain' => true), + 'max_poll_options' => array('lang' => 'MAX_POLL_OPTIONS', 'validate' => 'int:2:127', 'type' => 'text:4:4', 'explain' => false), + 'max_post_chars' => array('lang' => 'CHAR_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:6', 'explain' => true), + 'min_post_chars' => array('lang' => 'MIN_CHAR_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:6', 'explain' => true), + 'max_post_smilies' => array('lang' => 'SMILIES_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true), + 'max_post_urls' => array('lang' => 'MAX_POST_URLS', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true), + 'max_post_font_size' => array('lang' => 'MAX_POST_FONT_SIZE', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' %'), + 'max_quote_depth' => array('lang' => 'QUOTE_DEPTH_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true), + 'max_post_img_width' => array('lang' => 'MAX_POST_IMG_WIDTH', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), + 'max_post_img_height' => array('lang' => 'MAX_POST_IMG_HEIGHT', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), + + 'legend3' => 'ACP_SUBMIT_CHANGES', + ) + ); + break; + + case 'signature': + $display_vars = array( + 'title' => 'ACP_SIGNATURE_SETTINGS', + 'vars' => array( + 'legend1' => 'GENERAL_OPTIONS', + 'allow_sig' => array('lang' => 'ALLOW_SIG', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_sig_bbcode' => array('lang' => 'ALLOW_SIG_BBCODE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_sig_img' => array('lang' => 'ALLOW_SIG_IMG', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_sig_flash' => array('lang' => 'ALLOW_SIG_FLASH', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_sig_smilies' => array('lang' => 'ALLOW_SIG_SMILIES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_sig_links' => array('lang' => 'ALLOW_SIG_LINKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + + 'legend2' => 'GENERAL_SETTINGS', + 'max_sig_chars' => array('lang' => 'MAX_SIG_LENGTH', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true), + 'max_sig_urls' => array('lang' => 'MAX_SIG_URLS', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true), + 'max_sig_font_size' => array('lang' => 'MAX_SIG_FONT_SIZE', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' %'), + 'max_sig_smilies' => array('lang' => 'MAX_SIG_SMILIES', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true), + 'max_sig_img_width' => array('lang' => 'MAX_SIG_IMG_WIDTH', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), + 'max_sig_img_height' => array('lang' => 'MAX_SIG_IMG_HEIGHT', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), + + 'legend3' => 'ACP_SUBMIT_CHANGES', + ) + ); + break; + + case 'registration': + $display_vars = array( + 'title' => 'ACP_REGISTER_SETTINGS', + 'vars' => array( + 'legend1' => 'GENERAL_SETTINGS', + 'max_name_chars' => array('lang' => 'USERNAME_LENGTH', 'validate' => 'int:8:180', 'type' => false, 'method' => false, 'explain' => false,), + 'max_pass_chars' => array('lang' => 'PASSWORD_LENGTH', 'validate' => 'int:8:255', 'type' => false, 'method' => false, 'explain' => false,), + + 'require_activation' => array('lang' => 'ACC_ACTIVATION', 'validate' => 'int', 'type' => 'custom', 'method' => 'select_acc_activation', 'explain' => true), + 'new_member_post_limit' => array('lang' => 'NEW_MEMBER_POST_LIMIT', 'validate' => 'int:0:255', 'type' => 'text:4:4', 'explain' => true, 'append' => ' ' . $user->lang['POSTS']), + 'new_member_group_default'=> array('lang' => 'NEW_MEMBER_GROUP_DEFAULT', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'min_name_chars' => array('lang' => 'USERNAME_LENGTH', 'validate' => 'int:1', 'type' => 'custom:5:180', 'method' => 'username_length', 'explain' => true), + 'min_pass_chars' => array('lang' => 'PASSWORD_LENGTH', 'validate' => 'int:1', 'type' => 'custom', 'method' => 'password_length', 'explain' => true), + 'allow_name_chars' => array('lang' => 'USERNAME_CHARS', 'validate' => 'string', 'type' => 'select', 'method' => 'select_username_chars', 'explain' => true), + 'pass_complex' => array('lang' => 'PASSWORD_TYPE', 'validate' => 'string', 'type' => 'select', 'method' => 'select_password_chars', 'explain' => true), + 'chg_passforce' => array('lang' => 'FORCE_PASS_CHANGE', 'validate' => 'int:0', 'type' => 'text:3:3', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']), + + 'legend2' => 'GENERAL_OPTIONS', + 'allow_namechange' => array('lang' => 'ALLOW_NAME_CHANGE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_emailreuse' => array('lang' => 'ALLOW_EMAIL_REUSE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'enable_confirm' => array('lang' => 'VISUAL_CONFIRM_REG', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'max_login_attempts' => array('lang' => 'MAX_LOGIN_ATTEMPTS', 'validate' => 'int:0', 'type' => 'text:3:3', 'explain' => true), + 'max_reg_attempts' => array('lang' => 'REG_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true), + + 'legend3' => 'COPPA', + 'coppa_enable' => array('lang' => 'ENABLE_COPPA', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'coppa_mail' => array('lang' => 'COPPA_MAIL', 'validate' => 'string', 'type' => 'textarea:5:40', 'explain' => true), + 'coppa_fax' => array('lang' => 'COPPA_FAX', 'validate' => 'string', 'type' => 'text:25:100', 'explain' => false), + + 'legend4' => 'ACP_SUBMIT_CHANGES', + ) + ); + break; + + case 'feed': + $display_vars = array( + 'title' => 'ACP_FEED_MANAGEMENT', + 'vars' => array( + 'legend1' => 'ACP_FEED_GENERAL', + 'feed_enable' => array('lang' => 'ACP_FEED_ENABLE', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true ), + 'feed_item_statistics' => array('lang' => 'ACP_FEED_ITEM_STATISTICS', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true), + 'feed_limit' => array('lang' => 'ACP_FEED_LIMIT', 'validate' => 'int:5', 'type' => 'text:3:4', 'explain' => true), + 'feed_overall_forums' => array('lang' => 'ACP_FEED_OVERALL_FORUMS', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true ), + 'feed_overall_forums_limit' => array('lang' => 'ACP_FEED_OVERALL_FORUMS_LIMIT', 'validate' => 'int:5', 'type' => 'text:3:4', 'explain' => false), + 'feed_overall_topics' => array('lang' => 'ACP_FEED_OVERALL_TOPIC', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true ), + 'feed_overall_topics_limit' => array('lang' => 'ACP_FEED_OVERALL_TOPIC_LIMIT', 'validate' => 'int:5', 'type' => 'text:3:4', 'explain' => false), + 'feed_forum' => array('lang' => 'ACP_FEED_FORUM', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true ), + 'feed_topic' => array('lang' => 'ACP_FEED_TOPIC', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true ), + 'feed_news_id' => array('lang' => 'ACP_FEED_NEWS', 'validate' => 'string', 'type' => 'custom', 'method' => 'select_news_forums', 'explain' => true), + 'feed_exclude_id' => array('lang' => 'ACP_FEED_EXCLUDE_ID', 'validate' => 'string', 'type' => 'custom', 'method' => 'select_exclude_forums', 'explain' => true), + ) + ); + break; + + case 'cookie': + $display_vars = array( + 'title' => 'ACP_COOKIE_SETTINGS', + 'vars' => array( + 'legend1' => 'ACP_COOKIE_SETTINGS', + 'cookie_domain' => array('lang' => 'COOKIE_DOMAIN', 'validate' => 'string', 'type' => 'text::255', 'explain' => false), + 'cookie_name' => array('lang' => 'COOKIE_NAME', 'validate' => 'string', 'type' => 'text::16', 'explain' => false), + 'cookie_path' => array('lang' => 'COOKIE_PATH', 'validate' => 'string', 'type' => 'text::255', 'explain' => false), + 'cookie_secure' => array('lang' => 'COOKIE_SECURE', 'validate' => 'bool', 'type' => 'radio:disabled_enabled', 'explain' => true) + ) + ); + break; + + case 'load': + $display_vars = array( + 'title' => 'ACP_LOAD_SETTINGS', + 'vars' => array( + 'legend1' => 'GENERAL_SETTINGS', + 'limit_load' => array('lang' => 'LIMIT_LOAD', 'validate' => 'string', 'type' => 'text:4:4', 'explain' => true), + 'session_length' => array('lang' => 'SESSION_LENGTH', 'validate' => 'int:60', 'type' => 'text:5:10', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']), + 'active_sessions' => array('lang' => 'LIMIT_SESSIONS', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true), + 'load_online_time' => array('lang' => 'ONLINE_LENGTH', 'validate' => 'int:0', 'type' => 'text:4:3', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']), + + 'legend2' => 'GENERAL_OPTIONS', + 'load_db_track' => array('lang' => 'YES_POST_MARKING', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'load_db_lastread' => array('lang' => 'YES_READ_MARKING', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'load_anon_lastread' => array('lang' => 'YES_ANON_READ_MARKING', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'load_online' => array('lang' => 'YES_ONLINE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'load_online_guests' => array('lang' => 'YES_ONLINE_GUESTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'load_onlinetrack' => array('lang' => 'YES_ONLINE_TRACK', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'load_birthdays' => array('lang' => 'YES_BIRTHDAYS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'load_moderators' => array('lang' => 'YES_MODERATORS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'load_jumpbox' => array('lang' => 'YES_JUMPBOX', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'load_user_activity' => array('lang' => 'LOAD_USER_ACTIVITY', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'load_tplcompile' => array('lang' => 'RECOMPILE_STYLES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + + 'legend3' => 'CUSTOM_PROFILE_FIELDS', + 'load_cpf_memberlist' => array('lang' => 'LOAD_CPF_MEMBERLIST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'load_cpf_viewprofile' => array('lang' => 'LOAD_CPF_VIEWPROFILE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'load_cpf_viewtopic' => array('lang' => 'LOAD_CPF_VIEWTOPIC', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + + 'legend4' => 'ACP_SUBMIT_CHANGES', + ) + ); + break; + + case 'auth': + $display_vars = array( + 'title' => 'ACP_AUTH_SETTINGS', + 'vars' => array( + 'legend1' => 'ACP_AUTH_SETTINGS', + 'auth_method' => array('lang' => 'AUTH_METHOD', 'validate' => 'string', 'type' => 'select', 'method' => 'select_auth_method', 'explain' => false) + ) + ); + break; + + case 'server': + $display_vars = array( + 'title' => 'ACP_SERVER_SETTINGS', + 'vars' => array( + 'legend1' => 'ACP_SERVER_SETTINGS', + 'gzip_compress' => array('lang' => 'ENABLE_GZIP', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + + 'legend2' => 'PATH_SETTINGS', + 'smilies_path' => array('lang' => 'SMILIES_PATH', 'validate' => 'rpath', 'type' => 'text:20:255', 'explain' => true), + 'icons_path' => array('lang' => 'ICONS_PATH', 'validate' => 'rpath', 'type' => 'text:20:255', 'explain' => true), + 'upload_icons_path' => array('lang' => 'UPLOAD_ICONS_PATH', 'validate' => 'rpath', 'type' => 'text:20:255', 'explain' => true), + 'ranks_path' => array('lang' => 'RANKS_PATH', 'validate' => 'rpath', 'type' => 'text:20:255', 'explain' => true), + + 'legend3' => 'SERVER_URL_SETTINGS', + 'force_server_vars' => array('lang' => 'FORCE_SERVER_VARS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'server_protocol' => array('lang' => 'SERVER_PROTOCOL', 'validate' => 'string', 'type' => 'text:10:10', 'explain' => true), + 'server_name' => array('lang' => 'SERVER_NAME', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => true), + 'server_port' => array('lang' => 'SERVER_PORT', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true), + 'script_path' => array('lang' => 'SCRIPT_PATH', 'validate' => 'script_path', 'type' => 'text::255', 'explain' => true), + + 'legend4' => 'ACP_SUBMIT_CHANGES', + ) + ); + break; + + case 'security': + $display_vars = array( + 'title' => 'ACP_SECURITY_SETTINGS', + 'vars' => array( + 'legend1' => 'ACP_SECURITY_SETTINGS', + 'allow_autologin' => array('lang' => 'ALLOW_AUTOLOGIN', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'max_autologin_time' => array('lang' => 'AUTOLOGIN_LENGTH', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']), + 'ip_check' => array('lang' => 'IP_VALID', 'validate' => 'int', 'type' => 'custom', 'method' => 'select_ip_check', 'explain' => true), + 'browser_check' => array('lang' => 'BROWSER_VALID', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'forwarded_for_check' => array('lang' => 'FORWARDED_FOR_VALID', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'referer_validation' => array('lang' => 'REFERER_VALID', 'validate' => 'int:0:3','type' => 'custom', 'method' => 'select_ref_check', 'explain' => true), + 'check_dnsbl' => array('lang' => 'CHECK_DNSBL', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'email_check_mx' => array('lang' => 'EMAIL_CHECK_MX', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'pass_complex' => array('lang' => 'PASSWORD_TYPE', 'validate' => 'string', 'type' => 'select', 'method' => 'select_password_chars', 'explain' => true), + 'chg_passforce' => array('lang' => 'FORCE_PASS_CHANGE', 'validate' => 'int:0', 'type' => 'text:3:3', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']), + 'max_login_attempts' => array('lang' => 'MAX_LOGIN_ATTEMPTS', 'validate' => 'int:0', 'type' => 'text:3:3', 'explain' => true), + 'tpl_allow_php' => array('lang' => 'TPL_ALLOW_PHP', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'form_token_lifetime' => array('lang' => 'FORM_TIME_MAX', 'validate' => 'int:-1', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']), + 'form_token_sid_guests' => array('lang' => 'FORM_SID_GUESTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + + ) + ); + break; + + case 'email': + $display_vars = array( + 'title' => 'ACP_EMAIL_SETTINGS', + 'vars' => array( + 'legend1' => 'GENERAL_SETTINGS', + 'email_enable' => array('lang' => 'ENABLE_EMAIL', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true), + 'board_email_form' => array('lang' => 'BOARD_EMAIL_FORM', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true), + 'email_function_name' => array('lang' => 'EMAIL_FUNCTION_NAME', 'validate' => 'string', 'type' => 'text:20:50', 'explain' => true), + 'email_package_size' => array('lang' => 'EMAIL_PACKAGE_SIZE', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true), + 'board_contact' => array('lang' => 'CONTACT_EMAIL', 'validate' => 'string', 'type' => 'text:25:100', 'explain' => true), + 'board_email' => array('lang' => 'ADMIN_EMAIL', 'validate' => 'string', 'type' => 'text:25:100', 'explain' => true), + 'board_email_sig' => array('lang' => 'EMAIL_SIG', 'validate' => 'string', 'type' => 'textarea:5:30', 'explain' => true), + 'board_hide_emails' => array('lang' => 'BOARD_HIDE_EMAILS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + + 'legend2' => 'SMTP_SETTINGS', + 'smtp_delivery' => array('lang' => 'USE_SMTP', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'smtp_host' => array('lang' => 'SMTP_SERVER', 'validate' => 'string', 'type' => 'text:25:50', 'explain' => false), + 'smtp_port' => array('lang' => 'SMTP_PORT', 'validate' => 'int:0', 'type' => 'text:4:5', 'explain' => true), + 'smtp_auth_method' => array('lang' => 'SMTP_AUTH_METHOD', 'validate' => 'string', 'type' => 'select', 'method' => 'mail_auth_select', 'explain' => true), + 'smtp_username' => array('lang' => 'SMTP_USERNAME', 'validate' => 'string', 'type' => 'text:25:255', 'explain' => true), + 'smtp_password' => array('lang' => 'SMTP_PASSWORD', 'validate' => 'string', 'type' => 'password:25:255', 'explain' => true), + + 'legend3' => 'ACP_SUBMIT_CHANGES', + ) + ); + break; + + default: + trigger_error('NO_MODE', E_USER_ERROR); + break; + } + + if (isset($display_vars['lang'])) + { + $user->add_lang($display_vars['lang']); + } + + $this->new_config = $config; + $cfg_array = (isset($_REQUEST['config'])) ? utf8_normalize_nfc(request_var('config', array('' => ''), true)) : $this->new_config; + $error = array(); + + // We validate the complete config if whished + validate_config_vars($display_vars['vars'], $cfg_array, $error); + + if ($submit && !check_form_key($form_key)) + { + $error[] = $user->lang['FORM_INVALID']; + } + // Do not write values if there is an error + if (sizeof($error)) + { + $submit = false; + } + + // We go through the display_vars to make sure no one is trying to set variables he/she is not allowed to... + foreach ($display_vars['vars'] as $config_name => $null) + { + if (!isset($cfg_array[$config_name]) || strpos($config_name, 'legend') !== false) + { + continue; + } + + if ($config_name == 'auth_method' || $config_name == 'feed_news_id' || $config_name == 'feed_exclude_id') + { + continue; + } + + $this->new_config[$config_name] = $config_value = $cfg_array[$config_name]; + + if ($config_name == 'email_function_name') + { + $this->new_config['email_function_name'] = trim(str_replace(array('(', ')'), array('', ''), $this->new_config['email_function_name'])); + $this->new_config['email_function_name'] = (empty($this->new_config['email_function_name']) || !function_exists($this->new_config['email_function_name'])) ? 'mail' : $this->new_config['email_function_name']; + $config_value = $this->new_config['email_function_name']; + } + + if ($submit) + { + set_config($config_name, $config_value); + } + } + + // Store news and exclude ids + if ($mode == 'feed' && $submit) + { + $this->store_feed_forums(FORUM_OPTION_FEED_NEWS, 'feed_news_id'); + $this->store_feed_forums(FORUM_OPTION_FEED_EXCLUDE, 'feed_exclude_id'); + } + + if ($mode == 'auth') + { + // Retrieve a list of auth plugins and check their config values + $auth_plugins = array(); + + $dp = @opendir($phpbb_root_path . 'includes/auth'); + + if ($dp) + { + while (($file = readdir($dp)) !== false) + { + if (preg_match('#^auth_(.*?)\.' . $phpEx . '$#', $file)) + { + $auth_plugins[] = basename(preg_replace('#^auth_(.*?)\.' . $phpEx . '$#', '\1', $file)); + } + } + closedir($dp); + + sort($auth_plugins); + } + + $updated_auth_settings = false; + $old_auth_config = array(); + foreach ($auth_plugins as $method) + { + if ($method && file_exists($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx)) + { + include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx); + + $method = 'acp_' . $method; + if (function_exists($method)) + { + if ($fields = $method($this->new_config)) + { + // Check if we need to create config fields for this plugin and save config when submit was pressed + foreach ($fields['config'] as $field) + { + if (!isset($config[$field])) + { + set_config($field, ''); + } + + if (!isset($cfg_array[$field]) || strpos($field, 'legend') !== false) + { + continue; + } + + $old_auth_config[$field] = $this->new_config[$field]; + $config_value = $cfg_array[$field]; + $this->new_config[$field] = $config_value; + + if ($submit) + { + $updated_auth_settings = true; + set_config($field, $config_value); + } + } + } + unset($fields); + } + } + } + + if ($submit && (($cfg_array['auth_method'] != $this->new_config['auth_method']) || $updated_auth_settings)) + { + $method = basename($cfg_array['auth_method']); + if ($method && in_array($method, $auth_plugins)) + { + include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx); + + $method = 'init_' . $method; + if (function_exists($method)) + { + if ($error = $method()) + { + foreach ($old_auth_config as $config_name => $config_value) + { + set_config($config_name, $config_value); + } + trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); + } + } + set_config('auth_method', basename($cfg_array['auth_method'])); + } + else + { + trigger_error('NO_AUTH_PLUGIN', E_USER_ERROR); + } + } + } + + if ($submit) + { + add_log('admin', 'LOG_CONFIG_' . strtoupper($mode)); + + trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); + } + + $this->tpl_name = 'acp_board'; + $this->page_title = $display_vars['title']; + + $template->assign_vars(array( + 'L_TITLE' => $user->lang[$display_vars['title']], + 'L_TITLE_EXPLAIN' => $user->lang[$display_vars['title'] . '_EXPLAIN'], + + 'S_ERROR' => (sizeof($error)) ? true : false, + 'ERROR_MSG' => implode('<br />', $error), + + 'U_ACTION' => $this->u_action) + ); + + // Output relevant page + foreach ($display_vars['vars'] as $config_key => $vars) + { + if (!is_array($vars) && strpos($config_key, 'legend') === false) + { + continue; + } + + if (strpos($config_key, 'legend') !== false) + { + $template->assign_block_vars('options', array( + 'S_LEGEND' => true, + 'LEGEND' => (isset($user->lang[$vars])) ? $user->lang[$vars] : $vars) + ); + + continue; + } + + $type = explode(':', $vars['type']); + + $l_explain = ''; + if ($vars['explain'] && isset($vars['lang_explain'])) + { + $l_explain = (isset($user->lang[$vars['lang_explain']])) ? $user->lang[$vars['lang_explain']] : $vars['lang_explain']; + } + else if ($vars['explain']) + { + $l_explain = (isset($user->lang[$vars['lang'] . '_EXPLAIN'])) ? $user->lang[$vars['lang'] . '_EXPLAIN'] : ''; + } + + $content = build_cfg_template($type, $config_key, $this->new_config, $config_key, $vars); + + if (empty($content)) + { + continue; + } + + $template->assign_block_vars('options', array( + 'KEY' => $config_key, + 'TITLE' => (isset($user->lang[$vars['lang']])) ? $user->lang[$vars['lang']] : $vars['lang'], + 'S_EXPLAIN' => $vars['explain'], + 'TITLE_EXPLAIN' => $l_explain, + 'CONTENT' => $content, + ) + ); + + unset($display_vars['vars'][$config_key]); + } + + if ($mode == 'auth') + { + $template->assign_var('S_AUTH', true); + + foreach ($auth_plugins as $method) + { + if ($method && file_exists($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx)) + { + $method = 'acp_' . $method; + if (function_exists($method)) + { + $fields = $method($this->new_config); + + if ($fields['tpl']) + { + $template->assign_block_vars('auth_tpl', array( + 'TPL' => $fields['tpl']) + ); + } + unset($fields); + } + } + } + } + } + + /** + * Select auth method + */ + function select_auth_method($selected_method, $key = '') + { + global $phpbb_root_path, $phpEx; + + $auth_plugins = array(); + + $dp = @opendir($phpbb_root_path . 'includes/auth'); + + if (!$dp) + { + return ''; + } + + while (($file = readdir($dp)) !== false) + { + if (preg_match('#^auth_(.*?)\.' . $phpEx . '$#', $file)) + { + $auth_plugins[] = preg_replace('#^auth_(.*?)\.' . $phpEx . '$#', '\1', $file); + } + } + closedir($dp); + + sort($auth_plugins); + + $auth_select = ''; + foreach ($auth_plugins as $method) + { + $selected = ($selected_method == $method) ? ' selected="selected"' : ''; + $auth_select .= '<option value="' . $method . '"' . $selected . '>' . ucfirst($method) . '</option>'; + } + + return $auth_select; + } + + /** + * Select mail authentication method + */ + function mail_auth_select($selected_method, $key = '') + { + global $user; + + $auth_methods = array('PLAIN', 'LOGIN', 'CRAM-MD5', 'DIGEST-MD5', 'POP-BEFORE-SMTP'); + $s_smtp_auth_options = ''; + + foreach ($auth_methods as $method) + { + $s_smtp_auth_options .= '<option value="' . $method . '"' . (($selected_method == $method) ? ' selected="selected"' : '') . '>' . $user->lang['SMTP_' . str_replace('-', '_', $method)] . '</option>'; + } + + return $s_smtp_auth_options; + } + + /** + * Select full folder action + */ + function full_folder_select($value, $key = '') + { + global $user; + + return '<option value="1"' . (($value == 1) ? ' selected="selected"' : '') . '>' . $user->lang['DELETE_OLDEST_MESSAGES'] . '</option><option value="2"' . (($value == 2) ? ' selected="selected"' : '') . '>' . $user->lang['HOLD_NEW_MESSAGES_SHORT'] . '</option>'; + } + + /** + * Select ip validation + */ + function select_ip_check($value, $key = '') + { + $radio_ary = array(4 => 'ALL', 3 => 'CLASS_C', 2 => 'CLASS_B', 0 => 'NO_IP_VALIDATION'); + + return h_radio('config[ip_check]', $radio_ary, $value, $key); + } + + /** + * Select referer validation + */ + function select_ref_check($value, $key = '') + { + $radio_ary = array(REFERER_VALIDATE_PATH => 'REF_PATH', REFERER_VALIDATE_HOST => 'REF_HOST', REFERER_VALIDATE_NONE => 'NO_REF_VALIDATION'); + + return h_radio('config[referer_validation]', $radio_ary, $value, $key); + } + + /** + * Select account activation method + */ + function select_acc_activation($value, $key = '') + { + global $user, $config; + + $radio_ary = array(USER_ACTIVATION_DISABLE => 'ACC_DISABLE', USER_ACTIVATION_NONE => 'ACC_NONE'); + if ($config['email_enable']) + { + $radio_ary += array(USER_ACTIVATION_SELF => 'ACC_USER', USER_ACTIVATION_ADMIN => 'ACC_ADMIN'); + } + + return h_radio('config[require_activation]', $radio_ary, $value, $key); + } + + /** + * Maximum/Minimum username length + */ + function username_length($value, $key = '') + { + global $user; + + return '<input id="' . $key . '" type="text" size="3" maxlength="3" name="config[min_name_chars]" value="' . $value . '" /> ' . $user->lang['MIN_CHARS'] . ' <input type="text" size="3" maxlength="3" name="config[max_name_chars]" value="' . $this->new_config['max_name_chars'] . '" /> ' . $user->lang['MAX_CHARS']; + } + + /** + * Allowed chars in usernames + */ + function select_username_chars($selected_value, $key) + { + global $user; + + $user_char_ary = array('USERNAME_CHARS_ANY', 'USERNAME_ALPHA_ONLY', 'USERNAME_ALPHA_SPACERS', 'USERNAME_LETTER_NUM', 'USERNAME_LETTER_NUM_SPACERS', 'USERNAME_ASCII'); + $user_char_options = ''; + foreach ($user_char_ary as $user_type) + { + $selected = ($selected_value == $user_type) ? ' selected="selected"' : ''; + $user_char_options .= '<option value="' . $user_type . '"' . $selected . '>' . $user->lang[$user_type] . '</option>'; + } + + return $user_char_options; + } + + /** + * Maximum/Minimum password length + */ + function password_length($value, $key) + { + global $user; + + return '<input id="' . $key . '" type="text" size="3" maxlength="3" name="config[min_pass_chars]" value="' . $value . '" /> ' . $user->lang['MIN_CHARS'] . ' <input type="text" size="3" maxlength="3" name="config[max_pass_chars]" value="' . $this->new_config['max_pass_chars'] . '" /> ' . $user->lang['MAX_CHARS']; + } + + /** + * Required chars in passwords + */ + function select_password_chars($selected_value, $key) + { + global $user; + + $pass_type_ary = array('PASS_TYPE_ANY', 'PASS_TYPE_CASE', 'PASS_TYPE_ALPHA', 'PASS_TYPE_SYMBOL'); + $pass_char_options = ''; + foreach ($pass_type_ary as $pass_type) + { + $selected = ($selected_value == $pass_type) ? ' selected="selected"' : ''; + $pass_char_options .= '<option value="' . $pass_type . '"' . $selected . '>' . $user->lang[$pass_type] . '</option>'; + } + + return $pass_char_options; + } + + /** + * Select bump interval + */ + function bump_interval($value, $key) + { + global $user; + + $s_bump_type = ''; + $types = array('m' => 'MINUTES', 'h' => 'HOURS', 'd' => 'DAYS'); + foreach ($types as $type => $lang) + { + $selected = ($this->new_config['bump_type'] == $type) ? ' selected="selected"' : ''; + $s_bump_type .= '<option value="' . $type . '"' . $selected . '>' . $user->lang[$lang] . '</option>'; + } + + return '<input id="' . $key . '" type="text" size="3" maxlength="4" name="config[bump_interval]" value="' . $value . '" /> <select name="config[bump_type]">' . $s_bump_type . '</select>'; + } + + /** + * Board disable option and message + */ + function board_disable($value, $key) + { + global $user; + + $radio_ary = array(1 => 'YES', 0 => 'NO'); + + return h_radio('config[board_disable]', $radio_ary, $value) . '<br /><input id="' . $key . '" type="text" name="config[board_disable_msg]" maxlength="255" size="40" value="' . $this->new_config['board_disable_msg'] . '" />'; + } + + /** + * Select default dateformat + */ + function dateformat_select($value, $key) + { + global $user, $config; + + // Let the format_date function operate with the acp values + $old_tz = $user->timezone; + $old_dst = $user->dst; + + $user->timezone = $config['board_timezone']; + $user->dst = $config['board_dst']; + + $dateformat_options = ''; + + foreach ($user->lang['dateformats'] as $format => $null) + { + $dateformat_options .= '<option value="' . $format . '"' . (($format == $value) ? ' selected="selected"' : '') . '>'; + $dateformat_options .= $user->format_date(time(), $format, false) . ((strpos($format, '|') !== false) ? $user->lang['VARIANT_DATE_SEPARATOR'] . $user->format_date(time(), $format, true) : ''); + $dateformat_options .= '</option>'; + } + + $dateformat_options .= '<option value="custom"'; + if (!isset($user->lang['dateformats'][$value])) + { + $dateformat_options .= ' selected="selected"'; + } + $dateformat_options .= '>' . $user->lang['CUSTOM_DATEFORMAT'] . '</option>'; + + // Reset users date options + $user->timezone = $old_tz; + $user->dst = $old_dst; + + return "<select name=\"dateoptions\" id=\"dateoptions\" onchange=\"if (this.value == 'custom') { document.getElementById('" . addslashes($key) . "').value = '" . addslashes($value) . "'; } else { document.getElementById('" . addslashes($key) . "').value = this.value; }\">$dateformat_options</select> + <input type=\"text\" name=\"config[$key]\" id=\"$key\" value=\"$value\" maxlength=\"30\" />"; + } + + /** + * Select multiple forums + */ + function select_news_forums($value, $key) + { + global $user, $config; + + $forum_list = make_forum_select(false, false, true, true, true, false, true); + + // Build forum options + $s_forum_options = '<select id="' . $key . '" name="' . $key . '[]" multiple="multiple">'; + foreach ($forum_list as $f_id => $f_row) + { + $f_row['selected'] = phpbb_optionget(FORUM_OPTION_FEED_NEWS, $f_row['forum_options']); + + $s_forum_options .= '<option value="' . $f_id . '"' . (($f_row['selected']) ? ' selected="selected"' : '') . (($f_row['disabled']) ? ' disabled="disabled" class="disabled-option"' : '') . '>' . $f_row['padding'] . $f_row['forum_name'] . '</option>'; + } + $s_forum_options .= '</select>'; + + return $s_forum_options; + } + + function select_exclude_forums($value, $key) + { + global $user, $config; + + $forum_list = make_forum_select(false, false, true, false, false, false, true); + + // Build forum options + $s_forum_options = '<select id="' . $key . '" name="' . $key . '[]" multiple="multiple">'; + foreach ($forum_list as $f_id => $f_row) + { + $f_row['selected'] = phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $f_row['forum_options']); + + $s_forum_options .= '<option value="' . $f_id . '"' . (($f_row['selected']) ? ' selected="selected"' : '') . (($f_row['disabled']) ? ' disabled="disabled" class="disabled-option"' : '') . '>' . $f_row['padding'] . $f_row['forum_name'] . '</option>'; + } + $s_forum_options .= '</select>'; + + return $s_forum_options; + } + + function store_feed_forums($option, $key) + { + global $db, $cache; + + // Get key + $values = request_var($key, array(0 => 0)); + + // Empty option bit for all forums + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET forum_options = forum_options - ' . (1 << $option) . ' + WHERE ' . $db->sql_bit_and('forum_options', $option, '<> 0'); + $db->sql_query($sql); + + // Already emptied for all... + if (sizeof($values)) + { + // Set for selected forums + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET forum_options = forum_options + ' . (1 << $option) . ' + WHERE ' . $db->sql_in_set('forum_id', $values); + $db->sql_query($sql); + } + + // Empty sql cache for forums table because options changed + $cache->destroy('sql', FORUMS_TABLE); + } + +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_bots.php b/phpBB/includes/acp/acp_bots.php new file mode 100644 index 0000000000..d08cabb062 --- /dev/null +++ b/phpBB/includes/acp/acp_bots.php @@ -0,0 +1,418 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_bots +{ + var $u_action; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $cache; + global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix; + + $action = request_var('action', ''); + $submit = (isset($_POST['submit'])) ? true : false; + $mark = request_var('mark', array(0)); + $bot_id = request_var('id', 0); + + if (isset($_POST['add'])) + { + $action = 'add'; + } + + $error = array(); + + $user->add_lang('acp/bots'); + $this->tpl_name = 'acp_bots'; + $this->page_title = 'ACP_BOTS'; + $form_key = 'acp_bots'; + add_form_key($form_key); + + if ($submit && !check_form_key($form_key)) + { + $error[] = $user->lang['FORM_INVALID']; + } + + // User wants to do something, how inconsiderate of them! + switch ($action) + { + case 'activate': + if ($bot_id || sizeof($mark)) + { + $sql_id = ($bot_id) ? " = $bot_id" : ' IN (' . implode(', ', $mark) . ')'; + + $sql = 'UPDATE ' . BOTS_TABLE . " + SET bot_active = 1 + WHERE bot_id $sql_id"; + $db->sql_query($sql); + } + + $cache->destroy('_bots'); + break; + + case 'deactivate': + if ($bot_id || sizeof($mark)) + { + $sql_id = ($bot_id) ? " = $bot_id" : ' IN (' . implode(', ', $mark) . ')'; + + $sql = 'UPDATE ' . BOTS_TABLE . " + SET bot_active = 0 + WHERE bot_id $sql_id"; + $db->sql_query($sql); + } + + $cache->destroy('_bots'); + break; + + case 'delete': + if ($bot_id || sizeof($mark)) + { + if (confirm_box(true)) + { + // We need to delete the relevant user, usergroup and bot entries ... + $sql_id = ($bot_id) ? " = $bot_id" : ' IN (' . implode(', ', $mark) . ')'; + + $sql = 'SELECT bot_name, user_id + FROM ' . BOTS_TABLE . " + WHERE bot_id $sql_id"; + $result = $db->sql_query($sql); + + $user_id_ary = $bot_name_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $user_id_ary[] = (int) $row['user_id']; + $bot_name_ary[] = $row['bot_name']; + } + $db->sql_freeresult($result); + + $db->sql_transaction('begin'); + + $sql = 'DELETE FROM ' . BOTS_TABLE . " + WHERE bot_id $sql_id"; + $db->sql_query($sql); + + if (sizeof($user_id_ary)) + { + $_tables = array(USERS_TABLE, USER_GROUP_TABLE); + foreach ($_tables as $table) + { + $sql = "DELETE FROM $table + WHERE " . $db->sql_in_set('user_id', $user_id_ary); + $db->sql_query($sql); + } + } + + $db->sql_transaction('commit'); + + $cache->destroy('_bots'); + + add_log('admin', 'LOG_BOT_DELETE', implode(', ', $bot_name_ary)); + trigger_error($user->lang['BOT_DELETED'] . adm_back_link($this->u_action)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'mark' => $mark, + 'id' => $bot_id, + 'mode' => $mode, + 'action' => $action)) + ); + } + } + break; + + case 'edit': + case 'add': + include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); + + $bot_row = array( + 'bot_name' => utf8_normalize_nfc(request_var('bot_name', '', true)), + 'bot_agent' => request_var('bot_agent', ''), + 'bot_ip' => request_var('bot_ip', ''), + 'bot_active' => request_var('bot_active', true), + 'bot_lang' => request_var('bot_lang', $config['default_lang']), + 'bot_style' => request_var('bot_style' , $config['default_style']), + ); + + if ($submit) + { + if (!$bot_row['bot_agent'] && !$bot_row['bot_ip']) + { + $error[] = $user->lang['ERR_BOT_NO_MATCHES']; + } + + if ($bot_row['bot_ip'] && !preg_match('#^[\d\.,:]+$#', $bot_row['bot_ip'])) + { + if (!$ip_list = gethostbynamel($bot_row['bot_ip'])) + { + $error[] = $user->lang['ERR_BOT_NO_IP']; + } + else + { + $bot_row['bot_ip'] = implode(',', $ip_list); + } + } + $bot_row['bot_ip'] = str_replace(' ', '', $bot_row['bot_ip']); + + // Make sure the admin is not adding a bot with an user agent similar to his one + if ($bot_row['bot_agent'] && substr($user->data['session_browser'], 0, 149) === substr($bot_row['bot_agent'], 0, 149)) + { + $error[] = $user->lang['ERR_BOT_AGENT_MATCHES_UA']; + } + + $bot_name = false; + if ($bot_id) + { + $sql = 'SELECT u.username_clean + FROM ' . BOTS_TABLE . ' b, ' . USERS_TABLE . " u + WHERE b.bot_id = $bot_id + AND u.user_id = b.user_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$bot_row) + { + $error[] = $user->lang['NO_BOT']; + } + else + { + $bot_name = $row['username_clean']; + } + } + if (!$this->validate_botname($bot_row['bot_name'], $bot_name)) + { + $error[] = $user->lang['BOT_NAME_TAKEN']; + } + + if (!sizeof($error)) + { + // New bot? Create a new user and group entry + if ($action == 'add') + { + $sql = 'SELECT group_id, group_colour + FROM ' . GROUPS_TABLE . " + WHERE group_name = 'BOTS' + AND group_type = " . GROUP_SPECIAL; + $result = $db->sql_query($sql); + $group_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$group_row) + { + trigger_error($user->lang['NO_BOT_GROUP'] . adm_back_link($this->u_action . "&id=$bot_id&action=$action"), E_USER_WARNING); + } + + + $user_id = user_add(array( + 'user_type' => (int) USER_IGNORE, + 'group_id' => (int) $group_row['group_id'], + 'username' => (string) $bot_row['bot_name'], + 'user_regdate' => time(), + 'user_password' => '', + 'user_colour' => (string) $group_row['group_colour'], + 'user_email' => '', + 'user_lang' => (string) $bot_row['bot_lang'], + 'user_style' => (int) $bot_row['bot_style'], + 'user_allow_massemail' => 0, + )); + + $sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $db->sql_build_array('INSERT', array( + 'user_id' => (int) $user_id, + 'bot_name' => (string) $bot_row['bot_name'], + 'bot_active' => (int) $bot_row['bot_active'], + 'bot_agent' => (string) $bot_row['bot_agent'], + 'bot_ip' => (string) $bot_row['bot_ip']) + ); + $db->sql_query($sql); + + $log = 'ADDED'; + } + else if ($bot_id) + { + $sql = 'SELECT user_id, bot_name + FROM ' . BOTS_TABLE . " + WHERE bot_id = $bot_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error($user->lang['NO_BOT'] . adm_back_link($this->u_action . "&id=$bot_id&action=$action"), E_USER_WARNING); + } + + $sql_ary = array( + 'user_style' => (int) $bot_row['bot_style'], + 'user_lang' => (string) $bot_row['bot_lang'], + ); + + if ($bot_row['bot_name'] !== $row['bot_name']) + { + $sql_ary['username'] = (string) $bot_row['bot_name']; + $sql_ary['username_clean'] = (string) utf8_clean_string($bot_row['bot_name']); + } + + $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " WHERE user_id = {$row['user_id']}"; + $db->sql_query($sql); + + $sql = 'UPDATE ' . BOTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array( + 'bot_name' => (string) $bot_row['bot_name'], + 'bot_active' => (int) $bot_row['bot_active'], + 'bot_agent' => (string) $bot_row['bot_agent'], + 'bot_ip' => (string) $bot_row['bot_ip']) + ) . " WHERE bot_id = $bot_id"; + $db->sql_query($sql); + + // Updated username? + if ($bot_row['bot_name'] !== $row['bot_name']) + { + user_update_name($row['bot_name'], $bot_row['bot_name']); + } + + $log = 'UPDATED'; + } + + $cache->destroy('_bots'); + + add_log('admin', 'LOG_BOT_' . $log, $bot_row['bot_name']); + trigger_error($user->lang['BOT_' . $log] . adm_back_link($this->u_action)); + + } + } + else if ($bot_id) + { + $sql = 'SELECT b.*, u.user_lang, u.user_style + FROM ' . BOTS_TABLE . ' b, ' . USERS_TABLE . " u + WHERE b.bot_id = $bot_id + AND u.user_id = b.user_id"; + $result = $db->sql_query($sql); + $bot_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$bot_row) + { + trigger_error($user->lang['NO_BOT'] . adm_back_link($this->u_action . "&id=$bot_id&action=$action"), E_USER_WARNING); + } + + $bot_row['bot_lang'] = $bot_row['user_lang']; + $bot_row['bot_style'] = $bot_row['user_style']; + unset($bot_row['user_lang'], $bot_row['user_style']); + } + + $s_active_options = ''; + $_options = array('0' => 'NO', '1' => 'YES'); + foreach ($_options as $value => $lang) + { + $selected = ($bot_row['bot_active'] == $value) ? ' selected="selected"' : ''; + $s_active_options .= '<option value="' . $value . '"' . $selected . '>' . $user->lang[$lang] . '</option>'; + } + + $style_select = style_select($bot_row['bot_style'], true); + $lang_select = language_select($bot_row['bot_lang']); + + $l_title = ($action == 'edit') ? 'EDIT' : 'ADD'; + + $template->assign_vars(array( + 'L_TITLE' => $user->lang['BOT_' . $l_title], + 'U_ACTION' => $this->u_action . "&id=$bot_id&action=$action", + 'U_BACK' => $this->u_action, + 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + + 'BOT_NAME' => $bot_row['bot_name'], + 'BOT_IP' => $bot_row['bot_ip'], + 'BOT_AGENT' => $bot_row['bot_agent'], + + 'S_EDIT_BOT' => true, + 'S_ACTIVE_OPTIONS' => $s_active_options, + 'S_STYLE_OPTIONS' => $style_select, + 'S_LANG_OPTIONS' => $lang_select, + 'S_ERROR' => (sizeof($error)) ? true : false, + ) + ); + + return; + + break; + } + + $s_options = ''; + $_options = array('activate' => 'BOT_ACTIVATE', 'deactivate' => 'BOT_DEACTIVATE', 'delete' => 'DELETE'); + foreach ($_options as $value => $lang) + { + $s_options .= '<option value="' . $value . '">' . $user->lang[$lang] . '</option>'; + } + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action, + 'S_BOT_OPTIONS' => $s_options) + ); + + $sql = 'SELECT b.bot_id, b.bot_name, b.bot_active, u.user_lastvisit + FROM ' . BOTS_TABLE . ' b, ' . USERS_TABLE . ' u + WHERE u.user_id = b.user_id + ORDER BY u.user_lastvisit DESC, b.bot_name ASC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $active_lang = (!$row['bot_active']) ? 'BOT_ACTIVATE' : 'BOT_DEACTIVATE'; + $active_value = (!$row['bot_active']) ? 'activate' : 'deactivate'; + + $template->assign_block_vars('bots', array( + 'BOT_NAME' => $row['bot_name'], + 'BOT_ID' => $row['bot_id'], + 'LAST_VISIT' => ($row['user_lastvisit']) ? $user->format_date($row['user_lastvisit']) : $user->lang['BOT_NEVER'], + + 'U_ACTIVATE_DEACTIVATE' => $this->u_action . "&id={$row['bot_id']}&action=$active_value", + 'L_ACTIVATE_DEACTIVATE' => $user->lang[$active_lang], + 'U_EDIT' => $this->u_action . "&id={$row['bot_id']}&action=edit", + 'U_DELETE' => $this->u_action . "&id={$row['bot_id']}&action=delete") + ); + } + $db->sql_freeresult($result); + } + + /** + * Validate bot name against username table + */ + function validate_botname($newname, $oldname = false) + { + global $db; + + if ($oldname && utf8_clean_string($newname) === $oldname) + { + return true; + } + + // Admins might want to use names otherwise forbidden, thus we only check for duplicates. + $sql = 'SELECT username + FROM ' . USERS_TABLE . " + WHERE username_clean = '" . $db->sql_escape(utf8_clean_string($newname)) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + return ($row) ? false : true; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_captcha.php b/phpBB/includes/acp/acp_captcha.php new file mode 100644 index 0000000000..e1fa764191 --- /dev/null +++ b/phpBB/includes/acp/acp_captcha.php @@ -0,0 +1,147 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_captcha +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + $user->add_lang('acp/board'); + + include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); + $captchas = phpbb_captcha_factory::get_captcha_types(); + + $selected = request_var('select_captcha', $config['captcha_plugin']); + $selected = (isset($captchas['available'][$selected]) || isset($captchas['unavailable'][$selected])) ? $selected : $config['captcha_plugin']; + $configure = request_var('configure', false); + + + // Oh, they are just here for the view + if (isset($_GET['captcha_demo'])) + { + $this->deliver_demo($selected); + } + + // Delegate + if ($configure) + { + $config_captcha =& phpbb_captcha_factory::get_instance($selected); + $config_captcha->acp_page($id, $this); + } + else + { + $config_vars = array( + 'enable_confirm' => array('tpl' => 'REG_ENABLE', 'default' => false), + 'enable_post_confirm' => array('tpl' => 'POST_ENABLE', 'default' => false), + 'confirm_refresh' => array('tpl' => 'CONFIRM_REFRESH', 'default' => false), + 'max_reg_attempts' => array('tpl' => 'REG_LIMIT', 'default' => 0), + ); + + $this->tpl_name = 'acp_captcha'; + $this->page_title = 'ACP_VC_SETTINGS'; + $form_key = 'acp_captcha'; + add_form_key($form_key); + + $submit = request_var('main_submit', false); + + if ($submit && check_form_key($form_key)) + { + foreach ($config_vars as $config_var => $options) + { + set_config($config_var, request_var($config_var, $options['default'])); + } + + if ($selected !== $config['captcha_plugin']) + { + // sanity check + if (isset($captchas['available'][$selected])) + { + $old_captcha =& phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $old_captcha->uninstall(); + + set_config('captcha_plugin', $selected); + $new_captcha =& phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $new_captcha->install(); + + add_log('admin', 'LOG_CONFIG_VISUAL'); + } + else + { + trigger_error($user->lang['CAPTCHA_UNAVAILABLE'] . adm_back_link($this->u_action)); + } + } + trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); + } + else if ($submit) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link()); + } + else + { + $captcha_select = ''; + foreach ($captchas['available'] as $value => $title) + { + $current = ($selected !== false && $value == $selected) ? ' selected="selected"' : ''; + $captcha_select .= '<option value="' . $value . '"' . $current . '>' . $user->lang[$title] . '</option>'; + } + + foreach ($captchas['unavailable'] as $value => $title) + { + $current = ($selected !== false && $value == $selected) ? ' selected="selected"' : ''; + $captcha_select .= '<option value="' . $value . '"' . $current . ' class="disabled-option">' . $user->lang[$title] . '</option>'; + } + + $demo_captcha =& phpbb_captcha_factory::get_instance($selected); + + foreach ($config_vars as $config_var => $options) + { + $template->assign_var($options['tpl'], (isset($_POST[$config_var])) ? request_var($config_var, $options['default']) : $config[$config_var]) ; + } + + $template->assign_vars(array( + 'CAPTCHA_PREVIEW_TPL' => $demo_captcha->get_demo_template($id), + 'S_CAPTCHA_HAS_CONFIG' => $demo_captcha->has_config(), + 'CAPTCHA_SELECT' => $captcha_select, + )); + } + } + } + + /** + * Entry point for delivering image CAPTCHAs in the ACP. + */ + function deliver_demo($selected) + { + global $db, $user, $config; + + $captcha =& phpbb_captcha_factory::get_instance($selected); + $captcha->init(CONFIRM_REG); + $captcha->execute_demo(); + + garbage_collection(); + exit_handler(); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php new file mode 100644 index 0000000000..5d7450bdfd --- /dev/null +++ b/phpBB/includes/acp/acp_database.php @@ -0,0 +1,2348 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_database +{ + var $u_action; + + function main($id, $mode) + { + global $cache, $db, $user, $auth, $template, $table_prefix; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + $user->add_lang('acp/database'); + + $this->tpl_name = 'acp_database'; + $this->page_title = 'ACP_DATABASE'; + + $action = request_var('action', ''); + $submit = (isset($_POST['submit'])) ? true : false; + + $template->assign_vars(array( + 'MODE' => $mode + )); + + switch ($mode) + { + case 'backup': + + $this->page_title = 'ACP_BACKUP'; + + switch ($action) + { + case 'download': + $type = request_var('type', ''); + $table = request_var('table', array('')); + $format = request_var('method', ''); + $where = request_var('where', ''); + + if (!sizeof($table)) + { + trigger_error($user->lang['TABLE_SELECT_ERROR'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $store = $download = $structure = $schema_data = false; + + if ($where == 'store_and_download' || $where == 'store') + { + $store = true; + } + + if ($where == 'store_and_download' || $where == 'download') + { + $download = true; + } + + if ($type == 'full' || $type == 'structure') + { + $structure = true; + } + + if ($type == 'full' || $type == 'data') + { + $schema_data = true; + } + + @set_time_limit(1200); + @set_time_limit(0); + + $time = time(); + + $filename = 'backup_' . $time . '_' . unique_id(); + switch ($db->sql_layer) + { + case 'mysqli': + case 'mysql4': + case 'mysql': + $extractor = new mysql_extractor($download, $store, $format, $filename, $time); + break; + + case 'sqlite': + $extractor = new sqlite_extractor($download, $store, $format, $filename, $time); + break; + + case 'postgres': + $extractor = new postgres_extractor($download, $store, $format, $filename, $time); + break; + + case 'oracle': + $extractor = new oracle_extractor($download, $store, $format, $filename, $time); + break; + + case 'mssql': + case 'mssql_odbc': + $extractor = new mssql_extractor($download, $store, $format, $filename, $time); + break; + + case 'firebird': + $extractor = new firebird_extractor($download, $store, $format, $filename, $time); + break; + } + + $extractor->write_start($table_prefix); + + foreach ($table as $table_name) + { + // Get the table structure + if ($structure) + { + $extractor->write_table($table_name); + } + else + { + // We might wanna empty out all that junk :D + switch ($db->sql_layer) + { + case 'sqlite': + case 'firebird': + $extractor->flush('DELETE FROM ' . $table_name . ";\n"); + break; + + case 'mssql': + case 'mssql_odbc': + $extractor->flush('TRUNCATE TABLE ' . $table_name . "GO\n"); + break; + + case 'oracle': + $extractor->flush('TRUNCATE TABLE ' . $table_name . "/\n"); + break; + + default: + $extractor->flush('TRUNCATE TABLE ' . $table_name . ";\n"); + break; + } + } + + // Data + if ($schema_data) + { + $extractor->write_data($table_name); + } + } + + $extractor->write_end(); + + add_log('admin', 'LOG_DB_BACKUP'); + + if ($download == true) + { + exit; + } + + trigger_error($user->lang['BACKUP_SUCCESS'] . adm_back_link($this->u_action)); + break; + + default: + include($phpbb_root_path . 'includes/functions_install.' . $phpEx); + $tables = get_tables($db); + asort($tables); + foreach ($tables as $table_name) + { + if (strlen($table_prefix) === 0 || stripos($table_name, $table_prefix) === 0) + { + $template->assign_block_vars('tables', array( + 'TABLE' => $table_name + )); + } + } + unset($tables); + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action . '&action=download' + )); + + $available_methods = array('gzip' => 'zlib', 'bzip2' => 'bz2'); + + foreach ($available_methods as $type => $module) + { + if (!@extension_loaded($module)) + { + continue; + } + + $template->assign_block_vars('methods', array( + 'TYPE' => $type + )); + } + + $template->assign_block_vars('methods', array( + 'TYPE' => 'text' + )); + break; + } + break; + + case 'restore': + + $this->page_title = 'ACP_RESTORE'; + + switch ($action) + { + case 'submit': + $delete = request_var('delete', ''); + $file = request_var('file', ''); + + if (!preg_match('#^backup_\d{10,}_[a-z\d]{16}\.(sql(?:\.(?:gz|bz2))?)$#', $file, $matches)) + { + trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $file_name = $phpbb_root_path . 'store/' . $matches[0]; + + if (!file_exists($file_name) || !is_readable($file_name)) + { + trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if ($delete) + { + if (confirm_box(true)) + { + unlink($file_name); + add_log('admin', 'LOG_DB_DELETE'); + trigger_error($user->lang['BACKUP_DELETE'] . adm_back_link($this->u_action)); + } + else + { + confirm_box(false, $user->lang['DELETE_SELECTED_BACKUP'], build_hidden_fields(array('delete' => $delete, 'file' => $file))); + } + } + else + { + $download = request_var('download', ''); + + if ($download) + { + $name = $matches[0]; + + switch ($matches[1]) + { + case 'sql': + $mimetype = 'text/x-sql'; + break; + case 'sql.bz2': + $mimetype = 'application/x-bzip2'; + break; + case 'sql.gz': + $mimetype = 'application/x-gzip'; + break; + } + + header('Pragma: no-cache'); + header("Content-Type: $mimetype; name=\"$name\""); + header("Content-disposition: attachment; filename=$name"); + + @set_time_limit(0); + + $fp = @fopen($file_name, 'rb'); + + if ($fp !== false) + { + while (!feof($fp)) + { + echo fread($fp, 8192); + } + fclose($fp); + } + + flush(); + exit; + } + + switch ($matches[1]) + { + case 'sql': + $fp = fopen($file_name, 'rb'); + $read = 'fread'; + $seek = 'fseek'; + $eof = 'feof'; + $close = 'fclose'; + $fgetd = 'fgetd'; + break; + + case 'sql.bz2': + $fp = bzopen($file_name, 'r'); + $read = 'bzread'; + $seek = ''; + $eof = 'feof'; + $close = 'bzclose'; + $fgetd = 'fgetd_seekless'; + break; + + case 'sql.gz': + $fp = gzopen($file_name, 'rb'); + $read = 'gzread'; + $seek = 'gzseek'; + $eof = 'gzeof'; + $close = 'gzclose'; + $fgetd = 'fgetd'; + break; + } + + switch ($db->sql_layer) + { + case 'mysql': + case 'mysql4': + case 'mysqli': + case 'sqlite': + while (($sql = $fgetd($fp, ";\n", $read, $seek, $eof)) !== false) + { + $db->sql_query($sql); + } + break; + + case 'firebird': + $delim = ";\n"; + while (($sql = $fgetd($fp, $delim, $read, $seek, $eof)) !== false) + { + $query = trim($sql); + if (substr($query, 0, 8) === 'SET TERM') + { + $delim = $query[9] . "\n"; + continue; + } + $db->sql_query($query); + } + break; + + case 'postgres': + $delim = ";\n"; + while (($sql = $fgetd($fp, $delim, $read, $seek, $eof)) !== false) + { + $query = trim($sql); + + if (substr($query, 0, 13) == 'CREATE DOMAIN') + { + list(, , $domain) = explode(' ', $query); + $sql = "SELECT domain_name + FROM information_schema.domains + WHERE domain_name = '$domain';"; + $result = $db->sql_query($sql); + if (!$db->sql_fetchrow($result)) + { + $db->sql_query($query); + } + $db->sql_freeresult($result); + } + else + { + $db->sql_query($query); + } + + if (substr($query, 0, 4) == 'COPY') + { + while (($sub = $fgetd($fp, "\n", $read, $seek, $eof)) !== '\.') + { + if ($sub === false) + { + trigger_error($user->lang['RESTORE_FAILURE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + pg_put_line($db->db_connect_id, $sub . "\n"); + } + pg_put_line($db->db_connect_id, "\\.\n"); + pg_end_copy($db->db_connect_id); + } + } + break; + + case 'oracle': + while (($sql = $fgetd($fp, "/\n", $read, $seek, $eof)) !== false) + { + $db->sql_query($sql); + } + break; + + case 'mssql': + case 'mssql_odbc': + while (($sql = $fgetd($fp, "GO\n", $read, $seek, $eof)) !== false) + { + $db->sql_query($sql); + } + break; + } + + $close($fp); + + // Purge the cache due to updated data + $cache->purge(); + + add_log('admin', 'LOG_DB_RESTORE'); + trigger_error($user->lang['RESTORE_SUCCESS'] . adm_back_link($this->u_action)); + break; + } + + default: + $methods = array('sql'); + $available_methods = array('sql.gz' => 'zlib', 'sql.bz2' => 'bz2'); + + foreach ($available_methods as $type => $module) + { + if (!@extension_loaded($module)) + { + continue; + } + $methods[] = $type; + } + + $dir = $phpbb_root_path . 'store/'; + $dh = @opendir($dir); + + $backup_files = array(); + + if ($dh) + { + while (($file = readdir($dh)) !== false) + { + if (preg_match('#^backup_(\d{10,})_[a-z\d]{16}\.(sql(?:\.(?:gz|bz2))?)$#', $file, $matches)) + { + if (in_array($matches[2], $methods)) + { + $backup_files[gmdate("d-m-Y H:i:s", $matches[1])] = $file; + } + } + } + closedir($dh); + } + + if (!empty($backup_files)) + { + krsort($backup_files); + + foreach ($backup_files as $name => $file) + { + $template->assign_block_vars('files', array( + 'FILE' => $file, + 'NAME' => $name, + 'SUPPORTED' => true, + )); + } + } + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action . '&action=submit' + )); + break; + } + break; + } + } +} + +/** +* @package acp +*/ +class base_extractor +{ + var $fh; + var $fp; + var $write; + var $close; + var $store; + var $download; + var $time; + var $format; + var $run_comp = false; + + function base_extractor($download = false, $store = false, $format, $filename, $time) + { + $this->download = $download; + $this->store = $store; + $this->time = $time; + $this->format = $format; + + switch ($format) + { + case 'text': + $ext = '.sql'; + $open = 'fopen'; + $this->write = 'fwrite'; + $this->close = 'fclose'; + $mimetype = 'text/x-sql'; + break; + case 'bzip2': + $ext = '.sql.bz2'; + $open = 'bzopen'; + $this->write = 'bzwrite'; + $this->close = 'bzclose'; + $mimetype = 'application/x-bzip2'; + break; + case 'gzip': + $ext = '.sql.gz'; + $open = 'gzopen'; + $this->write = 'gzwrite'; + $this->close = 'gzclose'; + $mimetype = 'application/x-gzip'; + break; + } + + if ($download == true) + { + $name = $filename . $ext; + header('Pragma: no-cache'); + header("Content-Type: $mimetype; name=\"$name\""); + header("Content-disposition: attachment; filename=$name"); + + switch ($format) + { + case 'bzip2': + ob_start(); + break; + + case 'gzip': + if ((isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false) && strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'msie') === false) + { + ob_start('ob_gzhandler'); + } + else + { + $this->run_comp = true; + } + break; + } + } + + if ($store == true) + { + global $phpbb_root_path; + $file = $phpbb_root_path . 'store/' . $filename . $ext; + + $this->fp = $open($file, 'w'); + + if (!$this->fp) + { + trigger_error('FILE_WRITE_FAIL', E_USER_ERROR); + } + } + } + + function write_end() + { + static $close; + + if ($this->store) + { + if ($close === null) + { + $close = $this->close; + } + $close($this->fp); + } + + // bzip2 must be written all the way at the end + if ($this->download && $this->format === 'bzip2') + { + $c = ob_get_clean(); + echo bzcompress($c); + } + } + + function flush($data) + { + static $write; + if ($this->store === true) + { + if ($write === null) + { + $write = $this->write; + } + $write($this->fp, $data); + } + + if ($this->download === true) + { + if ($this->format === 'bzip2' || $this->format === 'text' || ($this->format === 'gzip' && !$this->run_comp)) + { + echo $data; + } + + // we can write the gzip data as soon as we get it + if ($this->format === 'gzip') + { + if ($this->run_comp) + { + echo gzencode($data); + } + else + { + ob_flush(); + flush(); + } + } + } + } +} + +/** +* @package acp +*/ +class mysql_extractor extends base_extractor +{ + function write_start($table_prefix) + { + $sql_data = "#\n"; + $sql_data .= "# phpBB Backup Script\n"; + $sql_data .= "# Dump of tables for $table_prefix\n"; + $sql_data .= "# DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; + $sql_data .= "#\n"; + $this->flush($sql_data); + } + + function write_table($table_name) + { + global $db; + static $new_extract; + + if ($new_extract === null) + { + if ($db->sql_layer === 'mysqli' || version_compare($db->sql_server_info(true), '3.23.20', '>=')) + { + $new_extract = true; + } + else + { + $new_extract = false; + } + } + + if ($new_extract) + { + $this->new_write_table($table_name); + } + else + { + $this->old_write_table($table_name); + } + } + + function write_data($table_name) + { + global $db; + if ($db->sql_layer === 'mysqli') + { + $this->write_data_mysqli($table_name); + } + else + { + $this->write_data_mysql($table_name); + } + } + + function write_data_mysqli($table_name) + { + global $db; + $sql = "SELECT * + FROM $table_name"; + $result = mysqli_query($db->db_connect_id, $sql, MYSQLI_USE_RESULT); + if ($result != false) + { + $fields_cnt = mysqli_num_fields($result); + + // Get field information + $field = mysqli_fetch_fields($result); + $field_set = array(); + + for ($j = 0; $j < $fields_cnt; $j++) + { + $field_set[] = $field[$j]->name; + } + + $search = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"'); + $replace = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"'); + $fields = implode(', ', $field_set); + $sql_data = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES '; + $first_set = true; + $query_len = 0; + $max_len = get_usable_memory(); + + while ($row = mysqli_fetch_row($result)) + { + $values = array(); + if ($first_set) + { + $query = $sql_data . '('; + } + else + { + $query .= ',('; + } + + for ($j = 0; $j < $fields_cnt; $j++) + { + if (!isset($row[$j]) || is_null($row[$j])) + { + $values[$j] = 'NULL'; + } + else if (($field[$j]->flags & 32768) && !($field[$j]->flags & 1024)) + { + $values[$j] = $row[$j]; + } + else + { + $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'"; + } + } + $query .= implode(', ', $values) . ')'; + + $query_len += strlen($query); + if ($query_len > $max_len) + { + $this->flush($query . ";\n\n"); + $query = ''; + $query_len = 0; + $first_set = true; + } + else + { + $first_set = false; + } + } + mysqli_free_result($result); + + // check to make sure we have nothing left to flush + if (!$first_set && $query) + { + $this->flush($query . ";\n\n"); + } + } + } + + function write_data_mysql($table_name) + { + global $db; + $sql = "SELECT * + FROM $table_name"; + $result = mysql_unbuffered_query($sql, $db->db_connect_id); + + if ($result != false) + { + $fields_cnt = mysql_num_fields($result); + + // Get field information + $field = array(); + for ($i = 0; $i < $fields_cnt; $i++) + { + $field[] = mysql_fetch_field($result, $i); + } + $field_set = array(); + + for ($j = 0; $j < $fields_cnt; $j++) + { + $field_set[] = $field[$j]->name; + } + + $search = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"'); + $replace = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"'); + $fields = implode(', ', $field_set); + $sql_data = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES '; + $first_set = true; + $query_len = 0; + $max_len = get_usable_memory(); + + while ($row = mysql_fetch_row($result)) + { + $values = array(); + if ($first_set) + { + $query = $sql_data . '('; + } + else + { + $query .= ',('; + } + + for ($j = 0; $j < $fields_cnt; $j++) + { + if (!isset($row[$j]) || is_null($row[$j])) + { + $values[$j] = 'NULL'; + } + else if ($field[$j]->numeric && ($field[$j]->type !== 'timestamp')) + { + $values[$j] = $row[$j]; + } + else + { + $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'"; + } + } + $query .= implode(', ', $values) . ')'; + + $query_len += strlen($query); + if ($query_len > $max_len) + { + $this->flush($query . ";\n\n"); + $query = ''; + $query_len = 0; + $first_set = true; + } + else + { + $first_set = false; + } + } + mysql_free_result($result); + + // check to make sure we have nothing left to flush + if (!$first_set && $query) + { + $this->flush($query . ";\n\n"); + } + } + } + + function new_write_table($table_name) + { + global $db; + + $sql = 'SHOW CREATE TABLE ' . $table_name; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + + $sql_data = '# Table: ' . $table_name . "\n"; + $sql_data .= "DROP TABLE IF EXISTS $table_name;\n"; + $this->flush($sql_data . $row['Create Table'] . ";\n\n"); + + $db->sql_freeresult($result); + } + + function old_write_table($table_name) + { + global $db; + + $sql_data = '# Table: ' . $table_name . "\n"; + $sql_data .= "DROP TABLE IF EXISTS $table_name;\n"; + $sql_data .= "CREATE TABLE $table_name(\n"; + $rows = array(); + + $sql = "SHOW FIELDS + FROM $table_name"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $line = ' ' . $row['Field'] . ' ' . $row['Type']; + + if (!is_null($row['Default'])) + { + $line .= " DEFAULT '{$row['Default']}'"; + } + + if ($row['Null'] != 'YES') + { + $line .= ' NOT NULL'; + } + + if ($row['Extra'] != '') + { + $line .= ' ' . $row['Extra']; + } + + $rows[] = $line; + } + $db->sql_freeresult($result); + + $sql = "SHOW KEYS + FROM $table_name"; + + $result = $db->sql_query($sql); + + $index = array(); + while ($row = $db->sql_fetchrow($result)) + { + $kname = $row['Key_name']; + + if ($kname != 'PRIMARY') + { + if ($row['Non_unique'] == 0) + { + $kname = "UNIQUE|$kname"; + } + } + + if ($row['Sub_part']) + { + $row['Column_name'] .= '(' . $row['Sub_part'] . ')'; + } + $index[$kname][] = $row['Column_name']; + } + $db->sql_freeresult($result); + + foreach ($index as $key => $columns) + { + $line = ' '; + + if ($key == 'PRIMARY') + { + $line .= 'PRIMARY KEY (' . implode(', ', $columns) . ')'; + } + else if (strpos($key, 'UNIQUE') === 0) + { + $line .= 'UNIQUE ' . substr($key, 7) . ' (' . implode(', ', $columns) . ')'; + } + else if (strpos($key, 'FULLTEXT') === 0) + { + $line .= 'FULLTEXT ' . substr($key, 9) . ' (' . implode(', ', $columns) . ')'; + } + else + { + $line .= "KEY $key (" . implode(', ', $columns) . ')'; + } + + $rows[] = $line; + } + + $sql_data .= implode(",\n", $rows); + $sql_data .= "\n);\n\n"; + + $this->flush($sql_data); + } +} + +/** +* @package acp +*/ +class sqlite_extractor extends base_extractor +{ + function write_start($prefix) + { + $sql_data = "--\n"; + $sql_data .= "-- phpBB Backup Script\n"; + $sql_data .= "-- Dump of tables for $prefix\n"; + $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; + $sql_data .= "--\n"; + $sql_data .= "BEGIN TRANSACTION;\n"; + $this->flush($sql_data); + } + + function write_table($table_name) + { + global $db; + $sql_data = '-- Table: ' . $table_name . "\n"; + $sql_data .= "DROP TABLE $table_name;\n"; + + $sql = "SELECT sql + FROM sqlite_master + WHERE type = 'table' + AND name = '" . $db->sql_escape($table_name) . "' + ORDER BY type DESC, name;"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + // Create Table + $sql_data .= $row['sql'] . ";\n"; + + $result = $db->sql_query("PRAGMA index_list('" . $db->sql_escape($table_name) . "');"); + + $ar = array(); + while ($row = $db->sql_fetchrow($result)) + { + $ar[] = $row; + } + $db->sql_freeresult($result); + + foreach ($ar as $value) + { + if (strpos($value['name'], 'autoindex') !== false) + { + continue; + } + + $result = $db->sql_query("PRAGMA index_info('" . $db->sql_escape($value['name']) . "');"); + + $fields = array(); + while ($row = $db->sql_fetchrow($result)) + { + $fields[] = $row['name']; + } + $db->sql_freeresult($result); + + $sql_data .= 'CREATE ' . ($value['unique'] ? 'UNIQUE ' : '') . 'INDEX ' . $value['name'] . ' on ' . $table_name . ' (' . implode(', ', $fields) . ");\n"; + } + + $this->flush($sql_data . "\n"); + } + + function write_data($table_name) + { + global $db; + static $proper; + + if (is_null($proper)) + { + $proper = version_compare(PHP_VERSION, '5.1.3', '>='); + } + + if ($proper) + { + $col_types = sqlite_fetch_column_types($db->db_connect_id, $table_name); + } + else + { + $sql = "SELECT sql + FROM sqlite_master + WHERE type = 'table' + AND name = '" . $table_name . "'"; + $table_data = sqlite_single_query($db->db_connect_id, $sql); + $table_data = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', '', $table_data); + $table_data = trim($table_data); + + preg_match('#\((.*)\)#s', $table_data, $matches); + + $table_cols = explode(',', trim($matches[1])); + foreach ($table_cols as $declaration) + { + $entities = preg_split('#\s+#', trim($declaration)); + $column_name = preg_replace('/"?([^"]+)"?/', '\1', $entities[0]); + + // Hit a primary key, those are not what we need :D + if (empty($entities[1]) || (strtolower($entities[0]) === 'primary' && strtolower($entities[1]) === 'key')) + { + continue; + } + $col_types[$column_name] = $entities[1]; + } + } + + $sql = "SELECT * + FROM $table_name"; + $result = sqlite_unbuffered_query($db->db_connect_id, $sql); + $rows = sqlite_fetch_all($result, SQLITE_ASSOC); + $sql_insert = 'INSERT INTO ' . $table_name . ' (' . implode(', ', array_keys($col_types)) . ') VALUES ('; + foreach ($rows as $row) + { + foreach ($row as $column_name => $column_data) + { + if (is_null($column_data)) + { + $row[$column_name] = 'NULL'; + } + else if ($column_data == '') + { + $row[$column_name] = "''"; + } + else if (strpos($col_types[$column_name], 'text') !== false || strpos($col_types[$column_name], 'char') !== false || strpos($col_types[$column_name], 'blob') !== false) + { + $row[$column_name] = sanitize_data_generic(str_replace("'", "''", $column_data)); + } + } + $this->flush($sql_insert . implode(', ', $row) . ");\n"); + } + } + + function write_end() + { + $this->flush("COMMIT;\n"); + parent::write_end(); + } +} + +/** +* @package acp +*/ +class postgres_extractor extends base_extractor +{ + function write_start($prefix) + { + $sql_data = "--\n"; + $sql_data .= "-- phpBB Backup Script\n"; + $sql_data .= "-- Dump of tables for $prefix\n"; + $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; + $sql_data .= "--\n"; + $sql_data .= "BEGIN TRANSACTION;\n"; + $this->flush($sql_data); + } + + function write_table($table_name) + { + global $db; + static $domains_created = array(); + + $sql = "SELECT a.domain_name, a.data_type, a.character_maximum_length, a.domain_default + FROM INFORMATION_SCHEMA.domains a, INFORMATION_SCHEMA.column_domain_usage b + WHERE a.domain_name = b.domain_name + AND b.table_name = '{$table_name}'"; + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + if (empty($domains_created[$row['domain_name']])) + { + $domains_created[$row['domain_name']] = true; + //$sql_data = "DROP DOMAIN {$row['domain_name']};\n"; + $sql_data = "CREATE DOMAIN {$row['domain_name']} as {$row['data_type']}"; + if (!empty($row['character_maximum_length'])) + { + $sql_data .= '(' . $row['character_maximum_length'] . ')'; + } + $sql_data .= ' NOT NULL'; + if (!empty($row['domain_default'])) + { + $sql_data .= ' DEFAULT ' . $row['domain_default']; + } + $this->flush($sql_data . ";\n"); + } + } + + $sql_data = '-- Table: ' . $table_name . "\n"; + $sql_data .= "DROP TABLE $table_name;\n"; + // 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 = $db->sql_query($sql); + // We don't even care about storing the results. We already know the answer if we get rows back. + if ($db->sql_fetchrow($result)) + { + $sql_data .= "DROP SEQUENCE {$table_name}_seq;\n"; + $sql_data .= "CREATE SEQUENCE {$table_name}_seq;\n"; + } + $db->sql_freeresult($result); + + $field_query = "SELECT a.attnum, a.attname as field, t.typname as type, a.attlen as length, a.atttypmod as lengthvar, a.attnotnull as notnull + FROM pg_class c, pg_attribute a, pg_type t + WHERE c.relname = '" . $db->sql_escape($table_name) . "' + AND a.attnum > 0 + AND a.attrelid = c.oid + AND a.atttypid = t.oid + ORDER BY a.attnum"; + $result = $db->sql_query($field_query); + + $sql_data .= "CREATE TABLE $table_name(\n"; + $lines = array(); + while ($row = $db->sql_fetchrow($result)) + { + // Get the data from the table + $sql_get_default = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault + FROM pg_attrdef d, pg_class c + WHERE (c.relname = '" . $db->sql_escape($table_name) . "') + AND (c.oid = d.adrelid) + AND d.adnum = " . $row['attnum']; + $def_res = $db->sql_query($sql_get_default); + $def_row = $db->sql_fetchrow($def_res); + $db->sql_freeresult($def_res); + + if (empty($def_row)) + { + unset($row['rowdefault']); + } + else + { + $row['rowdefault'] = $def_row['rowdefault']; + } + + if ($row['type'] == 'bpchar') + { + // Internally stored as bpchar, but isn't accepted in a CREATE TABLE statement. + $row['type'] = 'char'; + } + + $line = ' ' . $row['field'] . ' ' . $row['type']; + + if (strpos($row['type'], 'char') !== false) + { + if ($row['lengthvar'] > 0) + { + $line .= '(' . ($row['lengthvar'] - 4) . ')'; + } + } + + if (strpos($row['type'], 'numeric') !== false) + { + $line .= '('; + $line .= sprintf("%s,%s", (($row['lengthvar'] >> 16) & 0xffff), (($row['lengthvar'] - 4) & 0xffff)); + $line .= ')'; + } + + if (isset($row['rowdefault'])) + { + $line .= ' DEFAULT ' . $row['rowdefault']; + } + + if ($row['notnull'] == 't') + { + $line .= ' NOT NULL'; + } + + $lines[] = $line; + } + $db->sql_freeresult($result); + + + // Get the listing of primary keys. + $sql_pri_keys = "SELECT ic.relname as index_name, bc.relname as tab_name, ta.attname as column_name, i.indisunique as unique_key, i.indisprimary as primary_key + FROM pg_class bc, pg_class ic, pg_index i, pg_attribute ta, pg_attribute ia + WHERE (bc.oid = i.indrelid) + AND (ic.oid = i.indexrelid) + AND (ia.attrelid = i.indexrelid) + AND (ta.attrelid = bc.oid) + AND (bc.relname = '" . $db->sql_escape($table_name) . "') + AND (ta.attrelid = i.indrelid) + AND (ta.attnum = i.indkey[ia.attnum-1]) + ORDER BY index_name, tab_name, column_name"; + + $result = $db->sql_query($sql_pri_keys); + + $index_create = $index_rows = $primary_key = array(); + + // We do this in two steps. It makes placing the comma easier + while ($row = $db->sql_fetchrow($result)) + { + if ($row['primary_key'] == 't') + { + $primary_key[] = $row['column_name']; + $primary_key_name = $row['index_name']; + } + else + { + // We have to store this all this info because it is possible to have a multi-column key... + // we can loop through it again and build the statement + $index_rows[$row['index_name']]['table'] = $table_name; + $index_rows[$row['index_name']]['unique'] = ($row['unique_key'] == 't') ? true : false; + $index_rows[$row['index_name']]['column_names'][] = $row['column_name']; + } + } + $db->sql_freeresult($result); + + if (!empty($index_rows)) + { + foreach ($index_rows as $idx_name => $props) + { + $index_create[] = 'CREATE ' . ($props['unique'] ? 'UNIQUE ' : '') . "INDEX $idx_name ON $table_name (" . implode(', ', $props['column_names']) . ");"; + } + } + + if (!empty($primary_key)) + { + $lines[] = " CONSTRAINT $primary_key_name PRIMARY KEY (" . implode(', ', $primary_key) . ")"; + } + + // Generate constraint clauses for CHECK constraints + $sql_checks = "SELECT conname as index_name, consrc + FROM pg_constraint, pg_class bc + WHERE conrelid = bc.oid + AND bc.relname = '" . $db->sql_escape($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 + )"; + $result = $db->sql_query($sql_checks); + + // Add the constraints to the sql file. + while ($row = $db->sql_fetchrow($result)) + { + if (!is_null($row['consrc'])) + { + $lines[] = ' CONSTRAINT ' . $row['index_name'] . ' CHECK ' . $row['consrc']; + } + } + $db->sql_freeresult($result); + + $sql_data .= implode(", \n", $lines); + $sql_data .= "\n);\n"; + + if (!empty($index_create)) + { + $sql_data .= implode("\n", $index_create) . "\n\n"; + } + $this->flush($sql_data); + } + + function write_data($table_name) + { + global $db; + // Grab all of the data from current table. + $sql = "SELECT * + FROM $table_name"; + $result = $db->sql_query($sql); + + $i_num_fields = pg_num_fields($result); + $seq = ''; + + for ($i = 0; $i < $i_num_fields; $i++) + { + $ary_type[] = pg_field_type($result, $i); + $ary_name[] = pg_field_name($result, $i); + + + $sql = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault + FROM pg_attrdef d, pg_class c + WHERE (c.relname = '{$table_name}') + AND (c.oid = d.adrelid) + AND d.adnum = " . strval($i + 1); + $result2 = $db->sql_query($sql); + if ($row = $db->sql_fetchrow($result2)) + { + // Determine if we must reset the sequences + if (strpos($row['rowdefault'], "nextval('") === 0) + { + $seq .= "SELECT SETVAL('{$table_name}_seq',(select case when max({$ary_name[$i]})>0 then max({$ary_name[$i]})+1 else 1 end FROM {$table_name}));\n"; + } + } + } + + $this->flush("COPY $table_name (" . implode(', ', $ary_name) . ') FROM stdin;' . "\n"); + while ($row = $db->sql_fetchrow($result)) + { + $schema_vals = array(); + + // Build the SQL statement to recreate the data. + for ($i = 0; $i < $i_num_fields; $i++) + { + $str_val = $row[$ary_name[$i]]; + + if (preg_match('#char|text|bool|bytea#i', $ary_type[$i])) + { + $str_val = str_replace(array("\n", "\t", "\r", "\b", "\f", "\v"), array('\n', '\t', '\r', '\b', '\f', '\v'), addslashes($str_val)); + $str_empty = ''; + } + else + { + $str_empty = '\N'; + } + + if (empty($str_val) && $str_val !== '0') + { + $str_val = $str_empty; + } + + $schema_vals[] = $str_val; + } + + // Take the ordered fields and their associated data and build it + // into a valid sql statement to recreate that field in the data. + $this->flush(implode("\t", $schema_vals) . "\n"); + } + $db->sql_freeresult($result); + $this->flush("\\.\n"); + + // Write out the sequence statements + $this->flush($seq); + } + + function write_end() + { + $this->flush("COMMIT;\n"); + parent::write_end(); + } +} + +/** +* @package acp +*/ +class mssql_extractor extends base_extractor +{ + function write_end() + { + $this->flush("COMMIT\nGO\n"); + parent::write_end(); + } + + function write_start($prefix) + { + $sql_data = "--\n"; + $sql_data .= "-- phpBB Backup Script\n"; + $sql_data .= "-- Dump of tables for $prefix\n"; + $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; + $sql_data .= "--\n"; + $sql_data .= "BEGIN TRANSACTION\n"; + $sql_data .= "GO\n"; + $this->flush($sql_data); + } + + function write_table($table_name) + { + global $db; + $sql_data = '-- Table: ' . $table_name . "\n"; + $sql_data .= "IF OBJECT_ID(N'$table_name', N'U') IS NOT NULL\n"; + $sql_data .= "DROP TABLE $table_name;\n"; + $sql_data .= "GO\n"; + $sql_data .= "\nCREATE TABLE [$table_name] (\n"; + $rows = array(); + + $text_flag = false; + + $sql = "SELECT COLUMN_NAME, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') as IS_IDENTITY + FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_NAME = '$table_name'"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $line = "\t[{$row['COLUMN_NAME']}] [{$row['DATA_TYPE']}]"; + + if ($row['DATA_TYPE'] == 'text') + { + $text_flag = true; + } + + if ($row['IS_IDENTITY']) + { + $line .= ' IDENTITY (1 , 1)'; + } + + if ($row['CHARACTER_MAXIMUM_LENGTH'] && $row['DATA_TYPE'] !== 'text') + { + $line .= ' (' . $row['CHARACTER_MAXIMUM_LENGTH'] . ')'; + } + + if ($row['IS_NULLABLE'] == 'YES') + { + $line .= ' NULL'; + } + else + { + $line .= ' NOT NULL'; + } + + if ($row['COLUMN_DEFAULT']) + { + $line .= ' DEFAULT ' . $row['COLUMN_DEFAULT']; + } + + $rows[] = $line; + } + $db->sql_freeresult($result); + + $sql_data .= implode(",\n", $rows); + $sql_data .= "\n) ON [PRIMARY]"; + + if ($text_flag) + { + $sql_data .= " TEXTIMAGE_ON [PRIMARY]"; + } + + $sql_data .= "\nGO\n\n"; + $rows = array(); + + $sql = "SELECT CONSTRAINT_NAME, COLUMN_NAME + FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE + WHERE TABLE_NAME = '$table_name'"; + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + if (!sizeof($rows)) + { + $sql_data .= "ALTER TABLE [$table_name] WITH NOCHECK ADD\n"; + $sql_data .= "\tCONSTRAINT [{$row['CONSTRAINT_NAME']}] PRIMARY KEY CLUSTERED \n\t(\n"; + } + $rows[] = "\t\t[{$row['COLUMN_NAME']}]"; + } + if (sizeof($rows)) + { + $sql_data .= implode(",\n", $rows); + $sql_data .= "\n\t) ON [PRIMARY] \nGO\n"; + } + $db->sql_freeresult($result); + + $index = array(); + $sql = "EXEC sp_statistics '$table_name'"; + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + if ($row['TYPE'] == 3) + { + $index[$row['INDEX_NAME']][] = '[' . $row['COLUMN_NAME'] . ']'; + } + } + $db->sql_freeresult($result); + + foreach ($index as $index_name => $column_name) + { + $index[$index_name] = implode(', ', $column_name); + } + + foreach ($index as $index_name => $columns) + { + $sql_data .= "\nCREATE INDEX [$index_name] ON [$table_name]($columns) ON [PRIMARY]\nGO\n"; + } + $this->flush($sql_data); + } + + function write_data($table_name) + { + global $db; + + if ($db->sql_layer === 'mssql') + { + $this->write_data_mssql($table_name); + } + else + { + $this->write_data_odbc($table_name); + } + } + + function write_data_mssql($table_name) + { + global $db; + $ary_type = $ary_name = array(); + $ident_set = false; + $sql_data = ''; + + // Grab all of the data from current table. + $sql = "SELECT * + FROM $table_name"; + $result = $db->sql_query($sql); + + $retrieved_data = mssql_num_rows($result); + + $i_num_fields = mssql_num_fields($result); + + for ($i = 0; $i < $i_num_fields; $i++) + { + $ary_type[$i] = mssql_field_type($result, $i); + $ary_name[$i] = mssql_field_name($result, $i); + } + + if ($retrieved_data) + { + $sql = "SELECT 1 as has_identity + FROM INFORMATION_SCHEMA.COLUMNS + WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1"; + $result2 = $db->sql_query($sql); + $row2 = $db->sql_fetchrow($result2); + if (!empty($row2['has_identity'])) + { + $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n"; + $ident_set = true; + } + $db->sql_freeresult($result2); + } + + while ($row = $db->sql_fetchrow($result)) + { + $schema_vals = $schema_fields = array(); + + // Build the SQL statement to recreate the data. + for ($i = 0; $i < $i_num_fields; $i++) + { + $str_val = $row[$ary_name[$i]]; + + if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i])) + { + $str_quote = ''; + $str_empty = "''"; + $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val)); + } + else if (preg_match('#date|timestamp#i', $ary_type[$i])) + { + if (empty($str_val)) + { + $str_quote = ''; + } + else + { + $str_quote = "'"; + } + } + else + { + $str_quote = ''; + $str_empty = 'NULL'; + } + + if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val))) + { + $str_val = $str_empty; + } + + $schema_vals[$i] = $str_quote . $str_val . $str_quote; + $schema_fields[$i] = $ary_name[$i]; + } + + // Take the ordered fields and their associated data and build it + // into a valid sql statement to recreate that field in the data. + $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n"; + + $this->flush($sql_data); + $sql_data = ''; + } + $db->sql_freeresult($result); + + if ($retrieved_data && $ident_set) + { + $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n"; + } + $this->flush($sql_data); + } + + function write_data_odbc($table_name) + { + global $db; + $ary_type = $ary_name = array(); + $ident_set = false; + $sql_data = ''; + + // Grab all of the data from current table. + $sql = "SELECT * + FROM $table_name"; + $result = $db->sql_query($sql); + + $retrieved_data = odbc_num_rows($result); + + if ($retrieved_data) + { + $sql = "SELECT 1 as has_identity + FROM INFORMATION_SCHEMA.COLUMNS + WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1"; + $result2 = $db->sql_query($sql); + $row2 = $db->sql_fetchrow($result2); + if (!empty($row2['has_identity'])) + { + $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n"; + $ident_set = true; + } + $db->sql_freeresult($result2); + } + + $i_num_fields = odbc_num_fields($result); + + for ($i = 0; $i < $i_num_fields; $i++) + { + $ary_type[$i] = odbc_field_type($result, $i + 1); + $ary_name[$i] = odbc_field_name($result, $i + 1); + } + + while ($row = $db->sql_fetchrow($result)) + { + $schema_vals = $schema_fields = array(); + + // Build the SQL statement to recreate the data. + for ($i = 0; $i < $i_num_fields; $i++) + { + $str_val = $row[$ary_name[$i]]; + + if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i])) + { + $str_quote = ''; + $str_empty = "''"; + $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val)); + } + else if (preg_match('#date|timestamp#i', $ary_type[$i])) + { + if (empty($str_val)) + { + $str_quote = ''; + } + else + { + $str_quote = "'"; + } + } + else + { + $str_quote = ''; + $str_empty = 'NULL'; + } + + if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val))) + { + $str_val = $str_empty; + } + + $schema_vals[$i] = $str_quote . $str_val . $str_quote; + $schema_fields[$i] = $ary_name[$i]; + } + + // Take the ordered fields and their associated data and build it + // into a valid sql statement to recreate that field in the data. + $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n"; + + $this->flush($sql_data); + + $sql_data = ''; + + } + $db->sql_freeresult($result); + + if ($retrieved_data && $ident_set) + { + $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n"; + } + $this->flush($sql_data); + } + +} + +/** +* @package acp +*/ +class oracle_extractor extends base_extractor +{ + function write_table($table_name) + { + global $db; + $sql_data = '-- Table: ' . $table_name . "\n"; + $sql_data .= "DROP TABLE $table_name\n/\n"; + $sql_data .= "\nCREATE TABLE $table_name (\n"; + + $sql = "SELECT COLUMN_NAME, DATA_TYPE, DATA_PRECISION, DATA_LENGTH, NULLABLE, DATA_DEFAULT + FROM ALL_TAB_COLS + WHERE table_name = '{$table_name}'"; + $result = $db->sql_query($sql); + + $rows = array(); + while ($row = $db->sql_fetchrow($result)) + { + $line = ' "' . $row['column_name'] . '" ' . $row['data_type']; + + if ($row['data_type'] !== 'CLOB') + { + if ($row['data_type'] !== 'VARCHAR2' && $row['data_type'] !== 'CHAR') + { + $line .= '(' . $row['data_precision'] . ')'; + } + else + { + $line .= '(' . $row['data_length'] . ')'; + } + } + + if (!empty($row['data_default'])) + { + $line .= ' DEFAULT ' . $row['data_default']; + } + + if ($row['nullable'] == 'N') + { + $line .= ' NOT NULL'; + } + $rows[] = $line; + } + $db->sql_freeresult($result); + + $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME + FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B + WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME + AND B.CONSTRAINT_TYPE = 'P' + AND A.TABLE_NAME = '{$table_name}'"; + $result = $db->sql_query($sql); + + $primary_key = array(); + $contraint_name = ''; + while ($row = $db->sql_fetchrow($result)) + { + $constraint_name = '"' . $row['constraint_name'] . '"'; + $primary_key[] = '"' . $row['column_name'] . '"'; + } + $db->sql_freeresult($result); + + if (sizeof($primary_key)) + { + $rows[] = " CONSTRAINT {$constraint_name} PRIMARY KEY (" . implode(', ', $primary_key) . ')'; + } + + $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME + FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B + WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME + AND B.CONSTRAINT_TYPE = 'U' + AND A.TABLE_NAME = '{$table_name}'"; + $result = $db->sql_query($sql); + + $unique = array(); + $contraint_name = ''; + while ($row = $db->sql_fetchrow($result)) + { + $constraint_name = '"' . $row['constraint_name'] . '"'; + $unique[] = '"' . $row['column_name'] . '"'; + } + $db->sql_freeresult($result); + + if (sizeof($unique)) + { + $rows[] = " CONSTRAINT {$constraint_name} UNIQUE (" . implode(', ', $unique) . ')'; + } + + $sql_data .= implode(",\n", $rows); + $sql_data .= "\n)\n/\n"; + + $sql = "SELECT A.REFERENCED_NAME, C.* + FROM USER_DEPENDENCIES A, USER_TRIGGERS B, USER_SEQUENCES C + WHERE A.REFERENCED_TYPE = 'SEQUENCE' + AND A.NAME = B.TRIGGER_NAME + AND B.TABLE_NAME = '{$table_name}' + AND C.SEQUENCE_NAME = A.REFERENCED_NAME"; + $result = $db->sql_query($sql); + + $type = request_var('type', ''); + + while ($row = $db->sql_fetchrow($result)) + { + $sql_data .= "\nDROP SEQUENCE \"{$row['referenced_name']}\"\n/\n"; + $sql_data .= "\nCREATE SEQUENCE \"{$row['referenced_name']}\""; + + if ($type == 'full') + { + $sql_data .= ' START WITH ' . $row['last_number']; + } + + $sql_data .= "\n/\n"; + } + $db->sql_freeresult($result); + + $sql = "SELECT DESCRIPTION, WHEN_CLAUSE, TRIGGER_BODY + FROM USER_TRIGGERS + WHERE TABLE_NAME = '{$table_name}'"; + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + $sql_data .= "\nCREATE OR REPLACE TRIGGER {$row['description']}WHEN ({$row['when_clause']})\n{$row['trigger_body']}\n/\n"; + } + $db->sql_freeresult($result); + + $sql = "SELECT A.INDEX_NAME, B.COLUMN_NAME + FROM USER_INDEXES A, USER_IND_COLUMNS B + WHERE A.UNIQUENESS = 'NONUNIQUE' + AND A.INDEX_NAME = B.INDEX_NAME + AND B.TABLE_NAME = '{$table_name}'"; + $result = $db->sql_query($sql); + + $index = array(); + + while ($row = $db->sql_fetchrow($result)) + { + $index[$row['index_name']][] = $row['column_name']; + } + + foreach ($index as $index_name => $column_names) + { + $sql_data .= "\nCREATE INDEX $index_name ON $table_name(" . implode(', ', $column_names) . ")\n/\n"; + } + $db->sql_freeresult($result); + $this->flush($sql_data); + } + + function write_data($table_name) + { + global $db; + $ary_type = $ary_name = array(); + + // Grab all of the data from current table. + $sql = "SELECT * + FROM $table_name"; + $result = $db->sql_query($sql); + + $i_num_fields = ocinumcols($result); + + for ($i = 0; $i < $i_num_fields; $i++) + { + $ary_type[$i] = ocicolumntype($result, $i + 1); + $ary_name[$i] = ocicolumnname($result, $i + 1); + } + + $sql_data = ''; + + while ($row = $db->sql_fetchrow($result)) + { + $schema_vals = $schema_fields = array(); + + // Build the SQL statement to recreate the data. + for ($i = 0; $i < $i_num_fields; $i++) + { + // Oracle uses uppercase - we use lowercase + $str_val = $row[strtolower($ary_name[$i])]; + + if (preg_match('#char|text|bool|raw|clob#i', $ary_type[$i])) + { + $str_quote = ''; + $str_empty = "''"; + $str_val = sanitize_data_oracle($str_val); + } + else if (preg_match('#date|timestamp#i', $ary_type[$i])) + { + if (empty($str_val)) + { + $str_quote = ''; + } + else + { + $str_quote = "'"; + } + } + else + { + $str_quote = ''; + $str_empty = 'NULL'; + } + + if (empty($str_val) && $str_val !== '0') + { + $str_val = $str_empty; + } + + $schema_vals[$i] = $str_quote . $str_val . $str_quote; + $schema_fields[$i] = '"' . $ary_name[$i] . '"'; + } + + // Take the ordered fields and their associated data and build it + // into a valid sql statement to recreate that field in the data. + $sql_data = "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ")\n/\n"; + + $this->flush($sql_data); + } + $db->sql_freeresult($result); + } + + function write_start($prefix) + { + $sql_data = "--\n"; + $sql_data .= "-- phpBB Backup Script\n"; + $sql_data .= "-- Dump of tables for $prefix\n"; + $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; + $sql_data .= "--\n"; + $this->flush($sql_data); + } +} + +/** +* @package acp +*/ +class firebird_extractor extends base_extractor +{ + function write_start($prefix) + { + $sql_data = "--\n"; + $sql_data .= "-- phpBB Backup Script\n"; + $sql_data .= "-- Dump of tables for $prefix\n"; + $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; + $sql_data .= "--\n"; + $this->flush($sql_data); + } + + function write_data($table_name) + { + global $db; + $ary_type = $ary_name = array(); + + // Grab all of the data from current table. + $sql = "SELECT * + FROM $table_name"; + $result = $db->sql_query($sql); + + $i_num_fields = ibase_num_fields($result); + + for ($i = 0; $i < $i_num_fields; $i++) + { + $info = ibase_field_info($result, $i); + $ary_type[$i] = $info['type']; + $ary_name[$i] = $info['name']; + } + + while ($row = $db->sql_fetchrow($result)) + { + $schema_vals = $schema_fields = array(); + + // Build the SQL statement to recreate the data. + for ($i = 0; $i < $i_num_fields; $i++) + { + $str_val = $row[strtolower($ary_name[$i])]; + + if (preg_match('#char|text|bool|varbinary|blob#i', $ary_type[$i])) + { + $str_quote = ''; + $str_empty = "''"; + $str_val = sanitize_data_generic(str_replace("'", "''", $str_val)); + } + else if (preg_match('#date|timestamp#i', $ary_type[$i])) + { + if (empty($str_val)) + { + $str_quote = ''; + } + else + { + $str_quote = "'"; + } + } + else + { + $str_quote = ''; + $str_empty = 'NULL'; + } + + if (empty($str_val) && $str_val !== '0') + { + $str_val = $str_empty; + } + + $schema_vals[$i] = $str_quote . $str_val . $str_quote; + $schema_fields[$i] = '"' . $ary_name[$i] . '"'; + } + + // Take the ordered fields and their associated data and build it + // into a valid sql statement to recreate that field in the data. + $sql_data = "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\n"; + + $this->flush($sql_data); + } + $db->sql_freeresult($result); + } + + function write_table($table_name) + { + global $db; + + $sql_data = '-- Table: ' . $table_name . "\n"; + $sql_data .= "DROP TABLE $table_name;\n"; + + $data_types = array(7 => 'SMALLINT', 8 => 'INTEGER', 10 => 'FLOAT', 12 => 'DATE', 13 => 'TIME', 14 => 'CHARACTER', 27 => 'DOUBLE PRECISION', 35 => 'TIMESTAMP', 37 => 'VARCHAR', 40 => 'CSTRING', 261 => 'BLOB', 701 => 'DECIMAL', 702 => 'NUMERIC'); + + $sql_data .= "\nCREATE TABLE $table_name (\n"; + + $sql = 'SELECT DISTINCT R.RDB$FIELD_NAME as FNAME, R.RDB$NULL_FLAG as NFLAG, R.RDB$DEFAULT_SOURCE as DSOURCE, F.RDB$FIELD_TYPE as FTYPE, F.RDB$FIELD_SUB_TYPE as STYPE, F.RDB$FIELD_LENGTH as FLEN + FROM RDB$RELATION_FIELDS R + JOIN RDB$FIELDS F ON R.RDB$FIELD_SOURCE=F.RDB$FIELD_NAME + LEFT JOIN RDB$FIELD_DIMENSIONS D ON R.RDB$FIELD_SOURCE = D.RDB$FIELD_NAME + WHERE F.RDB$SYSTEM_FLAG = 0 + AND R.RDB$RELATION_NAME = \''. $table_name . '\' + ORDER BY R.RDB$FIELD_POSITION'; + $result = $db->sql_query($sql); + + $rows = array(); + while ($row = $db->sql_fetchrow($result)) + { + $line = "\t" . '"' . $row['fname'] . '" ' . $data_types[$row['ftype']]; + + if ($row['ftype'] == 261 && $row['stype'] == 1) + { + $line .= ' SUB_TYPE TEXT'; + } + + if ($row['ftype'] == 37 || $row['ftype'] == 14) + { + $line .= ' (' . $row['flen'] . ')'; + } + + if (!empty($row['dsource'])) + { + $line .= ' ' . $row['dsource']; + } + + if (!empty($row['nflag'])) + { + $line .= ' NOT NULL'; + } + $rows[] = $line; + } + $db->sql_freeresult($result); + + $sql_data .= implode(",\n", $rows); + $sql_data .= "\n);\n"; + $keys = array(); + + $sql = 'SELECT I.RDB$FIELD_NAME as NAME + FROM RDB$RELATION_CONSTRAINTS RC, RDB$INDEX_SEGMENTS I, RDB$INDICES IDX + WHERE (I.RDB$INDEX_NAME = RC.RDB$INDEX_NAME) + AND (IDX.RDB$INDEX_NAME = RC.RDB$INDEX_NAME) + AND (RC.RDB$RELATION_NAME = \''. $table_name . '\') + ORDER BY I.RDB$FIELD_POSITION'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $keys[] = $row['name']; + } + + if (sizeof($keys)) + { + $sql_data .= "\nALTER TABLE $table_name ADD PRIMARY KEY (" . implode(', ', $keys) . ');'; + } + + $db->sql_freeresult($result); + + $sql = 'SELECT I.RDB$INDEX_NAME as INAME, I.RDB$UNIQUE_FLAG as UFLAG, S.RDB$FIELD_NAME as FNAME + FROM RDB$INDICES I JOIN RDB$INDEX_SEGMENTS S ON S.RDB$INDEX_NAME=I.RDB$INDEX_NAME + WHERE (I.RDB$SYSTEM_FLAG IS NULL OR I.RDB$SYSTEM_FLAG=0) + AND I.RDB$FOREIGN_KEY IS NULL + AND I.RDB$RELATION_NAME = \''. $table_name . '\' + AND I.RDB$INDEX_NAME NOT STARTING WITH \'RDB$\' + ORDER BY S.RDB$FIELD_POSITION'; + $result = $db->sql_query($sql); + + $index = array(); + while ($row = $db->sql_fetchrow($result)) + { + $index[$row['iname']]['unique'] = !empty($row['uflag']); + $index[$row['iname']]['values'][] = $row['fname']; + } + + foreach ($index as $index_name => $data) + { + $sql_data .= "\nCREATE "; + if ($data['unique']) + { + $sql_data .= 'UNIQUE '; + } + $sql_data .= "INDEX $index_name ON $table_name(" . implode(', ', $data['values']) . ");"; + } + $sql_data .= "\n"; + + $db->sql_freeresult($result); + + $sql = 'SELECT D1.RDB$DEPENDENT_NAME as DNAME, D1.RDB$FIELD_NAME as FNAME, D1.RDB$DEPENDENT_TYPE, R1.RDB$RELATION_NAME + FROM RDB$DEPENDENCIES D1 + LEFT JOIN RDB$RELATIONS R1 ON ((D1.RDB$DEPENDENT_NAME = R1.RDB$RELATION_NAME) AND (NOT (R1.RDB$VIEW_BLR IS NULL))) + WHERE (D1.RDB$DEPENDED_ON_TYPE = 0) + AND (D1.RDB$DEPENDENT_TYPE <> 3) + AND (D1.RDB$DEPENDED_ON_NAME = \'' . $table_name . '\') + UNION SELECT DISTINCT F2.RDB$RELATION_NAME, D2.RDB$FIELD_NAME, D2.RDB$DEPENDENT_TYPE, R2.RDB$RELATION_NAME FROM RDB$DEPENDENCIES D2, RDB$RELATION_FIELDS F2 + LEFT JOIN RDB$RELATIONS R2 ON ((F2.RDB$RELATION_NAME = R2.RDB$RELATION_NAME) AND (NOT (R2.RDB$VIEW_BLR IS NULL))) + WHERE (D2.RDB$DEPENDENT_TYPE = 3) + AND (D2.RDB$DEPENDENT_NAME = F2.RDB$FIELD_SOURCE) + AND (D2.RDB$DEPENDED_ON_NAME = \'' . $table_name . '\') + ORDER BY 1, 2'; + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + $sql = 'SELECT T1.RDB$DEPENDED_ON_NAME as GEN, T1.RDB$FIELD_NAME, T1.RDB$DEPENDED_ON_TYPE + FROM RDB$DEPENDENCIES T1 + WHERE (T1.RDB$DEPENDENT_NAME = \'' . $row['dname'] . '\') + AND (T1.RDB$DEPENDENT_TYPE = 2 AND T1.RDB$DEPENDED_ON_TYPE = 14) + UNION ALL SELECT DISTINCT D.RDB$DEPENDED_ON_NAME, D.RDB$FIELD_NAME, D.RDB$DEPENDED_ON_TYPE + FROM RDB$DEPENDENCIES D, RDB$RELATION_FIELDS F + WHERE (D.RDB$DEPENDENT_TYPE = 3) + AND (D.RDB$DEPENDENT_NAME = F.RDB$FIELD_SOURCE) + AND (F.RDB$RELATION_NAME = \'' . $row['dname'] . '\') + ORDER BY 1,2'; + $result2 = $db->sql_query($sql); + $row2 = $db->sql_fetchrow($result2); + $db->sql_freeresult($result2); + $gen_name = $row2['gen']; + + $sql_data .= "\nDROP GENERATOR " . $gen_name . ";"; + $sql_data .= "\nSET TERM ^ ;"; + $sql_data .= "\nCREATE GENERATOR " . $gen_name . "^"; + $sql_data .= "\nSET GENERATOR " . $gen_name . " TO 0^\n"; + $sql_data .= "\nCREATE TRIGGER {$row['dname']} FOR $table_name"; + $sql_data .= "\nBEFORE INSERT\nAS\nBEGIN"; + $sql_data .= "\n NEW.{$row['fname']} = GEN_ID(" . $gen_name . ", 1);"; + $sql_data .= "\nEND^\n"; + $sql_data .= "\nSET TERM ; ^\n"; + } + + $this->flush($sql_data); + + $db->sql_freeresult($result); + } +} + +// get how much space we allow for a chunk of data, very similar to phpMyAdmin's way of doing things ;-) (hey, we only do this for MySQL anyway :P) +function get_usable_memory() +{ + $val = trim(@ini_get('memory_limit')); + + if (preg_match('/(\\d+)([mkg]?)/i', $val, $regs)) + { + $memory_limit = (int) $regs[1]; + switch ($regs[2]) + { + + case 'k': + case 'K': + $memory_limit *= 1024; + break; + + case 'm': + case 'M': + $memory_limit *= 1048576; + break; + + case 'g': + case 'G': + $memory_limit *= 1073741824; + break; + } + + // how much memory PHP requires at the start of export (it is really a little less) + if ($memory_limit > 6100000) + { + $memory_limit -= 6100000; + } + + // allow us to consume half of the total memory available + $memory_limit /= 2; + } + else + { + // set the buffer to 1M if we have no clue how much memory PHP will give us :P + $memory_limit = 1048576; + } + + return $memory_limit; +} + +function sanitize_data_mssql($text) +{ + $data = preg_split('/[\n\t\r\b\f]/', $text); + preg_match_all('/[\n\t\r\b\f]/', $text, $matches); + + $val = array(); + + foreach ($data as $value) + { + if (strlen($value)) + { + $val[] = "'" . $value . "'"; + } + if (sizeof($matches[0])) + { + $val[] = 'char(' . ord(array_shift($matches[0])) . ')'; + } + } + + return implode('+', $val); +} + +function sanitize_data_oracle($text) +{ +// $data = preg_split('/[\0\n\t\r\b\f\'"\/\\\]/', $text); +// preg_match_all('/[\0\n\t\r\b\f\'"\/\\\]/', $text, $matches); + $data = preg_split('/[\0\b\f\'\/]/', $text); + preg_match_all('/[\0\r\b\f\'\/]/', $text, $matches); + + $val = array(); + + foreach ($data as $value) + { + if (strlen($value)) + { + $val[] = "'" . $value . "'"; + } + if (sizeof($matches[0])) + { + $val[] = 'chr(' . ord(array_shift($matches[0])) . ')'; + } + } + + return implode('||', $val); +} + +function sanitize_data_generic($text) +{ + $data = preg_split('/[\n\t\r\b\f]/', $text); + preg_match_all('/[\n\t\r\b\f]/', $text, $matches); + + $val = array(); + + foreach ($data as $value) + { + if (strlen($value)) + { + $val[] = "'" . $value . "'"; + } + if (sizeof($matches[0])) + { + $val[] = "'" . array_shift($matches[0]) . "'"; + } + } + + return implode('||', $val); +} + +// modified from PHP.net +function fgetd(&$fp, $delim, $read, $seek, $eof, $buffer = 8192) +{ + $record = ''; + $delim_len = strlen($delim); + + while (!$eof($fp)) + { + $pos = strpos($record, $delim); + if ($pos === false) + { + $record .= $read($fp, $buffer); + if ($eof($fp) && ($pos = strpos($record, $delim)) !== false) + { + $seek($fp, $pos + $delim_len - strlen($record), SEEK_CUR); + return substr($record, 0, $pos); + } + } + else + { + $seek($fp, $pos + $delim_len - strlen($record), SEEK_CUR); + return substr($record, 0, $pos); + } + } + + return false; +} + +function fgetd_seekless(&$fp, $delim, $read, $seek, $eof, $buffer = 8192) +{ + static $array = array(); + static $record = ''; + + if (!sizeof($array)) + { + while (!$eof($fp)) + { + if (strpos($record, $delim) !== false) + { + $array = explode($delim, $record); + $record = array_pop($array); + break; + } + else + { + $record .= $read($fp, $buffer); + } + } + if ($eof($fp) && strpos($record, $delim) !== false) + { + $array = explode($delim, $record); + $record = array_pop($array); + } + } + + if (sizeof($array)) + { + return array_shift($array); + } + + return false; +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_disallow.php b/phpBB/includes/acp/acp_disallow.php new file mode 100644 index 0000000000..9549955cc8 --- /dev/null +++ b/phpBB/includes/acp/acp_disallow.php @@ -0,0 +1,108 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_disallow +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + + $user->add_lang('acp/posting'); + + // Set up general vars + $this->tpl_name = 'acp_disallow'; + $this->page_title = 'ACP_DISALLOW_USERNAMES'; + + $form_key = 'acp_disallow'; + add_form_key($form_key); + + $disallow = (isset($_POST['disallow'])) ? true : false; + $allow = (isset($_POST['allow'])) ? true : false; + + if (($allow || $disallow) && !check_form_key($form_key)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if ($disallow) + { + $disallowed_user = str_replace('*', '%', utf8_normalize_nfc(request_var('disallowed_user', '', true))); + + if (!$disallowed_user) + { + trigger_error($user->lang['NO_USERNAME_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'INSERT INTO ' . DISALLOW_TABLE . ' ' . $db->sql_build_array('INSERT', array('disallow_username' => $disallowed_user)); + $db->sql_query($sql); + + $cache->destroy('_disallowed_usernames'); + + $message = $user->lang['DISALLOW_SUCCESSFUL']; + add_log('admin', 'LOG_DISALLOW_ADD', str_replace('%', '*', $disallowed_user)); + + trigger_error($message . adm_back_link($this->u_action)); + } + else if ($allow) + { + $disallowed_id = request_var('disallowed_id', 0); + + if (!$disallowed_id) + { + trigger_error($user->lang['NO_USERNAME_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'DELETE FROM ' . DISALLOW_TABLE . ' + WHERE disallow_id = ' . $disallowed_id; + $db->sql_query($sql); + + $cache->destroy('_disallowed_usernames'); + + add_log('admin', 'LOG_DISALLOW_DELETE'); + + trigger_error($user->lang['DISALLOWED_DELETED'] . adm_back_link($this->u_action)); + } + + // Grab the current list of disallowed usernames... + $sql = 'SELECT * + FROM ' . DISALLOW_TABLE; + $result = $db->sql_query($sql); + + $disallow_select = ''; + while ($row = $db->sql_fetchrow($result)) + { + $disallow_select .= '<option value="' . $row['disallow_id'] . '">' . str_replace('%', '*', $row['disallow_username']) . '</option>'; + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action, + 'S_DISALLOWED_NAMES' => $disallow_select) + ); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_email.php b/phpBB/includes/acp/acp_email.php new file mode 100644 index 0000000000..350693a630 --- /dev/null +++ b/phpBB/includes/acp/acp_email.php @@ -0,0 +1,262 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_email +{ + var $u_action; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $cache; + global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix; + + $user->add_lang('acp/email'); + $this->tpl_name = 'acp_email'; + $this->page_title = 'ACP_MASS_EMAIL'; + + $form_key = 'acp_email'; + add_form_key($form_key); + + // Set some vars + $submit = (isset($_POST['submit'])) ? true : false; + $error = array(); + + $usernames = request_var('usernames', '', true); + $group_id = request_var('g', 0); + $subject = utf8_normalize_nfc(request_var('subject', '', true)); + $message = utf8_normalize_nfc(request_var('message', '', true)); + + // Do the job ... + if ($submit) + { + // Error checking needs to go here ... if no subject and/or no message then skip + // over the send and return to the form + $use_queue = (isset($_POST['send_immediately'])) ? false : true; + $priority = request_var('mail_priority_flag', MAIL_NORMAL_PRIORITY); + + if (!check_form_key($form_key)) + { + $error[] = $user->lang['FORM_INVALID']; + } + + if (!$subject) + { + $error[] = $user->lang['NO_EMAIL_SUBJECT']; + } + + if (!$message) + { + $error[] = $user->lang['NO_EMAIL_MESSAGE']; + } + + if (!sizeof($error)) + { + if ($usernames) + { + // If giving usernames the admin is able to email inactive users too... + $sql = 'SELECT username, user_email, user_jabber, user_notify_type, user_lang + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('username_clean', array_map('utf8_clean_string', explode("\n", $usernames))) . ' + AND user_allow_massemail = 1 + ORDER BY user_lang, user_notify_type'; // , SUBSTRING(user_email FROM INSTR(user_email, '@')) + } + else + { + if ($group_id) + { + $sql = 'SELECT u.user_email, u.username, u.username_clean, u.user_lang, u.user_jabber, u.user_notify_type + FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . ' ug + WHERE ug.group_id = ' . $group_id . ' + AND ug.user_pending = 0 + AND u.user_id = ug.user_id + AND u.user_allow_massemail = 1 + AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ') + ORDER BY u.user_lang, u.user_notify_type'; + } + else + { + $sql = 'SELECT username, username_clean, user_email, user_jabber, user_notify_type, user_lang + FROM ' . USERS_TABLE . ' + WHERE user_allow_massemail = 1 + AND user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ') + ORDER BY user_lang, user_notify_type'; + } + } + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + + if (!$row) + { + $db->sql_freeresult($result); + trigger_error($user->lang['NO_USER'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $i = $j = 0; + + // Send with BCC, no more than 50 recipients for one mail (to not exceed the limit) + $max_chunk_size = 50; + $email_list = array(); + $old_lang = $row['user_lang']; + $old_notify_type = $row['user_notify_type']; + + do + { + if (($row['user_notify_type'] == NOTIFY_EMAIL && $row['user_email']) || + ($row['user_notify_type'] == NOTIFY_IM && $row['user_jabber']) || + ($row['user_notify_type'] == NOTIFY_BOTH && ($row['user_email'] || $row['user_jabber']))) + { + if ($i == $max_chunk_size || $row['user_lang'] != $old_lang || $row['user_notify_type'] != $old_notify_type) + { + $i = 0; + + if (sizeof($email_list)) + { + $j++; + } + + $old_lang = $row['user_lang']; + $old_notify_type = $row['user_notify_type']; + } + + $email_list[$j][$i]['lang'] = $row['user_lang']; + $email_list[$j][$i]['method'] = $row['user_notify_type']; + $email_list[$j][$i]['email'] = $row['user_email']; + $email_list[$j][$i]['name'] = $row['username']; + $email_list[$j][$i]['jabber'] = $row['user_jabber']; + $i++; + } + } + while ($row = $db->sql_fetchrow($result)); + $db->sql_freeresult($result); + + // Send the messages + include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); + $messenger = new messenger($use_queue); + + $errored = false; + + for ($i = 0, $size = sizeof($email_list); $i < $size; $i++) + { + $used_lang = $email_list[$i][0]['lang']; + $used_method = $email_list[$i][0]['method']; + + for ($j = 0, $list_size = sizeof($email_list[$i]); $j < $list_size; $j++) + { + $email_row = $email_list[$i][$j]; + + $messenger->{((sizeof($email_list[$i]) == 1) ? 'to' : 'bcc')}($email_row['email'], $email_row['name']); + $messenger->im($email_row['jabber'], $email_row['name']); + } + + $messenger->template('admin_send_email', $used_lang); + + $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); + $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); + $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); + $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + + $messenger->subject(htmlspecialchars_decode($subject)); + $messenger->set_mail_priority($priority); + + $messenger->assign_vars(array( + 'CONTACT_EMAIL' => $config['board_contact'], + 'MESSAGE' => htmlspecialchars_decode($message)) + ); + + if (!($messenger->send($used_method))) + { + $errored = true; + } + } + unset($email_list); + + $messenger->save_queue(); + + if ($usernames) + { + $usernames = explode("\n", $usernames); + add_log('admin', 'LOG_MASS_EMAIL', implode(', ', utf8_normalize_nfc($usernames))); + } + else + { + if ($group_id) + { + $group_name = get_group_name($group_id); + } + else + { + // Not great but the logging routine doesn't cope well with localising on the fly + $group_name = $user->lang['ALL_USERS']; + } + + add_log('admin', 'LOG_MASS_EMAIL', $group_name); + } + + if (!$errored) + { + $message = ($use_queue) ? $user->lang['EMAIL_SENT_QUEUE'] : $user->lang['EMAIL_SENT']; + trigger_error($message . adm_back_link($this->u_action)); + } + else + { + $message = sprintf($user->lang['EMAIL_SEND_ERROR'], '<a href="' . append_sid("{$phpbb_admin_path}index.$phpEx", 'i=logs&mode=critical') . '">', '</a>'); + trigger_error($message . adm_back_link($this->u_action), E_USER_WARNING); + } + } + } + + // Exclude bots and guests... + $sql = 'SELECT group_id + FROM ' . GROUPS_TABLE . " + WHERE group_name IN ('BOTS', 'GUESTS')"; + $result = $db->sql_query($sql); + + $exclude = array(); + while ($row = $db->sql_fetchrow($result)) + { + $exclude[] = $row['group_id']; + } + $db->sql_freeresult($result); + + $select_list = '<option value="0"' . ((!$group_id) ? ' selected="selected"' : '') . '>' . $user->lang['ALL_USERS'] . '</option>'; + $select_list .= group_select_options($group_id, $exclude); + + $s_priority_options = '<option value="' . MAIL_LOW_PRIORITY . '">' . $user->lang['MAIL_LOW_PRIORITY'] . '</option>'; + $s_priority_options .= '<option value="' . MAIL_NORMAL_PRIORITY . '" selected="selected">' . $user->lang['MAIL_NORMAL_PRIORITY'] . '</option>'; + $s_priority_options .= '<option value="' . MAIL_HIGH_PRIORITY . '">' . $user->lang['MAIL_HIGH_PRIORITY'] . '</option>'; + + $template->assign_vars(array( + 'S_WARNING' => (sizeof($error)) ? true : false, + 'WARNING_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + 'U_ACTION' => $this->u_action, + 'S_GROUP_OPTIONS' => $select_list, + 'USERNAMES' => $usernames, + 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=acp_email&field=usernames'), + 'SUBJECT' => $subject, + 'MESSAGE' => $message, + 'S_PRIORITY_OPTIONS' => $s_priority_options) + ); + + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php new file mode 100644 index 0000000000..2ff597ee98 --- /dev/null +++ b/phpBB/includes/acp/acp_forums.php @@ -0,0 +1,1947 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_forums +{ + var $u_action; + var $parent_id = 0; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache; + global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx; + + $user->add_lang('acp/forums'); + $this->tpl_name = 'acp_forums'; + $this->page_title = 'ACP_MANAGE_FORUMS'; + + $form_key = 'acp_forums'; + add_form_key($form_key); + + $action = request_var('action', ''); + $update = (isset($_POST['update'])) ? true : false; + $forum_id = request_var('f', 0); + + $this->parent_id = request_var('parent_id', 0); + $forum_data = $errors = array(); + if ($update && !check_form_key($form_key)) + { + $update = false; + $errors[] = $user->lang['FORM_INVALID']; + } + + // Check additional permissions + switch ($action) + { + case 'progress_bar': + $start = request_var('start', 0); + $total = request_var('total', 0); + + $this->display_progress_bar($start, $total); + exit; + break; + + case 'delete': + + if (!$auth->acl_get('a_forumdel')) + { + trigger_error($user->lang['NO_PERMISSION_FORUM_DELETE'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + break; + + case 'add': + + if (!$auth->acl_get('a_forumadd')) + { + trigger_error($user->lang['NO_PERMISSION_FORUM_ADD'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + case 'copy_perm': + + if (!(($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth')))) + { + trigger_error($user->lang['NO_PERMISSION_COPY'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + break; + } + + // Major routines + if ($update) + { + switch ($action) + { + case 'delete': + $action_subforums = request_var('action_subforums', ''); + $subforums_to_id = request_var('subforums_to_id', 0); + $action_posts = request_var('action_posts', ''); + $posts_to_id = request_var('posts_to_id', 0); + + $errors = $this->delete_forum($forum_id, $action_posts, $action_subforums, $posts_to_id, $subforums_to_id); + + if (sizeof($errors)) + { + break; + } + + $auth->acl_clear_prefetch(); + $cache->destroy('sql', FORUMS_TABLE); + + trigger_error($user->lang['FORUM_DELETED'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); + + break; + + case 'edit': + $forum_data = array( + 'forum_id' => $forum_id + ); + + // No break here + + case 'add': + + $forum_data += array( + 'parent_id' => request_var('forum_parent_id', $this->parent_id), + 'forum_type' => request_var('forum_type', FORUM_POST), + 'type_action' => request_var('type_action', ''), + 'forum_status' => request_var('forum_status', ITEM_UNLOCKED), + 'forum_parents' => '', + 'forum_options' => 0, + 'forum_name' => utf8_normalize_nfc(request_var('forum_name', '', true)), + 'forum_link' => request_var('forum_link', ''), + 'forum_link_track' => request_var('forum_link_track', false), + 'forum_desc' => utf8_normalize_nfc(request_var('forum_desc', '', true)), + 'forum_desc_uid' => '', + 'forum_desc_options' => 7, + 'forum_desc_bitfield' => '', + 'forum_rules' => utf8_normalize_nfc(request_var('forum_rules', '', true)), + 'forum_rules_uid' => '', + 'forum_rules_options' => 7, + 'forum_rules_bitfield' => '', + 'forum_rules_link' => request_var('forum_rules_link', ''), + 'forum_image' => request_var('forum_image', ''), + 'forum_style' => request_var('forum_style', 0), + 'display_subforum_list' => request_var('display_subforum_list', false), + 'display_on_index' => request_var('display_on_index', false), + 'forum_topics_per_page' => request_var('topics_per_page', 0), + 'enable_indexing' => request_var('enable_indexing', true), + 'enable_icons' => request_var('enable_icons', false), + 'enable_prune' => request_var('enable_prune', false), + 'enable_post_review' => request_var('enable_post_review', true), + 'enable_quick_reply' => request_var('enable_quick_reply', false), + 'prune_days' => request_var('prune_days', 7), + 'prune_viewed' => request_var('prune_viewed', 7), + 'prune_freq' => request_var('prune_freq', 1), + 'prune_old_polls' => request_var('prune_old_polls', false), + 'prune_announce' => request_var('prune_announce', false), + 'prune_sticky' => request_var('prune_sticky', false), + 'forum_password' => request_var('forum_password', '', true), + 'forum_password_confirm'=> request_var('forum_password_confirm', '', true), + 'forum_password_unset' => request_var('forum_password_unset', false), + ); + + // Use link_display_on_index setting if forum type is link + if ($forum_data['forum_type'] == FORUM_LINK) + { + $forum_data['display_on_index'] = request_var('link_display_on_index', false); + } + + // Linked forums and categories are not able to be locked... + if ($forum_data['forum_type'] == FORUM_LINK || $forum_data['forum_type'] == FORUM_CAT) + { + $forum_data['forum_status'] = ITEM_UNLOCKED; + } + + $forum_data['show_active'] = ($forum_data['forum_type'] == FORUM_POST) ? request_var('display_recent', true) : request_var('display_active', true); + + // Get data for forum rules if specified... + if ($forum_data['forum_rules']) + { + generate_text_for_storage($forum_data['forum_rules'], $forum_data['forum_rules_uid'], $forum_data['forum_rules_bitfield'], $forum_data['forum_rules_options'], request_var('rules_parse_bbcode', false), request_var('rules_parse_urls', false), request_var('rules_parse_smilies', false)); + } + + // Get data for forum description if specified + if ($forum_data['forum_desc']) + { + generate_text_for_storage($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options'], request_var('desc_parse_bbcode', false), request_var('desc_parse_urls', false), request_var('desc_parse_smilies', false)); + } + + $errors = $this->update_forum_data($forum_data); + + if (!sizeof($errors)) + { + $forum_perm_from = request_var('forum_perm_from', 0); + $cache->destroy('sql', FORUMS_TABLE); + + // Copy permissions? + if ($forum_perm_from && $forum_perm_from != $forum_data['forum_id'] && + ($action != 'edit' || empty($forum_id) || ($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth')))) + { + copy_forum_permissions($forum_perm_from, $forum_data['forum_id'], ($action == 'edit') ? true : false); + cache_moderators(); + } +/* Commented out because of questionable UI workflow - re-visit for 3.0.7 + else if (!$this->parent_id && $action != 'edit' && $auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth')) + { + $this->copy_permission_page($forum_data); + return; + } +*/ + $auth->acl_clear_prefetch(); + + $acl_url = '&mode=setting_forum_local&forum_id[]=' . $forum_data['forum_id']; + + $message = ($action == 'add') ? $user->lang['FORUM_CREATED'] : $user->lang['FORUM_UPDATED']; + + // Redirect to permissions + if ($auth->acl_get('a_fauth')) + { + $message .= '<br /><br />' . sprintf($user->lang['REDIRECT_ACL'], '<a href="' . append_sid("{$phpbb_admin_path}index.$phpEx", 'i=permissions' . $acl_url) . '">', '</a>'); + } + + // redirect directly to permission settings screen if authed + if ($action == 'add' && !$forum_perm_from && $auth->acl_get('a_fauth')) + { + meta_refresh(4, append_sid("{$phpbb_admin_path}index.$phpEx", 'i=permissions' . $acl_url)); + } + + trigger_error($message . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); + } + + break; + } + } + + switch ($action) + { + case 'move_up': + case 'move_down': + + if (!$forum_id) + { + trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + $sql = 'SELECT * + FROM ' . FORUMS_TABLE . " + WHERE forum_id = $forum_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + $move_forum_name = $this->move_forum_by($row, $action, 1); + + if ($move_forum_name !== false) + { + add_log('admin', 'LOG_FORUM_' . strtoupper($action), $row['forum_name'], $move_forum_name); + $cache->destroy('sql', FORUMS_TABLE); + } + + break; + + case 'sync': + if (!$forum_id) + { + trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + @set_time_limit(0); + + $sql = 'SELECT forum_name, forum_topics_real + FROM ' . FORUMS_TABLE . " + WHERE forum_id = $forum_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + if ($row['forum_topics_real']) + { + $sql = 'SELECT MIN(topic_id) as min_topic_id, MAX(topic_id) as max_topic_id + FROM ' . TOPICS_TABLE . ' + WHERE forum_id = ' . $forum_id; + $result = $db->sql_query($sql); + $row2 = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + // Typecast to int if there is no data available + $row2['min_topic_id'] = (int) $row2['min_topic_id']; + $row2['max_topic_id'] = (int) $row2['max_topic_id']; + + $start = request_var('start', $row2['min_topic_id']); + + $batch_size = 2000; + $end = $start + $batch_size; + + // Sync all topics in batch mode... + sync('topic_approved', 'range', 'topic_id BETWEEN ' . $start . ' AND ' . $end, true, false); + sync('topic', 'range', 'topic_id BETWEEN ' . $start . ' AND ' . $end, true, true); + + if ($end < $row2['max_topic_id']) + { + // We really need to find a way of showing statistics... no progress here + $sql = 'SELECT COUNT(topic_id) as num_topics + FROM ' . TOPICS_TABLE . ' + WHERE forum_id = ' . $forum_id . ' + AND topic_id BETWEEN ' . $start . ' AND ' . $end; + $result = $db->sql_query($sql); + $topics_done = request_var('topics_done', 0) + (int) $db->sql_fetchfield('num_topics'); + $db->sql_freeresult($result); + + $start += $batch_size; + + $url = $this->u_action . "&parent_id={$this->parent_id}&f=$forum_id&action=sync&start=$start&topics_done=$topics_done&total={$row['forum_topics_real']}"; + + meta_refresh(0, $url); + + $template->assign_vars(array( + 'U_PROGRESS_BAR' => $this->u_action . "&action=progress_bar&start=$topics_done&total={$row['forum_topics_real']}", + 'UA_PROGRESS_BAR' => addslashes($this->u_action . "&action=progress_bar&start=$topics_done&total={$row['forum_topics_real']}"), + 'S_CONTINUE_SYNC' => true, + 'L_PROGRESS_EXPLAIN' => sprintf($user->lang['SYNC_IN_PROGRESS_EXPLAIN'], $topics_done, $row['forum_topics_real'])) + ); + + return; + } + } + + $url = $this->u_action . "&parent_id={$this->parent_id}&f=$forum_id&action=sync_forum"; + meta_refresh(0, $url); + + $template->assign_vars(array( + 'U_PROGRESS_BAR' => $this->u_action . '&action=progress_bar', + 'UA_PROGRESS_BAR' => addslashes($this->u_action . '&action=progress_bar'), + 'S_CONTINUE_SYNC' => true, + 'L_PROGRESS_EXPLAIN' => sprintf($user->lang['SYNC_IN_PROGRESS_EXPLAIN'], 0, $row['forum_topics_real'])) + ); + + return; + + break; + + case 'sync_forum': + + $sql = 'SELECT forum_name, forum_type + FROM ' . FORUMS_TABLE . " + WHERE forum_id = $forum_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + sync('forum', 'forum_id', $forum_id, false, true); + + add_log('admin', 'LOG_FORUM_SYNC', $row['forum_name']); + $cache->destroy('sql', FORUMS_TABLE); + + $template->assign_var('L_FORUM_RESYNCED', sprintf($user->lang['FORUM_RESYNCED'], $row['forum_name'])); + + break; + + case 'add': + case 'edit': + + if ($update) + { + $forum_data['forum_flags'] = 0; + $forum_data['forum_flags'] += (request_var('forum_link_track', false)) ? FORUM_FLAG_LINK_TRACK : 0; + $forum_data['forum_flags'] += (request_var('prune_old_polls', false)) ? FORUM_FLAG_PRUNE_POLL : 0; + $forum_data['forum_flags'] += (request_var('prune_announce', false)) ? FORUM_FLAG_PRUNE_ANNOUNCE : 0; + $forum_data['forum_flags'] += (request_var('prune_sticky', false)) ? FORUM_FLAG_PRUNE_STICKY : 0; + $forum_data['forum_flags'] += ($forum_data['show_active']) ? FORUM_FLAG_ACTIVE_TOPICS : 0; + $forum_data['forum_flags'] += (request_var('enable_post_review', true)) ? FORUM_FLAG_POST_REVIEW : 0; + $forum_data['forum_flags'] += (request_var('enable_quick_reply', false)) ? FORUM_FLAG_QUICK_REPLY : 0; + } + + // Show form to create/modify a forum + if ($action == 'edit') + { + $this->page_title = 'EDIT_FORUM'; + $row = $this->get_forum_info($forum_id); + $old_forum_type = $row['forum_type']; + + if (!$update) + { + $forum_data = $row; + } + else + { + $forum_data['left_id'] = $row['left_id']; + $forum_data['right_id'] = $row['right_id']; + } + + // Make sure no direct child forums are able to be selected as parents. + $exclude_forums = array(); + foreach (get_forum_branch($forum_id, 'children') as $row) + { + $exclude_forums[] = $row['forum_id']; + } + + $parents_list = make_forum_select($forum_data['parent_id'], $exclude_forums, false, false, false); + + $forum_data['forum_password_confirm'] = $forum_data['forum_password']; + } + else + { + $this->page_title = 'CREATE_FORUM'; + + $forum_id = $this->parent_id; + $parents_list = make_forum_select($this->parent_id, false, false, false, false); + + // Fill forum data with default values + if (!$update) + { + $forum_data = array( + 'parent_id' => $this->parent_id, + 'forum_type' => FORUM_POST, + 'forum_status' => ITEM_UNLOCKED, + 'forum_name' => utf8_normalize_nfc(request_var('forum_name', '', true)), + 'forum_link' => '', + 'forum_link_track' => false, + 'forum_desc' => '', + 'forum_rules' => '', + 'forum_rules_link' => '', + 'forum_image' => '', + 'forum_style' => 0, + 'display_subforum_list' => true, + 'display_on_index' => false, + 'forum_topics_per_page' => 0, + 'enable_indexing' => true, + 'enable_icons' => false, + 'enable_prune' => false, + 'prune_days' => 7, + 'prune_viewed' => 7, + 'prune_freq' => 1, + 'forum_flags' => FORUM_FLAG_POST_REVIEW + FORUM_FLAG_ACTIVE_TOPICS, + 'forum_options' => 0, + 'forum_password' => '', + 'forum_password_confirm'=> '', + ); + } + } + + $forum_rules_data = array( + 'text' => $forum_data['forum_rules'], + 'allow_bbcode' => true, + 'allow_smilies' => true, + 'allow_urls' => true + ); + + $forum_desc_data = array( + 'text' => $forum_data['forum_desc'], + 'allow_bbcode' => true, + 'allow_smilies' => true, + 'allow_urls' => true + ); + + $forum_rules_preview = ''; + + // Parse rules if specified + if ($forum_data['forum_rules']) + { + if (!isset($forum_data['forum_rules_uid'])) + { + // Before we are able to display the preview and plane text, we need to parse our request_var()'d value... + $forum_data['forum_rules_uid'] = ''; + $forum_data['forum_rules_bitfield'] = ''; + $forum_data['forum_rules_options'] = 0; + + generate_text_for_storage($forum_data['forum_rules'], $forum_data['forum_rules_uid'], $forum_data['forum_rules_bitfield'], $forum_data['forum_rules_options'], request_var('rules_allow_bbcode', false), request_var('rules_allow_urls', false), request_var('rules_allow_smilies', false)); + } + + // Generate preview content + $forum_rules_preview = generate_text_for_display($forum_data['forum_rules'], $forum_data['forum_rules_uid'], $forum_data['forum_rules_bitfield'], $forum_data['forum_rules_options']); + + // decode... + $forum_rules_data = generate_text_for_edit($forum_data['forum_rules'], $forum_data['forum_rules_uid'], $forum_data['forum_rules_options']); + } + + // Parse desciption if specified + if ($forum_data['forum_desc']) + { + if (!isset($forum_data['forum_desc_uid'])) + { + // Before we are able to display the preview and plane text, we need to parse our request_var()'d value... + $forum_data['forum_desc_uid'] = ''; + $forum_data['forum_desc_bitfield'] = ''; + $forum_data['forum_desc_options'] = 0; + + generate_text_for_storage($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options'], request_var('desc_allow_bbcode', false), request_var('desc_allow_urls', false), request_var('desc_allow_smilies', false)); + } + + // decode... + $forum_desc_data = generate_text_for_edit($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_options']); + } + + $forum_type_options = ''; + $forum_type_ary = array(FORUM_CAT => 'CAT', FORUM_POST => 'FORUM', FORUM_LINK => 'LINK'); + + foreach ($forum_type_ary as $value => $lang) + { + $forum_type_options .= '<option value="' . $value . '"' . (($value == $forum_data['forum_type']) ? ' selected="selected"' : '') . '>' . $user->lang['TYPE_' . $lang] . '</option>'; + } + + $styles_list = style_select($forum_data['forum_style'], true); + + $statuslist = '<option value="' . ITEM_UNLOCKED . '"' . (($forum_data['forum_status'] == ITEM_UNLOCKED) ? ' selected="selected"' : '') . '>' . $user->lang['UNLOCKED'] . '</option><option value="' . ITEM_LOCKED . '"' . (($forum_data['forum_status'] == ITEM_LOCKED) ? ' selected="selected"' : '') . '>' . $user->lang['LOCKED'] . '</option>'; + + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE . ' + WHERE forum_type = ' . FORUM_POST . " + AND forum_id <> $forum_id"; + $result = $db->sql_query_limit($sql, 1); + + $postable_forum_exists = false; + if ($db->sql_fetchrow($result)) + { + $postable_forum_exists = true; + } + $db->sql_freeresult($result); + + // Subforum move options + if ($action == 'edit' && $forum_data['forum_type'] == FORUM_CAT) + { + $subforums_id = array(); + $subforums = get_forum_branch($forum_id, 'children'); + + foreach ($subforums as $row) + { + $subforums_id[] = $row['forum_id']; + } + + $forums_list = make_forum_select($forum_data['parent_id'], $subforums_id); + + if ($postable_forum_exists) + { + $template->assign_vars(array( + 'S_MOVE_FORUM_OPTIONS' => make_forum_select($forum_data['parent_id'], $subforums_id)) // , false, true, false??? + ); + } + + $template->assign_vars(array( + 'S_HAS_SUBFORUMS' => ($forum_data['right_id'] - $forum_data['left_id'] > 1) ? true : false, + 'S_FORUMS_LIST' => $forums_list) + ); + } + else if ($postable_forum_exists) + { + $template->assign_vars(array( + 'S_MOVE_FORUM_OPTIONS' => make_forum_select($forum_data['parent_id'], $forum_id, false, true, false)) + ); + } + + $s_show_display_on_index = false; + + if ($forum_data['parent_id'] > 0) + { + // if this forum is a subforum put the "display on index" checkbox + if ($parent_info = $this->get_forum_info($forum_data['parent_id'])) + { + if ($parent_info['parent_id'] > 0 || $parent_info['forum_type'] == FORUM_CAT) + { + $s_show_display_on_index = true; + } + } + } + + if (strlen($forum_data['forum_password']) == 32) + { + $errors[] = $user->lang['FORUM_PASSWORD_OLD']; + } + + $template->assign_vars(array( + 'S_EDIT_FORUM' => true, + 'S_ERROR' => (sizeof($errors)) ? true : false, + 'S_PARENT_ID' => $this->parent_id, + 'S_FORUM_PARENT_ID' => $forum_data['parent_id'], + 'S_ADD_ACTION' => ($action == 'add') ? true : false, + + 'U_BACK' => $this->u_action . '&parent_id=' . $this->parent_id, + 'U_EDIT_ACTION' => $this->u_action . "&parent_id={$this->parent_id}&action=$action&f=$forum_id", + + 'L_COPY_PERMISSIONS_EXPLAIN' => $user->lang['COPY_PERMISSIONS_' . strtoupper($action) . '_EXPLAIN'], + 'L_TITLE' => $user->lang[$this->page_title], + 'ERROR_MSG' => (sizeof($errors)) ? implode('<br />', $errors) : '', + + 'FORUM_NAME' => $forum_data['forum_name'], + 'FORUM_DATA_LINK' => $forum_data['forum_link'], + 'FORUM_IMAGE' => $forum_data['forum_image'], + 'FORUM_IMAGE_SRC' => ($forum_data['forum_image']) ? $phpbb_root_path . $forum_data['forum_image'] : '', + 'FORUM_POST' => FORUM_POST, + 'FORUM_LINK' => FORUM_LINK, + 'FORUM_CAT' => FORUM_CAT, + 'PRUNE_FREQ' => $forum_data['prune_freq'], + 'PRUNE_DAYS' => $forum_data['prune_days'], + 'PRUNE_VIEWED' => $forum_data['prune_viewed'], + 'TOPICS_PER_PAGE' => $forum_data['forum_topics_per_page'], + 'FORUM_RULES_LINK' => $forum_data['forum_rules_link'], + 'FORUM_RULES' => $forum_data['forum_rules'], + 'FORUM_RULES_PREVIEW' => $forum_rules_preview, + 'FORUM_RULES_PLAIN' => $forum_rules_data['text'], + 'S_BBCODE_CHECKED' => ($forum_rules_data['allow_bbcode']) ? true : false, + 'S_SMILIES_CHECKED' => ($forum_rules_data['allow_smilies']) ? true : false, + 'S_URLS_CHECKED' => ($forum_rules_data['allow_urls']) ? true : false, + 'S_FORUM_PASSWORD_SET' => (empty($forum_data['forum_password'])) ? false : true, + + 'FORUM_DESC' => $forum_desc_data['text'], + 'S_DESC_BBCODE_CHECKED' => ($forum_desc_data['allow_bbcode']) ? true : false, + 'S_DESC_SMILIES_CHECKED' => ($forum_desc_data['allow_smilies']) ? true : false, + 'S_DESC_URLS_CHECKED' => ($forum_desc_data['allow_urls']) ? true : false, + + 'S_FORUM_TYPE_OPTIONS' => $forum_type_options, + 'S_STATUS_OPTIONS' => $statuslist, + 'S_PARENT_OPTIONS' => $parents_list, + 'S_STYLES_OPTIONS' => $styles_list, + 'S_FORUM_OPTIONS' => make_forum_select(($action == 'add') ? $forum_data['parent_id'] : false, ($action == 'edit') ? $forum_data['forum_id'] : false, false, false, false), + 'S_SHOW_DISPLAY_ON_INDEX' => $s_show_display_on_index, + 'S_FORUM_POST' => ($forum_data['forum_type'] == FORUM_POST) ? true : false, + 'S_FORUM_ORIG_POST' => (isset($old_forum_type) && $old_forum_type == FORUM_POST) ? true : false, + 'S_FORUM_ORIG_CAT' => (isset($old_forum_type) && $old_forum_type == FORUM_CAT) ? true : false, + 'S_FORUM_ORIG_LINK' => (isset($old_forum_type) && $old_forum_type == FORUM_LINK) ? true : false, + 'S_FORUM_LINK' => ($forum_data['forum_type'] == FORUM_LINK) ? true : false, + 'S_FORUM_CAT' => ($forum_data['forum_type'] == FORUM_CAT) ? true : false, + 'S_ENABLE_INDEXING' => ($forum_data['enable_indexing']) ? true : false, + 'S_TOPIC_ICONS' => ($forum_data['enable_icons']) ? true : false, + 'S_DISPLAY_SUBFORUM_LIST' => ($forum_data['display_subforum_list']) ? true : false, + 'S_DISPLAY_ON_INDEX' => ($forum_data['display_on_index']) ? true : false, + 'S_PRUNE_ENABLE' => ($forum_data['enable_prune']) ? true : false, + 'S_FORUM_LINK_TRACK' => ($forum_data['forum_flags'] & FORUM_FLAG_LINK_TRACK) ? true : false, + 'S_PRUNE_OLD_POLLS' => ($forum_data['forum_flags'] & FORUM_FLAG_PRUNE_POLL) ? true : false, + 'S_PRUNE_ANNOUNCE' => ($forum_data['forum_flags'] & FORUM_FLAG_PRUNE_ANNOUNCE) ? true : false, + 'S_PRUNE_STICKY' => ($forum_data['forum_flags'] & FORUM_FLAG_PRUNE_STICKY) ? true : false, + 'S_DISPLAY_ACTIVE_TOPICS' => ($forum_data['forum_flags'] & FORUM_FLAG_ACTIVE_TOPICS) ? true : false, + 'S_ENABLE_POST_REVIEW' => ($forum_data['forum_flags'] & FORUM_FLAG_POST_REVIEW) ? true : false, + 'S_ENABLE_QUICK_REPLY' => ($forum_data['forum_flags'] & FORUM_FLAG_QUICK_REPLY) ? true : false, + 'S_CAN_COPY_PERMISSIONS' => ($action != 'edit' || empty($forum_id) || ($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth'))) ? true : false, + )); + + return; + + break; + + case 'delete': + + if (!$forum_id) + { + trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + $forum_data = $this->get_forum_info($forum_id); + + $subforums_id = array(); + $subforums = get_forum_branch($forum_id, 'children'); + + foreach ($subforums as $row) + { + $subforums_id[] = $row['forum_id']; + } + + $forums_list = make_forum_select($forum_data['parent_id'], $subforums_id); + + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE . ' + WHERE forum_type = ' . FORUM_POST . " + AND forum_id <> $forum_id"; + $result = $db->sql_query_limit($sql, 1); + + if ($db->sql_fetchrow($result)) + { + $template->assign_vars(array( + 'S_MOVE_FORUM_OPTIONS' => make_forum_select($forum_data['parent_id'], $subforums_id, false, true)) // , false, true, false??? + ); + } + $db->sql_freeresult($result); + + $parent_id = ($this->parent_id == $forum_id) ? 0 : $this->parent_id; + + $template->assign_vars(array( + 'S_DELETE_FORUM' => true, + 'U_ACTION' => $this->u_action . "&parent_id={$parent_id}&action=delete&f=$forum_id", + 'U_BACK' => $this->u_action . '&parent_id=' . $this->parent_id, + + 'FORUM_NAME' => $forum_data['forum_name'], + 'S_FORUM_POST' => ($forum_data['forum_type'] == FORUM_POST) ? true : false, + 'S_FORUM_LINK' => ($forum_data['forum_type'] == FORUM_LINK) ? true : false, + 'S_HAS_SUBFORUMS' => ($forum_data['right_id'] - $forum_data['left_id'] > 1) ? true : false, + 'S_FORUMS_LIST' => $forums_list, + 'S_ERROR' => (sizeof($errors)) ? true : false, + 'ERROR_MSG' => (sizeof($errors)) ? implode('<br />', $errors) : '') + ); + + return; + break; + + case 'copy_perm': + $forum_perm_from = request_var('forum_perm_from', 0); + + // Copy permissions? + if (!empty($forum_perm_from) && $forum_perm_from != $forum_id) + { + copy_forum_permissions($forum_perm_from, $forum_id, true); + cache_moderators(); + $auth->acl_clear_prefetch(); + $cache->destroy('sql', FORUMS_TABLE); + + $acl_url = '&mode=setting_forum_local&forum_id[]=' . $forum_id; + + $message = $user->lang['FORUM_UPDATED']; + + // Redirect to permissions + if ($auth->acl_get('a_fauth')) + { + $message .= '<br /><br />' . sprintf($user->lang['REDIRECT_ACL'], '<a href="' . append_sid("{$phpbb_admin_path}index.$phpEx", 'i=permissions' . $acl_url) . '">', '</a>'); + } + + trigger_error($message . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); + } + + break; + } + + // Default management page + if (!$this->parent_id) + { + $navigation = $user->lang['FORUM_INDEX']; + } + else + { + $navigation = '<a href="' . $this->u_action . '">' . $user->lang['FORUM_INDEX'] . '</a>'; + + $forums_nav = get_forum_branch($this->parent_id, 'parents', 'descending'); + foreach ($forums_nav as $row) + { + if ($row['forum_id'] == $this->parent_id) + { + $navigation .= ' -> ' . $row['forum_name']; + } + else + { + $navigation .= ' -> <a href="' . $this->u_action . '&parent_id=' . $row['forum_id'] . '">' . $row['forum_name'] . '</a>'; + } + } + } + + // Jumpbox + $forum_box = make_forum_select($this->parent_id, false, false, false, false); //make_forum_select($this->parent_id); + + if ($action == 'sync' || $action == 'sync_forum') + { + $template->assign_var('S_RESYNCED', true); + } + + $sql = 'SELECT * + FROM ' . FORUMS_TABLE . " + WHERE parent_id = $this->parent_id + ORDER BY left_id"; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + do + { + $forum_type = $row['forum_type']; + + if ($row['forum_status'] == ITEM_LOCKED) + { + $folder_image = '<img src="images/icon_folder_lock.gif" alt="' . $user->lang['LOCKED'] . '" />'; + } + else + { + switch ($forum_type) + { + case FORUM_LINK: + $folder_image = '<img src="images/icon_folder_link.gif" alt="' . $user->lang['LINK'] . '" />'; + break; + + default: + $folder_image = ($row['left_id'] + 1 != $row['right_id']) ? '<img src="images/icon_subfolder.gif" alt="' . $user->lang['SUBFORUM'] . '" />' : '<img src="images/icon_folder.gif" alt="' . $user->lang['FOLDER'] . '" />'; + break; + } + } + + $url = $this->u_action . "&parent_id=$this->parent_id&f={$row['forum_id']}"; + + $template->assign_block_vars('forums', array( + 'FOLDER_IMAGE' => $folder_image, + 'FORUM_IMAGE' => ($row['forum_image']) ? '<img src="' . $phpbb_root_path . $row['forum_image'] . '" alt="" />' : '', + 'FORUM_IMAGE_SRC' => ($row['forum_image']) ? $phpbb_root_path . $row['forum_image'] : '', + 'FORUM_NAME' => $row['forum_name'], + 'FORUM_DESCRIPTION' => generate_text_for_display($row['forum_desc'], $row['forum_desc_uid'], $row['forum_desc_bitfield'], $row['forum_desc_options']), + 'FORUM_TOPICS' => $row['forum_topics'], + 'FORUM_POSTS' => $row['forum_posts'], + + 'S_FORUM_LINK' => ($forum_type == FORUM_LINK) ? true : false, + 'S_FORUM_POST' => ($forum_type == FORUM_POST) ? true : false, + + 'U_FORUM' => $this->u_action . '&parent_id=' . $row['forum_id'], + 'U_MOVE_UP' => $url . '&action=move_up', + 'U_MOVE_DOWN' => $url . '&action=move_down', + 'U_EDIT' => $url . '&action=edit', + 'U_DELETE' => $url . '&action=delete', + 'U_SYNC' => $url . '&action=sync') + ); + } + while ($row = $db->sql_fetchrow($result)); + } + else if ($this->parent_id) + { + $row = $this->get_forum_info($this->parent_id); + + $url = $this->u_action . '&parent_id=' . $this->parent_id . '&f=' . $row['forum_id']; + + $template->assign_vars(array( + 'S_NO_FORUMS' => true, + + 'U_EDIT' => $url . '&action=edit', + 'U_DELETE' => $url . '&action=delete', + 'U_SYNC' => $url . '&action=sync') + ); + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'ERROR_MSG' => (sizeof($errors)) ? implode('<br />', $errors) : '', + 'NAVIGATION' => $navigation, + 'FORUM_BOX' => $forum_box, + 'U_SEL_ACTION' => $this->u_action, + 'U_ACTION' => $this->u_action . '&parent_id=' . $this->parent_id, + + 'U_PROGRESS_BAR' => $this->u_action . '&action=progress_bar', + 'UA_PROGRESS_BAR' => addslashes($this->u_action . '&action=progress_bar'), + )); + } + + /** + * Get forum details + */ + function get_forum_info($forum_id) + { + global $db; + + $sql = 'SELECT * + FROM ' . FORUMS_TABLE . " + WHERE forum_id = $forum_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error("Forum #$forum_id does not exist", E_USER_ERROR); + } + + return $row; + } + + /** + * Update forum data + */ + function update_forum_data(&$forum_data) + { + global $db, $user, $cache, $phpbb_root_path; + + $errors = array(); + + if (!$forum_data['forum_name']) + { + $errors[] = $user->lang['FORUM_NAME_EMPTY']; + } + + if (utf8_strlen($forum_data['forum_desc']) > 4000) + { + $errors[] = $user->lang['FORUM_DESC_TOO_LONG']; + } + + if (utf8_strlen($forum_data['forum_rules']) > 4000) + { + $errors[] = $user->lang['FORUM_RULES_TOO_LONG']; + } + + if ($forum_data['forum_password'] || $forum_data['forum_password_confirm']) + { + if ($forum_data['forum_password'] != $forum_data['forum_password_confirm']) + { + $forum_data['forum_password'] = $forum_data['forum_password_confirm'] = ''; + $errors[] = $user->lang['FORUM_PASSWORD_MISMATCH']; + } + } + + if ($forum_data['prune_days'] < 0 || $forum_data['prune_viewed'] < 0 || $forum_data['prune_freq'] < 0) + { + $forum_data['prune_days'] = $forum_data['prune_viewed'] = $forum_data['prune_freq'] = 0; + $errors[] = $user->lang['FORUM_DATA_NEGATIVE']; + } + + $range_test_ary = array( + array('lang' => 'FORUM_TOPICS_PAGE', 'value' => $forum_data['forum_topics_per_page'], 'column_type' => 'TINT:0'), + ); + + if (!empty($forum_data['forum_image']) && !file_exists($phpbb_root_path . $forum_data['forum_image'])) + { + $errors[] = $user->lang['FORUM_IMAGE_NO_EXIST']; + } + + validate_range($range_test_ary, $errors); + + // Set forum flags + // 1 = link tracking + // 2 = prune old polls + // 4 = prune announcements + // 8 = prune stickies + // 16 = show active topics + // 32 = enable post review + $forum_data['forum_flags'] = 0; + $forum_data['forum_flags'] += ($forum_data['forum_link_track']) ? FORUM_FLAG_LINK_TRACK : 0; + $forum_data['forum_flags'] += ($forum_data['prune_old_polls']) ? FORUM_FLAG_PRUNE_POLL : 0; + $forum_data['forum_flags'] += ($forum_data['prune_announce']) ? FORUM_FLAG_PRUNE_ANNOUNCE : 0; + $forum_data['forum_flags'] += ($forum_data['prune_sticky']) ? FORUM_FLAG_PRUNE_STICKY : 0; + $forum_data['forum_flags'] += ($forum_data['show_active']) ? FORUM_FLAG_ACTIVE_TOPICS : 0; + $forum_data['forum_flags'] += ($forum_data['enable_post_review']) ? FORUM_FLAG_POST_REVIEW : 0; + $forum_data['forum_flags'] += ($forum_data['enable_quick_reply']) ? FORUM_FLAG_QUICK_REPLY : 0; + + // Unset data that are not database fields + $forum_data_sql = $forum_data; + + unset($forum_data_sql['forum_link_track']); + unset($forum_data_sql['prune_old_polls']); + unset($forum_data_sql['prune_announce']); + unset($forum_data_sql['prune_sticky']); + unset($forum_data_sql['show_active']); + unset($forum_data_sql['enable_post_review']); + unset($forum_data_sql['enable_quick_reply']); + unset($forum_data_sql['forum_password_confirm']); + + // What are we going to do tonight Brain? The same thing we do everynight, + // try to take over the world ... or decide whether to continue update + // and if so, whether it's a new forum/cat/link or an existing one + if (sizeof($errors)) + { + return $errors; + } + + // As we don't know the old password, it's kinda tricky to detect changes + if ($forum_data_sql['forum_password_unset']) + { + $forum_data_sql['forum_password'] = ''; + } + else if (empty($forum_data_sql['forum_password'])) + { + unset($forum_data_sql['forum_password']); + } + else + { + $forum_data_sql['forum_password'] = phpbb_hash($forum_data_sql['forum_password']); + } + unset($forum_data_sql['forum_password_unset']); + + if (!isset($forum_data_sql['forum_id'])) + { + // no forum_id means we're creating a new forum + unset($forum_data_sql['type_action']); + + if ($forum_data_sql['parent_id']) + { + $sql = 'SELECT left_id, right_id, forum_type + FROM ' . FORUMS_TABLE . ' + WHERE forum_id = ' . $forum_data_sql['parent_id']; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error($user->lang['PARENT_NOT_EXIST'] . adm_back_link($this->u_action . '&' . $this->parent_id), E_USER_WARNING); + } + + if ($row['forum_type'] == FORUM_LINK) + { + $errors[] = $user->lang['PARENT_IS_LINK_FORUM']; + return $errors; + } + + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET left_id = left_id + 2, right_id = right_id + 2 + WHERE left_id > ' . $row['right_id']; + $db->sql_query($sql); + + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET right_id = right_id + 2 + WHERE ' . $row['left_id'] . ' BETWEEN left_id AND right_id'; + $db->sql_query($sql); + + $forum_data_sql['left_id'] = $row['right_id']; + $forum_data_sql['right_id'] = $row['right_id'] + 1; + } + else + { + $sql = 'SELECT MAX(right_id) AS right_id + FROM ' . FORUMS_TABLE; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $forum_data_sql['left_id'] = $row['right_id'] + 1; + $forum_data_sql['right_id'] = $row['right_id'] + 2; + } + + $sql = 'INSERT INTO ' . FORUMS_TABLE . ' ' . $db->sql_build_array('INSERT', $forum_data_sql); + $db->sql_query($sql); + + $forum_data['forum_id'] = $db->sql_nextid(); + + add_log('admin', 'LOG_FORUM_ADD', $forum_data['forum_name']); + } + else + { + $row = $this->get_forum_info($forum_data_sql['forum_id']); + + if ($row['forum_type'] == FORUM_POST && $row['forum_type'] != $forum_data_sql['forum_type']) + { + // Has subforums and want to change into a link? + if ($row['right_id'] - $row['left_id'] > 1 && $forum_data_sql['forum_type'] == FORUM_LINK) + { + $errors[] = $user->lang['FORUM_WITH_SUBFORUMS_NOT_TO_LINK']; + return $errors; + } + + // we're turning a postable forum into a non-postable forum + if ($forum_data_sql['type_action'] == 'move') + { + $to_forum_id = request_var('to_forum_id', 0); + + if ($to_forum_id) + { + $errors = $this->move_forum_content($forum_data_sql['forum_id'], $to_forum_id); + } + else + { + return array($user->lang['NO_DESTINATION_FORUM']); + } + } + else if ($forum_data_sql['type_action'] == 'delete') + { + $errors = $this->delete_forum_content($forum_data_sql['forum_id']); + } + else + { + return array($user->lang['NO_FORUM_ACTION']); + } + + $forum_data_sql['forum_posts'] = $forum_data_sql['forum_topics'] = $forum_data_sql['forum_topics_real'] = $forum_data_sql['forum_last_post_id'] = $forum_data_sql['forum_last_poster_id'] = $forum_data_sql['forum_last_post_time'] = 0; + $forum_data_sql['forum_last_poster_name'] = $forum_data_sql['forum_last_poster_colour'] = ''; + } + else if ($row['forum_type'] == FORUM_CAT && $forum_data_sql['forum_type'] == FORUM_LINK) + { + // Has subforums? + if ($row['right_id'] - $row['left_id'] > 1) + { + // We are turning a category into a link - but need to decide what to do with the subforums. + $action_subforums = request_var('action_subforums', ''); + $subforums_to_id = request_var('subforums_to_id', 0); + + if ($action_subforums == 'delete') + { + $rows = get_forum_branch($row['forum_id'], 'children', 'descending', false); + + foreach ($rows as $_row) + { + // Do not remove the forum id we are about to change. ;) + if ($_row['forum_id'] == $row['forum_id']) + { + continue; + } + + $forum_ids[] = $_row['forum_id']; + $errors = array_merge($errors, $this->delete_forum_content($_row['forum_id'])); + } + + if (sizeof($errors)) + { + return $errors; + } + + if (sizeof($forum_ids)) + { + $sql = 'DELETE FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_ids); + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_ids); + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_USERS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_ids); + $db->sql_query($sql); + + // Delete forum ids from extension groups table + $sql = 'SELECT group_id, allowed_forums + FROM ' . EXTENSION_GROUPS_TABLE; + $result = $db->sql_query($sql); + + while ($_row = $db->sql_fetchrow($result)) + { + if (!$_row['allowed_forums']) + { + continue; + } + + $allowed_forums = unserialize(trim($_row['allowed_forums'])); + $allowed_forums = array_diff($allowed_forums, $forum_ids); + + $sql = 'UPDATE ' . EXTENSION_GROUPS_TABLE . " + SET allowed_forums = '" . ((sizeof($allowed_forums)) ? serialize($allowed_forums) : '') . "' + WHERE group_id = {$_row['group_id']}"; + $db->sql_query($sql); + } + $db->sql_freeresult($result); + + $cache->destroy('_extensions'); + } + } + else if ($action_subforums == 'move') + { + if (!$subforums_to_id) + { + return array($user->lang['NO_DESTINATION_FORUM']); + } + + $sql = 'SELECT forum_name + FROM ' . FORUMS_TABLE . ' + WHERE forum_id = ' . $subforums_to_id; + $result = $db->sql_query($sql); + $_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$_row) + { + return array($user->lang['NO_FORUM']); + } + + $subforums_to_name = $_row['forum_name']; + + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE . " + WHERE parent_id = {$row['forum_id']}"; + $result = $db->sql_query($sql); + + while ($_row = $db->sql_fetchrow($result)) + { + $this->move_forum($_row['forum_id'], $subforums_to_id); + } + $db->sql_freeresult($result); + + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET parent_id = $subforums_to_id + WHERE parent_id = {$row['forum_id']}"; + $db->sql_query($sql); + } + + // Adjust the left/right id + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET right_id = left_id + 1 + WHERE forum_id = ' . $row['forum_id']; + $db->sql_query($sql); + } + } + else if ($row['forum_type'] == FORUM_CAT && $forum_data_sql['forum_type'] == FORUM_POST) + { + // Changing a category to a forum? Reset the data (you can't post directly in a cat, you must use a forum) + $forum_data_sql['forum_posts'] = 0; + $forum_data_sql['forum_topics'] = 0; + $forum_data_sql['forum_topics_real'] = 0; + $forum_data_sql['forum_last_post_id'] = 0; + $forum_data_sql['forum_last_post_subject'] = ''; + $forum_data_sql['forum_last_post_time'] = 0; + $forum_data_sql['forum_last_poster_id'] = 0; + $forum_data_sql['forum_last_poster_name'] = ''; + $forum_data_sql['forum_last_poster_colour'] = ''; + } + + if (sizeof($errors)) + { + return $errors; + } + + if ($row['parent_id'] != $forum_data_sql['parent_id']) + { + if ($row['forum_id'] != $forum_data_sql['parent_id']) + { + $errors = $this->move_forum($forum_data_sql['forum_id'], $forum_data_sql['parent_id']); + } + else + { + $forum_data_sql['parent_id'] = $row['parent_id']; + } + } + + if (sizeof($errors)) + { + return $errors; + } + + unset($forum_data_sql['type_action']); + + if ($row['forum_name'] != $forum_data_sql['forum_name']) + { + // the forum name has changed, clear the parents list of all forums (for safety) + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET forum_parents = ''"; + $db->sql_query($sql); + } + + // Setting the forum id to the forum id is not really received well by some dbs. ;) + $forum_id = $forum_data_sql['forum_id']; + unset($forum_data_sql['forum_id']); + + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $forum_data_sql) . ' + WHERE forum_id = ' . $forum_id; + $db->sql_query($sql); + + // Add it back + $forum_data['forum_id'] = $forum_id; + + add_log('admin', 'LOG_FORUM_EDIT', $forum_data['forum_name']); + } + + return $errors; + } + + /** + * Move forum + */ + function move_forum($from_id, $to_id) + { + global $db, $user; + + $to_data = $moved_ids = $errors = array(); + + // Check if we want to move to a parent with link type + if ($to_id > 0) + { + $to_data = $this->get_forum_info($to_id); + + if ($to_data['forum_type'] == FORUM_LINK) + { + $errors[] = $user->lang['PARENT_IS_LINK_FORUM']; + return $errors; + } + } + + $moved_forums = get_forum_branch($from_id, 'children', 'descending'); + $from_data = $moved_forums[0]; + $diff = sizeof($moved_forums) * 2; + + $moved_ids = array(); + for ($i = 0; $i < sizeof($moved_forums); ++$i) + { + $moved_ids[] = $moved_forums[$i]['forum_id']; + } + + // Resync parents + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET right_id = right_id - $diff, forum_parents = '' + WHERE left_id < " . $from_data['right_id'] . " + AND right_id > " . $from_data['right_id']; + $db->sql_query($sql); + + // Resync righthand side of tree + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET left_id = left_id - $diff, right_id = right_id - $diff, forum_parents = '' + WHERE left_id > " . $from_data['right_id']; + $db->sql_query($sql); + + if ($to_id > 0) + { + // Retrieve $to_data again, it may have been changed... + $to_data = $this->get_forum_info($to_id); + + // Resync new parents + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET right_id = right_id + $diff, forum_parents = '' + WHERE " . $to_data['right_id'] . ' BETWEEN left_id AND right_id + AND ' . $db->sql_in_set('forum_id', $moved_ids, true); + $db->sql_query($sql); + + // Resync the righthand side of the tree + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET left_id = left_id + $diff, right_id = right_id + $diff, forum_parents = '' + WHERE left_id > " . $to_data['right_id'] . ' + AND ' . $db->sql_in_set('forum_id', $moved_ids, true); + $db->sql_query($sql); + + // Resync moved branch + $to_data['right_id'] += $diff; + + if ($to_data['right_id'] > $from_data['right_id']) + { + $diff = '+ ' . ($to_data['right_id'] - $from_data['right_id'] - 1); + } + else + { + $diff = '- ' . abs($to_data['right_id'] - $from_data['right_id'] - 1); + } + } + else + { + $sql = 'SELECT MAX(right_id) AS right_id + FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $moved_ids, true); + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $diff = '+ ' . ($row['right_id'] - $from_data['left_id'] + 1); + } + + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET left_id = left_id $diff, right_id = right_id $diff, forum_parents = '' + WHERE " . $db->sql_in_set('forum_id', $moved_ids); + $db->sql_query($sql); + + return $errors; + } + + /** + * Move forum content from one to another forum + */ + function move_forum_content($from_id, $to_id, $sync = true) + { + global $db; + + $table_ary = array(LOG_TABLE, POSTS_TABLE, TOPICS_TABLE, DRAFTS_TABLE, TOPICS_TRACK_TABLE); + + foreach ($table_ary as $table) + { + $sql = "UPDATE $table + SET forum_id = $to_id + WHERE forum_id = $from_id"; + $db->sql_query($sql); + } + unset($table_ary); + + $table_ary = array(FORUMS_ACCESS_TABLE, FORUMS_TRACK_TABLE, FORUMS_WATCH_TABLE, MODERATOR_CACHE_TABLE); + + foreach ($table_ary as $table) + { + $sql = "DELETE FROM $table + WHERE forum_id = $from_id"; + $db->sql_query($sql); + } + + if ($sync) + { + // Delete ghost topics that link back to the same forum then resync counters + sync('topic_moved'); + sync('forum', 'forum_id', $to_id, false, true); + } + + return array(); + } + + /** + * Remove complete forum + */ + function delete_forum($forum_id, $action_posts = 'delete', $action_subforums = 'delete', $posts_to_id = 0, $subforums_to_id = 0) + { + global $db, $user, $cache; + + $forum_data = $this->get_forum_info($forum_id); + + $errors = array(); + $log_action_posts = $log_action_forums = $posts_to_name = $subforums_to_name = ''; + $forum_ids = array($forum_id); + + if ($action_posts == 'delete') + { + $log_action_posts = 'POSTS'; + $errors = array_merge($errors, $this->delete_forum_content($forum_id)); + } + else if ($action_posts == 'move') + { + if (!$posts_to_id) + { + $errors[] = $user->lang['NO_DESTINATION_FORUM']; + } + else + { + $log_action_posts = 'MOVE_POSTS'; + + $sql = 'SELECT forum_name + FROM ' . FORUMS_TABLE . ' + WHERE forum_id = ' . $posts_to_id; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + $errors[] = $user->lang['NO_FORUM']; + } + else + { + $posts_to_name = $row['forum_name']; + $errors = array_merge($errors, $this->move_forum_content($forum_id, $posts_to_id)); + } + } + } + + if (sizeof($errors)) + { + return $errors; + } + + if ($action_subforums == 'delete') + { + $log_action_forums = 'FORUMS'; + $rows = get_forum_branch($forum_id, 'children', 'descending', false); + + foreach ($rows as $row) + { + $forum_ids[] = $row['forum_id']; + $errors = array_merge($errors, $this->delete_forum_content($row['forum_id'])); + } + + if (sizeof($errors)) + { + return $errors; + } + + $diff = sizeof($forum_ids) * 2; + + $sql = 'DELETE FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_ids); + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_ids); + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_USERS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_ids); + $db->sql_query($sql); + } + else if ($action_subforums == 'move') + { + if (!$subforums_to_id) + { + $errors[] = $user->lang['NO_DESTINATION_FORUM']; + } + else + { + $log_action_forums = 'MOVE_FORUMS'; + + $sql = 'SELECT forum_name + FROM ' . FORUMS_TABLE . ' + WHERE forum_id = ' . $subforums_to_id; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + $errors[] = $user->lang['NO_FORUM']; + } + else + { + $subforums_to_name = $row['forum_name']; + + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE . " + WHERE parent_id = $forum_id"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $this->move_forum($row['forum_id'], $subforums_to_id); + } + $db->sql_freeresult($result); + + // Grab new forum data for correct tree updating later + $forum_data = $this->get_forum_info($forum_id); + + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET parent_id = $subforums_to_id + WHERE parent_id = $forum_id"; + $db->sql_query($sql); + + $diff = 2; + $sql = 'DELETE FROM ' . FORUMS_TABLE . " + WHERE forum_id = $forum_id"; + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . " + WHERE forum_id = $forum_id"; + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_USERS_TABLE . " + WHERE forum_id = $forum_id"; + $db->sql_query($sql); + } + } + + if (sizeof($errors)) + { + return $errors; + } + } + else + { + $diff = 2; + $sql = 'DELETE FROM ' . FORUMS_TABLE . " + WHERE forum_id = $forum_id"; + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . " + WHERE forum_id = $forum_id"; + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_USERS_TABLE . " + WHERE forum_id = $forum_id"; + $db->sql_query($sql); + } + + // Resync tree + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET right_id = right_id - $diff + WHERE left_id < {$forum_data['right_id']} AND right_id > {$forum_data['right_id']}"; + $db->sql_query($sql); + + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET left_id = left_id - $diff, right_id = right_id - $diff + WHERE left_id > {$forum_data['right_id']}"; + $db->sql_query($sql); + + // Delete forum ids from extension groups table + $sql = 'SELECT group_id, allowed_forums + FROM ' . EXTENSION_GROUPS_TABLE; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if (!$row['allowed_forums']) + { + continue; + } + + $allowed_forums = unserialize(trim($row['allowed_forums'])); + $allowed_forums = array_diff($allowed_forums, $forum_ids); + + $sql = 'UPDATE ' . EXTENSION_GROUPS_TABLE . " + SET allowed_forums = '" . ((sizeof($allowed_forums)) ? serialize($allowed_forums) : '') . "' + WHERE group_id = {$row['group_id']}"; + $db->sql_query($sql); + } + $db->sql_freeresult($result); + + $cache->destroy('_extensions'); + + $log_action = implode('_', array($log_action_posts, $log_action_forums)); + + switch ($log_action) + { + case 'MOVE_POSTS_MOVE_FORUMS': + add_log('admin', 'LOG_FORUM_DEL_MOVE_POSTS_MOVE_FORUMS', $posts_to_name, $subforums_to_name, $forum_data['forum_name']); + break; + + case 'MOVE_POSTS_FORUMS': + add_log('admin', 'LOG_FORUM_DEL_MOVE_POSTS_FORUMS', $posts_to_name, $forum_data['forum_name']); + break; + + case 'POSTS_MOVE_FORUMS': + add_log('admin', 'LOG_FORUM_DEL_POSTS_MOVE_FORUMS', $subforums_to_name, $forum_data['forum_name']); + break; + + case '_MOVE_FORUMS': + add_log('admin', 'LOG_FORUM_DEL_MOVE_FORUMS', $subforums_to_name, $forum_data['forum_name']); + break; + + case 'MOVE_POSTS_': + add_log('admin', 'LOG_FORUM_DEL_MOVE_POSTS', $posts_to_name, $forum_data['forum_name']); + break; + + case 'POSTS_FORUMS': + add_log('admin', 'LOG_FORUM_DEL_POSTS_FORUMS', $forum_data['forum_name']); + break; + + case '_FORUMS': + add_log('admin', 'LOG_FORUM_DEL_FORUMS', $forum_data['forum_name']); + break; + + case 'POSTS_': + add_log('admin', 'LOG_FORUM_DEL_POSTS', $forum_data['forum_name']); + break; + + default: + add_log('admin', 'LOG_FORUM_DEL_FORUM', $forum_data['forum_name']); + break; + } + + return $errors; + } + + /** + * Delete forum content + */ + function delete_forum_content($forum_id) + { + global $db, $config, $phpbb_root_path, $phpEx; + + include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); + + $db->sql_transaction('begin'); + + // Select then delete all attachments + $sql = 'SELECT a.topic_id + FROM ' . POSTS_TABLE . ' p, ' . ATTACHMENTS_TABLE . " a + WHERE p.forum_id = $forum_id + AND a.in_message = 0 + AND a.topic_id = p.topic_id"; + $result = $db->sql_query($sql); + + $topic_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $topic_ids[] = $row['topic_id']; + } + $db->sql_freeresult($result); + + delete_attachments('topic', $topic_ids, false); + + // Before we remove anything we make sure we are able to adjust the post counts later. ;) + $sql = 'SELECT poster_id + FROM ' . POSTS_TABLE . ' + WHERE forum_id = ' . $forum_id . ' + AND post_postcount = 1 + AND post_approved = 1'; + $result = $db->sql_query($sql); + + $post_counts = array(); + while ($row = $db->sql_fetchrow($result)) + { + $post_counts[$row['poster_id']] = (!empty($post_counts[$row['poster_id']])) ? $post_counts[$row['poster_id']] + 1 : 1; + } + $db->sql_freeresult($result); + + switch ($db->sql_layer) + { + case 'mysql4': + case 'mysqli': + + // Delete everything else and thank MySQL for offering multi-table deletion + $tables_ary = array( + SEARCH_WORDMATCH_TABLE => 'post_id', + REPORTS_TABLE => 'post_id', + WARNINGS_TABLE => 'post_id', + BOOKMARKS_TABLE => 'topic_id', + TOPICS_WATCH_TABLE => 'topic_id', + TOPICS_POSTED_TABLE => 'topic_id', + POLL_OPTIONS_TABLE => 'topic_id', + POLL_VOTES_TABLE => 'topic_id', + ); + + $sql = 'DELETE ' . POSTS_TABLE; + $sql_using = "\nFROM " . POSTS_TABLE; + $sql_where = "\nWHERE " . POSTS_TABLE . ".forum_id = $forum_id\n"; + + foreach ($tables_ary as $table => $field) + { + $sql .= ", $table "; + $sql_using .= ", $table "; + $sql_where .= "\nAND $table.$field = " . POSTS_TABLE . ".$field"; + } + + $db->sql_query($sql . $sql_using . $sql_where); + + break; + + default: + + // Delete everything else and curse your DB for not offering multi-table deletion + $tables_ary = array( + 'post_id' => array( + SEARCH_WORDMATCH_TABLE, + REPORTS_TABLE, + WARNINGS_TABLE, + ), + + 'topic_id' => array( + BOOKMARKS_TABLE, + TOPICS_WATCH_TABLE, + TOPICS_POSTED_TABLE, + POLL_OPTIONS_TABLE, + POLL_VOTES_TABLE, + ) + ); + + foreach ($tables_ary as $field => $tables) + { + $start = 0; + + do + { + $sql = "SELECT $field + FROM " . POSTS_TABLE . ' + WHERE forum_id = ' . $forum_id; + $result = $db->sql_query_limit($sql, 500, $start); + + $ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $ids[] = $row[$field]; + } + $db->sql_freeresult($result); + + if (sizeof($ids)) + { + $start += sizeof($ids); + + foreach ($tables as $table) + { + $db->sql_query("DELETE FROM $table WHERE " . $db->sql_in_set($field, $ids)); + } + } + } + while ($row); + } + unset($ids); + + break; + } + + $table_ary = array(FORUMS_ACCESS_TABLE, FORUMS_TRACK_TABLE, FORUMS_WATCH_TABLE, LOG_TABLE, MODERATOR_CACHE_TABLE, POSTS_TABLE, TOPICS_TABLE, TOPICS_TRACK_TABLE); + + foreach ($table_ary as $table) + { + $db->sql_query("DELETE FROM $table WHERE forum_id = $forum_id"); + } + + // Set forum ids to 0 + $table_ary = array(DRAFTS_TABLE); + + foreach ($table_ary as $table) + { + $db->sql_query("UPDATE $table SET forum_id = 0 WHERE forum_id = $forum_id"); + } + + // Adjust users post counts + if (sizeof($post_counts)) + { + foreach ($post_counts as $poster_id => $substract) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_posts = 0 + WHERE user_id = ' . $poster_id . ' + AND user_posts < ' . $substract; + $db->sql_query($sql); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_posts = user_posts - ' . $substract . ' + WHERE user_id = ' . $poster_id . ' + AND user_posts >= ' . $substract; + $db->sql_query($sql); + } + } + + $db->sql_transaction('commit'); + + // Make sure the overall post/topic count is correct... + $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(attach_id) as stat + FROM ' . ATTACHMENTS_TABLE; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + set_config('num_files', (int) $row['stat'], true); + + $sql = 'SELECT SUM(filesize) as stat + FROM ' . ATTACHMENTS_TABLE; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + set_config('upload_dir_size', (float) $row['stat'], true); + + return array(); + } + + /** + * Move forum position by $steps up/down + */ + function move_forum_by($forum_row, $action = 'move_up', $steps = 1) + { + global $db; + + /** + * Fetch all the siblings between the module's current spot + * and where we want to move it to. If there are less than $steps + * siblings between the current spot and the target then the + * module will move as far as possible + */ + $sql = 'SELECT forum_id, forum_name, left_id, right_id + FROM ' . FORUMS_TABLE . " + WHERE parent_id = {$forum_row['parent_id']} + AND " . (($action == 'move_up') ? "right_id < {$forum_row['right_id']} ORDER BY right_id DESC" : "left_id > {$forum_row['left_id']} ORDER BY left_id ASC"); + $result = $db->sql_query_limit($sql, $steps); + + $target = array(); + while ($row = $db->sql_fetchrow($result)) + { + $target = $row; + } + $db->sql_freeresult($result); + + if (!sizeof($target)) + { + // The forum is already on top or bottom + return false; + } + + /** + * $left_id and $right_id define the scope of the nodes that are affected by the move. + * $diff_up and $diff_down are the values to substract or add to each node's left_id + * and right_id in order to move them up or down. + * $move_up_left and $move_up_right define the scope of the nodes that are moving + * up. Other nodes in the scope of ($left_id, $right_id) are considered to move down. + */ + if ($action == 'move_up') + { + $left_id = $target['left_id']; + $right_id = $forum_row['right_id']; + + $diff_up = $forum_row['left_id'] - $target['left_id']; + $diff_down = $forum_row['right_id'] + 1 - $forum_row['left_id']; + + $move_up_left = $forum_row['left_id']; + $move_up_right = $forum_row['right_id']; + } + else + { + $left_id = $forum_row['left_id']; + $right_id = $target['right_id']; + + $diff_up = $forum_row['right_id'] + 1 - $forum_row['left_id']; + $diff_down = $target['right_id'] - $forum_row['right_id']; + + $move_up_left = $forum_row['right_id'] + 1; + $move_up_right = $target['right_id']; + } + + // Now do the dirty job + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET left_id = left_id + CASE + WHEN left_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up} + ELSE {$diff_down} + END, + right_id = right_id + CASE + WHEN right_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up} + ELSE {$diff_down} + END, + forum_parents = '' + WHERE + left_id BETWEEN {$left_id} AND {$right_id} + AND right_id BETWEEN {$left_id} AND {$right_id}"; + $db->sql_query($sql); + + return $target['forum_name']; + } + + /** + * Display progress bar for syncinc forums + */ + function display_progress_bar($start, $total) + { + global $template, $user; + + adm_page_header($user->lang['SYNC_IN_PROGRESS']); + + $template->set_filenames(array( + 'body' => 'progress_bar.html') + ); + + $template->assign_vars(array( + 'L_PROGRESS' => $user->lang['SYNC_IN_PROGRESS'], + 'L_PROGRESS_EXPLAIN' => ($start && $total) ? sprintf($user->lang['SYNC_IN_PROGRESS_EXPLAIN'], $start, $total) : $user->lang['SYNC_IN_PROGRESS']) + ); + + adm_page_footer(); + } + + /** + * Display copy permission page + * Not used at the moment - we will have a look at it for 3.0.7 + */ + function copy_permission_page($forum_data) + { + global $phpEx, $phpbb_admin_path, $template, $user; + + $acl_url = '&mode=setting_forum_local&forum_id[]=' . $forum_data['forum_id']; + $action = append_sid($this->u_action . "&parent_id={$this->parent_id}&f={$forum_data['forum_id']}&action=copy_perm"); + + $l_acl = sprintf($user->lang['COPY_TO_ACL'], '<a href="' . append_sid("{$phpbb_admin_path}index.$phpEx", 'i=permissions' . $acl_url) . '">', '</a>'); + + $this->tpl_name = 'acp_forums_copy_perm'; + + $template->assign_vars(array( + 'U_ACL' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=permissions' . $acl_url), + 'L_ACL_LINK' => $l_acl, + 'L_BACK_LINK' => adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), + 'S_COPY_ACTION' => $action, + 'S_FORUM_OPTIONS' => make_forum_select($forum_data['parent_id'], $forum_data['forum_id'], false, false, false), + )); + } + +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_groups.php b/phpBB/includes/acp/acp_groups.php new file mode 100644 index 0000000000..3df61ff4e2 --- /dev/null +++ b/phpBB/includes/acp/acp_groups.php @@ -0,0 +1,789 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_groups +{ + var $u_action; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $cache; + global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix, $file_uploads; + + $user->add_lang('acp/groups'); + $this->tpl_name = 'acp_groups'; + $this->page_title = 'ACP_GROUPS_MANAGE'; + + $form_key = 'acp_groups'; + add_form_key($form_key); + + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + + // Check and set some common vars + $action = (isset($_POST['add'])) ? 'add' : ((isset($_POST['addusers'])) ? 'addusers' : request_var('action', '')); + $group_id = request_var('g', 0); + $mark_ary = request_var('mark', array(0)); + $name_ary = request_var('usernames', '', true); + $leader = request_var('leader', 0); + $default = request_var('default', 0); + $start = request_var('start', 0); + $update = (isset($_POST['update'])) ? true : false; + + + // Clear some vars + $can_upload = (file_exists($phpbb_root_path . $config['avatar_path']) && @is_writable($phpbb_root_path . $config['avatar_path']) && $file_uploads) ? true : false; + $group_row = array(); + + // Grab basic data for group, if group_id is set and exists + if ($group_id) + { + $sql = 'SELECT * + FROM ' . GROUPS_TABLE . " + WHERE group_id = $group_id"; + $result = $db->sql_query($sql); + $group_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$group_row) + { + trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Check if the user is allowed to manage this group if set to founder only. + if ($user->data['user_type'] != USER_FOUNDER && $group_row['group_founder_manage']) + { + trigger_error($user->lang['NOT_ALLOWED_MANAGE_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + + // Which page? + switch ($action) + { + case 'approve': + case 'demote': + case 'promote': + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Approve, demote or promote + $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + $error = group_user_attributes($action, $group_id, $mark_ary, false, $group_name); + + if (!$error) + { + switch ($action) + { + case 'demote': + $message = 'GROUP_MODS_DEMOTED'; + break; + + case 'promote': + $message = 'GROUP_MODS_PROMOTED'; + break; + + case 'approve': + $message = 'USERS_APPROVED'; + break; + } + + trigger_error($user->lang[$message] . adm_back_link($this->u_action . '&action=list&g=' . $group_id)); + } + else + { + trigger_error($user->lang[$error] . adm_back_link($this->u_action . '&action=list&g=' . $group_id), E_USER_WARNING); + } + + break; + + case 'default': + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (confirm_box(true)) + { + $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + + if (!sizeof($mark_ary)) + { + $start = 0; + + do + { + $sql = 'SELECT user_id + FROM ' . USER_GROUP_TABLE . " + WHERE group_id = $group_id + ORDER BY user_id"; + $result = $db->sql_query_limit($sql, 200, $start); + + $mark_ary = array(); + if ($row = $db->sql_fetchrow($result)) + { + do + { + $mark_ary[] = $row['user_id']; + } + while ($row = $db->sql_fetchrow($result)); + + group_user_attributes('default', $group_id, $mark_ary, false, $group_name, $group_row); + + $start = (sizeof($mark_ary) < 200) ? 0 : $start + 200; + } + else + { + $start = 0; + } + $db->sql_freeresult($result); + } + while ($start); + } + else + { + group_user_attributes('default', $group_id, $mark_ary, false, $group_name, $group_row); + } + + trigger_error($user->lang['GROUP_DEFS_UPDATED'] . adm_back_link($this->u_action . '&action=list&g=' . $group_id)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'mark' => $mark_ary, + 'g' => $group_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action)) + ); + } + + break; + + case 'deleteusers': + case 'delete': + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING); + } + else if ($action === 'delete' && $group_row['group_type'] == GROUP_SPECIAL) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (confirm_box(true)) + { + $error = ''; + + switch ($action) + { + case 'delete': + if (!$auth->acl_get('a_groupdel')) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $error = group_delete($group_id, $group_row['group_name']); + break; + + case 'deleteusers': + $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + $error = group_user_del($group_id, $mark_ary, false, $group_name); + break; + } + + $back_link = ($action == 'delete') ? $this->u_action : $this->u_action . '&action=list&g=' . $group_id; + + if ($error) + { + trigger_error($user->lang[$error] . adm_back_link($back_link), E_USER_WARNING); + } + + $message = ($action == 'delete') ? 'GROUP_DELETED' : 'GROUP_USERS_REMOVE'; + trigger_error($user->lang[$message] . adm_back_link($back_link)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'mark' => $mark_ary, + 'g' => $group_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action)) + ); + } + break; + + case 'addusers': + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (!$name_ary) + { + trigger_error($user->lang['NO_USERS'] . adm_back_link($this->u_action . '&action=list&g=' . $group_id), E_USER_WARNING); + } + + $name_ary = array_unique(explode("\n", $name_ary)); + $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + + // Add user/s to group + if ($error = group_user_add($group_id, false, $name_ary, $group_name, $default, $leader, 0, $group_row)) + { + trigger_error($user->lang[$error] . adm_back_link($this->u_action . '&action=list&g=' . $group_id), E_USER_WARNING); + } + + $message = ($leader) ? 'GROUP_MODS_ADDED' : 'GROUP_USERS_ADDED'; + trigger_error($user->lang[$message] . adm_back_link($this->u_action . '&action=list&g=' . $group_id)); + break; + + case 'edit': + case 'add': + + include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + + $data = $submit_ary = array(); + + if ($action == 'edit' && !$group_id) + { + trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if ($action == 'add' && !$auth->acl_get('a_groupadd')) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $error = array(); + $user->add_lang('ucp'); + + $avatar_select = basename(request_var('avatar_select', '')); + $category = basename(request_var('category', '')); + + // Did we submit? + if ($update) + { + if (!check_form_key($form_key)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $group_name = utf8_normalize_nfc(request_var('group_name', '', true)); + $group_desc = utf8_normalize_nfc(request_var('group_desc', '', true)); + $group_type = request_var('group_type', GROUP_FREE); + + $allow_desc_bbcode = request_var('desc_parse_bbcode', false); + $allow_desc_urls = request_var('desc_parse_urls', false); + $allow_desc_smilies = request_var('desc_parse_smilies', false); + + $data['uploadurl'] = request_var('uploadurl', ''); + $data['remotelink'] = request_var('remotelink', ''); + $data['width'] = request_var('width', ''); + $data['height'] = request_var('height', ''); + $delete = request_var('delete', ''); + + $submit_ary = array( + 'colour' => request_var('group_colour', ''), + 'rank' => request_var('group_rank', 0), + 'receive_pm' => isset($_REQUEST['group_receive_pm']) ? 1 : 0, + 'legend' => isset($_REQUEST['group_legend']) ? 1 : 0, + 'message_limit' => request_var('group_message_limit', 0), + 'max_recipients' => request_var('group_max_recipients', 0), + 'founder_manage' => 0, + 'skip_auth' => request_var('group_skip_auth', 0), + ); + + if ($user->data['user_type'] == USER_FOUNDER) + { + $submit_ary['founder_manage'] = isset($_REQUEST['group_founder_manage']) ? 1 : 0; + } + + if (!empty($_FILES['uploadfile']['tmp_name']) || $data['uploadurl'] || $data['remotelink']) + { + // Avatar stuff + $var_ary = 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 (!($error = validate_data($data, $var_ary))) + { + $data['user_id'] = "g$group_id"; + + if ((!empty($_FILES['uploadfile']['tmp_name']) || $data['uploadurl']) && $can_upload) + { + list($submit_ary['avatar_type'], $submit_ary['avatar'], $submit_ary['avatar_width'], $submit_ary['avatar_height']) = avatar_upload($data, $error); + } + else if ($data['remotelink']) + { + list($submit_ary['avatar_type'], $submit_ary['avatar'], $submit_ary['avatar_width'], $submit_ary['avatar_height']) = avatar_remote($data, $error); + } + } + } + else if ($avatar_select && $config['allow_avatar_local']) + { + // check avatar gallery + if (is_dir($phpbb_root_path . $config['avatar_gallery_path'] . '/' . $category)) + { + $submit_ary['avatar_type'] = AVATAR_GALLERY; + + list($submit_ary['avatar_width'], $submit_ary['avatar_height']) = getimagesize($phpbb_root_path . $config['avatar_gallery_path'] . '/' . $category . '/' . $avatar_select); + $submit_ary['avatar'] = $category . '/' . $avatar_select; + } + } + else if ($delete) + { + $submit_ary['avatar'] = ''; + $submit_ary['avatar_type'] = $submit_ary['avatar_width'] = $submit_ary['avatar_height'] = 0; + } + else if ($data['width'] && $data['height']) + { + // Only update the dimensions? + if ($config['avatar_max_width'] || $config['avatar_max_height']) + { + if ($data['width'] > $config['avatar_max_width'] || $data['height'] > $config['avatar_max_height']) + { + $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $data['width'], $data['height']); + } + } + + if (!sizeof($error)) + { + if ($config['avatar_min_width'] || $config['avatar_min_height']) + { + if ($data['width'] < $config['avatar_min_width'] || $data['height'] < $config['avatar_min_height']) + { + $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $data['width'], $data['height']); + } + } + } + + if (!sizeof($error)) + { + $submit_ary['avatar_width'] = $data['width']; + $submit_ary['avatar_height'] = $data['height']; + } + } + + if ((isset($submit_ary['avatar']) && $submit_ary['avatar'] && (!isset($group_row['group_avatar']))) || $delete) + { + if (isset($group_row['group_avatar']) && $group_row['group_avatar']) + { + avatar_delete('group', $group_row, true); + } + } + + if (!sizeof($error)) + { + // Only set the rank, colour, etc. if it's changed or if we're adding a new + // group. This prevents existing group members being updated if no changes + // were made. + + $group_attributes = array(); + $test_variables = array( + 'rank' => 'int', + 'colour' => 'string', + 'avatar' => 'string', + 'avatar_type' => 'int', + 'avatar_width' => 'int', + 'avatar_height' => 'int', + 'receive_pm' => 'int', + 'legend' => 'int', + 'message_limit' => 'int', + 'max_recipients'=> 'int', + 'founder_manage'=> 'int', + 'skip_auth' => 'int', + ); + + foreach ($test_variables as $test => $type) + { + if (isset($submit_ary[$test]) && ($action == 'add' || $group_row['group_' . $test] != $submit_ary[$test])) + { + settype($submit_ary[$test], $type); + $group_attributes['group_' . $test] = $group_row['group_' . $test] = $submit_ary[$test]; + } + } + + if (!($error = group_create($group_id, $group_type, $group_name, $group_desc, $group_attributes, $allow_desc_bbcode, $allow_desc_urls, $allow_desc_smilies))) + { + $group_perm_from = request_var('group_perm_from', 0); + + // Copy permissions? + // If the user has the a_authgroups permission and at least one additional permission ability set the permissions are fully transferred. + // We do not limit on one auth category because this can lead to incomplete permissions being tricky to fix for the admin, roles being assigned or added non-default permissions. + // Since the user only has the option to copy permissions from non leader managed groups this seems to be a good compromise. + if ($group_perm_from && $action == 'add' && $auth->acl_get('a_authgroups') && $auth->acl_gets('a_aauth', 'a_fauth', 'a_mauth', 'a_uauth')) + { + $sql = 'SELECT group_founder_manage + FROM ' . GROUPS_TABLE . ' + WHERE group_id = ' . $group_perm_from; + $result = $db->sql_query($sql); + $check_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + // Check the group if non-founder + if ($check_row && ($user->data['user_type'] == USER_FOUNDER || $check_row['group_founder_manage'] == 0)) + { + // From the mysql documentation: + // Prior to MySQL 4.0.14, the target table of the INSERT statement cannot appear in the FROM clause of the SELECT part of the query. This limitation is lifted in 4.0.14. + // Due to this we stay on the safe side if we do the insertion "the manual way" + + // Copy permisisons from/to the acl groups table (only group_id gets changed) + $sql = 'SELECT forum_id, auth_option_id, auth_role_id, auth_setting + FROM ' . ACL_GROUPS_TABLE . ' + WHERE group_id = ' . $group_perm_from; + $result = $db->sql_query($sql); + + $groups_sql_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $groups_sql_ary[] = array( + 'group_id' => (int) $group_id, + 'forum_id' => (int) $row['forum_id'], + 'auth_option_id' => (int) $row['auth_option_id'], + 'auth_role_id' => (int) $row['auth_role_id'], + 'auth_setting' => (int) $row['auth_setting'] + ); + } + $db->sql_freeresult($result); + + // Now insert the data + $db->sql_multi_insert(ACL_GROUPS_TABLE, $groups_sql_ary); + + $auth->acl_clear_prefetch(); + } + } + + $cache->destroy('sql', GROUPS_TABLE); + + $message = ($action == 'edit') ? 'GROUP_UPDATED' : 'GROUP_CREATED'; + trigger_error($user->lang[$message] . adm_back_link($this->u_action)); + } + } + + if (sizeof($error)) + { + $group_rank = $submit_ary['rank']; + + $group_desc_data = array( + 'text' => $group_desc, + 'allow_bbcode' => $allow_desc_bbcode, + 'allow_smilies' => $allow_desc_smilies, + 'allow_urls' => $allow_desc_urls + ); + } + } + else if (!$group_id) + { + $group_name = utf8_normalize_nfc(request_var('group_name', '', true)); + $group_desc_data = array( + 'text' => '', + 'allow_bbcode' => true, + 'allow_smilies' => true, + 'allow_urls' => true + ); + $group_rank = 0; + $group_type = GROUP_OPEN; + } + else + { + $group_name = $group_row['group_name']; + $group_desc_data = generate_text_for_edit($group_row['group_desc'], $group_row['group_desc_uid'], $group_row['group_desc_options']); + $group_type = $group_row['group_type']; + $group_rank = $group_row['group_rank']; + } + + $sql = 'SELECT * + FROM ' . RANKS_TABLE . ' + WHERE rank_special = 1 + ORDER BY rank_title'; + $result = $db->sql_query($sql); + + $rank_options = '<option value="0"' . ((!$group_rank) ? ' selected="selected"' : '') . '>' . $user->lang['USER_DEFAULT'] . '</option>'; + + while ($row = $db->sql_fetchrow($result)) + { + $selected = ($group_rank && $row['rank_id'] == $group_rank) ? ' selected="selected"' : ''; + $rank_options .= '<option value="' . $row['rank_id'] . '"' . $selected . '>' . $row['rank_title'] . '</option>'; + } + $db->sql_freeresult($result); + + $type_free = ($group_type == GROUP_FREE) ? ' checked="checked"' : ''; + $type_open = ($group_type == GROUP_OPEN) ? ' checked="checked"' : ''; + $type_closed = ($group_type == GROUP_CLOSED) ? ' checked="checked"' : ''; + $type_hidden = ($group_type == GROUP_HIDDEN) ? ' checked="checked"' : ''; + + $avatar_img = (!empty($group_row['group_avatar'])) ? get_user_avatar($group_row['group_avatar'], $group_row['group_avatar_type'], $group_row['group_avatar_width'], $group_row['group_avatar_height'], 'GROUP_AVATAR') : '<img src="' . $phpbb_admin_path . 'images/no_avatar.gif" alt="" />'; + + $display_gallery = (isset($_POST['display_gallery'])) ? true : false; + + if ($config['allow_avatar_local'] && $display_gallery) + { + avatar_gallery($category, $avatar_select, 4); + } + + $back_link = request_var('back_link', ''); + + switch ($back_link) + { + case 'acp_users_groups': + $u_back = append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&mode=groups&u=' . request_var('u', 0)); + break; + + default: + $u_back = $this->u_action; + break; + } + + $template->assign_vars(array( + 'S_EDIT' => true, + 'S_ADD_GROUP' => ($action == 'add') ? true : false, + 'S_GROUP_PERM' => ($action == 'add' && $auth->acl_get('a_authgroups') && $auth->acl_gets('a_aauth', 'a_fauth', 'a_mauth', 'a_uauth')) ? true : false, + 'S_INCLUDE_SWATCH' => true, + 'S_CAN_UPLOAD' => $can_upload, + 'S_ERROR' => (sizeof($error)) ? true : false, + 'S_SPECIAL_GROUP' => ($group_type == GROUP_SPECIAL) ? true : false, + 'S_DISPLAY_GALLERY' => ($config['allow_avatar_local'] && !$display_gallery) ? true : false, + 'S_IN_GALLERY' => ($config['allow_avatar_local'] && $display_gallery) ? true : false, + 'S_USER_FOUNDER' => ($user->data['user_type'] == USER_FOUNDER) ? true : false, + + 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + 'GROUP_NAME' => ($group_type == GROUP_SPECIAL) ? $user->lang['G_' . $group_name] : $group_name, + 'GROUP_INTERNAL_NAME' => $group_name, + 'GROUP_DESC' => $group_desc_data['text'], + 'GROUP_RECEIVE_PM' => (isset($group_row['group_receive_pm']) && $group_row['group_receive_pm']) ? ' checked="checked"' : '', + 'GROUP_FOUNDER_MANAGE' => (isset($group_row['group_founder_manage']) && $group_row['group_founder_manage']) ? ' checked="checked"' : '', + 'GROUP_LEGEND' => (isset($group_row['group_legend']) && $group_row['group_legend']) ? ' checked="checked"' : '', + 'GROUP_MESSAGE_LIMIT' => (isset($group_row['group_message_limit'])) ? $group_row['group_message_limit'] : 0, + 'GROUP_MAX_RECIPIENTS' => (isset($group_row['group_max_recipients'])) ? $group_row['group_max_recipients'] : 0, + 'GROUP_COLOUR' => (isset($group_row['group_colour'])) ? $group_row['group_colour'] : '', + 'GROUP_SKIP_AUTH' => (!empty($group_row['group_skip_auth'])) ? ' checked="checked"' : '', + + 'S_DESC_BBCODE_CHECKED' => $group_desc_data['allow_bbcode'], + 'S_DESC_URLS_CHECKED' => $group_desc_data['allow_urls'], + 'S_DESC_SMILIES_CHECKED'=> $group_desc_data['allow_smilies'], + + 'S_RANK_OPTIONS' => $rank_options, + 'S_GROUP_OPTIONS' => group_select_options(false, false, (($user->data['user_type'] == USER_FOUNDER) ? false : 0)), + 'AVATAR' => $avatar_img, + 'AVATAR_IMAGE' => $avatar_img, + 'AVATAR_MAX_FILESIZE' => $config['avatar_filesize'], + 'AVATAR_WIDTH' => (isset($group_row['group_avatar_width'])) ? $group_row['group_avatar_width'] : '', + 'AVATAR_HEIGHT' => (isset($group_row['group_avatar_height'])) ? $group_row['group_avatar_height'] : '', + + 'GROUP_TYPE_FREE' => GROUP_FREE, + 'GROUP_TYPE_OPEN' => GROUP_OPEN, + 'GROUP_TYPE_CLOSED' => GROUP_CLOSED, + 'GROUP_TYPE_HIDDEN' => GROUP_HIDDEN, + 'GROUP_TYPE_SPECIAL' => GROUP_SPECIAL, + + 'GROUP_FREE' => $type_free, + 'GROUP_OPEN' => $type_open, + 'GROUP_CLOSED' => $type_closed, + 'GROUP_HIDDEN' => $type_hidden, + + 'U_BACK' => $u_back, + 'U_SWATCH' => append_sid("{$phpbb_admin_path}swatch.$phpEx", 'form=settings&name=group_colour'), + 'U_ACTION' => "{$this->u_action}&action=$action&g=$group_id", + 'L_AVATAR_EXPLAIN' => sprintf($user->lang['AVATAR_EXPLAIN'], $config['avatar_max_width'], $config['avatar_max_height'], round($config['avatar_filesize'] / 1024)), + )); + + return; + break; + + case 'list': + + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $this->page_title = 'GROUP_MEMBERS'; + + // Grab the leaders - always, on every page... + $sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_regdate, u.user_colour, u.user_posts, u.group_id, ug.group_leader, ug.user_pending + FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . " ug + WHERE ug.group_id = $group_id + AND u.user_id = ug.user_id + AND ug.group_leader = 1 + ORDER BY ug.group_leader DESC, ug.user_pending ASC, u.username_clean"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $template->assign_block_vars('leader', array( + 'U_USER_EDIT' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=users&action=edit&u={$row['user_id']}"), + + 'USERNAME' => $row['username'], + 'USERNAME_COLOUR' => $row['user_colour'], + 'S_GROUP_DEFAULT' => ($row['group_id'] == $group_id) ? true : false, + 'JOINED' => ($row['user_regdate']) ? $user->format_date($row['user_regdate']) : ' - ', + 'USER_POSTS' => $row['user_posts'], + 'USER_ID' => $row['user_id'], + )); + } + $db->sql_freeresult($result); + + // Total number of group members (non-leaders) + $sql = 'SELECT COUNT(user_id) AS total_members + FROM ' . USER_GROUP_TABLE . " + WHERE group_id = $group_id + AND group_leader = 0"; + $result = $db->sql_query($sql); + $total_members = (int) $db->sql_fetchfield('total_members'); + $db->sql_freeresult($result); + + $s_action_options = ''; + $options = array('default' => 'DEFAULT', 'approve' => 'APPROVE', 'demote' => 'DEMOTE', 'promote' => 'PROMOTE', 'deleteusers' => 'DELETE'); + + foreach ($options as $option => $lang) + { + $s_action_options .= '<option value="' . $option . '">' . $user->lang['GROUP_' . $lang] . '</option>'; + } + + $template->assign_vars(array( + 'S_LIST' => true, + 'S_GROUP_SPECIAL' => ($group_row['group_type'] == GROUP_SPECIAL) ? true : false, + 'S_ACTION_OPTIONS' => $s_action_options, + + 'S_ON_PAGE' => on_page($total_members, $config['topics_per_page'], $start), + 'PAGINATION' => generate_pagination($this->u_action . "&action=$action&g=$group_id", $total_members, $config['topics_per_page'], $start, true), + 'GROUP_NAME' => ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'], + + 'U_ACTION' => $this->u_action . "&g=$group_id", + 'U_BACK' => $this->u_action, + 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=list&field=usernames'), + 'U_DEFAULT_ALL' => "{$this->u_action}&action=default&g=$group_id", + )); + + // Grab the members + $sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_colour, u.user_regdate, u.user_posts, u.group_id, ug.group_leader, ug.user_pending + FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . " ug + WHERE ug.group_id = $group_id + AND u.user_id = ug.user_id + AND ug.group_leader = 0 + ORDER BY ug.group_leader DESC, ug.user_pending ASC, u.username_clean"; + $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); + + $pending = false; + + while ($row = $db->sql_fetchrow($result)) + { + if ($row['user_pending'] && !$pending) + { + $template->assign_block_vars('member', array( + 'S_PENDING' => true) + ); + + $pending = true; + } + + $template->assign_block_vars('member', array( + 'U_USER_EDIT' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=users&action=edit&u={$row['user_id']}"), + + 'USERNAME' => $row['username'], + 'USERNAME_COLOUR' => $row['user_colour'], + 'S_GROUP_DEFAULT' => ($row['group_id'] == $group_id) ? true : false, + 'JOINED' => ($row['user_regdate']) ? $user->format_date($row['user_regdate']) : ' - ', + 'USER_POSTS' => $row['user_posts'], + 'USER_ID' => $row['user_id']) + ); + } + $db->sql_freeresult($result); + + return; + break; + } + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action, + 'S_GROUP_ADD' => ($auth->acl_get('a_groupadd')) ? true : false) + ); + + // Get us all the groups + $sql = 'SELECT g.group_id, g.group_name, g.group_type + FROM ' . GROUPS_TABLE . ' g + ORDER BY g.group_type ASC, g.group_name'; + $result = $db->sql_query($sql); + + $lookup = $cached_group_data = array(); + while ($row = $db->sql_fetchrow($result)) + { + $type = ($row['group_type'] == GROUP_SPECIAL) ? 'special' : 'normal'; + + // used to determine what type a group is + $lookup[$row['group_id']] = $type; + + // used for easy access to the data within a group + $cached_group_data[$type][$row['group_id']] = $row; + $cached_group_data[$type][$row['group_id']]['total_members'] = 0; + } + $db->sql_freeresult($result); + + // How many people are in which group? + $sql = 'SELECT COUNT(ug.user_id) AS total_members, ug.group_id + FROM ' . USER_GROUP_TABLE . ' ug + WHERE ' . $db->sql_in_set('ug.group_id', array_keys($lookup)) . ' + GROUP BY ug.group_id'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $type = $lookup[$row['group_id']]; + $cached_group_data[$type][$row['group_id']]['total_members'] = $row['total_members']; + } + $db->sql_freeresult($result); + + // The order is... normal, then special + ksort($cached_group_data); + + foreach ($cached_group_data as $type => $row_ary) + { + if ($type == 'special') + { + $template->assign_block_vars('groups', array( + 'S_SPECIAL' => true) + ); + } + + foreach ($row_ary as $group_id => $row) + { + $group_name = (!empty($user->lang['G_' . $row['group_name']]))? $user->lang['G_' . $row['group_name']] : $row['group_name']; + + $template->assign_block_vars('groups', array( + 'U_LIST' => "{$this->u_action}&action=list&g=$group_id", + 'U_EDIT' => "{$this->u_action}&action=edit&g=$group_id", + 'U_DELETE' => ($auth->acl_get('a_groupdel')) ? "{$this->u_action}&action=delete&g=$group_id" : '', + + 'S_GROUP_SPECIAL' => ($row['group_type'] == GROUP_SPECIAL) ? true : false, + + 'GROUP_NAME' => $group_name, + 'TOTAL_MEMBERS' => $row['total_members'], + )); + } + } + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_icons.php b/phpBB/includes/acp/acp_icons.php new file mode 100644 index 0000000000..8213c55ccb --- /dev/null +++ b/phpBB/includes/acp/acp_icons.php @@ -0,0 +1,946 @@ +<?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; +} + +/** +* @todo [smilies] check regular expressions for special char replacements (stored specialchared in db) +* @package acp +*/ +class acp_icons +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + $user->add_lang('acp/posting'); + + // Set up general vars + $action = request_var('action', ''); + $action = (isset($_POST['add'])) ? 'add' : $action; + $action = (isset($_POST['edit'])) ? 'edit' : $action; + $action = (isset($_POST['import'])) ? 'import' : $action; + $icon_id = request_var('id', 0); + + $mode = ($mode == 'smilies') ? 'smilies' : 'icons'; + + $this->tpl_name = 'acp_icons'; + + // What are we working on? + switch ($mode) + { + case 'smilies': + $table = SMILIES_TABLE; + $lang = 'SMILIES'; + $fields = 'smiley'; + $img_path = $config['smilies_path']; + break; + + case 'icons': + $table = ICONS_TABLE; + $lang = 'ICONS'; + $fields = 'icons'; + $img_path = $config['icons_path']; + break; + } + + $this->page_title = 'ACP_' . $lang; + + // Clear some arrays + $_images = $_paks = array(); + $notice = ''; + + // Grab file list of paks and images + if ($action == 'edit' || $action == 'add' || $action == 'import') + { + $imglist = filelist($phpbb_root_path . $img_path, ''); + + foreach ($imglist as $path => $img_ary) + { + if (empty($img_ary)) + { + continue; + } + + asort($img_ary, SORT_STRING); + + foreach ($img_ary as $img) + { + $img_size = getimagesize($phpbb_root_path . $img_path . '/' . $path . $img); + + if (!$img_size[0] || !$img_size[1] || strlen($img) > 255) + { + continue; + } + + // adjust the width and height to be lower than 128px while perserving the aspect ratio + if ($img_size[0] > 127 && $img_size[0] > $img_size[1]) + { + $img_size[1] = (int) ($img_size[1] * (127 / $img_size[0])); + $img_size[0] = 127; + } + else if ($img_size[1] > 127) + { + $img_size[0] = (int) ($img_size[0] * (127 / $img_size[1])); + $img_size[1] = 127; + } + + $_images[$path . $img]['file'] = $path . $img; + $_images[$path . $img]['width'] = $img_size[0]; + $_images[$path . $img]['height'] = $img_size[1]; + } + } + unset($imglist); + + if ($dir = @opendir($phpbb_root_path . $img_path)) + { + while (($file = readdir($dir)) !== false) + { + if (is_file($phpbb_root_path . $img_path . '/' . $file) && preg_match('#\.pak$#i', $file)) + { + $_paks[] = $file; + } + } + closedir($dir); + + if (!empty($_paks)) + { + asort($_paks, SORT_STRING); + } + } + } + + // What shall we do today? Oops, I believe that's trademarked ... + switch ($action) + { + case 'edit': + unset($_images); + $_images = array(); + + // no break; + + case 'add': + + $smilies = $default_row = array(); + $smiley_options = $order_list = $add_order_list = ''; + + if ($action == 'add' && $mode == 'smilies') + { + $sql = 'SELECT * + FROM ' . SMILIES_TABLE . ' + ORDER BY smiley_order'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if (empty($smilies[$row['smiley_url']])) + { + $smilies[$row['smiley_url']] = $row; + } + } + $db->sql_freeresult($result); + + if (sizeof($smilies)) + { + foreach ($smilies as $row) + { + $selected = false; + + if (!$smiley_options) + { + $selected = true; + $default_row = $row; + } + $smiley_options .= '<option value="' . $row['smiley_url'] . '"' . (($selected) ? ' selected="selected"' : '') . '>' . $row['smiley_url'] . '</option>'; + + $template->assign_block_vars('smile', array( + 'SMILEY_URL' => addslashes($row['smiley_url']), + 'CODE' => addslashes($row['code']), + 'EMOTION' => addslashes($row['emotion']), + 'WIDTH' => $row['smiley_width'], + 'HEIGHT' => $row['smiley_height'], + 'ORDER' => $row['smiley_order'] + 1, + )); + } + } + } + + $sql = "SELECT * + FROM $table + ORDER BY {$fields}_order " . (($icon_id || $action == 'add') ? 'DESC' : 'ASC'); + $result = $db->sql_query($sql); + + $data = array(); + $after = false; + $display = 0; + $order_lists = array('', ''); + $add_order_lists = array('', ''); + $display_count = 0; + + while ($row = $db->sql_fetchrow($result)) + { + if ($action == 'add') + { + unset($_images[$row[$fields . '_url']]); + } + + + if ($row[$fields . '_id'] == $icon_id) + { + $after = true; + $display = $row['display_on_posting']; + $data[$row[$fields . '_url']] = $row; + } + else + { + if ($action == 'edit' && !$icon_id) + { + $data[$row[$fields . '_url']] = $row; + } + + $selected = ''; + if (!empty($after)) + { + $selected = ' selected="selected"'; + $after = false; + } + if ($row['display_on_posting']) + { + $display_count++; + } + $after_txt = ($mode == 'smilies') ? $row['code'] : $row['icons_url']; + $order_lists[$row['display_on_posting']] = '<option value="' . ($row[$fields . '_order'] + 1) . '"' . $selected . '>' . sprintf($user->lang['AFTER_' . $lang], ' -> ' . $after_txt) . '</option>' . $order_lists[$row['display_on_posting']]; + + if (!empty($default_row)) + { + $add_order_lists[$row['display_on_posting']] = '<option value="' . ($row[$fields . '_order'] + 1) . '"' . (($row[$fields . '_id'] == $default_row['smiley_id']) ? ' selected="selected"' : '') . '>' . sprintf($user->lang['AFTER_' . $lang], ' -> ' . $after_txt) . '</option>' . $add_order_lists[$row['display_on_posting']]; + } + } + } + $db->sql_freeresult($result); + + $order_list = '<option value="1"' . ((!isset($after)) ? ' selected="selected"' : '') . '>' . $user->lang['FIRST'] . '</option>'; + $add_order_list = '<option value="1">' . $user->lang['FIRST'] . '</option>'; + + if ($action == 'add') + { + $data = $_images; + } + + $colspan = (($mode == 'smilies') ? 7 : 5); + $colspan += ($icon_id) ? 1 : 0; + $colspan += ($action == 'add') ? 2 : 0; + + $template->assign_vars(array( + 'S_EDIT' => true, + 'S_SMILIES' => ($mode == 'smilies') ? true : false, + 'S_ADD' => ($action == 'add') ? true : false, + + 'S_ORDER_LIST_DISPLAY' => $order_list . $order_lists[1], + 'S_ORDER_LIST_UNDISPLAY' => $order_list . $order_lists[0], + 'S_ORDER_LIST_DISPLAY_COUNT' => $display_count + 1, + + 'L_TITLE' => $user->lang['ACP_' . $lang], + 'L_EXPLAIN' => $user->lang['ACP_' . $lang . '_EXPLAIN'], + 'L_CONFIG' => $user->lang[$lang . '_CONFIG'], + 'L_URL' => $user->lang[$lang . '_URL'], + 'L_LOCATION' => $user->lang[$lang . '_LOCATION'], + 'L_WIDTH' => $user->lang[$lang . '_WIDTH'], + 'L_HEIGHT' => $user->lang[$lang . '_HEIGHT'], + 'L_ORDER' => $user->lang[$lang . '_ORDER'], + 'L_NO_ICONS' => $user->lang['NO_' . $lang . '_' . strtoupper($action)], + + 'COLSPAN' => $colspan, + 'ID' => $icon_id, + + 'U_BACK' => $this->u_action, + 'U_ACTION' => $this->u_action . '&action=' . (($action == 'add') ? 'create' : 'modify'), + )); + + foreach ($data as $img => $img_row) + { + $template->assign_block_vars('items', array( + 'IMG' => $img, + 'A_IMG' => addslashes($img), + 'IMG_SRC' => $phpbb_root_path . $img_path . '/' . $img, + + 'CODE' => ($mode == 'smilies' && isset($img_row['code'])) ? $img_row['code'] : '', + 'EMOTION' => ($mode == 'smilies' && isset($img_row['emotion'])) ? $img_row['emotion'] : '', + + 'S_ID' => (isset($img_row[$fields . '_id'])) ? true : false, + 'ID' => (isset($img_row[$fields . '_id'])) ? $img_row[$fields . '_id'] : 0, + 'WIDTH' => (!empty($img_row[$fields .'_width'])) ? $img_row[$fields .'_width'] : $img_row['width'], + 'HEIGHT' => (!empty($img_row[$fields .'_height'])) ? $img_row[$fields .'_height'] : $img_row['height'], + 'POSTING_CHECKED' => (!empty($img_row['display_on_posting']) || $action == 'add') ? ' checked="checked"' : '', + )); + } + + // Ok, another row for adding an addition code for a pre-existing image... + if ($action == 'add' && $mode == 'smilies' && sizeof($smilies)) + { + $template->assign_vars(array( + 'S_ADD_CODE' => true, + + 'S_IMG_OPTIONS' => $smiley_options, + + 'S_ADD_ORDER_LIST_DISPLAY' => $add_order_list . $add_order_lists[1], + 'S_ADD_ORDER_LIST_UNDISPLAY' => $add_order_list . $add_order_lists[0], + + 'IMG_SRC' => $phpbb_root_path . $img_path . '/' . $default_row['smiley_url'], + 'IMG_PATH' => $img_path, + 'PHPBB_ROOT_PATH' => $phpbb_root_path, + + 'CODE' => $default_row['code'], + 'EMOTION' => $default_row['emotion'], + + 'WIDTH' => $default_row['smiley_width'], + 'HEIGHT' => $default_row['smiley_height'], + )); + } + + return; + + break; + + case 'create': + case 'modify': + + // Get items to create/modify + $images = (isset($_POST['image'])) ? array_keys(request_var('image', array('' => 0))) : array(); + + // Now really get the items + $image_id = (isset($_POST['id'])) ? request_var('id', array('' => 0)) : array(); + $image_order = (isset($_POST['order'])) ? request_var('order', array('' => 0)) : array(); + $image_width = (isset($_POST['width'])) ? request_var('width', array('' => 0)) : array(); + $image_height = (isset($_POST['height'])) ? request_var('height', array('' => 0)) : array(); + $image_add = (isset($_POST['add_img'])) ? request_var('add_img', array('' => 0)) : array(); + $image_emotion = utf8_normalize_nfc(request_var('emotion', array('' => ''), true)); + $image_code = utf8_normalize_nfc(request_var('code', array('' => ''), true)); + $image_display_on_posting = (isset($_POST['display_on_posting'])) ? request_var('display_on_posting', array('' => 0)) : array(); + + // Ok, add the relevant bits if we are adding new codes to existing emoticons... + if (!empty($_POST['add_additional_code'])) + { + $add_image = request_var('add_image', ''); + $add_code = utf8_normalize_nfc(request_var('add_code', '', true)); + $add_emotion = utf8_normalize_nfc(request_var('add_emotion', '', true)); + + if ($add_image && $add_emotion && $add_code) + { + $images[] = $add_image; + $image_add[$add_image] = true; + + $image_code[$add_image] = $add_code; + $image_emotion[$add_image] = $add_emotion; + $image_width[$add_image] = request_var('add_width', 0); + $image_height[$add_image] = request_var('add_height', 0); + + if (!empty($_POST['add_display_on_posting'])) + { + $image_display_on_posting[$add_image] = 1; + } + + $image_order[$add_image] = request_var('add_order', 0); + } + } + + if ($mode == 'smilies' && $action == 'create') + { + $smiley_count = $this->item_count($table); + + $addable_smileys_count = sizeof($images); + foreach ($images as $image) + { + if (!isset($image_add[$image])) + { + --$addable_smileys_count; + } + } + + if ($smiley_count + $addable_smileys_count > SMILEY_LIMIT) + { + trigger_error(sprintf($user->lang['TOO_MANY_SMILIES'], SMILEY_LIMIT) . adm_back_link($this->u_action), E_USER_WARNING); + } + } + + $icons_updated = 0; + $errors = array(); + foreach ($images as $image) + { + if ($mode == 'smilies' && ($image_emotion[$image] == '' || $image_code[$image] == '')) + { + $errors[$image] = 'SMILIE_NO_' . (($image_emotion[$image] == '') ? 'EMOTION' : 'CODE'); + } + else if ($action == 'create' && !isset($image_add[$image])) + { + // skip images where add wasn't checked + } + else + { + if ($image_width[$image] == 0 || $image_height[$image] == 0) + { + $img_size = getimagesize($phpbb_root_path . $img_path . '/' . $image); + $image_width[$image] = $img_size[0]; + $image_height[$image] = $img_size[1]; + } + + if ($image_width[$image] > 127 && $image_width[$image] > $image_height[$image]) + { + $image_height[$image] = (int) ($image_height[$image] * (127 / $image_width[$image])); + $image_width[$image] = 127; + } + else if ($image_height[$image] > 127) + { + $image_width[$image] = (int) ($image_width[$image] * (127 / $image_height[$image])); + $image_height[$image] = 127; + } + + $img_sql = array( + $fields . '_url' => $image, + $fields . '_width' => $image_width[$image], + $fields . '_height' => $image_height[$image], + 'display_on_posting' => (isset($image_display_on_posting[$image])) ? 1 : 0, + ); + + if ($mode == 'smilies') + { + $img_sql = array_merge($img_sql, array( + 'emotion' => $image_emotion[$image], + 'code' => $image_code[$image]) + ); + } + + // Image_order holds the 'new' order value + if (!empty($image_order[$image])) + { + $img_sql = array_merge($img_sql, array( + $fields . '_order' => $image_order[$image]) + ); + + // Since we always add 'after' an item, we just need to increase all following + the current by one + $sql = "UPDATE $table + SET {$fields}_order = {$fields}_order + 1 + WHERE {$fields}_order >= {$image_order[$image]}"; + $db->sql_query($sql); + + // If we adjust the order, we need to adjust all other orders too - they became inaccurate... + foreach ($image_order as $_image => $_order) + { + if ($_image == $image) + { + continue; + } + + if ($_order >= $image_order[$image]) + { + $image_order[$_image]++; + } + } + } + + if ($action == 'modify' && !empty($image_id[$image])) + { + $sql = "UPDATE $table + SET " . $db->sql_build_array('UPDATE', $img_sql) . " + WHERE {$fields}_id = " . $image_id[$image]; + $db->sql_query($sql); + $icons_updated++; + } + else if ($action !== 'modify') + { + $sql = "INSERT INTO $table " . $db->sql_build_array('INSERT', $img_sql); + $db->sql_query($sql); + $icons_updated++; + } + + } + } + + $cache->destroy('_icons'); + $cache->destroy('sql', $table); + + $level = E_USER_NOTICE; + switch ($icons_updated) + { + case 0: + $suc_lang = "{$lang}_NONE"; + $level = E_USER_WARNING; + break; + + case 1: + $suc_lang = "{$lang}_ONE"; + break; + + default: + $suc_lang = $lang; + } + $errormsgs = ''; + foreach ($errors as $img => $error) + { + $errormsgs .= '<br />' . sprintf($user->lang[$error], $img); + } + if ($action == 'modify') + { + trigger_error($user->lang[$suc_lang . '_EDITED'] . $errormsgs . adm_back_link($this->u_action), $level); + } + else + { + trigger_error($user->lang[$suc_lang . '_ADDED'] . $errormsgs . adm_back_link($this->u_action), $level); + } + + break; + + case 'import': + + $pak = request_var('pak', ''); + $current = request_var('current', ''); + + if ($pak != '') + { + $order = 0; + + if (!($pak_ary = @file($phpbb_root_path . $img_path . '/' . $pak))) + { + trigger_error($user->lang['PAK_FILE_NOT_READABLE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Make sure the pak_ary is valid + foreach ($pak_ary as $pak_entry) + { + if (preg_match_all("#'(.*?)', ?#", $pak_entry, $data)) + { + if ((sizeof($data[1]) != 4 && $mode == 'icons') || + ((sizeof($data[1]) != 6 || (empty($data[1][4]) || empty($data[1][5]))) && $mode == 'smilies' )) + { + trigger_error($user->lang['WRONG_PAK_TYPE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + else + { + trigger_error($user->lang['WRONG_PAK_TYPE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + + // The user has already selected a smilies_pak file + if ($current == 'delete') + { + switch ($db->sql_layer) + { + case 'sqlite': + case 'firebird': + $db->sql_query('DELETE FROM ' . $table); + break; + + default: + $db->sql_query('TRUNCATE TABLE ' . $table); + break; + } + + switch ($mode) + { + case 'smilies': + break; + + case 'icons': + // Reset all icon_ids + $db->sql_query('UPDATE ' . TOPICS_TABLE . ' SET icon_id = 0'); + $db->sql_query('UPDATE ' . POSTS_TABLE . ' SET icon_id = 0'); + break; + } + } + else + { + $cur_img = array(); + + $field_sql = ($mode == 'smilies') ? 'code' : 'icons_url'; + + $sql = "SELECT $field_sql + FROM $table"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + ++$order; + $cur_img[$row[$field_sql]] = 1; + } + $db->sql_freeresult($result); + } + + if ($mode == 'smilies') + { + $smiley_count = $this->item_count($table); + if ($smiley_count + sizeof($pak_ary) > SMILEY_LIMIT) + { + trigger_error(sprintf($user->lang['TOO_MANY_SMILIES'], SMILEY_LIMIT) . adm_back_link($this->u_action), E_USER_WARNING); + } + } + + foreach ($pak_ary as $pak_entry) + { + $data = array(); + if (preg_match_all("#'(.*?)', ?#", $pak_entry, $data)) + { + if ((sizeof($data[1]) != 4 && $mode == 'icons') || + (sizeof($data[1]) != 6 && $mode == 'smilies')) + { + trigger_error($user->lang['WRONG_PAK_TYPE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Stripslash here because it got addslashed before... (on export) + $img = stripslashes($data[1][0]); + $width = stripslashes($data[1][1]); + $height = stripslashes($data[1][2]); + $display_on_posting = stripslashes($data[1][3]); + + if (isset($data[1][4]) && isset($data[1][5])) + { + $emotion = stripslashes($data[1][4]); + $code = stripslashes($data[1][5]); + } + + if ($current == 'replace' && + (($mode == 'smilies' && !empty($cur_img[$code])) || + ($mode == 'icons' && !empty($cur_img[$img])))) + { + $replace_sql = ($mode == 'smilies') ? $code : $img; + $sql = array( + $fields . '_url' => $img, + $fields . '_height' => (int) $height, + $fields . '_width' => (int) $width, + 'display_on_posting' => (int) $display_on_posting, + ); + + if ($mode == 'smilies') + { + $sql = array_merge($sql, array( + 'emotion' => $emotion, + )); + } + + $sql = "UPDATE $table SET " . $db->sql_build_array('UPDATE', $sql) . " + WHERE $field_sql = '" . $db->sql_escape($replace_sql) . "'"; + $db->sql_query($sql); + } + else + { + ++$order; + + $sql = array( + $fields . '_url' => $img, + $fields . '_height' => (int) $height, + $fields . '_width' => (int) $width, + $fields . '_order' => (int) $order, + 'display_on_posting'=> (int) $display_on_posting, + ); + + if ($mode == 'smilies') + { + $sql = array_merge($sql, array( + 'code' => $code, + 'emotion' => $emotion, + )); + } + $db->sql_query("INSERT INTO $table " . $db->sql_build_array('INSERT', $sql)); + } + } + } + + $cache->destroy('_icons'); + $cache->destroy('sql', $table); + + trigger_error($user->lang[$lang . '_IMPORT_SUCCESS'] . adm_back_link($this->u_action)); + } + else + { + $pak_options = ''; + + foreach ($_paks as $pak) + { + $pak_options .= '<option value="' . $pak . '">' . htmlspecialchars($pak) . '</option>'; + } + + $template->assign_vars(array( + 'S_CHOOSE_PAK' => true, + 'S_PAK_OPTIONS' => $pak_options, + + 'L_TITLE' => $user->lang['ACP_' . $lang], + 'L_EXPLAIN' => $user->lang['ACP_' . $lang . '_EXPLAIN'], + 'L_NO_PAK_OPTIONS' => $user->lang['NO_' . $lang . '_PAK'], + 'L_CURRENT' => $user->lang['CURRENT_' . $lang], + 'L_CURRENT_EXPLAIN' => $user->lang['CURRENT_' . $lang . '_EXPLAIN'], + 'L_IMPORT_SUBMIT' => $user->lang['IMPORT_' . $lang], + + 'U_BACK' => $this->u_action, + 'U_ACTION' => $this->u_action . '&action=import', + ) + ); + } + break; + + case 'export': + + $this->page_title = 'EXPORT_' . $lang; + $this->tpl_name = 'message_body'; + + $template->assign_vars(array( + 'MESSAGE_TITLE' => $user->lang['EXPORT_' . $lang], + 'MESSAGE_TEXT' => sprintf($user->lang['EXPORT_' . $lang . '_EXPLAIN'], '<a href="' . $this->u_action . '&action=send">', '</a>'), + + 'S_USER_NOTICE' => true, + ) + ); + + return; + + break; + + case 'send': + + $sql = "SELECT * + FROM $table + ORDER BY {$fields}_order"; + $result = $db->sql_query($sql); + + $pak = ''; + while ($row = $db->sql_fetchrow($result)) + { + $pak .= "'" . addslashes($row[$fields . '_url']) . "', "; + $pak .= "'" . addslashes($row[$fields . '_width']) . "', "; + $pak .= "'" . addslashes($row[$fields . '_height']) . "', "; + $pak .= "'" . addslashes($row['display_on_posting']) . "', "; + + if ($mode == 'smilies') + { + $pak .= "'" . addslashes($row['emotion']) . "', "; + $pak .= "'" . addslashes($row['code']) . "', "; + } + + $pak .= "\n"; + } + $db->sql_freeresult($result); + + if ($pak != '') + { + garbage_collection(); + + header('Pragma: public'); + + // Send out the Headers + header('Content-Type: text/x-delimtext; name="' . $mode . '.pak"'); + header('Content-Disposition: inline; filename="' . $mode . '.pak"'); + echo $pak; + + flush(); + exit; + } + else + { + trigger_error($user->lang['NO_' . strtoupper($fields) . '_EXPORT'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + break; + + case 'delete': + + if (confirm_box(true)) + { + $sql = "DELETE FROM $table + WHERE {$fields}_id = $icon_id"; + $db->sql_query($sql); + + switch ($mode) + { + case 'smilies': + break; + + case 'icons': + // Reset appropriate icon_ids + $db->sql_query('UPDATE ' . TOPICS_TABLE . " + SET icon_id = 0 + WHERE icon_id = $icon_id"); + + $db->sql_query('UPDATE ' . POSTS_TABLE . " + SET icon_id = 0 + WHERE icon_id = $icon_id"); + break; + } + + $notice = $user->lang[$lang . '_DELETED']; + + $cache->destroy('_icons'); + $cache->destroy('sql', $table); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'id' => $icon_id, + 'action' => 'delete', + ))); + } + + break; + + case 'move_up': + case 'move_down': + + // Get current order id... + $sql = "SELECT {$fields}_order as current_order + FROM $table + WHERE {$fields}_id = $icon_id"; + $result = $db->sql_query($sql); + $current_order = (int) $db->sql_fetchfield('current_order'); + $db->sql_freeresult($result); + + if ($current_order == 0 && $action == 'move_up') + { + break; + } + + // on move_down, switch position with next order_id... + // on move_up, switch position with previous order_id... + $switch_order_id = ($action == 'move_down') ? $current_order + 1 : $current_order - 1; + + // + $sql = "UPDATE $table + SET {$fields}_order = $current_order + WHERE {$fields}_order = $switch_order_id + AND {$fields}_id <> $icon_id"; + $db->sql_query($sql); + + // Only update the other entry too if the previous entry got updated + if ($db->sql_affectedrows()) + { + $sql = "UPDATE $table + SET {$fields}_order = $switch_order_id + WHERE {$fields}_order = $current_order + AND {$fields}_id = $icon_id"; + $db->sql_query($sql); + } + + $cache->destroy('_icons'); + $cache->destroy('sql', $table); + + break; + } + + // By default, check that image_order is valid and fix it if necessary + $sql = "SELECT {$fields}_id AS order_id, {$fields}_order AS fields_order + FROM $table + ORDER BY display_on_posting DESC, {$fields}_order"; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + $order = 0; + do + { + ++$order; + if ($row['fields_order'] != $order) + { + $db->sql_query("UPDATE $table + SET {$fields}_order = $order + WHERE {$fields}_id = " . $row['order_id']); + } + } + while ($row = $db->sql_fetchrow($result)); + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'L_TITLE' => $user->lang['ACP_' . $lang], + 'L_EXPLAIN' => $user->lang['ACP_' . $lang . '_EXPLAIN'], + 'L_IMPORT' => $user->lang['IMPORT_' . $lang], + 'L_EXPORT' => $user->lang['EXPORT_' . $lang], + 'L_NOT_DISPLAYED' => $user->lang[$lang . '_NOT_DISPLAYED'], + 'L_ICON_ADD' => $user->lang['ADD_' . $lang], + 'L_ICON_EDIT' => $user->lang['EDIT_' . $lang], + + 'NOTICE' => $notice, + 'COLSPAN' => ($mode == 'smilies') ? 5 : 3, + + 'S_SMILIES' => ($mode == 'smilies') ? true : false, + + 'U_ACTION' => $this->u_action, + 'U_IMPORT' => $this->u_action . '&action=import', + 'U_EXPORT' => $this->u_action . '&action=export', + ) + ); + + $spacer = false; + $pagination_start = request_var('start', 0); + + $item_count = $this->item_count($table); + + $sql = "SELECT * + FROM $table + ORDER BY {$fields}_order ASC"; + $result = $db->sql_query_limit($sql, $config['smilies_per_page'], $pagination_start); + + while ($row = $db->sql_fetchrow($result)) + { + $alt_text = ($mode == 'smilies') ? $row['code'] : ''; + + $template->assign_block_vars('items', array( + 'S_SPACER' => (!$spacer && !$row['display_on_posting']) ? true : false, + 'ALT_TEXT' => $alt_text, + 'IMG_SRC' => $phpbb_root_path . $img_path . '/' . $row[$fields . '_url'], + 'WIDTH' => $row[$fields . '_width'], + 'HEIGHT' => $row[$fields . '_height'], + 'CODE' => (isset($row['code'])) ? $row['code'] : '', + 'EMOTION' => (isset($row['emotion'])) ? $row['emotion'] : '', + 'U_EDIT' => $this->u_action . '&action=edit&id=' . $row[$fields . '_id'], + 'U_DELETE' => $this->u_action . '&action=delete&id=' . $row[$fields . '_id'], + 'U_MOVE_UP' => $this->u_action . '&action=move_up&id=' . $row[$fields . '_id'] . '&start=' . $pagination_start, + 'U_MOVE_DOWN' => $this->u_action . '&action=move_down&id=' . $row[$fields . '_id'] . '&start=' . $pagination_start, + )); + + if (!$spacer && !$row['display_on_posting']) + { + $spacer = true; + } + } + $db->sql_freeresult($result); + + $template->assign_var('PAGINATION', + generate_pagination($this->u_action, $item_count, $config['smilies_per_page'], $pagination_start, true) + ); + } + + /** + * Returns the count of smilies or icons in the database + * + * @param string $table The table of items to count. + * @return int number of items + */ + /* private */ function item_count($table) + { + global $db; + + $sql = "SELECT COUNT(*) AS count + FROM $table"; + $result = $db->sql_query($sql); + $item_count = (int) $db->sql_fetchfield('count'); + $db->sql_freeresult($result); + return $item_count; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_inactive.php b/phpBB/includes/acp/acp_inactive.php new file mode 100644 index 0000000000..3d0c0a2780 --- /dev/null +++ b/phpBB/includes/acp/acp_inactive.php @@ -0,0 +1,306 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2006 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_inactive +{ + var $u_action; + var $p_master; + + function acp_inactive(&$p_master) + { + $this->p_master = &$p_master; + } + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template; + global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix; + + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + + $user->add_lang('memberlist'); + + $action = request_var('action', ''); + $mark = (isset($_REQUEST['mark'])) ? request_var('mark', array(0)) : array(); + $start = request_var('start', 0); + $submit = isset($_POST['submit']); + + // Sort keys + $sort_days = request_var('st', 0); + $sort_key = request_var('sk', 'i'); + $sort_dir = request_var('sd', 'd'); + + $form_key = 'acp_inactive'; + add_form_key($form_key); + + // We build the sort key and per page settings here, because they may be needed later + + // Number of entries to display + $per_page = request_var('users_per_page', (int) $config['topics_per_page']); + + // Sorting + $limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + $sort_by_text = array('i' => $user->lang['SORT_INACTIVE'], 'j' => $user->lang['SORT_REG_DATE'], 'l' => $user->lang['SORT_LAST_VISIT'], 'd' => $user->lang['SORT_LAST_REMINDER'], 'r' => $user->lang['SORT_REASON'], 'u' => $user->lang['SORT_USERNAME'], 'p' => $user->lang['SORT_POSTS'], 'e' => $user->lang['SORT_REMINDER']); + $sort_by_sql = array('i' => 'user_inactive_time', 'j' => 'user_regdate', 'l' => 'user_lastvisit', 'd' => 'user_reminded_time', 'r' => 'user_inactive_reason', 'u' => 'username_clean', 'p' => 'user_posts', 'e' => 'user_reminded'); + + $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = ''; + 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); + + if ($submit && sizeof($mark)) + { + if ($action !== 'delete' && !check_form_key($form_key)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + switch ($action) + { + case 'activate': + case 'delete': + + $sql = 'SELECT user_id, username + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', $mark); + $result = $db->sql_query($sql); + + $user_affected = array(); + while ($row = $db->sql_fetchrow($result)) + { + $user_affected[$row['user_id']] = $row['username']; + } + $db->sql_freeresult($result); + + if ($action == 'activate') + { + if ($config['require_activation'] == USER_ACTIVATION_ADMIN) + { + // Get those 'being activated'... + $sql = 'SELECT user_id, username, user_email, user_lang + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', $mark) . ' + AND user_type = ' . USER_INACTIVE; + $result = $db->sql_query($sql); + + $inactive_users = array(); + while ($row = $db->sql_fetchrow($result)) + { + $inactive_users[] = $row; + } + $db->sql_freeresult($result); + } + + user_active_flip('activate', $mark); + + if ($config['require_activation'] == USER_ACTIVATION_ADMIN && !empty($inactive_users)) + { + include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + + $messenger = new messenger(false); + + foreach ($inactive_users as $row) + { + $messenger->template('admin_welcome_activated', $row['user_lang']); + + $messenger->to($row['user_email'], $row['username']); + + $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); + $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); + $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); + $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($row['username'])) + ); + + $messenger->send(NOTIFY_EMAIL); + } + + $messenger->save_queue(); + } + + // For activate we really need to redirect, else a refresh can result in users being deactivated again + $u_action = $this->u_action . "&$u_sort_param&start=$start"; + $u_action .= ($per_page != $config['topics_per_page']) ? "&users_per_page=$per_page" : ''; + + redirect($u_action); + } + else if ($action == 'delete') + { + if (confirm_box(true)) + { + if (!$auth->acl_get('a_userdel')) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + foreach ($mark as $user_id) + { + user_delete('retain', $user_id, $user_affected[$user_id]); + } + + add_log('admin', 'LOG_INACTIVE_' . strtoupper($action), implode(', ', $user_affected)); + } + else + { + $s_hidden_fields = array( + 'mode' => $mode, + 'action' => $action, + 'mark' => $mark, + 'submit' => 1, + 'start' => $start, + ); + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($s_hidden_fields)); + } + } + + break; + + case 'remind': + if (empty($config['email_enable'])) + { + trigger_error($user->lang['EMAIL_DISABLED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT user_id, username, user_email, user_lang, user_jabber, user_notify_type, user_regdate, user_actkey + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', $mark) . ' + AND user_inactive_reason'; + + $sql .= ($config['require_activation'] == USER_ACTIVATION_ADMIN) ? ' = ' . INACTIVE_REMIND : ' <> ' . INACTIVE_MANUAL; + + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + // Send the messages + include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + + $messenger = new messenger(); + $usernames = $user_ids = array(); + + do + { + $messenger->template('user_remind_inactive', $row['user_lang']); + + $messenger->to($row['user_email'], $row['username']); + $messenger->im($row['user_jabber'], $row['username']); + + $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); + $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); + $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); + $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($row['username']), + 'REGISTER_DATE' => $user->format_date($row['user_regdate'], false, true), + 'U_ACTIVATE' => generate_board_url() . "/ucp.$phpEx?mode=activate&u=" . $row['user_id'] . '&k=' . $row['user_actkey']) + ); + + $messenger->send($row['user_notify_type']); + + $usernames[] = $row['username']; + $user_ids[] = (int) $row['user_id']; + } + while ($row = $db->sql_fetchrow($result)); + + $messenger->save_queue(); + + // Add the remind state to the database + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_reminded = user_reminded + 1, + user_reminded_time = ' . time() . ' + WHERE ' . $db->sql_in_set('user_id', $user_ids); + $db->sql_query($sql); + + add_log('admin', 'LOG_INACTIVE_REMIND', implode(', ', $usernames)); + unset($usernames); + } + $db->sql_freeresult($result); + + // For remind we really need to redirect, else a refresh can result in more than one reminder + $u_action = $this->u_action . "&$u_sort_param&start=$start"; + $u_action .= ($per_page != $config['topics_per_page']) ? "&users_per_page=$per_page" : ''; + + redirect($u_action); + + break; + } + } + + // Define where and sort sql for use in displaying logs + $sql_where = ($sort_days) ? (time() - ($sort_days * 86400)) : 0; + $sql_sort = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC'); + + $inactive = array(); + $inactive_count = 0; + + $start = view_inactive_users($inactive, $inactive_count, $per_page, $start, $sql_where, $sql_sort); + + foreach ($inactive as $row) + { + $template->assign_block_vars('inactive', array( + 'INACTIVE_DATE' => $user->format_date($row['user_inactive_time']), + 'REMINDED_DATE' => $user->format_date($row['user_reminded_time']), + 'JOINED' => $user->format_date($row['user_regdate']), + 'LAST_VISIT' => (!$row['user_lastvisit']) ? ' - ' : $user->format_date($row['user_lastvisit']), + + 'REASON' => $row['inactive_reason'], + 'USER_ID' => $row['user_id'], + 'POSTS' => ($row['user_posts']) ? $row['user_posts'] : 0, + 'REMINDED' => $row['user_reminded'], + + 'REMINDED_EXPLAIN' => $user->lang('USER_LAST_REMINDED', (int) $row['user_reminded'], $user->format_date($row['user_reminded_time'])), + + 'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], false, append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&mode=overview')), + 'USERNAME' => get_username_string('username', $row['user_id'], $row['username'], $row['user_colour']), + 'USER_COLOR' => get_username_string('colour', $row['user_id'], $row['username'], $row['user_colour']), + + 'U_USER_ADMIN' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=users&mode=overview&u={$row['user_id']}"), + 'U_SEARCH_USER' => ($auth->acl_get('u_search')) ? append_sid("{$phpbb_root_path}search.$phpEx", "author_id={$row['user_id']}&sr=posts") : '', + )); + } + + $option_ary = array('activate' => 'ACTIVATE', 'delete' => 'DELETE'); + if ($config['email_enable']) + { + $option_ary += array('remind' => 'REMIND'); + } + + $template->assign_vars(array( + 'S_INACTIVE_USERS' => true, + 'S_INACTIVE_OPTIONS' => build_select($option_ary), + + 'S_LIMIT_DAYS' => $s_limit_days, + 'S_SORT_KEY' => $s_sort_key, + 'S_SORT_DIR' => $s_sort_dir, + 'S_ON_PAGE' => on_page($inactive_count, $per_page, $start), + 'PAGINATION' => generate_pagination($this->u_action . "&$u_sort_param&users_per_page=$per_page", $inactive_count, $per_page, $start, true), + 'USERS_PER_PAGE' => $per_page, + + 'U_ACTION' => $this->u_action . '&start=' . $start, + )); + + $this->tpl_name = 'acp_inactive'; + $this->page_title = 'ACP_INACTIVE_USERS'; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_jabber.php b/phpBB/includes/acp/acp_jabber.php new file mode 100644 index 0000000000..3ab6eb64ed --- /dev/null +++ b/phpBB/includes/acp/acp_jabber.php @@ -0,0 +1,131 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +* @todo Check/enter/update transport info +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_jabber +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + $user->add_lang('acp/board'); + + include_once($phpbb_root_path . 'includes/functions_jabber.' . $phpEx); + + $action = request_var('action', ''); + $submit = (isset($_POST['submit'])) ? true : false; + + if ($mode != 'settings') + { + return; + } + + $this->tpl_name = 'acp_jabber'; + $this->page_title = 'ACP_JABBER_SETTINGS'; + + $jab_enable = request_var('jab_enable', $config['jab_enable']); + $jab_host = request_var('jab_host', $config['jab_host']); + $jab_port = request_var('jab_port', $config['jab_port']); + $jab_username = request_var('jab_username', $config['jab_username']); + $jab_password = request_var('jab_password', $config['jab_password']); + $jab_package_size = request_var('jab_package_size', $config['jab_package_size']); + $jab_use_ssl = request_var('jab_use_ssl', $config['jab_use_ssl']); + + $form_name = 'acp_jabber'; + add_form_key($form_name); + + if ($submit) + { + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); + } + + $error = array(); + + $message = $user->lang['JAB_SETTINGS_CHANGED']; + $log = 'JAB_SETTINGS_CHANGED'; + + // Is this feature enabled? Then try to establish a connection + if ($jab_enable) + { + $jabber = new jabber($jab_host, $jab_port, $jab_username, $jab_password, $jab_use_ssl); + + if (!$jabber->connect()) + { + trigger_error($user->lang['ERR_JAB_CONNECT'] . '<br /><br />' . $jabber->get_log() . adm_back_link($this->u_action), E_USER_WARNING); + } + + // We'll try to authorise using this account + if (!$jabber->login()) + { + trigger_error($user->lang['ERR_JAB_AUTH'] . '<br /><br />' . $jabber->get_log() . adm_back_link($this->u_action), E_USER_WARNING); + } + + $jabber->disconnect(); + } + else + { + // This feature is disabled. + // We update the user table to be sure all users that have IM as notify type are set to both as notify type + // We set this to both because users still have their jabber address entered and may want to receive jabber notifications again once it is re-enabled. + $sql_ary = array( + 'user_notify_type' => NOTIFY_BOTH, + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_notify_type = ' . NOTIFY_IM; + $db->sql_query($sql); + } + + set_config('jab_enable', $jab_enable); + set_config('jab_host', $jab_host); + set_config('jab_port', $jab_port); + set_config('jab_username', $jab_username); + set_config('jab_password', $jab_password); + set_config('jab_package_size', $jab_package_size); + set_config('jab_use_ssl', $jab_use_ssl); + + add_log('admin', 'LOG_' . $log); + trigger_error($message . adm_back_link($this->u_action)); + } + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action, + 'JAB_ENABLE' => $jab_enable, + 'L_JAB_SERVER_EXPLAIN' => sprintf($user->lang['JAB_SERVER_EXPLAIN'], '<a href="http://www.jabber.org/">', '</a>'), + 'JAB_HOST' => $jab_host, + 'JAB_PORT' => $jab_port, + 'JAB_USERNAME' => $jab_username, + 'JAB_PASSWORD' => $jab_password, + 'JAB_PACKAGE_SIZE' => $jab_package_size, + 'JAB_USE_SSL' => $jab_use_ssl, + 'S_CAN_USE_SSL' => jabber::can_use_ssl(), + 'S_GTALK_NOTE' => (!@function_exists('dns_get_record')) ? true : false, + )); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_language.php b/phpBB/includes/acp/acp_language.php new file mode 100644 index 0000000000..8ca45a27f6 --- /dev/null +++ b/phpBB/includes/acp/acp_language.php @@ -0,0 +1,1453 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_language +{ + var $u_action; + var $main_files; + var $language_header = ''; + var $lang_header = ''; + + var $language_file = ''; + var $language_directory = ''; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $cache; + global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix; + global $safe_mode, $file_uploads; + + include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); + + $this->default_variables(); + + // Check and set some common vars + + $action = (isset($_POST['update_details'])) ? 'update_details' : ''; + $action = (isset($_POST['download_file'])) ? 'download_file' : $action; + $action = (isset($_POST['upload_file'])) ? 'upload_file' : $action; + $action = (isset($_POST['upload_data'])) ? 'upload_data' : $action; + $action = (isset($_POST['submit_file'])) ? 'submit_file' : $action; + $action = (isset($_POST['remove_store'])) ? 'details' : $action; + + $submit = (empty($action) && !isset($_POST['update']) && !isset($_POST['test_connection'])) ? false : true; + $action = (empty($action)) ? request_var('action', '') : $action; + + $form_name = 'acp_lang'; + add_form_key('acp_lang'); + + $lang_id = request_var('id', 0); + if (isset($_POST['missing_file'])) + { + $missing_file = request_var('missing_file', array('' => 0)); + list($_REQUEST['language_file'], ) = array_keys($missing_file); + } + + $selected_lang_file = request_var('language_file', '|common.' . $phpEx); + + list($this->language_directory, $this->language_file) = explode('|', $selected_lang_file); + + $this->language_directory = basename($this->language_directory); + $this->language_file = basename($this->language_file); + + $user->add_lang('acp/language'); + $this->tpl_name = 'acp_language'; + $this->page_title = 'ACP_LANGUAGE_PACKS'; + + if ($submit && $action == 'upload_data' && request_var('test_connection', '')) + { + $test_connection = false; + $action = 'upload_file'; + $method = request_var('method', ''); + + include_once($phpbb_root_path . 'includes/functions_transfer.' . $phpEx); + + switch ($method) + { + case 'ftp': + $transfer = new ftp(request_var('host', ''), request_var('username', ''), request_var('password', ''), request_var('root_path', ''), request_var('port', ''), request_var('timeout', '')); + break; + + case 'ftp_fsock': + $transfer = new ftp_fsock(request_var('host', ''), request_var('username', ''), request_var('password', ''), request_var('root_path', ''), request_var('port', ''), request_var('timeout', '')); + break; + + default: + trigger_error($user->lang['INVALID_UPLOAD_METHOD'], E_USER_ERROR); + break; + } + + $test_connection = $transfer->open_session(); + $transfer->close_session(); + } + + switch ($action) + { + case 'upload_file': + + include_once($phpbb_root_path . 'includes/functions_transfer.' . $phpEx); + + $method = request_var('method', ''); + + 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) + { + $template->assign_block_vars('data', array( + 'DATA' => $data, + 'NAME' => $user->lang[strtoupper($method . '_' . $data)], + 'EXPLAIN' => $user->lang[strtoupper($method . '_' . $data) . '_EXPLAIN'], + 'DEFAULT' => (!empty($_REQUEST[$data])) ? request_var($data, '') : $default + )); + } + + $hidden_data = build_hidden_fields(array( + 'file' => $this->language_file, + 'dir' => $this->language_directory, + 'language_file' => $selected_lang_file, + 'method' => $method) + ); + + $hidden_data .= build_hidden_fields(array('entry' => $_POST['entry']), true, STRIP); + + $template->assign_vars(array( + 'S_UPLOAD' => true, + 'NAME' => $method, + 'U_ACTION' => $this->u_action . "&id=$lang_id&action=upload_data", + 'U_BACK' => $this->u_action . "&id=$lang_id&action=details&language_file=" . urlencode($selected_lang_file), + 'HIDDEN' => $hidden_data, + + 'S_CONNECTION_SUCCESS' => (request_var('test_connection', '') && $test_connection === true) ? true : false, + 'S_CONNECTION_FAILED' => (request_var('test_connection', '') && $test_connection !== true) ? true : false + )); + break; + + case 'update_details': + + if (!$submit || !check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); + } + + if (!$lang_id) + { + trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT * + FROM ' . LANG_TABLE . " + WHERE lang_id = $lang_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $sql_ary = array( + 'lang_english_name' => request_var('lang_english_name', $row['lang_english_name']), + 'lang_local_name' => utf8_normalize_nfc(request_var('lang_local_name', $row['lang_local_name'], true)), + 'lang_author' => utf8_normalize_nfc(request_var('lang_author', $row['lang_author'], true)), + ); + + $db->sql_query('UPDATE ' . LANG_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE lang_id = ' . $lang_id); + + add_log('admin', 'LOG_LANGUAGE_PACK_UPDATED', $sql_ary['lang_english_name']); + + trigger_error($user->lang['LANGUAGE_DETAILS_UPDATED'] . adm_back_link($this->u_action)); + break; + + case 'submit_file': + case 'download_file': + case 'upload_data': + + if (!$submit || !check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); + } + + if (!$lang_id || empty($_POST['entry'])) + { + trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if ($this->language_directory != 'email' && !is_array($_POST['entry'])) + { + trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (!$this->language_file || (!$this->language_directory && !in_array($this->language_file, $this->main_files))) + { + trigger_error($user->lang['NO_FILE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT * + FROM ' . LANG_TABLE . " + WHERE lang_id = $lang_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Before we attempt to write anything let's check if the admin really chose a correct filename + switch ($this->language_directory) + { + case 'email': + // Get email templates + $email_files = filelist($phpbb_root_path . 'language/' . $row['lang_iso'], 'email', 'txt'); + $email_files = $email_files['email/']; + + if (!in_array($this->language_file, $email_files)) + { + trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); + } + break; + + case 'acp': + // Get acp files + $acp_files = filelist($phpbb_root_path . 'language/' . $row['lang_iso'], 'acp', $phpEx); + $acp_files = $acp_files['acp/']; + + if (!in_array($this->language_file, $acp_files)) + { + trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); + } + break; + + case 'mods': + // Get mod files + $mods_files = filelist($phpbb_root_path . 'language/' . $row['lang_iso'], 'mods', $phpEx); + $mods_files = (isset($mods_files['mods/'])) ? $mods_files['mods/'] : array(); + + if (!in_array($this->language_file, $mods_files)) + { + trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); + } + break; + + default: + if (!in_array($this->language_file, $this->main_files)) + { + trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); + } + break; + } + + if (!$safe_mode) + { + $mkdir_ary = array('language', 'language/' . $row['lang_iso']); + + if ($this->language_directory) + { + $mkdir_ary[] = 'language/' . $row['lang_iso'] . '/' . $this->language_directory; + } + + foreach ($mkdir_ary as $dir) + { + $dir = $phpbb_root_path . 'store/' . $dir; + + if (!is_dir($dir)) + { + if (!@mkdir($dir, 0777)) + { + trigger_error("Could not create directory $dir", E_USER_ERROR); + } + @chmod($dir, 0777); + } + } + } + + // Get target filename for storage folder + $filename = $this->get_filename($row['lang_iso'], $this->language_directory, $this->language_file, true, true); + $fp = @fopen($phpbb_root_path . $filename, 'wb'); + + if (!$fp) + { + trigger_error(sprintf($user->lang['UNABLE_TO_WRITE_FILE'], $filename) . adm_back_link($this->u_action . '&id=' . $lang_id . '&action=details&language_file=' . urlencode($selected_lang_file)), E_USER_WARNING); + } + + if ($this->language_directory == 'email') + { + // Email Template + $entry = $this->prepare_lang_entry($_POST['entry'], false); + fwrite($fp, $entry); + } + else + { + $name = (($this->language_directory) ? $this->language_directory . '_' : '') . $this->language_file; + $header = str_replace(array('{FILENAME}', '{LANG_NAME}', '{CHANGED}', '{AUTHOR}'), array($name, $row['lang_english_name'], date('Y-m-d', time()), $row['lang_author']), $this->language_file_header); + + if (strpos($this->language_file, 'help_') === 0) + { + // Help File + $header .= '$help = array(' . "\n"; + fwrite($fp, $header); + + foreach ($_POST['entry'] as $key => $value) + { + if (!is_array($value)) + { + continue; + } + + $entry = "\tarray(\n"; + + foreach ($value as $_key => $_value) + { + $entry .= "\t\t" . (int) $_key . "\t=> '" . $this->prepare_lang_entry($_value) . "',\n"; + } + + $entry .= "\t),\n"; + fwrite($fp, $entry); + } + + $footer = ");\n\n?>"; + fwrite($fp, $footer); + } + else + { + // Language File + $header .= $this->lang_header; + fwrite($fp, $header); + + foreach ($_POST['entry'] as $key => $value) + { + $entry = $this->format_lang_array($key, $value); + fwrite($fp, $entry); + } + + $footer = "));\n\n?>"; + fwrite($fp, $footer); + } + } + + fclose($fp); + + if ($action == 'download_file') + { + header('Pragma: no-cache'); + header('Content-Type: application/octetstream; name="' . $this->language_file . '"'); + header('Content-disposition: attachment; filename=' . $this->language_file); + + $fp = @fopen($phpbb_root_path . $filename, 'rb'); + while ($buffer = fread($fp, 1024)) + { + echo $buffer; + } + fclose($fp); + + add_log('admin', 'LOG_LANGUAGE_FILE_SUBMITTED', $this->language_file); + + exit; + } + else if ($action == 'upload_data') + { + $sql = 'SELECT lang_iso + FROM ' . LANG_TABLE . " + WHERE lang_id = $lang_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $file = request_var('file', ''); + $dir = request_var('dir', ''); + + $selected_lang_file = $dir . '|' . $file; + + $old_file = '/' . $this->get_filename($row['lang_iso'], $dir, $file, false, true); + $lang_path = 'language/' . $row['lang_iso'] . '/' . (($dir) ? $dir . '/' : ''); + + include_once($phpbb_root_path . 'includes/functions_transfer.' . $phpEx); + $method = request_var('method', ''); + + if ($method != 'ftp' && $method != 'ftp_fsock') + { + trigger_error($user->lang['INVALID_UPLOAD_METHOD'], E_USER_ERROR); + } + + $transfer = new $method(request_var('host', ''), request_var('username', ''), request_var('password', ''), request_var('root_path', ''), request_var('port', ''), request_var('timeout', '')); + + if (($result = $transfer->open_session()) !== true) + { + trigger_error($user->lang[$result] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id . '&language_file=' . urlencode($selected_lang_file)), E_USER_WARNING); + } + + $transfer->rename($lang_path . $file, $lang_path . $file . '.bak'); + $result = $transfer->copy_file('store/' . $lang_path . $file, $lang_path . $file); + + if ($result === false) + { + // If failed, try to rename again and print error out... + $transfer->delete_file($lang_path . $file); + $transfer->rename($lang_path . $file . '.bak', $lang_path . $file); + + trigger_error($user->lang['UPLOAD_FAILED'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id . '&language_file=' . urlencode($selected_lang_file)), E_USER_WARNING); + } + + $transfer->close_session(); + + // Remove from storage folder + if (file_exists($phpbb_root_path . 'store/' . $lang_path . $file)) + { + @unlink($phpbb_root_path . 'store/' . $lang_path . $file); + } + + add_log('admin', 'LOG_LANGUAGE_FILE_REPLACED', $file); + + trigger_error($user->lang['UPLOAD_COMPLETED'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id . '&language_file=' . urlencode($selected_lang_file))); + } + + add_log('admin', 'LOG_LANGUAGE_FILE_SUBMITTED', $this->language_file); + $action = 'details'; + + // no break; + + case 'details': + + if (!$lang_id) + { + trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $this->page_title = 'LANGUAGE_PACK_DETAILS'; + + $sql = 'SELECT * + FROM ' . LANG_TABLE . ' + WHERE lang_id = ' . $lang_id; + $result = $db->sql_query($sql); + $lang_entries = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $lang_iso = $lang_entries['lang_iso']; + $missing_vars = $missing_files = array(); + + // Get email templates + $email_files = filelist($phpbb_root_path . 'language/' . $config['default_lang'], 'email', 'txt'); + $email_files = $email_files['email/']; + + // Get acp files + $acp_files = filelist($phpbb_root_path . 'language/' . $config['default_lang'], 'acp', $phpEx); + $acp_files = $acp_files['acp/']; + + // Get mod files + $mods_files = filelist($phpbb_root_path . 'language/' . $config['default_lang'], 'mods', $phpEx); + $mods_files = (isset($mods_files['mods/'])) ? $mods_files['mods/'] : array(); + + // Check if our current filename matches the files + switch ($this->language_directory) + { + case 'email': + if (!in_array($this->language_file, $email_files)) + { + trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); + } + break; + + case 'acp': + if (!in_array($this->language_file, $acp_files)) + { + trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); + } + break; + + case 'mods': + if (!in_array($this->language_file, $mods_files)) + { + trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); + } + break; + + default: + if (!in_array($this->language_file, $this->main_files)) + { + trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); + } + } + + if (isset($_POST['remove_store'])) + { + $store_filename = $this->get_filename($lang_iso, $this->language_directory, $this->language_file, true, true); + + if (file_exists($phpbb_root_path . $store_filename)) + { + @unlink($phpbb_root_path . $store_filename); + } + } + + include_once($phpbb_root_path . 'includes/functions_transfer.' . $phpEx); + + $methods = transfer::methods(); + + foreach ($methods as $method) + { + $template->assign_block_vars('buttons', array( + 'VALUE' => $method + )); + } + + $template->assign_vars(array( + 'S_DETAILS' => true, + 'U_ACTION' => $this->u_action . "&action=details&id=$lang_id", + 'U_BACK' => $this->u_action, + 'LANG_LOCAL_NAME' => $lang_entries['lang_local_name'], + 'LANG_ENGLISH_NAME' => $lang_entries['lang_english_name'], + 'LANG_ISO' => $lang_entries['lang_iso'], + 'LANG_AUTHOR' => $lang_entries['lang_author'], + 'ALLOW_UPLOAD' => sizeof($methods) + ) + ); + + // If current lang is different from the default lang, then first try to grab missing/additional vars + if ($lang_iso != $config['default_lang']) + { + $is_missing_var = false; + + foreach ($this->main_files as $file) + { + if (file_exists($phpbb_root_path . $this->get_filename($lang_iso, '', $file))) + { + $missing_vars[$file] = $this->compare_language_files($config['default_lang'], $lang_iso, '', $file); + + if (sizeof($missing_vars[$file])) + { + $is_missing_var = true; + } + } + else + { + $missing_files[] = $this->get_filename($lang_iso, '', $file); + } + } + + // Now go through acp/mods directories + foreach ($acp_files as $file) + { + if (file_exists($phpbb_root_path . $this->get_filename($lang_iso, 'acp', $file))) + { + $missing_vars['acp/' . $file] = $this->compare_language_files($config['default_lang'], $lang_iso, 'acp', $file); + + if (sizeof($missing_vars['acp/' . $file])) + { + $is_missing_var = true; + } + } + else + { + $missing_files[] = $this->get_filename($lang_iso, 'acp', $file); + } + } + + if (sizeof($mods_files)) + { + foreach ($mods_files as $file) + { + if (file_exists($phpbb_root_path . $this->get_filename($lang_iso, 'mods', $file))) + { + $missing_vars['mods/' . $file] = $this->compare_language_files($config['default_lang'], $lang_iso, 'mods', $file); + + if (sizeof($missing_vars['mods/' . $file])) + { + $is_missing_var = true; + } + } + else + { + $missing_files[] = $this->get_filename($lang_iso, 'mods', $file); + } + } + } + + // More missing files... for example email templates? + foreach ($email_files as $file) + { + if (!file_exists($phpbb_root_path . $this->get_filename($lang_iso, 'email', $file))) + { + $missing_files[] = $this->get_filename($lang_iso, 'email', $file); + } + } + + if (sizeof($missing_files)) + { + $template->assign_vars(array( + 'S_MISSING_FILES' => true, + 'L_MISSING_FILES' => sprintf($user->lang['THOSE_MISSING_LANG_FILES'], $lang_entries['lang_local_name']), + 'MISSING_FILES' => implode('<br />', $missing_files)) + ); + } + + if ($is_missing_var) + { + $template->assign_vars(array( + 'S_MISSING_VARS' => true, + 'L_MISSING_VARS_EXPLAIN' => sprintf($user->lang['THOSE_MISSING_LANG_VARIABLES'], $lang_entries['lang_local_name']), + 'U_MISSING_ACTION' => $this->u_action . "&action=$action&id=$lang_id") + ); + + foreach ($missing_vars as $file => $vars) + { + if (!sizeof($vars)) + { + continue; + } + + $template->assign_block_vars('missing', array( + 'FILE' => $file, + 'TPL' => $this->print_language_entries($vars, '', false), + 'KEY' => (strpos($file, '/') === false) ? '|' . $file : str_replace('/', '|', $file)) + ); + } + } + } + + // Main language files + $s_lang_options = '<option value="|common.' . $phpEx . '" class="sep">' . $user->lang['LANGUAGE_FILES'] . '</option>'; + foreach ($this->main_files as $file) + { + if (strpos($file, 'help_') === 0) + { + continue; + } + + $prefix = (file_exists($phpbb_root_path . $this->get_filename($lang_iso, '', $file, true, true))) ? '* ' : ''; + + $selected = (!$this->language_directory && $this->language_file == $file) ? ' selected="selected"' : ''; + $s_lang_options .= '<option value="|' . $file . '"' . $selected . '>' . $prefix . $file . '</option>'; + } + + // Help Files + $s_lang_options .= '<option value="|common.' . $phpEx . '" class="sep">' . $user->lang['HELP_FILES'] . '</option>'; + foreach ($this->main_files as $file) + { + if (strpos($file, 'help_') !== 0) + { + continue; + } + + $prefix = (file_exists($phpbb_root_path . $this->get_filename($lang_iso, '', $file, true, true))) ? '* ' : ''; + + $selected = (!$this->language_directory && $this->language_file == $file) ? ' selected="selected"' : ''; + $s_lang_options .= '<option value="|' . $file . '"' . $selected . '>' . $prefix . $file . '</option>'; + } + + // Now every other language directory + $check_files = array('email', 'acp', 'mods'); + + foreach ($check_files as $check) + { + if (!sizeof(${$check . '_files'})) + { + continue; + } + + $s_lang_options .= '<option value="|common.' . $phpEx . '" class="sep">' . $user->lang[strtoupper($check) . '_FILES'] . '</option>'; + + foreach (${$check . '_files'} as $file) + { + $prefix = (file_exists($phpbb_root_path . $this->get_filename($lang_iso, $check, $file, true, true))) ? '* ' : ''; + + $selected = ($this->language_directory == $check && $this->language_file == $file) ? ' selected="selected"' : ''; + $s_lang_options .= '<option value="' . $check . '|' . $file . '"' . $selected . '>' . $prefix . $file . '</option>'; + } + } + + // Get Language Entries - if saved within store folder, we take this one (with the option to remove it) + $lang = array(); + + $is_email_file = ($this->language_directory == 'email') ? true : false; + $is_help_file = (strpos($this->language_file, 'help_') === 0) ? true : false; + + $file_from_store = (file_exists($phpbb_root_path . $this->get_filename($lang_iso, $this->language_directory, $this->language_file, true, true))) ? true : false; + $no_store_filename = $this->get_filename($lang_iso, $this->language_directory, $this->language_file); + + if (!$file_from_store && !file_exists($phpbb_root_path . $no_store_filename)) + { + $print_message = sprintf($user->lang['MISSING_LANGUAGE_FILE'], $no_store_filename); + } + else + { + if ($is_email_file) + { + $lang = file_get_contents($phpbb_root_path . $this->get_filename($lang_iso, $this->language_directory, $this->language_file, $file_from_store)); + } + else + { + $help = array(); + include($phpbb_root_path . $this->get_filename($lang_iso, $this->language_directory, $this->language_file, $file_from_store)); + + if ($is_help_file) + { + $lang = $help; + unset($help); + } + } + + $print_message = (($this->language_directory) ? $this->language_directory . '/' : '') . $this->language_file; + } + + // Normal language pack entries + $template->assign_vars(array( + 'U_ENTRY_ACTION' => $this->u_action . "&action=details&id=$lang_id#entries", + 'S_EMAIL_FILE' => $is_email_file, + 'S_FROM_STORE' => $file_from_store, + 'S_LANG_OPTIONS' => $s_lang_options, + 'PRINT_MESSAGE' => $print_message, + ) + ); + + if (!$is_email_file) + { + $tpl = ''; + $name = (($this->language_directory) ? $this->language_directory . '/' : '') . $this->language_file; + + if (isset($missing_vars[$name]) && sizeof($missing_vars[$name])) + { + $tpl .= $this->print_language_entries($missing_vars[$name], '* '); + } + + $tpl .= $this->print_language_entries($lang); + + $template->assign_var('TPL', $tpl); + unset($tpl); + } + else + { + $template->assign_vars(array( + 'LANG' => $lang) + ); + + unset($lang); + } + + return; + + break; + + case 'delete': + + if (!$lang_id) + { + trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT * + FROM ' . LANG_TABLE . ' + WHERE lang_id = ' . $lang_id; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row['lang_iso'] == $config['default_lang']) + { + trigger_error($user->lang['NO_REMOVE_DEFAULT_LANG'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (confirm_box(true)) + { + $db->sql_query('DELETE FROM ' . LANG_TABLE . ' WHERE lang_id = ' . $lang_id); + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_lang = '" . $db->sql_escape($config['default_lang']) . "' + WHERE user_lang = '" . $db->sql_escape($row['lang_iso']) . "'"; + $db->sql_query($sql); + + // We also need to remove the translated entries for custom profile fields - we want clean tables, don't we? + $sql = 'DELETE FROM ' . PROFILE_LANG_TABLE . ' WHERE lang_id = ' . $lang_id; + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . ' WHERE lang_id = ' . $lang_id; + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . " WHERE image_lang = '" . $db->sql_escape($row['lang_iso']) . "'"; + $result = $db->sql_query($sql); + + $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE); + + add_log('admin', 'LOG_LANGUAGE_PACK_DELETED', $row['lang_english_name']); + + trigger_error(sprintf($user->lang['LANGUAGE_PACK_DELETED'], $row['lang_english_name']) . adm_back_link($this->u_action)); + } + else + { + $s_hidden_fields = array( + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'id' => $lang_id, + ); + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($s_hidden_fields)); + } + break; + + case 'install': + $lang_iso = request_var('iso', ''); + $lang_iso = basename($lang_iso); + + if (!$lang_iso || !file_exists("{$phpbb_root_path}language/$lang_iso/iso.txt")) + { + trigger_error($user->lang['LANGUAGE_PACK_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $file = file("{$phpbb_root_path}language/$lang_iso/iso.txt"); + + $lang_pack = array( + 'iso' => $lang_iso, + 'name' => trim(htmlspecialchars($file[0])), + 'local_name'=> trim(htmlspecialchars($file[1], ENT_COMPAT, 'UTF-8')), + 'author' => trim(htmlspecialchars($file[2], ENT_COMPAT, 'UTF-8')) + ); + unset($file); + + $sql = 'SELECT lang_iso + FROM ' . LANG_TABLE . " + WHERE lang_iso = '" . $db->sql_escape($lang_iso) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + trigger_error($user->lang['LANGUAGE_PACK_ALREADY_INSTALLED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (!$lang_pack['name'] || !$lang_pack['local_name']) + { + trigger_error($user->lang['INVALID_LANGUAGE_PACK'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Add language pack + $sql_ary = array( + 'lang_iso' => $lang_pack['iso'], + 'lang_dir' => $lang_pack['iso'], + 'lang_english_name' => $lang_pack['name'], + 'lang_local_name' => $lang_pack['local_name'], + 'lang_author' => $lang_pack['author'] + ); + + $db->sql_query('INSERT INTO ' . LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + $lang_id = $db->sql_nextid(); + + $valid_localized = array( + 'icon_back_top', 'icon_contact_aim', 'icon_contact_email', 'icon_contact_icq', 'icon_contact_jabber', 'icon_contact_msnm', 'icon_contact_pm', 'icon_contact_yahoo', 'icon_contact_www', 'icon_post_delete', 'icon_post_edit', 'icon_post_info', 'icon_post_quote', 'icon_post_report', 'icon_user_online', 'icon_user_offline', 'icon_user_profile', 'icon_user_search', 'icon_user_warn', 'button_pm_forward', 'button_pm_new', 'button_pm_reply', 'button_topic_locked', 'button_topic_new', 'button_topic_reply', + ); + + $sql_ary = array(); + + $sql = 'SELECT * + FROM ' . STYLES_IMAGESET_TABLE; + $result = $db->sql_query($sql); + while ($imageset_row = $db->sql_fetchrow($result)) + { + if (@file_exists("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/{$lang_pack['iso']}/imageset.cfg")) + { + $cfg_data_imageset_data = parse_cfg_file("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/{$lang_pack['iso']}/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); + if (in_array($image_name, $valid_localized)) + { + $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) $imageset_row['imageset_id'], + 'image_lang' => (string) $lang_pack['iso'], + ); + } + } + } + } + } + $db->sql_freeresult($result); + + if (sizeof($sql_ary)) + { + $db->sql_multi_insert(STYLES_IMAGESET_DATA_TABLE, $sql_ary); + $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE); + } + + // Now let's copy the default language entries for custom profile fields for this new language - makes admin's life easier. + $sql = 'SELECT lang_id + FROM ' . LANG_TABLE . " + WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'"; + $result = $db->sql_query($sql); + $default_lang_id = (int) $db->sql_fetchfield('lang_id'); + $db->sql_freeresult($result); + + // From the mysql documentation: + // Prior to MySQL 4.0.14, the target table of the INSERT statement cannot appear in the FROM clause of the SELECT part of the query. This limitation is lifted in 4.0.14. + // Due to this we stay on the safe side if we do the insertion "the manual way" + + $sql = 'SELECT field_id, lang_name, lang_explain, lang_default_value + FROM ' . PROFILE_LANG_TABLE . ' + WHERE lang_id = ' . $default_lang_id; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $row['lang_id'] = $lang_id; + $db->sql_query('INSERT INTO ' . PROFILE_LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $row)); + } + $db->sql_freeresult($result); + + $sql = 'SELECT field_id, option_id, field_type, lang_value + FROM ' . PROFILE_FIELDS_LANG_TABLE . ' + WHERE lang_id = ' . $default_lang_id; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $row['lang_id'] = $lang_id; + $db->sql_query('INSERT INTO ' . PROFILE_FIELDS_LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $row)); + } + $db->sql_freeresult($result); + + add_log('admin', 'LOG_LANGUAGE_PACK_INSTALLED', $lang_pack['name']); + + trigger_error(sprintf($user->lang['LANGUAGE_PACK_INSTALLED'], $lang_pack['name']) . adm_back_link($this->u_action)); + + break; + + case 'download': + + if (!$lang_id) + { + trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT * + FROM ' . LANG_TABLE . ' + WHERE lang_id = ' . $lang_id; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $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) + { + $this->page_title = 'SELECT_DOWNLOAD_FORMAT'; + + $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>'; + } + + $template->assign_vars(array( + 'S_SELECT_METHOD' => true, + 'U_BACK' => $this->u_action, + 'U_ACTION' => $this->u_action . "&action=$action&id=$lang_id", + 'RADIO_BUTTONS' => $radio_buttons) + ); + + return; + } + + if (!in_array($use_method, $methods)) + { + $use_method = '.tar'; + } + + include_once($phpbb_root_path . 'includes/functions_compress.' . $phpEx); + + if ($use_method == '.zip') + { + $compress = new compress_zip('w', $phpbb_root_path . 'store/lang_' . $row['lang_iso'] . $use_method); + } + else + { + $compress = new compress_tar('w', $phpbb_root_path . 'store/lang_' . $row['lang_iso'] . $use_method, $use_method); + } + + // Get email templates + $email_templates = filelist($phpbb_root_path . 'language/' . $row['lang_iso'], 'email', 'txt'); + $email_templates = $email_templates['email/']; + + // Get acp files + $acp_files = filelist($phpbb_root_path . 'language/' . $row['lang_iso'], 'acp', $phpEx); + $acp_files = $acp_files['acp/']; + + // Get mod files + $mod_files = filelist($phpbb_root_path . 'language/' . $row['lang_iso'], 'mods', $phpEx); + $mod_files = (isset($mod_files['mods/'])) ? $mod_files['mods/'] : array(); + + // Add main files + $this->add_to_archive($compress, $this->main_files, $row['lang_iso']); + + // Add search files if they exist... + if (file_exists($phpbb_root_path . 'language/' . $row['lang_iso'] . '/search_ignore_words.' . $phpEx)) + { + $this->add_to_archive($compress, array("search_ignore_words.$phpEx"), $row['lang_iso']); + } + + if (file_exists($phpbb_root_path . 'language/' . $row['lang_iso'] . '/search_synonyms.' . $phpEx)) + { + $this->add_to_archive($compress, array("search_synonyms.$phpEx"), $row['lang_iso']); + } + + // Write files in folders + $this->add_to_archive($compress, $email_templates, $row['lang_iso'], 'email'); + $this->add_to_archive($compress, $acp_files, $row['lang_iso'], 'acp'); + $this->add_to_archive($compress, $mod_files, $row['lang_iso'], 'mods'); + + // Write ISO File + $iso_src = htmlspecialchars_decode($row['lang_english_name']) . "\n"; + $iso_src .= htmlspecialchars_decode($row['lang_local_name']) . "\n"; + $iso_src .= htmlspecialchars_decode($row['lang_author']); + $compress->add_data($iso_src, 'language/' . $row['lang_iso'] . '/iso.txt'); + + // index.html files + $compress->add_data('', 'language/' . $row['lang_iso'] . '/index.html'); + $compress->add_data('', 'language/' . $row['lang_iso'] . '/email/index.html'); + $compress->add_data('', 'language/' . $row['lang_iso'] . '/acp/index.html'); + + if (sizeof($mod_files)) + { + $compress->add_data('', 'language/' . $row['lang_iso'] . '/mods/index.html'); + } + + $compress->close(); + + $compress->download('lang_' . $row['lang_iso']); + @unlink($phpbb_root_path . 'store/lang_' . $row['lang_iso'] . $use_method); + + exit; + + break; + } + + $sql = 'SELECT user_lang, COUNT(user_lang) AS lang_count + FROM ' . USERS_TABLE . ' + GROUP BY user_lang'; + $result = $db->sql_query($sql); + + $lang_count = array(); + while ($row = $db->sql_fetchrow($result)) + { + $lang_count[$row['user_lang']] = $row['lang_count']; + } + $db->sql_freeresult($result); + + $sql = 'SELECT * + FROM ' . LANG_TABLE . ' + ORDER BY lang_english_name'; + $result = $db->sql_query($sql); + + $installed = array(); + + while ($row = $db->sql_fetchrow($result)) + { + $installed[] = $row['lang_iso']; + $tagstyle = ($row['lang_iso'] == $config['default_lang']) ? '*' : ''; + + $template->assign_block_vars('lang', array( + 'U_DETAILS' => $this->u_action . "&action=details&id={$row['lang_id']}", + 'U_DOWNLOAD' => $this->u_action . "&action=download&id={$row['lang_id']}", + 'U_DELETE' => $this->u_action . "&action=delete&id={$row['lang_id']}", + + 'ENGLISH_NAME' => $row['lang_english_name'], + 'TAG' => $tagstyle, + 'LOCAL_NAME' => $row['lang_local_name'], + 'ISO' => $row['lang_iso'], + 'USED_BY' => (isset($lang_count[$row['lang_iso']])) ? $lang_count[$row['lang_iso']] : 0, + )); + } + $db->sql_freeresult($result); + + $new_ary = $iso = array(); + $dp = @opendir("{$phpbb_root_path}language"); + + if ($dp) + { + while (($file = readdir($dp)) !== false) + { + if ($file[0] != '.' && file_exists("{$phpbb_root_path}language/$file/iso.txt")) + { + if (!in_array($file, $installed)) + { + if ($iso = file("{$phpbb_root_path}language/$file/iso.txt")) + { + if (sizeof($iso) == 3) + { + $new_ary[$file] = array( + 'iso' => $file, + 'name' => trim($iso[0]), + 'local_name'=> trim($iso[1]), + 'author' => trim($iso[2]) + ); + } + } + } + } + } + closedir($dp); + } + + unset($installed); + + if (sizeof($new_ary)) + { + foreach ($new_ary as $iso => $lang_ary) + { + $template->assign_block_vars('notinst', array( + 'ISO' => htmlspecialchars($lang_ary['iso']), + 'LOCAL_NAME' => htmlspecialchars($lang_ary['local_name'], ENT_COMPAT, 'UTF-8'), + 'NAME' => htmlspecialchars($lang_ary['name'], ENT_COMPAT, 'UTF-8'), + 'U_INSTALL' => $this->u_action . '&action=install&iso=' . urlencode($lang_ary['iso'])) + ); + } + } + + unset($new_ary); + } + + + /** + * Set default language variables/header + */ + function default_variables() + { + global $phpEx; + + $this->language_file_header = '<?php +/** +* +* {FILENAME} [{LANG_NAME}] +* +* @package language +* @version $' . 'Id: ' . '$ +* @copyright (c) ' . date('Y') . ' phpBB Group +* @author {CHANGED} - {AUTHOR} +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* DO NOT CHANGE +*/ +if (!defined(\'IN_PHPBB\')) +{ + exit; +} + +if (empty($lang) || !is_array($lang)) +{ + $lang = array(); +} + +// DEVELOPERS PLEASE NOTE +// +// All language files should use UTF-8 as their encoding and the files must not contain a BOM. +// +// Placeholders can now contain order information, e.g. instead of +// \'Page %s of %s\' you can (and should) write \'Page %1$s of %2$s\', this allows +// translators to re-order the output of data while ensuring it remains correct +// +// You do not need this where single placeholders are used, e.g. \'Message %d\' is fine +// equally where a string contains only two placeholders which are used to wrap text +// in a url you again do not need to specify an order e.g., \'Click %sHERE%s\' is fine +'; + + $this->lang_header = ' +$lang = array_merge($lang, array( +'; + + // Language files in language root directory + $this->main_files = array("common.$phpEx", "groups.$phpEx", "install.$phpEx", "mcp.$phpEx", "memberlist.$phpEx", "posting.$phpEx", "search.$phpEx", "ucp.$phpEx", "viewforum.$phpEx", "viewtopic.$phpEx", "help_bbcode.$phpEx", "help_faq.$phpEx"); + } + + /** + * Get filename/location of language file + */ + function get_filename($lang_iso, $directory, $filename, $check_store = false, $only_return_filename = false) + { + global $phpbb_root_path, $safe_mode; + + $check_filename = "language/$lang_iso/" . (($directory) ? $directory . '/' : '') . $filename; + + if ($check_store) + { + $check_store_filename = ($safe_mode) ? "store/langfile_{$lang_iso}" . (($directory) ? '_' . $directory : '') . "_{$filename}" : "store/language/$lang_iso/" . (($directory) ? $directory . '/' : '') . $filename; + + if (!$only_return_filename && file_exists($phpbb_root_path . $check_store_filename)) + { + return $check_store_filename; + } + else if ($only_return_filename) + { + return $check_store_filename; + } + } + + return $check_filename; + } + + /** + * Add files to archive + */ + function add_to_archive(&$compress, $filelist, $lang_iso, $directory = '') + { + global $phpbb_root_path; + + foreach ($filelist as $file) + { + // Get source filename + $source = $this->get_filename($lang_iso, $directory, $file, true); + $destination = 'language/' . $lang_iso . '/' . (($directory) ? $directory . '/' : '') . $file; + + // Add file to archive + $compress->add_custom_file($phpbb_root_path . $source, $destination); + } + } + + /** + * Little helper to add some hardcoded template bits + */ + function add_input_field() + { + $keys = func_get_args(); + + $non_static = array_shift($keys); + $value = utf8_normalize_nfc(array_shift($keys)); + + if (!$non_static) + { + return '<strong>' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '</strong>'; + } + + // If more then 270 characters, then we present a textarea, else an input field + $textarea = (utf8_strlen($value) > 270) ? true : false; + $tpl = ''; + + $tpl .= ($textarea) ? '<textarea name="' : '<input type="text" name="'; + $tpl .= 'entry[' . implode('][', array_map('utf8_htmlspecialchars', $keys)) . ']"'; + + $tpl .= ($textarea) ? ' cols="80" rows="5" class="langvalue">' : ' class="langvalue" value="'; + $tpl .= htmlspecialchars($value, ENT_COMPAT, 'UTF-8'); + $tpl .= ($textarea) ? '</textarea>' : '" />'; + + return $tpl; + } + + /** + * Print language entries + */ + function print_language_entries(&$lang_ary, $key_prefix = '', $input_field = true) + { + $tpl = ''; + + foreach ($lang_ary as $key => $value) + { + if (is_array($value)) + { + // Write key + $tpl .= ' + <tr> + <td class="row3" colspan="2">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<strong>' . htmlspecialchars($key, ENT_COMPAT, 'UTF-8') . '</strong></td> + </tr>'; + + foreach ($value as $_key => $_value) + { + if (is_array($_value)) + { + // Write key + $tpl .= ' + <tr> + <td class="row3" colspan="2">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . ' <strong>' . htmlspecialchars($_key, ENT_COMPAT, 'UTF-8') . '</strong></td> + </tr>'; + + foreach ($_value as $__key => $__value) + { + // Write key + $tpl .= ' + <tr> + <td class="row1" style="white-space: nowrap;">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<strong>' . htmlspecialchars($__key, ENT_COMPAT, 'UTF-8') . '</strong></td> + <td class="row2">'; + + $tpl .= $this->add_input_field($input_field, $__value, $key, $_key, $__key); + + $tpl .= '</td> + </tr>'; + } + } + else + { + // Write key + $tpl .= ' + <tr> + <td class="row1" style="white-space: nowrap;">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<strong>' . htmlspecialchars($_key, ENT_COMPAT, 'UTF-8') . '</strong></td> + <td class="row2">'; + + $tpl .= $this->add_input_field($input_field, $_value, $key, $_key); + + $tpl .= '</td> + </tr>'; + } + } + + $tpl .= ' + <tr> + <td class="spacer" colspan="2"> </td> + </tr>'; + } + else + { + // Write key + $tpl .= ' + <tr> + <td class="row1" style="white-space: nowrap;">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<strong>' . htmlspecialchars($key, ENT_COMPAT, 'UTF-8') . '</strong></td> + <td class="row2">'; + + $tpl .= $this->add_input_field($input_field, $value, $key); + + $tpl .= '</td> + </tr>'; + } + } + + return $tpl; + } + + /** + * Compare two language files + */ + function compare_language_files($source_lang, $dest_lang, $directory, $file) + { + global $phpbb_root_path, $phpEx; + + $return_ary = array(); + + $lang = array(); + include("{$phpbb_root_path}language/{$source_lang}/" . (($directory) ? $directory . '/' : '') . $file); + $lang_entry_src = $lang; + + $lang = array(); + + if (!file_exists($phpbb_root_path . $this->get_filename($dest_lang, $directory, $file, true))) + { + return array(); + } + + include($phpbb_root_path . $this->get_filename($dest_lang, $directory, $file, true)); + + $lang_entry_dst = $lang; + + unset($lang); + + $diff_array_keys = array_diff(array_keys($lang_entry_src), array_keys($lang_entry_dst)); + unset($lang_entry_dst); + + foreach ($diff_array_keys as $key) + { + $return_ary[$key] = $lang_entry_src[$key]; + } + + unset($lang_entry_src); + + return $return_ary; + } + + /** + * Return language string value for storage + */ + function prepare_lang_entry($text, $store = true) + { + $text = (STRIP) ? stripslashes($text) : $text; + + // Adjust for storage... + if ($store) + { + $text = str_replace("'", "\\'", str_replace('\\', '\\\\', $text)); + } + + return $text; + } + + /** + * Format language array for storage + */ + function format_lang_array($key, $value, $tabs = "\t") + { + $entry = ''; + + if (!is_array($value)) + { + $entry .= "{$tabs}'" . $this->prepare_lang_entry($key) . "'\t=> '" . $this->prepare_lang_entry($value) . "',\n"; + } + else + { + $_tabs = $tabs . "\t"; + $entry .= "\n{$tabs}'" . $this->prepare_lang_entry($key) . "'\t=> array(\n"; + + foreach ($value as $_key => $_value) + { + $entry .= $this->format_lang_array($_key, $_value, $_tabs); + } + + $entry .= "{$tabs}),\n\n"; + } + + return $entry; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_logs.php b/phpBB/includes/acp/acp_logs.php new file mode 100644 index 0000000000..0f4f78fcdd --- /dev/null +++ b/phpBB/includes/acp/acp_logs.php @@ -0,0 +1,176 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_logs +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + $user->add_lang('mcp'); + + // Set up general vars + $action = request_var('action', ''); + $forum_id = request_var('f', 0); + $topic_id = request_var('t', 0); + $start = request_var('start', 0); + $deletemark = (!empty($_POST['delmarked'])) ? true : false; + $deleteall = (!empty($_POST['delall'])) ? true : false; + $marked = request_var('mark', array(0)); + + // Sort keys + $sort_days = request_var('st', 0); + $sort_key = request_var('sk', 't'); + $sort_dir = request_var('sd', 'd'); + + $this->tpl_name = 'acp_logs'; + $this->log_type = constant('LOG_' . strtoupper($mode)); + + // Delete entries if requested and able + if (($deletemark || $deleteall) && $auth->acl_get('a_clearlogs')) + { + if (confirm_box(true)) + { + $where_sql = ''; + + if ($deletemark && sizeof($marked)) + { + $sql_in = array(); + foreach ($marked as $mark) + { + $sql_in[] = $mark; + } + $where_sql = ' AND ' . $db->sql_in_set('log_id', $sql_in); + unset($sql_in); + } + + if ($where_sql || $deleteall) + { + $sql = 'DELETE FROM ' . LOG_TABLE . " + WHERE log_type = {$this->log_type} + $where_sql"; + $db->sql_query($sql); + + add_log('admin', 'LOG_CLEAR_' . strtoupper($mode)); + } + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'f' => $forum_id, + 'start' => $start, + 'delmarked' => $deletemark, + 'delall' => $deleteall, + 'mark' => $marked, + 'st' => $sort_days, + 'sk' => $sort_key, + 'sd' => $sort_dir, + 'i' => $id, + 'mode' => $mode, + 'action' => $action)) + ); + } + } + + // Sorting + $limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + $sort_by_text = array('u' => $user->lang['SORT_USERNAME'], 't' => $user->lang['SORT_DATE'], 'i' => $user->lang['SORT_IP'], 'o' => $user->lang['SORT_ACTION']); + $sort_by_sql = array('u' => 'u.username_clean', 't' => 'l.log_time', 'i' => 'l.log_ip', 'o' => 'l.log_operation'); + + $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = ''; + 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); + + // Define where and sort sql for use in displaying logs + $sql_where = ($sort_days) ? (time() - ($sort_days * 86400)) : 0; + $sql_sort = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC'); + + $keywords = utf8_normalize_nfc(request_var('keywords', '', true)); + $keywords_param = !empty($keywords) ? '&keywords=' . urlencode(htmlspecialchars_decode($keywords)) : ''; + + $l_title = $user->lang['ACP_' . strtoupper($mode) . '_LOGS']; + $l_title_explain = $user->lang['ACP_' . strtoupper($mode) . '_LOGS_EXPLAIN']; + + $this->page_title = $l_title; + + // Define forum list if we're looking @ mod logs + if ($mode == 'mod') + { + $forum_box = '<option value="0">' . $user->lang['ALL_FORUMS'] . '</option>' . make_forum_select($forum_id); + + $template->assign_vars(array( + 'S_SHOW_FORUMS' => true, + 'S_FORUM_BOX' => $forum_box) + ); + } + + // Grab log data + $log_data = array(); + $log_count = 0; + view_log($mode, $log_data, $log_count, $config['topics_per_page'], $start, $forum_id, 0, 0, $sql_where, $sql_sort, $keywords); + + $template->assign_vars(array( + 'L_TITLE' => $l_title, + 'L_EXPLAIN' => $l_title_explain, + 'U_ACTION' => $this->u_action, + + 'S_ON_PAGE' => on_page($log_count, $config['topics_per_page'], $start), + 'PAGINATION' => generate_pagination($this->u_action . "&$u_sort_param$keywords_param", $log_count, $config['topics_per_page'], $start, true), + + 'S_LIMIT_DAYS' => $s_limit_days, + 'S_SORT_KEY' => $s_sort_key, + 'S_SORT_DIR' => $s_sort_dir, + 'S_CLEARLOGS' => $auth->acl_get('a_clearlogs'), + 'S_KEYWORDS' => $keywords, + ) + ); + + foreach ($log_data as $row) + { + $data = array(); + + $checks = array('viewtopic', 'viewlogs', 'viewforum'); + foreach ($checks as $check) + { + if (isset($row[$check]) && $row[$check]) + { + $data[] = '<a href="' . $row[$check] . '">' . $user->lang['LOGVIEW_' . strtoupper($check)] . '</a>'; + } + } + + $template->assign_block_vars('log', array( + 'USERNAME' => $row['username_full'], + 'REPORTEE_USERNAME' => ($row['reportee_username'] && $row['user_id'] != $row['reportee_id']) ? $row['reportee_username_full'] : '', + + 'IP' => $row['ip'], + 'DATE' => $user->format_date($row['time']), + 'ACTION' => $row['action'], + 'DATA' => (sizeof($data)) ? implode(' | ', $data) : '', + 'ID' => $row['id'], + ) + ); + } + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php new file mode 100644 index 0000000000..cd83c52e01 --- /dev/null +++ b/phpBB/includes/acp/acp_main.php @@ -0,0 +1,609 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_main +{ + var $u_action; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template; + global $phpbb_root_path, $phpbb_admin_path, $phpEx; + + // Show restore permissions notice + if ($user->data['user_perm_from'] && $auth->acl_get('a_switchperm')) + { + $this->tpl_name = 'acp_main'; + $this->page_title = 'ACP_MAIN'; + + $sql = 'SELECT user_id, username, user_colour + FROM ' . USERS_TABLE . ' + WHERE user_id = ' . $user->data['user_perm_from']; + $result = $db->sql_query($sql); + $user_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $perm_from = '<strong' . (($user_row['user_colour']) ? ' style="color: #' . $user_row['user_colour'] . '">' : '>'); + $perm_from .= ($user_row['user_id'] != ANONYMOUS) ? '<a href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $user_row['user_id']) . '">' : ''; + $perm_from .= $user_row['username']; + $perm_from .= ($user_row['user_id'] != ANONYMOUS) ? '</a>' : ''; + $perm_from .= '</strong>'; + + $template->assign_vars(array( + 'S_RESTORE_PERMISSIONS' => true, + 'U_RESTORE_PERMISSIONS' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=restore_perm'), + 'PERM_FROM' => $perm_from, + 'L_PERMISSIONS_TRANSFERRED_EXPLAIN' => sprintf($user->lang['PERMISSIONS_TRANSFERRED_EXPLAIN'], $perm_from, append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=restore_perm')), + )); + + return; + } + + $action = request_var('action', ''); + + if ($action) + { + if ($action === 'admlogout') + { + $user->unset_admin(); + $redirect_url = append_sid("{$phpbb_root_path}index.$phpEx"); + meta_refresh(3, $redirect_url); + trigger_error($user->lang['ADM_LOGGED_OUT'] . '<br /><br />' . sprintf($user->lang['RETURN_INDEX'], '<a href="' . $redirect_url . '">', '</a>')); + } + + if (!confirm_box(true)) + { + switch ($action) + { + case 'online': + $confirm = true; + $confirm_lang = 'RESET_ONLINE_CONFIRM'; + break; + case 'stats': + $confirm = true; + $confirm_lang = 'RESYNC_STATS_CONFIRM'; + break; + case 'user': + $confirm = true; + $confirm_lang = 'RESYNC_POSTCOUNTS_CONFIRM'; + break; + case 'date': + $confirm = true; + $confirm_lang = 'RESET_DATE_CONFIRM'; + break; + case 'db_track': + $confirm = true; + $confirm_lang = 'RESYNC_POST_MARKING_CONFIRM'; + break; + case 'purge_cache': + $confirm = true; + $confirm_lang = 'PURGE_CACHE_CONFIRM'; + break; + case 'purge_sessions': + $confirm = true; + $confirm_lang = 'PURGE_SESSIONS_CONFIRM'; + break; + + default: + $confirm = true; + $confirm_lang = 'CONFIRM_OPERATION'; + } + + if ($confirm) + { + confirm_box(false, $user->lang[$confirm_lang], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + ))); + } + } + else + { + switch ($action) + { + + case 'online': + if (!$auth->acl_get('a_board')) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + set_config('record_online_users', 1, true); + set_config('record_online_date', time(), true); + add_log('admin', 'LOG_RESET_ONLINE'); + break; + + case 'stats': + if (!$auth->acl_get('a_board')) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT COUNT(post_id) AS stat + FROM ' . POSTS_TABLE . ' + WHERE post_approved = 1'; + $result = $db->sql_query($sql); + set_config('num_posts', (int) $db->sql_fetchfield('stat'), true); + $db->sql_freeresult($result); + + $sql = 'SELECT COUNT(topic_id) AS stat + FROM ' . TOPICS_TABLE . ' + WHERE topic_approved = 1'; + $result = $db->sql_query($sql); + set_config('num_topics', (int) $db->sql_fetchfield('stat'), true); + $db->sql_freeresult($result); + + $sql = 'SELECT COUNT(user_id) AS stat + FROM ' . USERS_TABLE . ' + WHERE user_type IN (' . USER_NORMAL . ',' . USER_FOUNDER . ')'; + $result = $db->sql_query($sql); + set_config('num_users', (int) $db->sql_fetchfield('stat'), true); + $db->sql_freeresult($result); + + $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); + + if (!function_exists('update_last_username')) + { + include($phpbb_root_path . "includes/functions_user.$phpEx"); + } + update_last_username(); + + add_log('admin', 'LOG_RESYNC_STATS'); + break; + + case 'user': + if (!$auth->acl_get('a_board')) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Resync post counts + $start = $max_post_id = 0; + + // Find the maximum post ID, we can only stop the cycle when we've reached it + $sql = 'SELECT MAX(forum_last_post_id) as max_post_id + FROM ' . FORUMS_TABLE; + $result = $db->sql_query($sql); + $max_post_id = (int) $db->sql_fetchfield('max_post_id'); + $db->sql_freeresult($result); + + // No maximum post id? :o + if (!$max_post_id) + { + $sql = 'SELECT MAX(post_id) + FROM ' . POSTS_TABLE; + $result = $db->sql_query($sql); + $max_post_id = (int) $db->sql_fetchfield('max_post_id'); + $db->sql_freeresult($result); + } + + // Still no maximum post id? Then we are finished + if (!$max_post_id) + { + add_log('admin', 'LOG_RESYNC_POSTCOUNTS'); + break; + } + + $step = ($config['num_posts']) ? (max((int) ($config['num_posts'] / 5), 20000)) : 20000; + $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_posts = 0'); + + while ($start < $max_post_id) + { + $sql = 'SELECT COUNT(post_id) AS num_posts, poster_id + FROM ' . POSTS_TABLE . ' + WHERE post_id BETWEEN ' . ($start + 1) . ' AND ' . ($start + $step) . ' + AND post_postcount = 1 AND post_approved = 1 + GROUP BY poster_id'; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + do + { + $sql = 'UPDATE ' . USERS_TABLE . " SET user_posts = user_posts + {$row['num_posts']} WHERE user_id = {$row['poster_id']}"; + $db->sql_query($sql); + } + while ($row = $db->sql_fetchrow($result)); + } + $db->sql_freeresult($result); + + $start += $step; + } + + add_log('admin', 'LOG_RESYNC_POSTCOUNTS'); + + break; + + case 'date': + if (!$auth->acl_get('a_board')) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + set_config('board_startdate', time() - 1); + add_log('admin', 'LOG_RESET_DATE'); + break; + + case 'db_track': + switch ($db->sql_layer) + { + case 'sqlite': + case 'firebird': + $db->sql_query('DELETE FROM ' . TOPICS_POSTED_TABLE); + break; + + default: + $db->sql_query('TRUNCATE TABLE ' . TOPICS_POSTED_TABLE); + break; + } + + // 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); + } + } + + add_log('admin', 'LOG_RESYNC_POST_MARKING'); + break; + + case 'purge_cache': + if ((int) $user->data['user_type'] !== USER_FOUNDER) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + global $cache; + $cache->purge(); + + // Clear permissions + $auth->acl_clear_prefetch(); + cache_moderators(); + + add_log('admin', 'LOG_PURGE_CACHE'); + break; + + case 'purge_sessions': + if ((int) $user->data['user_type'] !== USER_FOUNDER) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $tables = array(CONFIRM_TABLE, SESSIONS_TABLE); + + foreach ($tables as $table) + { + switch ($db->sql_layer) + { + case 'sqlite': + case 'firebird': + $db->sql_query("DELETE FROM $table"); + break; + + default: + $db->sql_query("TRUNCATE TABLE $table"); + break; + } + } + + // let's restore the admin session + $reinsert_ary = array( + 'session_id' => (string) $user->session_id, + 'session_page' => (string) substr($user->page['page'], 0, 199), + 'session_forum_id' => $user->page['forum'], + 'session_user_id' => (int) $user->data['user_id'], + 'session_start' => (int) $user->data['session_start'], + 'session_last_visit' => (int) $user->data['session_last_visit'], + 'session_time' => (int) $user->time_now, + 'session_browser' => (string) trim(substr($user->browser, 0, 149)), + 'session_forwarded_for' => (string) $user->forwarded_for, + 'session_ip' => (string) $user->ip, + 'session_autologin' => (int) $user->data['session_autologin'], + 'session_admin' => 1, + 'session_viewonline' => (int) $user->data['session_viewonline'], + ); + + $sql = 'INSERT INTO ' . SESSIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $reinsert_ary); + $db->sql_query($sql); + + add_log('admin', 'LOG_PURGE_SESSIONS'); + break; + } + } + } + + // Version check + $user->add_lang('install'); + + $latest_version_info = false; + if (($latest_version_info = obtain_latest_version_info(request_var('versioncheck_force', false))) === false) + { + $template->assign_var('S_VERSIONCHECK_FAIL', true); + } + else + { + $latest_version_info = explode("\n", $latest_version_info); + + $latest_version = str_replace('rc', 'RC', strtolower(trim($latest_version_info[0]))); + $current_version = str_replace('rc', 'RC', strtolower($config['version'])); + + $template->assign_vars(array( + 'S_VERSION_UP_TO_DATE' => version_compare($current_version, $latest_version, '<') ? false : true, + )); + } + + // Get forum statistics + $total_posts = $config['num_posts']; + $total_topics = $config['num_topics']; + $total_users = $config['num_users']; + $total_files = $config['num_files']; + + $start_date = $user->format_date($config['board_startdate']); + + $boarddays = (time() - $config['board_startdate']) / 86400; + + $posts_per_day = sprintf('%.2f', $total_posts / $boarddays); + $topics_per_day = sprintf('%.2f', $total_topics / $boarddays); + $users_per_day = sprintf('%.2f', $total_users / $boarddays); + $files_per_day = sprintf('%.2f', $total_files / $boarddays); + + $upload_dir_size = get_formatted_filesize($config['upload_dir_size']); + + $avatar_dir_size = 0; + + if ($avatar_dir = @opendir($phpbb_root_path . $config['avatar_path'])) + { + while (($file = readdir($avatar_dir)) !== false) + { + if ($file[0] != '.' && $file != 'CVS' && strpos($file, 'index.') === false) + { + $avatar_dir_size += filesize($phpbb_root_path . $config['avatar_path'] . '/' . $file); + } + } + closedir($avatar_dir); + + $avatar_dir_size = get_formatted_filesize($avatar_dir_size); + } + else + { + // Couldn't open Avatar dir. + $avatar_dir_size = $user->lang['NOT_AVAILABLE']; + } + + if ($posts_per_day > $total_posts) + { + $posts_per_day = $total_posts; + } + + if ($topics_per_day > $total_topics) + { + $topics_per_day = $total_topics; + } + + if ($users_per_day > $total_users) + { + $users_per_day = $total_users; + } + + if ($files_per_day > $total_files) + { + $files_per_day = $total_files; + } + + if ($config['allow_attachments'] || $config['allow_pm_attach']) + { + $sql = 'SELECT COUNT(attach_id) AS total_orphan + FROM ' . ATTACHMENTS_TABLE . ' + WHERE is_orphan = 1 + AND filetime < ' . (time() - 3*60*60); + $result = $db->sql_query($sql); + $total_orphan = (int) $db->sql_fetchfield('total_orphan'); + $db->sql_freeresult($result); + } + else + { + $total_orphan = false; + } + + $dbsize = get_database_size(); + + $template->assign_vars(array( + 'TOTAL_POSTS' => $total_posts, + 'POSTS_PER_DAY' => $posts_per_day, + 'TOTAL_TOPICS' => $total_topics, + 'TOPICS_PER_DAY' => $topics_per_day, + 'TOTAL_USERS' => $total_users, + 'USERS_PER_DAY' => $users_per_day, + 'TOTAL_FILES' => $total_files, + 'FILES_PER_DAY' => $files_per_day, + 'START_DATE' => $start_date, + 'AVATAR_DIR_SIZE' => $avatar_dir_size, + 'DBSIZE' => $dbsize, + 'UPLOAD_DIR_SIZE' => $upload_dir_size, + 'TOTAL_ORPHAN' => $total_orphan, + 'S_TOTAL_ORPHAN' => ($total_orphan === false) ? false : true, + 'GZIP_COMPRESSION' => ($config['gzip_compress'] && @extension_loaded('zlib')) ? $user->lang['ON'] : $user->lang['OFF'], + 'DATABASE_INFO' => $db->sql_server_info(), + 'BOARD_VERSION' => $config['version'], + + 'U_ACTION' => $this->u_action, + 'U_ADMIN_LOG' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=logs&mode=admin'), + 'U_INACTIVE_USERS' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=inactive&mode=list'), + 'U_VERSIONCHECK' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=update&mode=version_check'), + 'U_VERSIONCHECK_FORCE' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=1&versioncheck_force=1'), + + 'S_ACTION_OPTIONS' => ($auth->acl_get('a_board')) ? true : false, + 'S_FOUNDER' => ($user->data['user_type'] == USER_FOUNDER) ? true : false, + ) + ); + + $log_data = array(); + $log_count = 0; + + if ($auth->acl_get('a_viewlogs')) + { + view_log('admin', $log_data, $log_count, 5); + + foreach ($log_data as $row) + { + $template->assign_block_vars('log', array( + 'USERNAME' => $row['username_full'], + 'IP' => $row['ip'], + 'DATE' => $user->format_date($row['time']), + 'ACTION' => $row['action']) + ); + } + } + + if ($auth->acl_get('a_user')) + { + $user->add_lang('memberlist'); + + $inactive = array(); + $inactive_count = 0; + + view_inactive_users($inactive, $inactive_count, 10); + + foreach ($inactive as $row) + { + $template->assign_block_vars('inactive', array( + 'INACTIVE_DATE' => $user->format_date($row['user_inactive_time']), + 'REMINDED_DATE' => $user->format_date($row['user_reminded_time']), + 'JOINED' => $user->format_date($row['user_regdate']), + 'LAST_VISIT' => (!$row['user_lastvisit']) ? ' - ' : $user->format_date($row['user_lastvisit']), + + 'REASON' => $row['inactive_reason'], + 'USER_ID' => $row['user_id'], + 'POSTS' => ($row['user_posts']) ? $row['user_posts'] : 0, + 'REMINDED' => $row['user_reminded'], + + 'REMINDED_EXPLAIN' => $user->lang('USER_LAST_REMINDED', (int) $row['user_reminded'], $user->format_date($row['user_reminded_time'])), + + 'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], false, append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&mode=overview')), + 'USERNAME' => get_username_string('username', $row['user_id'], $row['username'], $row['user_colour']), + 'USER_COLOR' => get_username_string('colour', $row['user_id'], $row['username'], $row['user_colour']), + + 'U_USER_ADMIN' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=users&mode=overview&u={$row['user_id']}"), + 'U_SEARCH_USER' => ($auth->acl_get('u_search')) ? append_sid("{$phpbb_root_path}search.$phpEx", "author_id={$row['user_id']}&sr=posts") : '', + )); + } + + $option_ary = array('activate' => 'ACTIVATE', 'delete' => 'DELETE'); + if ($config['email_enable']) + { + $option_ary += array('remind' => 'REMIND'); + } + + $template->assign_vars(array( + 'S_INACTIVE_USERS' => true, + 'S_INACTIVE_OPTIONS' => build_select($option_ary)) + ); + } + + // Warn if install is still present + if (file_exists($phpbb_root_path . 'install') && !is_file($phpbb_root_path . 'install')) + { + $template->assign_var('S_REMOVE_INSTALL', true); + } + + if (!defined('PHPBB_DISABLE_CONFIG_CHECK') && file_exists($phpbb_root_path . 'config.' . $phpEx) && phpbb_is_writable($phpbb_root_path . 'config.' . $phpEx)) + { + // World-Writable? (000x) + $template->assign_var('S_WRITABLE_CONFIG', (bool) (@fileperms($phpbb_root_path . 'config.' . $phpEx) & 0x0002)); + } + + // Fill dbms version if not yet filled + if (empty($config['dbms_version'])) + { + set_config('dbms_version', $db->sql_server_info(true)); + } + + $this->tpl_name = 'acp_main'; + $this->page_title = 'ACP_MAIN'; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_modules.php b/phpBB/includes/acp/acp_modules.php new file mode 100644 index 0000000000..75bc5766a9 --- /dev/null +++ b/phpBB/includes/acp/acp_modules.php @@ -0,0 +1,1065 @@ +<?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; +} + +/** +* - Able to check for new module versions (modes changed/adjusted/added/removed) +* Icons for: +* - module enabled and displayed (common) +* - module enabled and not displayed +* - module deactivated +* - category (enabled) +* - category disabled +*/ + +/** +* @package acp +*/ +class acp_modules +{ + var $module_class = ''; + var $parent_id; + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $module; + global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx; + + // Set a global define for modules we might include (the author is able to prevent execution of code by checking this constant) + define('MODULE_INCLUDE', true); + + $user->add_lang('acp/modules'); + $this->tpl_name = 'acp_modules'; + + // module class + $this->module_class = $mode; + + if ($this->module_class == 'ucp') + { + $user->add_lang('ucp'); + } + else if ($this->module_class == 'mcp') + { + $user->add_lang('mcp'); + } + + if ($module->p_class != $this->module_class) + { + $module->add_mod_info($this->module_class); + } + + $this->page_title = strtoupper($this->module_class); + + $this->parent_id = request_var('parent_id', 0); + $module_id = request_var('m', 0); + $action = request_var('action', ''); + $errors = array(); + + switch ($action) + { + case 'delete': + if (!$module_id) + { + trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + if (confirm_box(true)) + { + // Make sure we are not directly within a module + if ($module_id == $this->parent_id) + { + $sql = 'SELECT parent_id + FROM ' . MODULES_TABLE . ' + WHERE module_id = ' . $module_id; + $result = $db->sql_query($sql); + $this->parent_id = (int) $db->sql_fetchfield('parent_id'); + $db->sql_freeresult($result); + } + + $errors = $this->delete_module($module_id); + + if (!sizeof($errors)) + { + $this->remove_cache_file(); + trigger_error($user->lang['MODULE_DELETED'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); + } + } + else + { + confirm_box(false, 'DELETE_MODULE', build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'parent_id' => $this->parent_id, + 'module_id' => $module_id, + 'action' => $action, + ))); + } + + break; + + case 'enable': + case 'disable': + if (!$module_id) + { + trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND module_id = $module_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error($user->lang['NO_MODULE'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + $sql = 'UPDATE ' . MODULES_TABLE . ' + SET module_enabled = ' . (($action == 'enable') ? 1 : 0) . " + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND module_id = $module_id"; + $db->sql_query($sql); + + add_log('admin', 'LOG_MODULE_' . strtoupper($action), $this->lang_name($row['module_langname'])); + $this->remove_cache_file(); + + break; + + case 'move_up': + case 'move_down': + if (!$module_id) + { + trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND module_id = $module_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error($user->lang['NO_MODULE'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + $move_module_name = $this->move_module_by($row, $action, 1); + + if ($move_module_name !== false) + { + add_log('admin', 'LOG_MODULE_' . strtoupper($action), $this->lang_name($row['module_langname']), $move_module_name); + $this->remove_cache_file(); + } + + break; + + case 'quickadd': + $quick_install = request_var('quick_install', ''); + + if (confirm_box(true)) + { + if (!$quick_install || strpos($quick_install, '::') === false) + { + break; + } + + list($module_basename, $module_mode) = explode('::', $quick_install); + + // Check if module name and mode exist... + $fileinfo = $this->get_module_infos($module_basename); + $fileinfo = $fileinfo[$module_basename]; + + if (isset($fileinfo['modes'][$module_mode])) + { + $module_data = array( + 'module_basename' => $module_basename, + 'module_enabled' => 0, + 'module_display' => (isset($fileinfo['modes'][$module_mode]['display'])) ? $fileinfo['modes'][$module_mode]['display'] : 1, + 'parent_id' => $this->parent_id, + 'module_class' => $this->module_class, + 'module_langname' => $fileinfo['modes'][$module_mode]['title'], + 'module_mode' => $module_mode, + 'module_auth' => $fileinfo['modes'][$module_mode]['auth'], + ); + + $errors = $this->update_module_data($module_data); + + if (!sizeof($errors)) + { + $this->remove_cache_file(); + + trigger_error($user->lang['MODULE_ADDED'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); + } + } + } + else + { + confirm_box(false, 'ADD_MODULE', build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'parent_id' => $this->parent_id, + 'action' => 'quickadd', + 'quick_install' => $quick_install, + ))); + } + + break; + + case 'edit': + + if (!$module_id) + { + trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + $module_row = $this->get_module_row($module_id); + + // no break + + case 'add': + + if ($action == 'add') + { + $module_row = array( + 'module_basename' => '', + 'module_enabled' => 0, + 'module_display' => 1, + 'parent_id' => 0, + 'module_langname' => utf8_normalize_nfc(request_var('module_langname', '', true)), + 'module_mode' => '', + 'module_auth' => '', + ); + } + + $module_data = array(); + + $module_data['module_basename'] = request_var('module_basename', (string) $module_row['module_basename']); + $module_data['module_enabled'] = request_var('module_enabled', (int) $module_row['module_enabled']); + $module_data['module_display'] = request_var('module_display', (int) $module_row['module_display']); + $module_data['parent_id'] = request_var('module_parent_id', (int) $module_row['parent_id']); + $module_data['module_class'] = $this->module_class; + $module_data['module_langname'] = utf8_normalize_nfc(request_var('module_langname', (string) $module_row['module_langname'], true)); + $module_data['module_mode'] = request_var('module_mode', (string) $module_row['module_mode']); + + $submit = (isset($_POST['submit'])) ? true : false; + + if ($submit) + { + if (!$module_data['module_langname']) + { + trigger_error($user->lang['NO_MODULE_LANGNAME'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + $module_type = request_var('module_type', 'category'); + + if ($module_type == 'category') + { + $module_data['module_basename'] = $module_data['module_mode'] = $module_data['module_auth'] = ''; + $module_data['module_display'] = 1; + } + + if ($action == 'edit') + { + $module_data['module_id'] = $module_id; + } + + // Adjust auth row + if ($module_data['module_basename'] && $module_data['module_mode']) + { + $fileinfo = $this->get_module_infos($module_data['module_basename']); + $module_data['module_auth'] = $fileinfo[$module_data['module_basename']]['modes'][$module_data['module_mode']]['auth']; + } + + $errors = $this->update_module_data($module_data); + + if (!sizeof($errors)) + { + $this->remove_cache_file(); + + trigger_error((($action == 'add') ? $user->lang['MODULE_ADDED'] : $user->lang['MODULE_EDITED']) . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); + } + } + + // Category/not category? + $is_cat = (!$module_data['module_basename']) ? true : false; + + // Get module information + $module_infos = $this->get_module_infos(); + + // Build name options + $s_name_options = $s_mode_options = ''; + foreach ($module_infos as $option => $values) + { + if (!$module_data['module_basename']) + { + $module_data['module_basename'] = $option; + } + + // Name options + $s_name_options .= '<option value="' . $option . '"' . (($option == $module_data['module_basename']) ? ' selected="selected"' : '') . '>' . $this->lang_name($values['title']) . ' [' . $this->module_class . '_' . $option . ']</option>'; + + $template->assign_block_vars('m_names', array('NAME' => $option, 'A_NAME' => addslashes($option))); + + // Build module modes + foreach ($values['modes'] as $m_mode => $m_values) + { + if ($option == $module_data['module_basename']) + { + $s_mode_options .= '<option value="' . $m_mode . '"' . (($m_mode == $module_data['module_mode']) ? ' selected="selected"' : '') . '>' . $this->lang_name($m_values['title']) . '</option>'; + } + + $template->assign_block_vars('m_names.modes', array( + 'OPTION' => $m_mode, + 'VALUE' => $this->lang_name($m_values['title']), + 'A_OPTION' => addslashes($m_mode), + 'A_VALUE' => addslashes($this->lang_name($m_values['title']))) + ); + } + } + + $s_cat_option = '<option value="0"' . (($module_data['parent_id'] == 0) ? ' selected="selected"' : '') . '>' . $user->lang['NO_PARENT'] . '</option>'; + + $template->assign_vars(array_merge(array( + 'S_EDIT_MODULE' => true, + 'S_IS_CAT' => $is_cat, + 'S_CAT_OPTIONS' => $s_cat_option . $this->make_module_select($module_data['parent_id'], ($action == 'edit') ? $module_row['module_id'] : false, false, false, false, true), + 'S_MODULE_NAMES' => $s_name_options, + 'S_MODULE_MODES' => $s_mode_options, + 'U_BACK' => $this->u_action . '&parent_id=' . $this->parent_id, + 'U_EDIT_ACTION' => $this->u_action . '&parent_id=' . $this->parent_id, + + 'L_TITLE' => $user->lang[strtoupper($action) . '_MODULE'], + + 'MODULENAME' => $this->lang_name($module_data['module_langname']), + 'ACTION' => $action, + 'MODULE_ID' => $module_id, + + ), + array_change_key_case($module_data, CASE_UPPER)) + ); + + if (sizeof($errors)) + { + $template->assign_vars(array( + 'S_ERROR' => true, + 'ERROR_MSG' => implode('<br />', $errors)) + ); + } + + return; + + break; + } + + // Default management page + if (sizeof($errors)) + { + $template->assign_vars(array( + 'S_ERROR' => true, + 'ERROR_MSG' => implode('<br />', $errors)) + ); + } + + if (!$this->parent_id) + { + $navigation = strtoupper($this->module_class); + } + else + { + $navigation = '<a href="' . $this->u_action . '">' . strtoupper($this->module_class) . '</a>'; + + $modules_nav = $this->get_module_branch($this->parent_id, 'parents', 'descending'); + + foreach ($modules_nav as $row) + { + $langname = $this->lang_name($row['module_langname']); + + if ($row['module_id'] == $this->parent_id) + { + $navigation .= ' -> ' . $langname; + } + else + { + $navigation .= ' -> <a href="' . $this->u_action . '&parent_id=' . $row['module_id'] . '">' . $langname . '</a>'; + } + } + } + + // Jumpbox + $module_box = $this->make_module_select($this->parent_id, false, false, false, false); + + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE parent_id = {$this->parent_id} + AND module_class = '" . $db->sql_escape($this->module_class) . "' + ORDER BY left_id"; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + do + { + $langname = $this->lang_name($row['module_langname']); + + if (!$row['module_enabled']) + { + $module_image = '<img src="images/icon_folder_lock.gif" alt="' . $user->lang['DEACTIVATED_MODULE'] .'" />'; + } + else + { + $module_image = (!$row['module_basename'] || $row['left_id'] + 1 != $row['right_id']) ? '<img src="images/icon_subfolder.gif" alt="' . $user->lang['CATEGORY'] . '" />' : '<img src="images/icon_folder.gif" alt="' . $user->lang['MODULE'] . '" />'; + } + + $url = $this->u_action . '&parent_id=' . $this->parent_id . '&m=' . $row['module_id']; + + $template->assign_block_vars('modules', array( + 'MODULE_IMAGE' => $module_image, + 'MODULE_TITLE' => $langname, + 'MODULE_ENABLED' => ($row['module_enabled']) ? true : false, + 'MODULE_DISPLAYED' => ($row['module_display']) ? true : false, + + 'S_ACP_CAT_SYSTEM' => ($this->module_class == 'acp' && $row['module_langname'] == 'ACP_CAT_SYSTEM') ? true : false, + 'S_ACP_MODULE_MANAGEMENT' => ($this->module_class == 'acp' && ($row['module_basename'] == 'modules' || $row['module_langname'] == 'ACP_MODULE_MANAGEMENT')) ? true : false, + + 'U_MODULE' => $this->u_action . '&parent_id=' . $row['module_id'], + 'U_MOVE_UP' => $url . '&action=move_up', + 'U_MOVE_DOWN' => $url . '&action=move_down', + 'U_EDIT' => $url . '&action=edit', + 'U_DELETE' => $url . '&action=delete', + 'U_ENABLE' => $url . '&action=enable', + 'U_DISABLE' => $url . '&action=disable') + ); + } + while ($row = $db->sql_fetchrow($result)); + } + else if ($this->parent_id) + { + $row = $this->get_module_row($this->parent_id); + + $url = $this->u_action . '&parent_id=' . $this->parent_id . '&m=' . $row['module_id']; + + $template->assign_vars(array( + 'S_NO_MODULES' => true, + 'MODULE_TITLE' => $langname, + 'MODULE_ENABLED' => ($row['module_enabled']) ? true : false, + 'MODULE_DISPLAYED' => ($row['module_display']) ? true : false, + + 'U_EDIT' => $url . '&action=edit', + 'U_DELETE' => $url . '&action=delete', + 'U_ENABLE' => $url . '&action=enable', + 'U_DISABLE' => $url . '&action=disable') + ); + } + $db->sql_freeresult($result); + + // Quick adding module + $module_infos = $this->get_module_infos(); + + // Build quick options + $s_install_options = ''; + foreach ($module_infos as $option => $values) + { + // Name options + $s_install_options .= '<optgroup label="' . $this->lang_name($values['title']) . ' [' . $this->module_class . '_' . $option . ']">'; + + // Build module modes + foreach ($values['modes'] as $m_mode => $m_values) + { + $s_install_options .= '<option value="' . $option . '::' . $m_mode . '"> ' . $this->lang_name($m_values['title']) . '</option>'; + } + + $s_install_options .= '</optgroup>'; + } + + $template->assign_vars(array( + 'U_SEL_ACTION' => $this->u_action, + 'U_ACTION' => $this->u_action . '&parent_id=' . $this->parent_id, + 'NAVIGATION' => $navigation, + 'MODULE_BOX' => $module_box, + 'PARENT_ID' => $this->parent_id, + 'S_INSTALL_OPTIONS' => $s_install_options, + ) + ); + } + + /** + * Get row for specified module + */ + function get_module_row($module_id) + { + global $db, $user; + + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND module_id = $module_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error($user->lang['NO_MODULE'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + return $row; + } + + /** + * Get available module information from module files + */ + function get_module_infos($module = '', $module_class = false) + { + global $phpbb_root_path, $phpEx; + + $module_class = ($module_class === false) ? $this->module_class : $module_class; + + $directory = $phpbb_root_path . 'includes/' . $module_class . '/info/'; + $fileinfo = array(); + + if (!$module) + { + $dh = @opendir($directory); + + if (!$dh) + { + return $fileinfo; + } + + while (($file = readdir($dh)) !== false) + { + // Is module? + if (preg_match('/^' . $module_class . '_.+\.' . $phpEx . '$/', $file)) + { + $class = str_replace(".$phpEx", '', $file) . '_info'; + + if (!class_exists($class)) + { + include($directory . $file); + } + + // Get module title tag + if (class_exists($class)) + { + $c_class = new $class(); + $module_info = $c_class->module(); + $fileinfo[str_replace($module_class . '_', '', $module_info['filename'])] = $module_info; + } + } + } + closedir($dh); + + ksort($fileinfo); + } + else + { + $filename = $module_class . '_' . basename($module); + $class = $module_class . '_' . basename($module) . '_info'; + + if (!class_exists($class)) + { + include($directory . $filename . '.' . $phpEx); + } + + // Get module title tag + if (class_exists($class)) + { + $c_class = new $class(); + $module_info = $c_class->module(); + $fileinfo[str_replace($module_class . '_', '', $module_info['filename'])] = $module_info; + } + } + + return $fileinfo; + } + + /** + * Simple version of jumpbox, just lists modules + */ + function make_module_select($select_id = false, $ignore_id = false, $ignore_acl = false, $ignore_nonpost = false, $ignore_emptycat = true, $ignore_noncat = false) + { + global $db, $user, $auth, $config; + + $sql = 'SELECT module_id, module_enabled, module_basename, parent_id, module_langname, left_id, right_id, module_auth + FROM ' . MODULES_TABLE . " + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + ORDER BY left_id ASC"; + $result = $db->sql_query($sql); + + $right = $iteration = 0; + $padding_store = array('0' => ''); + $module_list = $padding = ''; + + while ($row = $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']; + + if (!$ignore_acl && $row['module_auth']) + { + // We use zero as the forum id to check - global setting. + if (!p_master::module_auth($row['module_auth'], 0)) + { + continue; + } + } + + // ignore this module? + if ((is_array($ignore_id) && in_array($row['module_id'], $ignore_id)) || $row['module_id'] == $ignore_id) + { + continue; + } + + // empty category + if (!$row['module_basename'] && ($row['left_id'] + 1 == $row['right_id']) && $ignore_emptycat) + { + continue; + } + + // ignore non-category? + if ($row['module_basename'] && $ignore_noncat) + { + continue; + } + + $selected = (is_array($select_id)) ? ((in_array($row['module_id'], $select_id)) ? ' selected="selected"' : '') : (($row['module_id'] == $select_id) ? ' selected="selected"' : ''); + + $langname = $this->lang_name($row['module_langname']); + $module_list .= '<option value="' . $row['module_id'] . '"' . $selected . ((!$row['module_enabled']) ? ' class="disabled"' : '') . '>' . $padding . $langname . '</option>'; + + $iteration++; + } + $db->sql_freeresult($result); + + unset($padding_store); + + return $module_list; + } + + /** + * Get module branch + */ + function get_module_branch($module_id, $type = 'all', $order = 'descending', $include_module = true) + { + global $db; + + switch ($type) + { + case 'parents': + $condition = 'm1.left_id BETWEEN m2.left_id AND m2.right_id'; + break; + + case 'children': + $condition = 'm2.left_id BETWEEN m1.left_id AND m1.right_id'; + break; + + default: + $condition = 'm2.left_id BETWEEN m1.left_id AND m1.right_id OR m1.left_id BETWEEN m2.left_id AND m2.right_id'; + break; + } + + $rows = array(); + + $sql = 'SELECT m2.* + FROM ' . MODULES_TABLE . ' m1 + LEFT JOIN ' . MODULES_TABLE . " m2 ON ($condition) + WHERE m1.module_class = '" . $db->sql_escape($this->module_class) . "' + AND m2.module_class = '" . $db->sql_escape($this->module_class) . "' + AND m1.module_id = $module_id + ORDER BY m2.left_id " . (($order == 'descending') ? 'ASC' : 'DESC'); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if (!$include_module && $row['module_id'] == $module_id) + { + continue; + } + + $rows[] = $row; + } + $db->sql_freeresult($result); + + return $rows; + } + + /** + * Remove modules cache file + */ + function remove_cache_file() + { + global $cache; + + // Sanitise for future path use, it's escaped as appropriate for queries + $p_class = str_replace(array('.', '/', '\\'), '', basename($this->module_class)); + + $cache->destroy('_modules_' . $p_class); + + // Additionally remove sql cache + $cache->destroy('sql', MODULES_TABLE); + } + + /** + * Return correct language name + */ + function lang_name($module_langname) + { + global $user; + + return (!empty($user->lang[$module_langname])) ? $user->lang[$module_langname] : $module_langname; + } + + /** + * Update/Add module + * + * @param bool $run_inline if set to true errors will be returned and no logs being written + */ + function update_module_data(&$module_data, $run_inline = false) + { + global $db, $user; + + if (!isset($module_data['module_id'])) + { + // no module_id means we're creating a new category/module + if ($module_data['parent_id']) + { + $sql = 'SELECT left_id, right_id + FROM ' . MODULES_TABLE . " + WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "' + AND module_id = " . (int) $module_data['parent_id']; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + if ($run_inline) + { + return 'PARENT_NO_EXIST'; + } + + trigger_error($user->lang['PARENT_NO_EXIST'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + // Workaround + $row['left_id'] = (int) $row['left_id']; + $row['right_id'] = (int) $row['right_id']; + + $sql = 'UPDATE ' . MODULES_TABLE . " + SET left_id = left_id + 2, right_id = right_id + 2 + WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "' + AND left_id > {$row['right_id']}"; + $db->sql_query($sql); + + $sql = 'UPDATE ' . MODULES_TABLE . " + SET right_id = right_id + 2 + WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "' + AND {$row['left_id']} BETWEEN left_id AND right_id"; + $db->sql_query($sql); + + $module_data['left_id'] = (int) $row['right_id']; + $module_data['right_id'] = (int) $row['right_id'] + 1; + } + else + { + $sql = 'SELECT MAX(right_id) AS right_id + FROM ' . MODULES_TABLE . " + WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $module_data['left_id'] = (int) $row['right_id'] + 1; + $module_data['right_id'] = (int) $row['right_id'] + 2; + } + + $sql = 'INSERT INTO ' . MODULES_TABLE . ' ' . $db->sql_build_array('INSERT', $module_data); + $db->sql_query($sql); + + $module_data['module_id'] = $db->sql_nextid(); + + if (!$run_inline) + { + add_log('admin', 'LOG_MODULE_ADD', $this->lang_name($module_data['module_langname'])); + } + } + else + { + $row = $this->get_module_row($module_data['module_id']); + + if ($module_data['module_basename'] && !$row['module_basename']) + { + // we're turning a category into a module + $branch = $this->get_module_branch($module_data['module_id'], 'children', 'descending', false); + + if (sizeof($branch)) + { + return array($user->lang['NO_CATEGORY_TO_MODULE']); + } + } + + if ($row['parent_id'] != $module_data['parent_id']) + { + $this->move_module($module_data['module_id'], $module_data['parent_id']); + } + + $update_ary = $module_data; + unset($update_ary['module_id']); + + $sql = 'UPDATE ' . MODULES_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $update_ary) . " + WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "' + AND module_id = " . (int) $module_data['module_id']; + $db->sql_query($sql); + + if (!$run_inline) + { + add_log('admin', 'LOG_MODULE_EDIT', $this->lang_name($module_data['module_langname'])); + } + } + + return array(); + } + + /** + * Move module around the tree + */ + function move_module($from_module_id, $to_parent_id) + { + global $db; + + $moved_modules = $this->get_module_branch($from_module_id, 'children', 'descending'); + $from_data = $moved_modules[0]; + $diff = sizeof($moved_modules) * 2; + + $moved_ids = array(); + for ($i = 0; $i < sizeof($moved_modules); ++$i) + { + $moved_ids[] = $moved_modules[$i]['module_id']; + } + + // Resync parents + $sql = 'UPDATE ' . MODULES_TABLE . " + SET right_id = right_id - $diff + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND left_id < " . (int) $from_data['right_id'] . ' + AND right_id > ' . (int) $from_data['right_id']; + $db->sql_query($sql); + + // Resync righthand side of tree + $sql = 'UPDATE ' . MODULES_TABLE . " + SET left_id = left_id - $diff, right_id = right_id - $diff + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND left_id > " . (int) $from_data['right_id']; + $db->sql_query($sql); + + if ($to_parent_id > 0) + { + $to_data = $this->get_module_row($to_parent_id); + + // Resync new parents + $sql = 'UPDATE ' . MODULES_TABLE . " + SET right_id = right_id + $diff + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND " . (int) $to_data['right_id'] . ' BETWEEN left_id AND right_id + AND ' . $db->sql_in_set('module_id', $moved_ids, true); + $db->sql_query($sql); + + // Resync the righthand side of the tree + $sql = 'UPDATE ' . MODULES_TABLE . " + SET left_id = left_id + $diff, right_id = right_id + $diff + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND left_id > " . (int) $to_data['right_id'] . ' + AND ' . $db->sql_in_set('module_id', $moved_ids, true); + $db->sql_query($sql); + + // Resync moved branch + $to_data['right_id'] += $diff; + if ($to_data['right_id'] > $from_data['right_id']) + { + $diff = '+ ' . ($to_data['right_id'] - $from_data['right_id'] - 1); + } + else + { + $diff = '- ' . abs($to_data['right_id'] - $from_data['right_id'] - 1); + } + } + else + { + $sql = 'SELECT MAX(right_id) AS right_id + FROM ' . MODULES_TABLE . " + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND " . $db->sql_in_set('module_id', $moved_ids, true); + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $diff = '+ ' . (int) ($row['right_id'] - $from_data['left_id'] + 1); + } + + $sql = 'UPDATE ' . MODULES_TABLE . " + SET left_id = left_id $diff, right_id = right_id $diff + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND " . $db->sql_in_set('module_id', $moved_ids); + $db->sql_query($sql); + } + + /** + * Remove module from tree + */ + function delete_module($module_id) + { + global $db, $user; + + $row = $this->get_module_row($module_id); + + $branch = $this->get_module_branch($module_id, 'children', 'descending', false); + + if (sizeof($branch)) + { + return array($user->lang['CANNOT_REMOVE_MODULE']); + } + + // If not move + $diff = 2; + $sql = 'DELETE FROM ' . MODULES_TABLE . " + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND module_id = $module_id"; + $db->sql_query($sql); + + $row['right_id'] = (int) $row['right_id']; + $row['left_id'] = (int) $row['left_id']; + + // Resync tree + $sql = 'UPDATE ' . MODULES_TABLE . " + SET right_id = right_id - $diff + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND left_id < {$row['right_id']} AND right_id > {$row['right_id']}"; + $db->sql_query($sql); + + $sql = 'UPDATE ' . MODULES_TABLE . " + SET left_id = left_id - $diff, right_id = right_id - $diff + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND left_id > {$row['right_id']}"; + $db->sql_query($sql); + + add_log('admin', 'LOG_MODULE_REMOVED', $this->lang_name($row['module_langname'])); + + return array(); + + } + + /** + * Move module position by $steps up/down + */ + function move_module_by($module_row, $action = 'move_up', $steps = 1) + { + global $db; + + /** + * Fetch all the siblings between the module's current spot + * and where we want to move it to. If there are less than $steps + * siblings between the current spot and the target then the + * module will move as far as possible + */ + $sql = 'SELECT module_id, left_id, right_id, module_langname + FROM ' . MODULES_TABLE . " + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND parent_id = " . (int) $module_row['parent_id'] . ' + AND ' . (($action == 'move_up') ? 'right_id < ' . (int) $module_row['right_id'] . ' ORDER BY right_id DESC' : 'left_id > ' . (int) $module_row['left_id'] . ' ORDER BY left_id ASC'); + $result = $db->sql_query_limit($sql, $steps); + + $target = array(); + while ($row = $db->sql_fetchrow($result)) + { + $target = $row; + } + $db->sql_freeresult($result); + + if (!sizeof($target)) + { + // The module is already on top or bottom + return false; + } + + /** + * $left_id and $right_id define the scope of the nodes that are affected by the move. + * $diff_up and $diff_down are the values to substract or add to each node's left_id + * and right_id in order to move them up or down. + * $move_up_left and $move_up_right define the scope of the nodes that are moving + * up. Other nodes in the scope of ($left_id, $right_id) are considered to move down. + */ + if ($action == 'move_up') + { + $left_id = (int) $target['left_id']; + $right_id = (int) $module_row['right_id']; + + $diff_up = (int) ($module_row['left_id'] - $target['left_id']); + $diff_down = (int) ($module_row['right_id'] + 1 - $module_row['left_id']); + + $move_up_left = (int) $module_row['left_id']; + $move_up_right = (int) $module_row['right_id']; + } + else + { + $left_id = (int) $module_row['left_id']; + $right_id = (int) $target['right_id']; + + $diff_up = (int) ($module_row['right_id'] + 1 - $module_row['left_id']); + $diff_down = (int) ($target['right_id'] - $module_row['right_id']); + + $move_up_left = (int) ($module_row['right_id'] + 1); + $move_up_right = (int) $target['right_id']; + } + + // Now do the dirty job + $sql = 'UPDATE ' . MODULES_TABLE . " + SET left_id = left_id + CASE + WHEN left_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up} + ELSE {$diff_down} + END, + right_id = right_id + CASE + WHEN right_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up} + ELSE {$diff_down} + END + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND left_id BETWEEN {$left_id} AND {$right_id} + AND right_id BETWEEN {$left_id} AND {$right_id}"; + $db->sql_query($sql); + + $this->remove_cache_file(); + + return $this->lang_name($target['module_langname']); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_permission_roles.php b/phpBB/includes/acp/acp_permission_roles.php new file mode 100644 index 0000000000..03ea5a39dd --- /dev/null +++ b/phpBB/includes/acp/acp_permission_roles.php @@ -0,0 +1,571 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_permission_roles +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); + include_once($phpbb_root_path . 'includes/acp/auth.' . $phpEx); + + $auth_admin = new auth_admin(); + + $user->add_lang('acp/permissions'); + add_permission_language(); + + $this->tpl_name = 'acp_permission_roles'; + + $submit = (isset($_POST['submit'])) ? true : false; + $role_id = request_var('role_id', 0); + $action = request_var('action', ''); + $action = (isset($_POST['add'])) ? 'add' : $action; + + $form_name = 'acp_permissions'; + add_form_key($form_name); + + switch ($mode) + { + case 'admin_roles': + $permission_type = 'a_'; + $this->page_title = 'ACP_ADMIN_ROLES'; + break; + + case 'user_roles': + $permission_type = 'u_'; + $this->page_title = 'ACP_USER_ROLES'; + break; + + case 'mod_roles': + $permission_type = 'm_'; + $this->page_title = 'ACP_MOD_ROLES'; + break; + + case 'forum_roles': + $permission_type = 'f_'; + $this->page_title = 'ACP_FORUM_ROLES'; + break; + + default: + trigger_error('NO_MODE', E_USER_ERROR); + break; + } + + $template->assign_vars(array( + 'L_TITLE' => $user->lang[$this->page_title], + 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN']) + ); + + // Take action... admin submitted something + if ($submit || $action == 'remove') + { + switch ($action) + { + case 'remove': + + if (!$role_id) + { + trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT * + FROM ' . ACL_ROLES_TABLE . ' + WHERE role_id = ' . $role_id; + $result = $db->sql_query($sql); + $role_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$role_row) + { + trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (confirm_box(true)) + { + $this->remove_role($role_id, $permission_type); + + $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name']; + add_log('admin', 'LOG_' . strtoupper($permission_type) . 'ROLE_REMOVED', $role_name); + trigger_error($user->lang['ROLE_DELETED'] . adm_back_link($this->u_action)); + } + else + { + confirm_box(false, 'DELETE_ROLE', build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'role_id' => $role_id, + 'action' => $action, + ))); + } + + break; + + case 'edit': + if (!$role_id) + { + trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Get role we edit + $sql = 'SELECT * + FROM ' . ACL_ROLES_TABLE . ' + WHERE role_id = ' . $role_id; + $result = $db->sql_query($sql); + $role_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$role_row) + { + trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // no break; + + case 'add': + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); + } + + $role_name = utf8_normalize_nfc(request_var('role_name', '', true)); + $role_description = utf8_normalize_nfc(request_var('role_description', '', true)); + $auth_settings = request_var('setting', array('' => 0)); + + if (!$role_name) + { + trigger_error($user->lang['NO_ROLE_NAME_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (utf8_strlen($role_description) > 4000) + { + trigger_error($user->lang['ROLE_DESCRIPTION_LONG'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // if we add/edit a role we check the name to be unique among the settings... + $sql = 'SELECT role_id + FROM ' . ACL_ROLES_TABLE . " + WHERE role_type = '" . $db->sql_escape($permission_type) . "' + AND role_name = '" . $db->sql_escape($role_name) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + // Make sure we only print out the error if we add the role or change it's name + if ($row && ($mode == 'add' || ($mode == 'edit' && $role_row['role_name'] != $role_name))) + { + trigger_error(sprintf($user->lang['ROLE_NAME_ALREADY_EXIST'], $role_name) . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql_ary = array( + 'role_name' => (string) $role_name, + 'role_description' => (string) $role_description, + 'role_type' => (string) $permission_type, + ); + + if ($action == 'edit') + { + $sql = 'UPDATE ' . ACL_ROLES_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE role_id = ' . $role_id; + $db->sql_query($sql); + } + else + { + // Get maximum role order for inserting a new role... + $sql = 'SELECT MAX(role_order) as max_order + FROM ' . ACL_ROLES_TABLE . " + WHERE role_type = '" . $db->sql_escape($permission_type) . "'"; + $result = $db->sql_query($sql); + $max_order = (int) $db->sql_fetchfield('max_order'); + $db->sql_freeresult($result); + + $sql_ary['role_order'] = $max_order + 1; + + $sql = 'INSERT INTO ' . ACL_ROLES_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); + $db->sql_query($sql); + + $role_id = $db->sql_nextid(); + } + + // Now add the auth settings + $auth_admin->acl_set_role($role_id, $auth_settings); + + $role_name = (!empty($user->lang[$role_name])) ? $user->lang[$role_name] : $role_name; + add_log('admin', 'LOG_' . strtoupper($permission_type) . 'ROLE_' . strtoupper($action), $role_name); + + trigger_error($user->lang['ROLE_' . strtoupper($action) . '_SUCCESS'] . adm_back_link($this->u_action)); + + break; + } + } + + // Display screens + switch ($action) + { + case 'add': + + $options_from = request_var('options_from', 0); + + $role_row = array( + 'role_name' => utf8_normalize_nfc(request_var('role_name', '', true)), + 'role_description' => utf8_normalize_nfc(request_var('role_description', '', true)), + 'role_type' => $permission_type, + ); + + if ($options_from) + { + $sql = 'SELECT p.auth_option_id, p.auth_setting, o.auth_option + FROM ' . ACL_ROLES_DATA_TABLE . ' p, ' . ACL_OPTIONS_TABLE . ' o + WHERE o.auth_option_id = p.auth_option_id + AND p.role_id = ' . $options_from . ' + ORDER BY p.auth_option_id'; + $result = $db->sql_query($sql); + + $auth_options = array(); + while ($row = $db->sql_fetchrow($result)) + { + $auth_options[$row['auth_option']] = $row['auth_setting']; + } + $db->sql_freeresult($result); + } + else + { + $sql = 'SELECT auth_option_id, auth_option + FROM ' . ACL_OPTIONS_TABLE . " + WHERE auth_option " . $db->sql_like_expression($permission_type . $db->any_char) . " + AND auth_option <> '{$permission_type}' + ORDER BY auth_option_id"; + $result = $db->sql_query($sql); + + $auth_options = array(); + while ($row = $db->sql_fetchrow($result)) + { + $auth_options[$row['auth_option']] = ACL_NO; + } + $db->sql_freeresult($result); + } + + // no break; + + case 'edit': + + if ($action == 'edit') + { + if (!$role_id) + { + trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT * + FROM ' . ACL_ROLES_TABLE . ' + WHERE role_id = ' . $role_id; + $result = $db->sql_query($sql); + $role_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $sql = 'SELECT p.auth_option_id, p.auth_setting, o.auth_option + FROM ' . ACL_ROLES_DATA_TABLE . ' p, ' . ACL_OPTIONS_TABLE . ' o + WHERE o.auth_option_id = p.auth_option_id + AND p.role_id = ' . $role_id . ' + ORDER BY p.auth_option_id'; + $result = $db->sql_query($sql); + + $auth_options = array(); + while ($row = $db->sql_fetchrow($result)) + { + $auth_options[$row['auth_option']] = $row['auth_setting']; + } + $db->sql_freeresult($result); + } + + if (!$role_row) + { + trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $template->assign_vars(array( + 'S_EDIT' => true, + + 'U_ACTION' => $this->u_action . "&action={$action}&role_id={$role_id}", + 'U_BACK' => $this->u_action, + + 'ROLE_NAME' => $role_row['role_name'], + 'ROLE_DESCRIPTION' => $role_row['role_description'], + 'L_ACL_TYPE' => $user->lang['ACL_TYPE_' . strtoupper($permission_type)], + ) + ); + + // We need to fill the auth options array with ACL_NO options ;) + $sql = 'SELECT auth_option_id, auth_option + FROM ' . ACL_OPTIONS_TABLE . " + WHERE auth_option " . $db->sql_like_expression($permission_type . $db->any_char) . " + AND auth_option <> '{$permission_type}' + ORDER BY auth_option_id"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if (!isset($auth_options[$row['auth_option']])) + { + $auth_options[$row['auth_option']] = ACL_NO; + } + } + $db->sql_freeresult($result); + + // Unset global permission option + unset($auth_options[$permission_type]); + + // Display auth options + $this->display_auth_options($auth_options); + + // Get users/groups/forums using this preset... + if ($action == 'edit') + { + $hold_ary = $auth_admin->get_role_mask($role_id); + + if (sizeof($hold_ary)) + { + $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name']; + + $template->assign_vars(array( + 'S_DISPLAY_ROLE_MASK' => true, + 'L_ROLE_ASSIGNED_TO' => sprintf($user->lang['ROLE_ASSIGNED_TO'], $role_name)) + ); + + $auth_admin->display_role_mask($hold_ary); + } + } + + return; + break; + + case 'move_up': + case 'move_down': + + $order = request_var('order', 0); + $order_total = $order * 2 + (($action == 'move_up') ? -1 : 1); + + $sql = 'UPDATE ' . ACL_ROLES_TABLE . ' + SET role_order = ' . $order_total . " - role_order + WHERE role_type = '" . $db->sql_escape($permission_type) . "' + AND role_order IN ($order, " . (($action == 'move_up') ? $order - 1 : $order + 1) . ')'; + $db->sql_query($sql); + + break; + } + + // By default, check that role_order is valid and fix it if necessary + $sql = 'SELECT role_id, role_order + FROM ' . ACL_ROLES_TABLE . " + WHERE role_type = '" . $db->sql_escape($permission_type) . "' + ORDER BY role_order ASC"; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + $order = 0; + do + { + $order++; + if ($row['role_order'] != $order) + { + $db->sql_query('UPDATE ' . ACL_ROLES_TABLE . " SET role_order = $order WHERE role_id = {$row['role_id']}"); + } + } + while ($row = $db->sql_fetchrow($result)); + } + $db->sql_freeresult($result); + + // Display assigned items? + $display_item = request_var('display_item', 0); + + // Select existing roles + $sql = 'SELECT * + FROM ' . ACL_ROLES_TABLE . " + WHERE role_type = '" . $db->sql_escape($permission_type) . "' + ORDER BY role_order ASC"; + $result = $db->sql_query($sql); + + $s_role_options = ''; + while ($row = $db->sql_fetchrow($result)) + { + $role_name = (!empty($user->lang[$row['role_name']])) ? $user->lang[$row['role_name']] : $row['role_name']; + + $template->assign_block_vars('roles', array( + 'ROLE_NAME' => $role_name, + 'ROLE_DESCRIPTION' => (!empty($user->lang[$row['role_description']])) ? $user->lang[$row['role_description']] : nl2br($row['role_description']), + + 'U_EDIT' => $this->u_action . '&action=edit&role_id=' . $row['role_id'], + 'U_REMOVE' => $this->u_action . '&action=remove&role_id=' . $row['role_id'], + 'U_MOVE_UP' => $this->u_action . '&action=move_up&order=' . $row['role_order'], + 'U_MOVE_DOWN' => $this->u_action . '&action=move_down&order=' . $row['role_order'], + 'U_DISPLAY_ITEMS' => ($row['role_id'] == $display_item) ? '' : $this->u_action . '&display_item=' . $row['role_id'] . '#assigned_to') + ); + + $s_role_options .= '<option value="' . $row['role_id'] . '">' . $role_name . '</option>'; + + if ($display_item == $row['role_id']) + { + $template->assign_vars(array( + 'L_ROLE_ASSIGNED_TO' => sprintf($user->lang['ROLE_ASSIGNED_TO'], $role_name)) + ); + } + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'S_ROLE_OPTIONS' => $s_role_options) + ); + + if ($display_item) + { + $template->assign_vars(array( + 'S_DISPLAY_ROLE_MASK' => true) + ); + + $hold_ary = $auth_admin->get_role_mask($display_item); + $auth_admin->display_role_mask($hold_ary); + } + } + + /** + * Display permission settings able to be set + */ + function display_auth_options($auth_options) + { + global $template, $user; + + $content_array = $categories = array(); + $key_sort_array = array(0); + $auth_options = array(0 => $auth_options); + + // Making use of auth_admin method here (we do not really want to change two similar code fragments) + auth_admin::build_permission_array($auth_options, $content_array, $categories, $key_sort_array); + + $content_array = $content_array[0]; + + $template->assign_var('S_NUM_PERM_COLS', sizeof($categories)); + + // Assign to template + foreach ($content_array as $cat => $cat_array) + { + $template->assign_block_vars('auth', array( + 'CAT_NAME' => $user->lang['permission_cat'][$cat], + + 'S_YES' => ($cat_array['S_YES'] && !$cat_array['S_NEVER'] && !$cat_array['S_NO']) ? true : false, + 'S_NEVER' => ($cat_array['S_NEVER'] && !$cat_array['S_YES'] && !$cat_array['S_NO']) ? true : false, + 'S_NO' => ($cat_array['S_NO'] && !$cat_array['S_NEVER'] && !$cat_array['S_YES']) ? true : false) + ); + + foreach ($cat_array['permissions'] as $permission => $allowed) + { + $template->assign_block_vars('auth.mask', array( + 'S_YES' => ($allowed == ACL_YES) ? true : false, + 'S_NEVER' => ($allowed == ACL_NEVER) ? true : false, + 'S_NO' => ($allowed == ACL_NO) ? true : false, + + 'FIELD_NAME' => $permission, + 'PERMISSION' => $user->lang['acl_' . $permission]['lang']) + ); + } + } + } + + /** + * Remove role + */ + function remove_role($role_id, $permission_type) + { + global $db; + + $auth_admin = new auth_admin(); + + // Get complete auth array + $sql = 'SELECT auth_option, auth_option_id + FROM ' . ACL_OPTIONS_TABLE . " + WHERE auth_option " . $db->sql_like_expression($permission_type . $db->any_char); + $result = $db->sql_query($sql); + + $auth_settings = array(); + while ($row = $db->sql_fetchrow($result)) + { + $auth_settings[$row['auth_option']] = ACL_NO; + } + $db->sql_freeresult($result); + + // Get the role auth settings we need to re-set... + $sql = 'SELECT o.auth_option, r.auth_setting + FROM ' . ACL_ROLES_DATA_TABLE . ' r, ' . ACL_OPTIONS_TABLE . ' o + WHERE o.auth_option_id = r.auth_option_id + AND r.role_id = ' . $role_id; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $auth_settings[$row['auth_option']] = $row['auth_setting']; + } + $db->sql_freeresult($result); + + // Get role assignments + $hold_ary = $auth_admin->get_role_mask($role_id); + + // Re-assign permissions + foreach ($hold_ary as $forum_id => $forum_ary) + { + if (isset($forum_ary['users'])) + { + $auth_admin->acl_set('user', $forum_id, $forum_ary['users'], $auth_settings, 0, false); + } + + if (isset($forum_ary['groups'])) + { + $auth_admin->acl_set('group', $forum_id, $forum_ary['groups'], $auth_settings, 0, false); + } + } + + // Remove role from users and groups just to be sure (happens through acl_set) + $sql = 'DELETE FROM ' . ACL_USERS_TABLE . ' + WHERE auth_role_id = ' . $role_id; + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . ' + WHERE auth_role_id = ' . $role_id; + $db->sql_query($sql); + + // Remove role data and role + $sql = 'DELETE FROM ' . ACL_ROLES_DATA_TABLE . ' + WHERE role_id = ' . $role_id; + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_ROLES_TABLE . ' + WHERE role_id = ' . $role_id; + $db->sql_query($sql); + + $auth_admin->acl_clear_prefetch(); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_permissions.php b/phpBB/includes/acp/acp_permissions.php new file mode 100644 index 0000000000..e9f0af5071 --- /dev/null +++ b/phpBB/includes/acp/acp_permissions.php @@ -0,0 +1,1315 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_permissions +{ + var $u_action; + var $permission_dropdown; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); + include_once($phpbb_root_path . 'includes/acp/auth.' . $phpEx); + + $auth_admin = new auth_admin(); + + $user->add_lang('acp/permissions'); + add_permission_language(); + + $this->tpl_name = 'acp_permissions'; + + // Trace has other vars + if ($mode == 'trace') + { + $user_id = request_var('u', 0); + $forum_id = request_var('f', 0); + $permission = request_var('auth', ''); + + $this->tpl_name = 'permission_trace'; + + if ($user_id && isset($auth_admin->acl_options['id'][$permission]) && $auth->acl_get('a_viewauth')) + { + $this->page_title = sprintf($user->lang['TRACE_PERMISSION'], $user->lang['acl_' . $permission]['lang']); + $this->permission_trace($user_id, $forum_id, $permission); + return; + } + trigger_error('NO_MODE', E_USER_ERROR); + } + + // Copy forum permissions + if ($mode == 'setting_forum_copy') + { + $this->tpl_name = 'permission_forum_copy'; + + if ($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth')) + { + $this->page_title = 'ACP_FORUM_PERMISSIONS_COPY'; + $this->copy_forum_permissions(); + return; + } + + trigger_error('NO_MODE', E_USER_ERROR); + } + + // Set some vars + $action = request_var('action', array('' => 0)); + $action = key($action); + $action = (isset($_POST['psubmit'])) ? 'apply_permissions' : $action; + + $all_forums = request_var('all_forums', 0); + $subforum_id = request_var('subforum_id', 0); + $forum_id = request_var('forum_id', array(0)); + + $username = request_var('username', array(''), true); + $usernames = request_var('usernames', '', true); + $user_id = request_var('user_id', array(0)); + + $group_id = request_var('group_id', array(0)); + $select_all_groups = request_var('select_all_groups', 0); + + $form_name = 'acp_permissions'; + add_form_key($form_name); + + // If select all groups is set, we pre-build the group id array (this option is used for other screens to link to the permission settings screen) + if ($select_all_groups) + { + // Add default groups to selection + $sql_and = (!$config['coppa_enable']) ? " AND group_name <> 'REGISTERED_COPPA'" : ''; + + $sql = 'SELECT group_id + FROM ' . GROUPS_TABLE . ' + WHERE group_type = ' . GROUP_SPECIAL . " + $sql_and"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $group_id[] = $row['group_id']; + } + $db->sql_freeresult($result); + } + + // Map usernames to ids and vice versa + if ($usernames) + { + $username = explode("\n", $usernames); + } + unset($usernames); + + if (sizeof($username) && !sizeof($user_id)) + { + user_get_id_name($user_id, $username); + + if (!sizeof($user_id)) + { + trigger_error($user->lang['SELECTED_USER_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + unset($username); + + // Build forum ids (of all forums are checked or subforum listing used) + if ($all_forums) + { + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE . ' + ORDER BY left_id'; + $result = $db->sql_query($sql); + + $forum_id = array(); + while ($row = $db->sql_fetchrow($result)) + { + $forum_id[] = (int) $row['forum_id']; + } + $db->sql_freeresult($result); + } + else if ($subforum_id) + { + $forum_id = array(); + foreach (get_forum_branch($subforum_id, 'children') as $row) + { + $forum_id[] = (int) $row['forum_id']; + } + } + + // Define some common variables for every mode + $error = array(); + + $permission_scope = (strpos($mode, '_global') !== false) ? 'global' : 'local'; + + // Showing introductionary page? + if ($mode == 'intro') + { + $this->page_title = 'ACP_PERMISSIONS'; + + $template->assign_vars(array( + 'S_INTRO' => true) + ); + + return; + } + + switch ($mode) + { + case 'setting_user_global': + case 'setting_group_global': + $this->permission_dropdown = array('u_', 'm_', 'a_'); + $permission_victim = ($mode == 'setting_user_global') ? array('user') : array('group'); + $this->page_title = ($mode == 'setting_user_global') ? 'ACP_USERS_PERMISSIONS' : 'ACP_GROUPS_PERMISSIONS'; + break; + + case 'setting_user_local': + case 'setting_group_local': + $this->permission_dropdown = array('f_', 'm_'); + $permission_victim = ($mode == 'setting_user_local') ? array('user', 'forums') : array('group', 'forums'); + $this->page_title = ($mode == 'setting_user_local') ? 'ACP_USERS_FORUM_PERMISSIONS' : 'ACP_GROUPS_FORUM_PERMISSIONS'; + break; + + case 'setting_admin_global': + case 'setting_mod_global': + $this->permission_dropdown = (strpos($mode, '_admin_') !== false) ? array('a_') : array('m_'); + $permission_victim = array('usergroup'); + $this->page_title = ($mode == 'setting_admin_global') ? 'ACP_ADMINISTRATORS' : 'ACP_GLOBAL_MODERATORS'; + break; + + case 'setting_mod_local': + case 'setting_forum_local': + $this->permission_dropdown = ($mode == 'setting_mod_local') ? array('m_') : array('f_'); + $permission_victim = array('forums', 'usergroup'); + $this->page_title = ($mode == 'setting_mod_local') ? 'ACP_FORUM_MODERATORS' : 'ACP_FORUM_PERMISSIONS'; + break; + + case 'view_admin_global': + case 'view_user_global': + case 'view_mod_global': + $this->permission_dropdown = ($mode == 'view_admin_global') ? array('a_') : (($mode == 'view_user_global') ? array('u_') : array('m_')); + $permission_victim = array('usergroup_view'); + $this->page_title = ($mode == 'view_admin_global') ? 'ACP_VIEW_ADMIN_PERMISSIONS' : (($mode == 'view_user_global') ? 'ACP_VIEW_USER_PERMISSIONS' : 'ACP_VIEW_GLOBAL_MOD_PERMISSIONS'); + break; + + case 'view_mod_local': + case 'view_forum_local': + $this->permission_dropdown = ($mode == 'view_mod_local') ? array('m_') : array('f_'); + $permission_victim = array('forums', 'usergroup_view'); + $this->page_title = ($mode == 'view_mod_local') ? 'ACP_VIEW_FORUM_MOD_PERMISSIONS' : 'ACP_VIEW_FORUM_PERMISSIONS'; + break; + + default: + trigger_error('NO_MODE', E_USER_ERROR); + break; + } + + $template->assign_vars(array( + 'L_TITLE' => $user->lang[$this->page_title], + 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN']) + ); + + // Get permission type + $permission_type = request_var('type', $this->permission_dropdown[0]); + + if (!in_array($permission_type, $this->permission_dropdown)) + { + trigger_error($user->lang['WRONG_PERMISSION_TYPE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Handle actions + if (strpos($mode, 'setting_') === 0 && $action) + { + switch ($action) + { + case 'delete': + if (confirm_box(true)) + { + // All users/groups selected? + $all_users = (isset($_POST['all_users'])) ? true : false; + $all_groups = (isset($_POST['all_groups'])) ? true : false; + + if ($all_users || $all_groups) + { + $items = $this->retrieve_defined_user_groups($permission_scope, $forum_id, $permission_type); + + if ($all_users && sizeof($items['user_ids'])) + { + $user_id = $items['user_ids']; + } + else if ($all_groups && sizeof($items['group_ids'])) + { + $group_id = $items['group_ids']; + } + } + + if (sizeof($user_id) || sizeof($group_id)) + { + $this->remove_permissions($mode, $permission_type, $auth_admin, $user_id, $group_id, $forum_id); + } + else + { + trigger_error($user->lang['NO_USER_GROUP_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + else + { + if (isset($_POST['cancel'])) + { + $u_redirect = $this->u_action . '&type=' . $permission_type; + foreach ($forum_id as $fid) + { + $u_redirect .= '&forum_id[]=' . $fid; + } + redirect($u_redirect); + } + + $s_hidden_fields = array( + 'i' => $id, + 'mode' => $mode, + 'action' => array($action => 1), + 'user_id' => $user_id, + 'group_id' => $group_id, + 'forum_id' => $forum_id, + 'type' => $permission_type, + ); + if (isset($_POST['all_users'])) + { + $s_hidden_fields['all_users'] = 1; + } + if (isset($_POST['all_groups'])) + { + $s_hidden_fields['all_groups'] = 1; + } + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($s_hidden_fields)); + } + break; + + case 'apply_permissions': + if (!isset($_POST['setting'])) + { + trigger_error($user->lang['NO_AUTH_SETTING_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING); + } + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); + } + + $this->set_permissions($mode, $permission_type, $auth_admin, $user_id, $group_id); + break; + + case 'apply_all_permissions': + if (!isset($_POST['setting'])) + { + trigger_error($user->lang['NO_AUTH_SETTING_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING); + } + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); + } + + $this->set_all_permissions($mode, $permission_type, $auth_admin, $user_id, $group_id); + break; + } + } + + + // Setting permissions screen + $s_hidden_fields = build_hidden_fields(array( + 'user_id' => $user_id, + 'group_id' => $group_id, + 'forum_id' => $forum_id, + 'type' => $permission_type) + ); + + // Go through the screens/options needed and present them in correct order + foreach ($permission_victim as $victim) + { + switch ($victim) + { + case 'forum_dropdown': + + if (sizeof($forum_id)) + { + $this->check_existence('forum', $forum_id); + continue 2; + } + + $template->assign_vars(array( + 'S_SELECT_FORUM' => true, + 'S_FORUM_OPTIONS' => make_forum_select(false, false, true, false, false)) + ); + + break; + + case 'forums': + + if (sizeof($forum_id)) + { + $this->check_existence('forum', $forum_id); + continue 2; + } + + $forum_list = make_forum_select(false, false, true, false, false, false, true); + + // Build forum options + $s_forum_options = ''; + foreach ($forum_list as $f_id => $f_row) + { + $s_forum_options .= '<option value="' . $f_id . '"' . (($f_row['selected']) ? ' selected="selected"' : '') . (($f_row['disabled']) ? ' disabled="disabled" class="disabled-option"' : '') . '>' . $f_row['padding'] . $f_row['forum_name'] . '</option>'; + } + + // Build subforum options + $s_subforum_options = $this->build_subforum_options($forum_list); + + $template->assign_vars(array( + 'S_SELECT_FORUM' => true, + 'S_FORUM_OPTIONS' => $s_forum_options, + 'S_SUBFORUM_OPTIONS' => $s_subforum_options, + 'S_FORUM_ALL' => true, + 'S_FORUM_MULTIPLE' => true) + ); + + break; + + case 'user': + + if (sizeof($user_id)) + { + $this->check_existence('user', $user_id); + continue 2; + } + + $template->assign_vars(array( + 'S_SELECT_USER' => true, + 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=select_victim&field=username&select_single=true'), + )); + + break; + + case 'group': + + if (sizeof($group_id)) + { + $this->check_existence('group', $group_id); + continue 2; + } + + $template->assign_vars(array( + 'S_SELECT_GROUP' => true, + 'S_GROUP_OPTIONS' => group_select_options(false, false, false), // Show all groups + )); + + break; + + case 'usergroup': + case 'usergroup_view': + + $all_users = (isset($_POST['all_users'])) ? true : false; + $all_groups = (isset($_POST['all_groups'])) ? true : false; + + if ((sizeof($user_id) && !$all_users) || (sizeof($group_id) && !$all_groups)) + { + if (sizeof($user_id)) + { + $this->check_existence('user', $user_id); + } + + if (sizeof($group_id)) + { + $this->check_existence('group', $group_id); + } + + continue 2; + } + + // Now we check the users... because the "all"-selection is different here (all defined users/groups) + $items = $this->retrieve_defined_user_groups($permission_scope, $forum_id, $permission_type); + + if ($all_users && sizeof($items['user_ids'])) + { + $user_id = $items['user_ids']; + continue 2; + } + + if ($all_groups && sizeof($items['group_ids'])) + { + $group_id = $items['group_ids']; + continue 2; + } + + $template->assign_vars(array( + 'S_SELECT_USERGROUP' => ($victim == 'usergroup') ? true : false, + 'S_SELECT_USERGROUP_VIEW' => ($victim == 'usergroup_view') ? true : false, + 'S_DEFINED_USER_OPTIONS' => $items['user_ids_options'], + 'S_DEFINED_GROUP_OPTIONS' => $items['group_ids_options'], + 'S_ADD_GROUP_OPTIONS' => group_select_options(false, $items['group_ids'], false), // Show all groups + 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=add_user&field=username&select_single=true'), + )); + + break; + } + + // The S_ALLOW_SELECT parameter below is a measure to lower memory usage. + // If there are more than 5 forums selected the admin is not able to select all users/groups too. + // We need to see if the number of forums can be increased or need to be decreased. + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action, + 'ANONYMOUS_USER_ID' => ANONYMOUS, + + 'S_SELECT_VICTIM' => true, + 'S_ALLOW_ALL_SELECT' => (sizeof($forum_id) > 5) ? false : true, + 'S_CAN_SELECT_USER' => ($auth->acl_get('a_authusers')) ? true : false, + 'S_CAN_SELECT_GROUP' => ($auth->acl_get('a_authgroups')) ? true : false, + 'S_HIDDEN_FIELDS' => $s_hidden_fields) + ); + + // Let the forum names being displayed + if (sizeof($forum_id)) + { + $sql = 'SELECT forum_name + FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_id) . ' + ORDER BY left_id ASC'; + $result = $db->sql_query($sql); + + $forum_names = array(); + while ($row = $db->sql_fetchrow($result)) + { + $forum_names[] = $row['forum_name']; + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'S_FORUM_NAMES' => (sizeof($forum_names)) ? true : false, + 'FORUM_NAMES' => implode(', ', $forum_names)) + ); + } + + return; + } + + // Do not allow forum_ids being set and no other setting defined (will bog down the server too much) + if (sizeof($forum_id) && !sizeof($user_id) && !sizeof($group_id)) + { + trigger_error($user->lang['ONLY_FORUM_DEFINED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $template->assign_vars(array( + 'S_PERMISSION_DROPDOWN' => (sizeof($this->permission_dropdown) > 1) ? $this->build_permission_dropdown($this->permission_dropdown, $permission_type, $permission_scope) : false, + 'L_PERMISSION_TYPE' => $user->lang['ACL_TYPE_' . strtoupper($permission_type)], + + 'U_ACTION' => $this->u_action, + 'S_HIDDEN_FIELDS' => $s_hidden_fields) + ); + + if (strpos($mode, 'setting_') === 0) + { + $template->assign_vars(array( + 'S_SETTING_PERMISSIONS' => true) + ); + + $hold_ary = $auth_admin->get_mask('set', (sizeof($user_id)) ? $user_id : false, (sizeof($group_id)) ? $group_id : false, (sizeof($forum_id)) ? $forum_id : false, $permission_type, $permission_scope, ACL_NO); + $auth_admin->display_mask('set', $permission_type, $hold_ary, ((sizeof($user_id)) ? 'user' : 'group'), (($permission_scope == 'local') ? true : false)); + } + else + { + $template->assign_vars(array( + 'S_VIEWING_PERMISSIONS' => true) + ); + + $hold_ary = $auth_admin->get_mask('view', (sizeof($user_id)) ? $user_id : false, (sizeof($group_id)) ? $group_id : false, (sizeof($forum_id)) ? $forum_id : false, $permission_type, $permission_scope, ACL_NEVER); + $auth_admin->display_mask('view', $permission_type, $hold_ary, ((sizeof($user_id)) ? 'user' : 'group'), (($permission_scope == 'local') ? true : false)); + } + } + + /** + * Build +subforum options + */ + function build_subforum_options($forum_list) + { + global $user; + + $s_options = ''; + + $forum_list = array_merge($forum_list); + + foreach ($forum_list as $key => $row) + { + if ($row['disabled']) + { + continue; + } + + $s_options .= '<option value="' . $row['forum_id'] . '"' . (($row['selected']) ? ' selected="selected"' : '') . '>' . $row['padding'] . $row['forum_name']; + + // We check if a branch is there... + $branch_there = false; + + foreach (array_slice($forum_list, $key + 1) as $temp_row) + { + if ($temp_row['left_id'] > $row['left_id'] && $temp_row['left_id'] < $row['right_id']) + { + $branch_there = true; + break; + } + continue; + } + + if ($branch_there) + { + $s_options .= ' [' . $user->lang['PLUS_SUBFORUMS'] . ']'; + } + + $s_options .= '</option>'; + } + + return $s_options; + } + + /** + * Build dropdown field for changing permission types + */ + function build_permission_dropdown($options, $default_option, $permission_scope) + { + global $user, $auth; + + $s_dropdown_options = ''; + foreach ($options as $setting) + { + if (!$auth->acl_get('a_' . str_replace('_', '', $setting) . 'auth')) + { + continue; + } + + $selected = ($setting == $default_option) ? ' selected="selected"' : ''; + $l_setting = (isset($user->lang['permission_type'][$permission_scope][$setting])) ? $user->lang['permission_type'][$permission_scope][$setting] : $user->lang['permission_type'][$setting]; + $s_dropdown_options .= '<option value="' . $setting . '"' . $selected . '>' . $l_setting . '</option>'; + } + + return $s_dropdown_options; + } + + /** + * Check if selected items exist. Remove not found ids and if empty return error. + */ + function check_existence($mode, &$ids) + { + global $db, $user; + + switch ($mode) + { + case 'user': + $table = USERS_TABLE; + $sql_id = 'user_id'; + break; + + case 'group': + $table = GROUPS_TABLE; + $sql_id = 'group_id'; + break; + + case 'forum': + $table = FORUMS_TABLE; + $sql_id = 'forum_id'; + break; + } + + if (sizeof($ids)) + { + $sql = "SELECT $sql_id + FROM $table + WHERE " . $db->sql_in_set($sql_id, $ids); + $result = $db->sql_query($sql); + + $ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $ids[] = (int) $row[$sql_id]; + } + $db->sql_freeresult($result); + } + + if (!sizeof($ids)) + { + trigger_error($user->lang['SELECTED_' . strtoupper($mode) . '_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + + /** + * Apply permissions + */ + function set_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id) + { + global $user, $auth; + + $psubmit = request_var('psubmit', array(0 => array(0 => 0))); + + // User or group to be set? + $ug_type = (sizeof($user_id)) ? 'user' : 'group'; + + // Check the permission setting again + if (!$auth->acl_get('a_' . str_replace('_', '', $permission_type) . 'auth') || !$auth->acl_get('a_auth' . $ug_type . 's')) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $ug_id = $forum_id = 0; + + // We loop through the auth settings defined in our submit + list($ug_id, ) = each($psubmit); + list($forum_id, ) = each($psubmit[$ug_id]); + + if (empty($_POST['setting']) || empty($_POST['setting'][$ug_id]) || empty($_POST['setting'][$ug_id][$forum_id]) || !is_array($_POST['setting'][$ug_id][$forum_id])) + { + trigger_error('WRONG_PERMISSION_SETTING_FORMAT', E_USER_WARNING); + } + + // We obtain and check $_POST['setting'][$ug_id][$forum_id] directly and not using request_var() because request_var() + // currently does not support the amount of dimensions required. ;) + // $auth_settings = request_var('setting', array(0 => array(0 => array('' => 0)))); + $auth_settings = array_map('intval', $_POST['setting'][$ug_id][$forum_id]); + + // Do we have a role we want to set? + $assigned_role = (isset($_POST['role'][$ug_id][$forum_id])) ? (int) $_POST['role'][$ug_id][$forum_id] : 0; + + // Do the admin want to set these permissions to other items too? + $inherit = request_var('inherit', array(0 => array(0))); + + $ug_id = array($ug_id); + $forum_id = array($forum_id); + + if (sizeof($inherit)) + { + foreach ($inherit as $_ug_id => $forum_id_ary) + { + // Inherit users/groups? + if (!in_array($_ug_id, $ug_id)) + { + $ug_id[] = $_ug_id; + } + + // Inherit forums? + $forum_id = array_merge($forum_id, array_keys($forum_id_ary)); + } + } + + $forum_id = array_unique($forum_id); + + // If the auth settings differ from the assigned role, then do not set a role... + if ($assigned_role) + { + if (!$this->check_assigned_role($assigned_role, $auth_settings)) + { + $assigned_role = 0; + } + } + + // Update the permission set... + $auth_admin->acl_set($ug_type, $forum_id, $ug_id, $auth_settings, $assigned_role); + + // Do we need to recache the moderator lists? + if ($permission_type == 'm_') + { + cache_moderators(); + } + + // Remove users who are now moderators or admins from everyones foes list + if ($permission_type == 'm_' || $permission_type == 'a_') + { + update_foes($group_id, $user_id); + } + + $this->log_action($mode, 'add', $permission_type, $ug_type, $ug_id, $forum_id); + + trigger_error($user->lang['AUTH_UPDATED'] . adm_back_link($this->u_action)); + } + + /** + * Apply all permissions + */ + function set_all_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id) + { + global $user, $auth; + + // User or group to be set? + $ug_type = (sizeof($user_id)) ? 'user' : 'group'; + + // Check the permission setting again + if (!$auth->acl_get('a_' . str_replace('_', '', $permission_type) . 'auth') || !$auth->acl_get('a_auth' . $ug_type . 's')) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $auth_settings = (isset($_POST['setting'])) ? $_POST['setting'] : array(); + $auth_roles = (isset($_POST['role'])) ? $_POST['role'] : array(); + $ug_ids = $forum_ids = array(); + + // We need to go through the auth settings + foreach ($auth_settings as $ug_id => $forum_auth_row) + { + $ug_id = (int) $ug_id; + $ug_ids[] = $ug_id; + + foreach ($forum_auth_row as $forum_id => $auth_options) + { + $forum_id = (int) $forum_id; + $forum_ids[] = $forum_id; + + // Check role... + $assigned_role = (isset($auth_roles[$ug_id][$forum_id])) ? (int) $auth_roles[$ug_id][$forum_id] : 0; + + // If the auth settings differ from the assigned role, then do not set a role... + if ($assigned_role) + { + if (!$this->check_assigned_role($assigned_role, $auth_options)) + { + $assigned_role = 0; + } + } + + // Update the permission set... + $auth_admin->acl_set($ug_type, $forum_id, $ug_id, $auth_options, $assigned_role, false); + } + } + + $auth_admin->acl_clear_prefetch(); + + // Do we need to recache the moderator lists? + if ($permission_type == 'm_') + { + cache_moderators(); + } + + // Remove users who are now moderators or admins from everyones foes list + if ($permission_type == 'm_' || $permission_type == 'a_') + { + update_foes($group_id, $user_id); + } + + $this->log_action($mode, 'add', $permission_type, $ug_type, $ug_ids, $forum_ids); + + if ($mode == 'setting_forum_local' || $mode == 'setting_mod_local') + { + trigger_error($user->lang['AUTH_UPDATED'] . adm_back_link($this->u_action . '&forum_id[]=' . implode('&forum_id[]=', $forum_ids))); + } + else + { + trigger_error($user->lang['AUTH_UPDATED'] . adm_back_link($this->u_action)); + } + } + + /** + * Compare auth settings with auth settings from role + * returns false if they differ, true if they are equal + */ + function check_assigned_role($role_id, &$auth_settings) + { + global $db; + + $sql = 'SELECT o.auth_option, r.auth_setting + FROM ' . ACL_OPTIONS_TABLE . ' o, ' . ACL_ROLES_DATA_TABLE . ' r + WHERE o.auth_option_id = r.auth_option_id + AND r.role_id = ' . $role_id; + $result = $db->sql_query($sql); + + $test_auth_settings = array(); + while ($row = $db->sql_fetchrow($result)) + { + $test_auth_settings[$row['auth_option']] = $row['auth_setting']; + } + $db->sql_freeresult($result); + + // We need to add any ACL_NO setting from auth_settings to compare correctly + foreach ($auth_settings as $option => $setting) + { + if ($setting == ACL_NO) + { + $test_auth_settings[$option] = $setting; + } + } + + if (sizeof(array_diff_assoc($auth_settings, $test_auth_settings))) + { + return false; + } + + return true; + } + + /** + * Remove permissions + */ + function remove_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id, &$forum_id) + { + global $user, $db, $auth; + + // User or group to be set? + $ug_type = (sizeof($user_id)) ? 'user' : 'group'; + + // Check the permission setting again + if (!$auth->acl_get('a_' . str_replace('_', '', $permission_type) . 'auth') || !$auth->acl_get('a_auth' . $ug_type . 's')) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $auth_admin->acl_delete($ug_type, (($ug_type == 'user') ? $user_id : $group_id), (sizeof($forum_id) ? $forum_id : false), $permission_type); + + // Do we need to recache the moderator lists? + if ($permission_type == 'm_') + { + cache_moderators(); + } + + $this->log_action($mode, 'del', $permission_type, $ug_type, (($ug_type == 'user') ? $user_id : $group_id), (sizeof($forum_id) ? $forum_id : array(0 => 0))); + + if ($mode == 'setting_forum_local' || $mode == 'setting_mod_local') + { + trigger_error($user->lang['AUTH_UPDATED'] . adm_back_link($this->u_action . '&forum_id[]=' . implode('&forum_id[]=', $forum_id))); + } + else + { + trigger_error($user->lang['AUTH_UPDATED'] . adm_back_link($this->u_action)); + } + } + + /** + * Log permission changes + */ + function log_action($mode, $action, $permission_type, $ug_type, $ug_id, $forum_id) + { + global $db, $user; + + if (!is_array($ug_id)) + { + $ug_id = array($ug_id); + } + + if (!is_array($forum_id)) + { + $forum_id = array($forum_id); + } + + // Logging ... first grab user or groupnames ... + $sql = ($ug_type == 'group') ? 'SELECT group_name as name, group_type FROM ' . GROUPS_TABLE . ' WHERE ' : 'SELECT username as name FROM ' . USERS_TABLE . ' WHERE '; + $sql .= $db->sql_in_set(($ug_type == 'group') ? 'group_id' : 'user_id', array_map('intval', $ug_id)); + $result = $db->sql_query($sql); + + $l_ug_list = ''; + while ($row = $db->sql_fetchrow($result)) + { + $l_ug_list .= (($l_ug_list != '') ? ', ' : '') . ((isset($row['group_type']) && $row['group_type'] == GROUP_SPECIAL) ? '<span class="sep">' . $user->lang['G_' . $row['name']] . '</span>' : $row['name']); + } + $db->sql_freeresult($result); + + $mode = str_replace('setting_', '', $mode); + + if ($forum_id[0] == 0) + { + add_log('admin', 'LOG_ACL_' . strtoupper($action) . '_' . strtoupper($mode) . '_' . strtoupper($permission_type), $l_ug_list); + } + else + { + // Grab the forum details if non-zero forum_id + $sql = 'SELECT forum_name + FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_id); + $result = $db->sql_query($sql); + + $l_forum_list = ''; + while ($row = $db->sql_fetchrow($result)) + { + $l_forum_list .= (($l_forum_list != '') ? ', ' : '') . $row['forum_name']; + } + $db->sql_freeresult($result); + + add_log('admin', 'LOG_ACL_' . strtoupper($action) . '_' . strtoupper($mode) . '_' . strtoupper($permission_type), $l_forum_list, $l_ug_list); + } + } + + /** + * Display a complete trace tree for the selected permission to determine where settings are set/unset + */ + function permission_trace($user_id, $forum_id, $permission) + { + global $db, $template, $user, $auth; + + if ($user_id != $user->data['user_id']) + { + $sql = 'SELECT user_id, username, user_permissions, user_type + FROM ' . USERS_TABLE . ' + WHERE user_id = ' . $user_id; + $result = $db->sql_query($sql); + $userdata = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + } + else + { + $userdata = $user->data; + } + + if (!$userdata) + { + trigger_error('NO_USERS', E_USER_ERROR); + } + + $forum_name = false; + + if ($forum_id) + { + $sql = 'SELECT forum_name + FROM ' . FORUMS_TABLE . " + WHERE forum_id = $forum_id"; + $result = $db->sql_query($sql, 3600); + $forum_name = $db->sql_fetchfield('forum_name'); + $db->sql_freeresult($result); + } + + $back = request_var('back', 0); + + $template->assign_vars(array( + 'PERMISSION' => $user->lang['acl_' . $permission]['lang'], + 'PERMISSION_USERNAME' => $userdata['username'], + 'FORUM_NAME' => $forum_name, + + 'S_GLOBAL_TRACE' => ($forum_id) ? false : true, + + 'U_BACK' => ($back) ? build_url(array('f', 'back')) . "&f=$back" : '') + ); + + $template->assign_block_vars('trace', array( + 'WHO' => $user->lang['DEFAULT'], + 'INFORMATION' => $user->lang['TRACE_DEFAULT'], + + 'S_SETTING_NO' => true, + 'S_TOTAL_NO' => true) + ); + + $sql = 'SELECT DISTINCT g.group_name, g.group_id, g.group_type + FROM ' . GROUPS_TABLE . ' g + LEFT JOIN ' . USER_GROUP_TABLE . ' ug ON (ug.group_id = g.group_id) + WHERE ug.user_id = ' . $user_id . ' + AND ug.user_pending = 0 + AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1) + ORDER BY g.group_type DESC, g.group_id DESC'; + $result = $db->sql_query($sql); + + $groups = array(); + while ($row = $db->sql_fetchrow($result)) + { + $groups[$row['group_id']] = array( + 'auth_setting' => ACL_NO, + 'group_name' => ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'] + ); + } + $db->sql_freeresult($result); + + $total = ACL_NO; + $add_key = (($forum_id) ? '_LOCAL' : ''); + + if (sizeof($groups)) + { + // Get group auth settings + $hold_ary = $auth->acl_group_raw_data(array_keys($groups), $permission, $forum_id); + + foreach ($hold_ary as $group_id => $forum_ary) + { + $groups[$group_id]['auth_setting'] = $hold_ary[$group_id][$forum_id][$permission]; + } + unset($hold_ary); + + foreach ($groups as $id => $row) + { + switch ($row['auth_setting']) + { + case ACL_NO: + $information = $user->lang['TRACE_GROUP_NO' . $add_key]; + break; + + case ACL_YES: + $information = ($total == ACL_YES) ? $user->lang['TRACE_GROUP_YES_TOTAL_YES' . $add_key] : (($total == ACL_NEVER) ? $user->lang['TRACE_GROUP_YES_TOTAL_NEVER' . $add_key] : $user->lang['TRACE_GROUP_YES_TOTAL_NO' . $add_key]); + $total = ($total == ACL_NO) ? ACL_YES : $total; + break; + + case ACL_NEVER: + $information = ($total == ACL_YES) ? $user->lang['TRACE_GROUP_NEVER_TOTAL_YES' . $add_key] : (($total == ACL_NEVER) ? $user->lang['TRACE_GROUP_NEVER_TOTAL_NEVER' . $add_key] : $user->lang['TRACE_GROUP_NEVER_TOTAL_NO' . $add_key]); + $total = ACL_NEVER; + break; + } + + $template->assign_block_vars('trace', array( + 'WHO' => $row['group_name'], + 'INFORMATION' => $information, + + 'S_SETTING_NO' => ($row['auth_setting'] == ACL_NO) ? true : false, + 'S_SETTING_YES' => ($row['auth_setting'] == ACL_YES) ? true : false, + 'S_SETTING_NEVER' => ($row['auth_setting'] == ACL_NEVER) ? true : false, + 'S_TOTAL_NO' => ($total == ACL_NO) ? true : false, + 'S_TOTAL_YES' => ($total == ACL_YES) ? true : false, + 'S_TOTAL_NEVER' => ($total == ACL_NEVER) ? true : false) + ); + } + } + + // Get user specific permission... globally or for this forum + $hold_ary = $auth->acl_user_raw_data($user_id, $permission, $forum_id); + $auth_setting = (!sizeof($hold_ary)) ? ACL_NO : $hold_ary[$user_id][$forum_id][$permission]; + + switch ($auth_setting) + { + case ACL_NO: + $information = ($total == ACL_NO) ? $user->lang['TRACE_USER_NO_TOTAL_NO' . $add_key] : $user->lang['TRACE_USER_KEPT' . $add_key]; + $total = ($total == ACL_NO) ? ACL_NEVER : $total; + break; + + case ACL_YES: + $information = ($total == ACL_YES) ? $user->lang['TRACE_USER_YES_TOTAL_YES' . $add_key] : (($total == ACL_NEVER) ? $user->lang['TRACE_USER_YES_TOTAL_NEVER' . $add_key] : $user->lang['TRACE_USER_YES_TOTAL_NO' . $add_key]); + $total = ($total == ACL_NO) ? ACL_YES : $total; + break; + + case ACL_NEVER: + $information = ($total == ACL_YES) ? $user->lang['TRACE_USER_NEVER_TOTAL_YES' . $add_key] : (($total == ACL_NEVER) ? $user->lang['TRACE_USER_NEVER_TOTAL_NEVER' . $add_key] : $user->lang['TRACE_USER_NEVER_TOTAL_NO' . $add_key]); + $total = ACL_NEVER; + break; + } + + $template->assign_block_vars('trace', array( + 'WHO' => $userdata['username'], + 'INFORMATION' => $information, + + 'S_SETTING_NO' => ($auth_setting == ACL_NO) ? true : false, + 'S_SETTING_YES' => ($auth_setting == ACL_YES) ? true : false, + 'S_SETTING_NEVER' => ($auth_setting == ACL_NEVER) ? true : false, + 'S_TOTAL_NO' => false, + 'S_TOTAL_YES' => ($total == ACL_YES) ? true : false, + 'S_TOTAL_NEVER' => ($total == ACL_NEVER) ? true : false) + ); + + if ($forum_id != 0 && isset($auth->acl_options['global'][$permission])) + { + if ($user_id != $user->data['user_id']) + { + $auth2 = new auth(); + $auth2->acl($userdata); + $auth_setting = $auth2->acl_get($permission); + } + else + { + $auth_setting = $auth->acl_get($permission); + } + + if ($auth_setting) + { + $information = ($total == ACL_YES) ? $user->lang['TRACE_USER_GLOBAL_YES_TOTAL_YES'] : $user->lang['TRACE_USER_GLOBAL_YES_TOTAL_NEVER']; + $total = ACL_YES; + } + else + { + $information = $user->lang['TRACE_USER_GLOBAL_NEVER_TOTAL_KEPT']; + } + + // If there is no auth information we do not need to worry the user by showing non-relevant data. + if ($auth_setting) + { + $template->assign_block_vars('trace', array( + 'WHO' => sprintf($user->lang['TRACE_GLOBAL_SETTING'], $userdata['username']), + 'INFORMATION' => sprintf($information, '<a href="' . $this->u_action . "&u=$user_id&f=0&auth=$permission&back=$forum_id\">", '</a>'), + + 'S_SETTING_NO' => false, + 'S_SETTING_YES' => $auth_setting, + 'S_SETTING_NEVER' => !$auth_setting, + 'S_TOTAL_NO' => false, + 'S_TOTAL_YES' => ($total == ACL_YES) ? true : false, + 'S_TOTAL_NEVER' => ($total == ACL_NEVER) ? true : false) + ); + } + } + + // Take founder status into account, overwriting the default values + if ($userdata['user_type'] == USER_FOUNDER && strpos($permission, 'a_') === 0) + { + $template->assign_block_vars('trace', array( + 'WHO' => $userdata['username'], + 'INFORMATION' => $user->lang['TRACE_USER_FOUNDER'], + + 'S_SETTING_NO' => ($auth_setting == ACL_NO) ? true : false, + 'S_SETTING_YES' => ($auth_setting == ACL_YES) ? true : false, + 'S_SETTING_NEVER' => ($auth_setting == ACL_NEVER) ? true : false, + 'S_TOTAL_NO' => false, + 'S_TOTAL_YES' => true, + 'S_TOTAL_NEVER' => false) + ); + + $total = ACL_YES; + } + + // Total value... + $template->assign_vars(array( + 'S_RESULT_NO' => ($total == ACL_NO) ? true : false, + 'S_RESULT_YES' => ($total == ACL_YES) ? true : false, + 'S_RESULT_NEVER' => ($total == ACL_NEVER) ? true : false, + )); + } + + /** + * Handles copying permissions from one forum to others + */ + function copy_forum_permissions() + { + global $auth, $cache, $template, $user; + + $user->add_lang('acp/forums'); + + $submit = isset($_POST['submit']) ? true : false; + + if ($submit) + { + $src = request_var('src_forum_id', 0); + $dest = request_var('dest_forum_ids', array(0)); + + if (confirm_box(true)) + { + if (copy_forum_permissions($src, $dest)) + { + cache_moderators(); + + $auth->acl_clear_prefetch(); + $cache->destroy('sql', FORUMS_TABLE); + + trigger_error($user->lang['AUTH_UPDATED'] . adm_back_link($this->u_action)); + } + else + { + trigger_error($user->lang['SELECTED_FORUM_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + else + { + $s_hidden_fields = array( + 'submit' => $submit, + 'src_forum_id' => $src, + 'dest_forum_ids' => $dest, + ); + + $s_hidden_fields = build_hidden_fields($s_hidden_fields); + + confirm_box(false, $user->lang['COPY_PERMISSIONS_CONFIRM'], $s_hidden_fields); + } + } + + $template->assign_vars(array( + 'S_FORUM_OPTIONS' => make_forum_select(false, false, false, false, false), + )); + } + + /** + * Get already assigned users/groups + */ + function retrieve_defined_user_groups($permission_scope, $forum_id, $permission_type) + { + global $db, $user; + + $sql_forum_id = ($permission_scope == 'global') ? 'AND a.forum_id = 0' : ((sizeof($forum_id)) ? 'AND ' . $db->sql_in_set('a.forum_id', $forum_id) : 'AND a.forum_id <> 0'); + + // Permission options are only able to be a permission set... therefore we will pre-fetch the possible options and also the possible roles + $option_ids = $role_ids = array(); + + $sql = 'SELECT auth_option_id + FROM ' . ACL_OPTIONS_TABLE . ' + WHERE auth_option ' . $db->sql_like_expression($permission_type . $db->any_char); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $option_ids[] = (int) $row['auth_option_id']; + } + $db->sql_freeresult($result); + + if (sizeof($option_ids)) + { + $sql = 'SELECT DISTINCT role_id + FROM ' . ACL_ROLES_DATA_TABLE . ' + WHERE ' . $db->sql_in_set('auth_option_id', $option_ids); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $role_ids[] = (int) $row['role_id']; + } + $db->sql_freeresult($result); + } + + if (sizeof($option_ids) && sizeof($role_ids)) + { + $sql_where = 'AND (' . $db->sql_in_set('a.auth_option_id', $option_ids) . ' OR ' . $db->sql_in_set('a.auth_role_id', $role_ids) . ')'; + } + else if (sizeof($role_ids)) + { + $sql_where = 'AND ' . $db->sql_in_set('a.auth_role_id', $role_ids); + } + else if (sizeof($option_ids)) + { + $sql_where = 'AND ' . $db->sql_in_set('a.auth_option_id', $option_ids); + } + + // Not ideal, due to the filesort, non-use of indexes, etc. + $sql = 'SELECT DISTINCT u.user_id, u.username, u.username_clean, u.user_regdate + FROM ' . USERS_TABLE . ' u, ' . ACL_USERS_TABLE . " a + WHERE u.user_id = a.user_id + $sql_forum_id + $sql_where + ORDER BY u.username_clean, u.user_regdate ASC"; + $result = $db->sql_query($sql); + + $s_defined_user_options = ''; + $defined_user_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $s_defined_user_options .= '<option value="' . $row['user_id'] . '">' . $row['username'] . '</option>'; + $defined_user_ids[] = $row['user_id']; + } + $db->sql_freeresult($result); + + $sql = 'SELECT DISTINCT g.group_type, g.group_name, g.group_id + FROM ' . GROUPS_TABLE . ' g, ' . ACL_GROUPS_TABLE . " a + WHERE g.group_id = a.group_id + $sql_forum_id + $sql_where + ORDER BY g.group_type DESC, g.group_name ASC"; + $result = $db->sql_query($sql); + + $s_defined_group_options = ''; + $defined_group_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $s_defined_group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '">' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>'; + $defined_group_ids[] = $row['group_id']; + } + $db->sql_freeresult($result); + + return array( + 'group_ids' => $defined_group_ids, + 'group_ids_options' => $s_defined_group_options, + 'user_ids' => $defined_user_ids, + 'user_ids_options' => $s_defined_user_options + ); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_php_info.php b/phpBB/includes/acp/acp_php_info.php new file mode 100644 index 0000000000..9935c0466e --- /dev/null +++ b/phpBB/includes/acp/acp_php_info.php @@ -0,0 +1,84 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_php_info +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + if ($mode != 'info') + { + trigger_error('NO_MODE', E_USER_ERROR); + } + + $this->tpl_name = 'acp_php_info'; + $this->page_title = 'ACP_PHP_INFO'; + + ob_start(); + @phpinfo(INFO_GENERAL | INFO_CONFIGURATION | INFO_MODULES | INFO_VARIABLES); + $phpinfo = ob_get_clean(); + + $phpinfo = trim($phpinfo); + + // Here we play around a little with the PHP Info HTML to try and stylise + // it along phpBB's lines ... hopefully without breaking anything. The idea + // for this was nabbed from the PHP annotated manual + preg_match_all('#<body[^>]*>(.*)</body>#si', $phpinfo, $output); + + if (empty($phpinfo) || empty($output)) + { + trigger_error('NO_PHPINFO_AVAILABLE', E_USER_WARNING); + } + + $output = $output[1][0]; + + // expose_php can make the image not exist + if (preg_match('#<a[^>]*><img[^>]*></a>#', $output)) + { + $output = preg_replace('#<tr class="v"><td>(.*?<a[^>]*><img[^>]*></a>)(.*?)</td></tr>#s', '<tr class="row1"><td><table class="type2"><tr><td>\2</td><td>\1</td></tr></table></td></tr>', $output); + } + else + { + $output = preg_replace('#<tr class="v"><td>(.*?)</td></tr>#s', '<tr class="row1"><td><table class="type2"><tr><td>\1</td></tr></table></td></tr>', $output); + } + $output = preg_replace('#<table[^>]+>#i', '<table>', $output); + $output = preg_replace('#<img border="0"#i', '<img', $output); + $output = str_replace(array('class="e"', 'class="v"', 'class="h"', '<hr />', '<font', '</font>'), array('class="row1"', 'class="row2"', '', '', '<span', '</span>'), $output); + + if (empty($output)) + { + trigger_error('NO_PHPINFO_AVAILABLE', E_USER_WARNING); + } + + $orig_output = $output; + + preg_match_all('#<div class="center">(.*)</div>#siU', $output, $output); + $output = (!empty($output[1][0])) ? $output[1][0] : $orig_output; + + $template->assign_var('PHPINFO', $output); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php new file mode 100644 index 0000000000..1b0ec4b5d5 --- /dev/null +++ b/phpBB/includes/acp/acp_profile.php @@ -0,0 +1,1617 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_profile +{ + var $u_action; + + var $edit_lang_id; + var $lang_defs; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $cache; + global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix; + + include($phpbb_root_path . 'includes/functions_posting.' . $phpEx); + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + include($phpbb_root_path . 'includes/functions_profile_fields.' . $phpEx); + + $user->add_lang(array('ucp', 'acp/profile')); + $this->tpl_name = 'acp_profile'; + $this->page_title = 'ACP_CUSTOM_PROFILE_FIELDS'; + + $action = (isset($_POST['create'])) ? 'create' : request_var('action', ''); + + $error = array(); + $s_hidden_fields = ''; + + // Define some default values for each field type + $default_values = array( + FIELD_STRING => array('field_length' => 10, 'field_minlen' => 0, 'field_maxlen' => 20, 'field_validation' => '.*', 'field_novalue' => '', 'field_default_value' => ''), + FIELD_TEXT => array('field_length' => '5|80', 'field_minlen' => 0, 'field_maxlen' => 1000, 'field_validation' => '.*', 'field_novalue' => '', 'field_default_value' => ''), + FIELD_INT => array('field_length' => 5, 'field_minlen' => 0, 'field_maxlen' => 100, 'field_validation' => '', 'field_novalue' => 0, 'field_default_value' => 0), + FIELD_DATE => array('field_length' => 10, 'field_minlen' => 10, 'field_maxlen' => 10, 'field_validation' => '', 'field_novalue' => ' 0- 0- 0', 'field_default_value' => ' 0- 0- 0'), + FIELD_BOOL => array('field_length' => 1, 'field_minlen' => 0, 'field_maxlen' => 0, 'field_validation' => '', 'field_novalue' => 0, 'field_default_value' => 0), + FIELD_DROPDOWN => array('field_length' => 0, 'field_minlen' => 0, 'field_maxlen' => 5, 'field_validation' => '', 'field_novalue' => 0, 'field_default_value' => 0), + ); + + $cp = new custom_profile_admin(); + + // Build Language array + // Based on this, we decide which elements need to be edited later and which language items are missing + $this->lang_defs = array(); + + $sql = 'SELECT lang_id, lang_iso + FROM ' . LANG_TABLE . ' + ORDER BY lang_english_name'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + // Make some arrays with all available languages + $this->lang_defs['id'][$row['lang_id']] = $row['lang_iso']; + $this->lang_defs['iso'][$row['lang_iso']] = $row['lang_id']; + } + $db->sql_freeresult($result); + + $sql = 'SELECT field_id, lang_id + FROM ' . PROFILE_LANG_TABLE . ' + ORDER BY lang_id'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + // Which languages are available for each item + $this->lang_defs['entry'][$row['field_id']][] = $row['lang_id']; + } + $db->sql_freeresult($result); + + // Have some fields been defined? + if (isset($this->lang_defs['entry'])) + { + foreach ($this->lang_defs['entry'] as $field_id => $field_ary) + { + // Fill an array with the languages that are missing for each field + $this->lang_defs['diff'][$field_id] = array_diff(array_values($this->lang_defs['iso']), $field_ary); + } + } + + switch ($action) + { + case 'delete': + $field_id = request_var('field_id', 0); + + if (!$field_id) + { + trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (confirm_box(true)) + { + $sql = 'SELECT field_ident + FROM ' . PROFILE_FIELDS_TABLE . " + WHERE field_id = $field_id"; + $result = $db->sql_query($sql); + $field_ident = (string) $db->sql_fetchfield('field_ident'); + $db->sql_freeresult($result); + + $db->sql_transaction('begin'); + + $db->sql_query('DELETE FROM ' . PROFILE_FIELDS_TABLE . " WHERE field_id = $field_id"); + $db->sql_query('DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . " WHERE field_id = $field_id"); + $db->sql_query('DELETE FROM ' . PROFILE_LANG_TABLE . " WHERE field_id = $field_id"); + + switch ($db->sql_layer) + { + case 'sqlite': + $sql = "SELECT sql + FROM sqlite_master + WHERE type = 'table' + AND name = '" . PROFILE_FIELDS_DATA_TABLE . "' + ORDER BY type DESC, name;"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + // Create a temp table and populate it, destroy the existing one + $db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . PROFILE_FIELDS_DATA_TABLE . '"?#i', 'CREATE TEMPORARY TABLE ' . PROFILE_FIELDS_DATA_TABLE . '_temp', $row['sql'])); + $db->sql_query('INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . '_temp SELECT * FROM ' . PROFILE_FIELDS_DATA_TABLE); + $db->sql_query('DROP TABLE ' . PROFILE_FIELDS_DATA_TABLE); + + preg_match('#\((.*)\)#s', $row['sql'], $matches); + + $new_table_cols = trim($matches[1]); + $old_table_cols = preg_split('/,(?=[\\sa-z])/im', $new_table_cols); + $column_list = array(); + + foreach ($old_table_cols as $declaration) + { + $entities = preg_split('#\s+#', trim($declaration)); + + if ($entities[0] == 'PRIMARY') + { + continue; + } + + if ($entities[0] !== 'pf_' . $field_ident) + { + $column_list[] = $entities[0]; + } + } + + $columns = implode(',', $column_list); + + $new_table_cols = preg_replace('/' . 'pf_' . $field_ident . '[^,]+,/', '', $new_table_cols); + + // create a new table and fill it up. destroy the temp one + $db->sql_query('CREATE TABLE ' . PROFILE_FIELDS_DATA_TABLE . ' (' . $new_table_cols . ');'); + $db->sql_query('INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . PROFILE_FIELDS_DATA_TABLE . '_temp;'); + $db->sql_query('DROP TABLE ' . PROFILE_FIELDS_DATA_TABLE . '_temp'); + break; + + default: + $db->sql_query('ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " DROP COLUMN pf_$field_ident"); + } + + $order = 0; + + $sql = 'SELECT * + FROM ' . PROFILE_FIELDS_TABLE . ' + ORDER BY field_order'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $order++; + if ($row['field_order'] != $order) + { + $sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . " + SET field_order = $order + WHERE field_id = {$row['field_id']}"; + $db->sql_query($sql); + } + } + $db->sql_freeresult($result); + + $db->sql_transaction('commit'); + + add_log('admin', 'LOG_PROFILE_FIELD_REMOVED', $field_ident); + trigger_error($user->lang['REMOVED_PROFILE_FIELD'] . adm_back_link($this->u_action)); + } + else + { + confirm_box(false, 'DELETE_PROFILE_FIELD', build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'field_id' => $field_id, + ))); + } + + break; + + case 'activate': + $field_id = request_var('field_id', 0); + + if (!$field_id) + { + trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT lang_id + FROM ' . LANG_TABLE . " + WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'"; + $result = $db->sql_query($sql); + $default_lang_id = (int) $db->sql_fetchfield('lang_id'); + $db->sql_freeresult($result); + + if (!in_array($default_lang_id, $this->lang_defs['entry'][$field_id])) + { + trigger_error($user->lang['DEFAULT_LANGUAGE_NOT_FILLED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . " + SET field_active = 1 + WHERE field_id = $field_id"; + $db->sql_query($sql); + + $sql = 'SELECT field_ident + FROM ' . PROFILE_FIELDS_TABLE . " + WHERE field_id = $field_id"; + $result = $db->sql_query($sql); + $field_ident = (string) $db->sql_fetchfield('field_ident'); + $db->sql_freeresult($result); + + add_log('admin', 'LOG_PROFILE_FIELD_ACTIVATE', $field_ident); + trigger_error($user->lang['PROFILE_FIELD_ACTIVATED'] . adm_back_link($this->u_action)); + + break; + + case 'deactivate': + $field_id = request_var('field_id', 0); + + if (!$field_id) + { + trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . " + SET field_active = 0 + WHERE field_id = $field_id"; + $db->sql_query($sql); + + $sql = 'SELECT field_ident + FROM ' . PROFILE_FIELDS_TABLE . " + WHERE field_id = $field_id"; + $result = $db->sql_query($sql); + $field_ident = (string) $db->sql_fetchfield('field_ident'); + $db->sql_freeresult($result); + + add_log('admin', 'LOG_PROFILE_FIELD_DEACTIVATE', $field_ident); + trigger_error($user->lang['PROFILE_FIELD_DEACTIVATED'] . adm_back_link($this->u_action)); + + break; + + case 'move_up': + case 'move_down': + $field_order = request_var('order', 0); + $order_total = $field_order * 2 + (($action == 'move_up') ? -1 : 1); + + $sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . " + SET field_order = $order_total - field_order + WHERE field_order IN ($field_order, " . (($action == 'move_up') ? $field_order - 1 : $field_order + 1) . ')'; + $db->sql_query($sql); + + break; + + case 'create': + case 'edit': + + $field_id = request_var('field_id', 0); + $step = request_var('step', 1); + + $submit = (isset($_REQUEST['next']) || isset($_REQUEST['prev'])) ? true : false; + $save = (isset($_REQUEST['save'])) ? true : false; + + // The language id of default language + $this->edit_lang_id = $this->lang_defs['iso'][$config['default_lang']]; + + // We are editing... we need to grab basic things + if ($action == 'edit') + { + if (!$field_id) + { + trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT l.*, f.* + FROM ' . PROFILE_LANG_TABLE . ' l, ' . PROFILE_FIELDS_TABLE . ' f + WHERE l.lang_id = ' . $this->edit_lang_id . " + AND f.field_id = $field_id + AND l.field_id = f.field_id"; + $result = $db->sql_query($sql); + $field_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$field_row) + { + // Some admin changed the default language? + $sql = 'SELECT l.*, f.* + FROM ' . PROFILE_LANG_TABLE . ' l, ' . PROFILE_FIELDS_TABLE . ' f + WHERE l.lang_id <> ' . $this->edit_lang_id . " + AND f.field_id = $field_id + AND l.field_id = f.field_id"; + $result = $db->sql_query($sql); + $field_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$field_row) + { + trigger_error($user->lang['FIELD_NOT_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $this->edit_lang_id = $field_row['lang_id']; + } + $field_type = $field_row['field_type']; + + // Get language entries + $sql = 'SELECT * + FROM ' . PROFILE_FIELDS_LANG_TABLE . ' + WHERE lang_id = ' . $this->edit_lang_id . " + AND field_id = $field_id + ORDER BY option_id ASC"; + $result = $db->sql_query($sql); + + $lang_options = array(); + while ($row = $db->sql_fetchrow($result)) + { + $lang_options[$row['option_id']] = $row['lang_value']; + } + $db->sql_freeresult($result); + + $s_hidden_fields = '<input type="hidden" name="field_id" value="' . $field_id . '" />'; + } + else + { + // We are adding a new field, define basic params + $lang_options = $field_row = array(); + + $field_type = request_var('field_type', 0); + + if (!$field_type) + { + trigger_error($user->lang['NO_FIELD_TYPE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $field_row = array_merge($default_values[$field_type], array( + 'field_ident' => str_replace(' ', '_', utf8_clean_string(request_var('field_ident', '', true))), + 'field_required' => 0, + 'field_hide' => 0, + 'field_show_profile'=> 0, + 'field_no_view' => 0, + 'field_show_on_reg' => 0, + 'field_show_on_vt' => 0, + 'lang_name' => utf8_normalize_nfc(request_var('field_ident', '', true)), + 'lang_explain' => '', + 'lang_default_value'=> '') + ); + + $s_hidden_fields = '<input type="hidden" name="field_type" value="' . $field_type . '" />'; + } + + // $exclude contains the data we gather in each step + $exclude = array( + 1 => array('field_ident', 'lang_name', 'lang_explain', 'field_option_none', 'field_show_on_reg', 'field_show_on_vt', 'field_required', 'field_hide', 'field_show_profile', 'field_no_view'), + 2 => array('field_length', 'field_maxlen', 'field_minlen', 'field_validation', 'field_novalue', 'field_default_value'), + 3 => array('l_lang_name', 'l_lang_explain', 'l_lang_default_value', 'l_lang_options') + ); + + // Text-based fields require the lang_default_value to be excluded + if ($field_type == FIELD_STRING || $field_type == FIELD_TEXT) + { + $exclude[1][] = 'lang_default_value'; + } + + // option-specific fields require lang_options to be excluded + if ($field_type == FIELD_BOOL || $field_type == FIELD_DROPDOWN) + { + $exclude[1][] = 'lang_options'; + } + + $cp->vars['field_ident'] = ($action == 'create' && $step == 1) ? utf8_clean_string(request_var('field_ident', $field_row['field_ident'], true)) : request_var('field_ident', $field_row['field_ident']); + $cp->vars['lang_name'] = utf8_normalize_nfc(request_var('lang_name', $field_row['lang_name'], true)); + $cp->vars['lang_explain'] = utf8_normalize_nfc(request_var('lang_explain', $field_row['lang_explain'], true)); + $cp->vars['lang_default_value'] = utf8_normalize_nfc(request_var('lang_default_value', $field_row['lang_default_value'], true)); + + // Visibility Options... + $visibility_ary = array( + 'field_required', + 'field_show_on_reg', + 'field_show_on_vt', + 'field_show_profile', + 'field_hide', + ); + + foreach ($visibility_ary as $val) + { + $cp->vars[$val] = ($submit || $save) ? request_var($val, 0) : $field_row[$val]; + } + + $cp->vars['field_no_view'] = request_var('field_no_view', (int) $field_row['field_no_view']); + + // A boolean field expects an array as the lang options + if ($field_type == FIELD_BOOL) + { + $options = utf8_normalize_nfc(request_var('lang_options', array(''), true)); + } + else + { + $options = utf8_normalize_nfc(request_var('lang_options', '', true)); + } + + // If the user has submitted a form with options (i.e. dropdown field) + if ($options) + { + $exploded_options = (is_array($options)) ? $options : explode("\n", $options); + + if (sizeof($exploded_options) == sizeof($lang_options) || $action == 'create') + { + // The number of options in the field is equal to the number of options already in the database + // Or we are creating a new dropdown list. + $cp->vars['lang_options'] = $exploded_options; + } + else if ($action == 'edit') + { + // Changing the number of options? (We remove and re-create the option fields) + $cp->vars['lang_options'] = $exploded_options; + } + } + else + { + $cp->vars['lang_options'] = $lang_options; + } + + // step 2 + foreach ($exclude[2] as $key) + { + $var = utf8_normalize_nfc(request_var($key, $field_row[$key], true)); + + // Manipulate the intended variables a little bit if needed + if ($field_type == FIELD_DROPDOWN && $key == 'field_maxlen') + { + // Get the number of options if this key is 'field_maxlen' + $var = sizeof(explode("\n", utf8_normalize_nfc(request_var('lang_options', '', true)))); + } + else if ($field_type == FIELD_TEXT && $key == 'field_length') + { + if (isset($_REQUEST['rows'])) + { + $cp->vars['rows'] = request_var('rows', 0); + $cp->vars['columns'] = request_var('columns', 0); + $var = $cp->vars['rows'] . '|' . $cp->vars['columns']; + } + else + { + $row_col = explode('|', $var); + $cp->vars['rows'] = $row_col[0]; + $cp->vars['columns'] = $row_col[1]; + } + } + else if ($field_type == FIELD_DATE && $key == 'field_default_value') + { + $always_now = request_var('always_now', -1); + + if ($always_now == 1 || ($always_now === -1 && $var == 'now')) + { + $now = getdate(); + + $cp->vars['field_default_value_day'] = $now['mday']; + $cp->vars['field_default_value_month'] = $now['mon']; + $cp->vars['field_default_value_year'] = $now['year']; + $var = $_POST['field_default_value'] = 'now'; + } + else + { + if (isset($_REQUEST['field_default_value_day'])) + { + $cp->vars['field_default_value_day'] = request_var('field_default_value_day', 0); + $cp->vars['field_default_value_month'] = request_var('field_default_value_month', 0); + $cp->vars['field_default_value_year'] = request_var('field_default_value_year', 0); + $var = $_POST['field_default_value'] = sprintf('%2d-%2d-%4d', $cp->vars['field_default_value_day'], $cp->vars['field_default_value_month'], $cp->vars['field_default_value_year']); + } + else + { + list($cp->vars['field_default_value_day'], $cp->vars['field_default_value_month'], $cp->vars['field_default_value_year']) = explode('-', $var); + } + } + } + /* else if ($field_type == FIELD_BOOL && $key == 'field_default_value') + { + // Get the number of options if this key is 'field_maxlen' + $var = request_var('field_default_value', 0); + }*/ + + $cp->vars[$key] = $var; + } + + // step 3 - all arrays + if ($action == 'edit') + { + // Get language entries + $sql = 'SELECT * + FROM ' . PROFILE_FIELDS_LANG_TABLE . ' + WHERE lang_id <> ' . $this->edit_lang_id . " + AND field_id = $field_id + ORDER BY option_id ASC"; + $result = $db->sql_query($sql); + + $l_lang_options = array(); + while ($row = $db->sql_fetchrow($result)) + { + $l_lang_options[$row['lang_id']][$row['option_id']] = $row['lang_value']; + } + $db->sql_freeresult($result); + + + $sql = 'SELECT lang_id, lang_name, lang_explain, lang_default_value + FROM ' . PROFILE_LANG_TABLE . ' + WHERE lang_id <> ' . $this->edit_lang_id . " + AND field_id = $field_id + ORDER BY lang_id ASC"; + $result = $db->sql_query($sql); + + $l_lang_name = $l_lang_explain = $l_lang_default_value = array(); + while ($row = $db->sql_fetchrow($result)) + { + $l_lang_name[$row['lang_id']] = $row['lang_name']; + $l_lang_explain[$row['lang_id']] = $row['lang_explain']; + $l_lang_default_value[$row['lang_id']] = $row['lang_default_value']; + } + $db->sql_freeresult($result); + } + + foreach ($exclude[3] as $key) + { + $cp->vars[$key] = utf8_normalize_nfc(request_var($key, array(0 => ''), true)); + + if (!$cp->vars[$key] && $action == 'edit') + { + $cp->vars[$key] = $$key; + } + else if ($key == 'l_lang_options' && $field_type == FIELD_BOOL) + { + $cp->vars[$key] = utf8_normalize_nfc(request_var($key, array(0 => array('')), true)); + } + else if ($key == 'l_lang_options' && is_array($cp->vars[$key])) + { + foreach ($cp->vars[$key] as $lang_id => $options) + { + $cp->vars[$key][$lang_id] = explode("\n", $options); + } + + } + } + + // Check for general issues in every step + if ($submit) // && $step == 1 + { + // Check values for step 1 + if ($cp->vars['field_ident'] == '') + { + $error[] = $user->lang['EMPTY_FIELD_IDENT']; + } + + if (!preg_match('/^[a-z_]+$/', $cp->vars['field_ident'])) + { + $error[] = $user->lang['INVALID_CHARS_FIELD_IDENT']; + } + + if (strlen($cp->vars['field_ident']) > 17) + { + $error[] = $user->lang['INVALID_FIELD_IDENT_LEN']; + } + + if ($cp->vars['lang_name'] == '') + { + $error[] = $user->lang['EMPTY_USER_FIELD_NAME']; + } + + if ($field_type == FIELD_DROPDOWN && !sizeof($cp->vars['lang_options'])) + { + $error[] = $user->lang['NO_FIELD_ENTRIES']; + } + + if ($field_type == FIELD_BOOL && (empty($cp->vars['lang_options'][0]) || empty($cp->vars['lang_options'][1]))) + { + $error[] = $user->lang['NO_FIELD_ENTRIES']; + } + + // Check for already existing field ident + if ($action != 'edit') + { + $sql = 'SELECT field_ident + FROM ' . PROFILE_FIELDS_TABLE . " + WHERE field_ident = '" . $db->sql_escape($cp->vars['field_ident']) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + $error[] = $user->lang['FIELD_IDENT_ALREADY_EXIST']; + } + } + } + + $step = (isset($_REQUEST['next'])) ? $step + 1 : ((isset($_REQUEST['prev'])) ? $step - 1 : $step); + + if (sizeof($error)) + { + $step--; + $submit = false; + } + + // Build up the specific hidden fields + foreach ($exclude as $num => $key_ary) + { + if ($num == $step) + { + continue; + } + + $_new_key_ary = array(); + + foreach ($key_ary as $key) + { + if ($field_type == FIELD_TEXT && $key == 'field_length' && isset($_REQUEST['rows'])) + { + $cp->vars['rows'] = request_var('rows', 0); + $cp->vars['columns'] = request_var('columns', 0); + $_new_key_ary[$key] = $cp->vars['rows'] . '|' . $cp->vars['columns']; + } + else if ($field_type == FIELD_DATE && $key == 'field_default_value') + { + $always_now = request_var('always_now', 0); + + if ($always_now) + { + $_new_key_ary[$key] = 'now'; + } + else if (isset($_REQUEST['field_default_value_day'])) + { + $cp->vars['field_default_value_day'] = request_var('field_default_value_day', 0); + $cp->vars['field_default_value_month'] = request_var('field_default_value_month', 0); + $cp->vars['field_default_value_year'] = request_var('field_default_value_year', 0); + $_new_key_ary[$key] = sprintf('%2d-%2d-%4d', $cp->vars['field_default_value_day'], $cp->vars['field_default_value_month'], $cp->vars['field_default_value_year']); + } + } + else if ($field_type == FIELD_BOOL && $key == 'l_lang_options' && isset($_REQUEST['l_lang_options'])) + { + $_new_key_ary[$key] = utf8_normalize_nfc(request_var($key, array(array('')), true)); + } + else + { + if (!isset($_REQUEST[$key])) + { + $var = false; + } + else if ($key == 'field_ident' && isset($cp->vars[$key])) + { + $_new_key_ary[$key]= $cp->vars[$key]; + } + else + { + $_new_key_ary[$key] = (is_array($_REQUEST[$key])) ? utf8_normalize_nfc(request_var($key, array(''), true)) : utf8_normalize_nfc(request_var($key, '', true)); + } + } + } + + $s_hidden_fields .= build_hidden_fields($_new_key_ary); + } + + if (!sizeof($error)) + { + if ($step == 3 && (sizeof($this->lang_defs['iso']) == 1 || $save)) + { + $this->save_profile_field($cp, $field_type, $action); + } + else if ($action == 'edit' && $save) + { + $this->save_profile_field($cp, $field_type, $action); + } + } + + $template->assign_vars(array( + 'S_EDIT' => true, + 'S_EDIT_MODE' => ($action == 'edit') ? true : false, + 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + + 'L_TITLE' => $user->lang['STEP_' . $step . '_TITLE_' . strtoupper($action)], + 'L_EXPLAIN' => $user->lang['STEP_' . $step . '_EXPLAIN_' . strtoupper($action)], + + 'U_ACTION' => $this->u_action . "&action=$action&step=$step", + 'U_BACK' => $this->u_action) + ); + + // Now go through the steps + switch ($step) + { + // Create basic options - only small differences between field types + case 1: + + // Build common create options + $template->assign_vars(array( + 'S_STEP_ONE' => true, + 'S_FIELD_REQUIRED' => ($cp->vars['field_required']) ? true : false, + 'S_SHOW_ON_REG' => ($cp->vars['field_show_on_reg']) ? true : false, + 'S_SHOW_ON_VT' => ($cp->vars['field_show_on_vt']) ? true : false, + 'S_FIELD_HIDE' => ($cp->vars['field_hide']) ? true : false, + 'S_SHOW_PROFILE' => ($cp->vars['field_show_profile']) ? true : false, + 'S_FIELD_NO_VIEW' => ($cp->vars['field_no_view']) ? true : false, + + 'L_LANG_SPECIFIC' => sprintf($user->lang['LANG_SPECIFIC_OPTIONS'], $config['default_lang']), + 'FIELD_TYPE' => $user->lang['FIELD_' . strtoupper($cp->profile_types[$field_type])], + 'FIELD_IDENT' => $cp->vars['field_ident'], + 'LANG_NAME' => $cp->vars['lang_name'], + 'LANG_EXPLAIN' => $cp->vars['lang_explain']) + ); + + // String and Text needs to set default values here... + if ($field_type == FIELD_STRING || $field_type == FIELD_TEXT) + { + $template->assign_vars(array( + 'S_TEXT' => ($field_type == FIELD_TEXT) ? true : false, + 'S_STRING' => ($field_type == FIELD_STRING) ? true : false, + + 'L_DEFAULT_VALUE_EXPLAIN' => $user->lang[strtoupper($cp->profile_types[$field_type]) . '_DEFAULT_VALUE_EXPLAIN'], + 'LANG_DEFAULT_VALUE' => $cp->vars['lang_default_value']) + ); + } + + if ($field_type == FIELD_BOOL || $field_type == FIELD_DROPDOWN) + { + // Initialize these array elements if we are creating a new field + if (!sizeof($cp->vars['lang_options'])) + { + if ($field_type == FIELD_BOOL) + { + // No options have been defined for a boolean field. + $cp->vars['lang_options'][0] = ''; + $cp->vars['lang_options'][1] = ''; + } + else + { + // No options have been defined for the dropdown menu + $cp->vars['lang_options'] = array(); + } + } + + $template->assign_vars(array( + 'S_BOOL' => ($field_type == FIELD_BOOL) ? true : false, + 'S_DROPDOWN' => ($field_type == FIELD_DROPDOWN) ? true : false, + + 'L_LANG_OPTIONS_EXPLAIN' => $user->lang[strtoupper($cp->profile_types[$field_type]) . '_ENTRIES_EXPLAIN'], + 'LANG_OPTIONS' => ($field_type == FIELD_DROPDOWN) ? implode("\n", $cp->vars['lang_options']) : '', + 'FIRST_LANG_OPTION' => ($field_type == FIELD_BOOL) ? $cp->vars['lang_options'][0] : '', + 'SECOND_LANG_OPTION' => ($field_type == FIELD_BOOL) ? $cp->vars['lang_options'][1] : '') + ); + } + + break; + + case 2: + + $template->assign_vars(array( + 'S_STEP_TWO' => true, + 'L_NEXT_STEP' => (sizeof($this->lang_defs['iso']) == 1) ? $user->lang['SAVE'] : $user->lang['PROFILE_LANG_OPTIONS']) + ); + + // Build options based on profile type + $function = 'get_' . $cp->profile_types[$field_type] . '_options'; + $options = $cp->$function(); + + foreach ($options as $num => $option_ary) + { + $template->assign_block_vars('option', $option_ary); + } + + break; + + // Define remaining language variables + case 3: + + $template->assign_var('S_STEP_THREE', true); + $options = $this->build_language_options($cp, $field_type, $action); + + foreach ($options as $lang_id => $lang_ary) + { + $template->assign_block_vars('options', array( + 'LANGUAGE' => sprintf($user->lang[(($lang_id == $this->edit_lang_id) ? 'DEFAULT_' : '') . 'ISO_LANGUAGE'], $lang_ary['lang_iso'])) + ); + + foreach ($lang_ary['fields'] as $field_ident => $field_ary) + { + $template->assign_block_vars('options.field', array( + 'L_TITLE' => $field_ary['TITLE'], + 'L_EXPLAIN' => (isset($field_ary['EXPLAIN'])) ? $field_ary['EXPLAIN'] : '', + 'FIELD' => $field_ary['FIELD']) + ); + } + } + + break; + } + + $template->assign_vars(array( + 'S_HIDDEN_FIELDS' => $s_hidden_fields) + ); + + return; + + break; + } + + $sql = 'SELECT * + FROM ' . PROFILE_FIELDS_TABLE . ' + ORDER BY field_order'; + $result = $db->sql_query($sql); + + $s_one_need_edit = false; + while ($row = $db->sql_fetchrow($result)) + { + $active_lang = (!$row['field_active']) ? 'ACTIVATE' : 'DEACTIVATE'; + $active_value = (!$row['field_active']) ? 'activate' : 'deactivate'; + $id = $row['field_id']; + + $s_need_edit = (sizeof($this->lang_defs['diff'][$row['field_id']])) ? true : false; + + if ($s_need_edit) + { + $s_one_need_edit = true; + } + + $template->assign_block_vars('fields', array( + 'FIELD_IDENT' => $row['field_ident'], + 'FIELD_TYPE' => $user->lang['FIELD_' . strtoupper($cp->profile_types[$row['field_type']])], + + 'L_ACTIVATE_DEACTIVATE' => $user->lang[$active_lang], + 'U_ACTIVATE_DEACTIVATE' => $this->u_action . "&action=$active_value&field_id=$id", + 'U_EDIT' => $this->u_action . "&action=edit&field_id=$id", + 'U_TRANSLATE' => $this->u_action . "&action=edit&field_id=$id&step=3", + 'U_DELETE' => $this->u_action . "&action=delete&field_id=$id", + 'U_MOVE_UP' => $this->u_action . "&action=move_up&order={$row['field_order']}", + 'U_MOVE_DOWN' => $this->u_action . "&action=move_down&order={$row['field_order']}", + + 'S_NEED_EDIT' => $s_need_edit) + ); + } + $db->sql_freeresult($result); + + // At least one option field needs editing? + if ($s_one_need_edit) + { + $template->assign_var('S_NEED_EDIT', true); + } + + $s_select_type = ''; + foreach ($cp->profile_types as $key => $value) + { + $s_select_type .= '<option value="' . $key . '">' . $user->lang['FIELD_' . strtoupper($value)] . '</option>'; + } + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action, + 'S_TYPE_OPTIONS' => $s_select_type) + ); + } + + /** + * Build all Language specific options + */ + function build_language_options(&$cp, $field_type, $action = 'create') + { + global $user, $config, $db; + + $default_lang_id = (!empty($this->edit_lang_id)) ? $this->edit_lang_id : $this->lang_defs['iso'][$config['default_lang']]; + + $sql = 'SELECT lang_id, lang_iso + FROM ' . LANG_TABLE . ' + WHERE lang_id <> ' . (int) $default_lang_id . ' + ORDER BY lang_english_name'; + $result = $db->sql_query($sql); + + $languages = array(); + while ($row = $db->sql_fetchrow($result)) + { + $languages[$row['lang_id']] = $row['lang_iso']; + } + $db->sql_freeresult($result); + + $options = array(); + $options['lang_name'] = 'string'; + if ($cp->vars['lang_explain']) + { + $options['lang_explain'] = 'text'; + } + + switch ($field_type) + { + case FIELD_BOOL: + $options['lang_options'] = 'two_options'; + break; + + case FIELD_DROPDOWN: + $options['lang_options'] = 'optionfield'; + break; + + case FIELD_TEXT: + case FIELD_STRING: + if (strlen($cp->vars['lang_default_value'])) + { + $options['lang_default_value'] = ($field_type == FIELD_STRING) ? 'string' : 'text'; + } + break; + } + + $lang_options = array(); + + foreach ($options as $field => $field_type) + { + $lang_options[1]['lang_iso'] = $this->lang_defs['id'][$default_lang_id]; + $lang_options[1]['fields'][$field] = array( + 'TITLE' => $user->lang['CP_' . strtoupper($field)], + 'FIELD' => '<dd>' . ((is_array($cp->vars[$field])) ? implode('<br />', $cp->vars[$field]) : bbcode_nl2br($cp->vars[$field])) . '</dd>' + ); + + if (isset($user->lang['CP_' . strtoupper($field) . '_EXPLAIN'])) + { + $lang_options[1]['fields'][$field]['EXPLAIN'] = $user->lang['CP_' . strtoupper($field) . '_EXPLAIN']; + } + } + + foreach ($languages as $lang_id => $lang_iso) + { + $lang_options[$lang_id]['lang_iso'] = $lang_iso; + foreach ($options as $field => $field_type) + { + $value = ($action == 'create') ? utf8_normalize_nfc(request_var('l_' . $field, array(0 => ''), true)) : $cp->vars['l_' . $field]; + if ($field == 'lang_options') + { + $var = (!isset($cp->vars['l_lang_options'][$lang_id]) || !is_array($cp->vars['l_lang_options'][$lang_id])) ? $cp->vars['lang_options'] : $cp->vars['l_lang_options'][$lang_id]; + + switch ($field_type) + { + case 'two_options': + + $lang_options[$lang_id]['fields'][$field] = array( + 'TITLE' => $user->lang['CP_' . strtoupper($field)], + 'FIELD' => ' + <dd><input class="medium" name="l_' . $field . '[' . $lang_id . '][]" value="' . ((isset($value[$lang_id][0])) ? $value[$lang_id][0] : $var[0]) . '" /> ' . $user->lang['FIRST_OPTION'] . '</dd> + <dd><input class="medium" name="l_' . $field . '[' . $lang_id . '][]" value="' . ((isset($value[$lang_id][1])) ? $value[$lang_id][1] : $var[1]) . '" /> ' . $user->lang['SECOND_OPTION'] . '</dd>' + ); + break; + + case 'optionfield': + $value = ((isset($value[$lang_id])) ? ((is_array($value[$lang_id])) ? implode("\n", $value[$lang_id]) : $value[$lang_id]) : implode("\n", $var)); + $lang_options[$lang_id]['fields'][$field] = array( + 'TITLE' => $user->lang['CP_' . strtoupper($field)], + 'FIELD' => '<dd><textarea name="l_' . $field . '[' . $lang_id . ']" rows="7" cols="80">' . $value . '</textarea></dd>' + ); + break; + } + + if (isset($user->lang['CP_' . strtoupper($field) . '_EXPLAIN'])) + { + $lang_options[$lang_id]['fields'][$field]['EXPLAIN'] = $user->lang['CP_' . strtoupper($field) . '_EXPLAIN']; + } + } + else + { + $var = ($action == 'create' || !is_array($cp->vars[$field])) ? $cp->vars[$field] : $cp->vars[$field][$lang_id]; + + $lang_options[$lang_id]['fields'][$field] = array( + 'TITLE' => $user->lang['CP_' . strtoupper($field)], + 'FIELD' => ($field_type == 'string') ? '<dd><input class="medium" type="text" name="l_' . $field . '[' . $lang_id . ']" value="' . ((isset($value[$lang_id])) ? $value[$lang_id] : $var) . '" /></dd>' : '<dd><textarea name="l_' . $field . '[' . $lang_id . ']" rows="3" cols="80">' . ((isset($value[$lang_id])) ? $value[$lang_id] : $var) . '</textarea></dd>' + ); + + if (isset($user->lang['CP_' . strtoupper($field) . '_EXPLAIN'])) + { + $lang_options[$lang_id]['fields'][$field]['EXPLAIN'] = $user->lang['CP_' . strtoupper($field) . '_EXPLAIN']; + } + } + } + } + + return $lang_options; + } + + /** + * Save Profile Field + */ + function save_profile_field(&$cp, $field_type, $action = 'create') + { + global $db, $config, $user; + + $field_id = request_var('field_id', 0); + + // Collect all information, if something is going wrong, abort the operation + $profile_sql = $profile_lang = $empty_lang = $profile_lang_fields = array(); + + $default_lang_id = (!empty($this->edit_lang_id)) ? $this->edit_lang_id : $this->lang_defs['iso'][$config['default_lang']]; + + if ($action == 'create') + { + $sql = 'SELECT MAX(field_order) as max_field_order + FROM ' . PROFILE_FIELDS_TABLE; + $result = $db->sql_query($sql); + $new_field_order = (int) $db->sql_fetchfield('max_field_order'); + $db->sql_freeresult($result); + + $field_ident = $cp->vars['field_ident']; + } + + // Save the field + $profile_fields = array( + 'field_length' => $cp->vars['field_length'], + 'field_minlen' => $cp->vars['field_minlen'], + 'field_maxlen' => $cp->vars['field_maxlen'], + 'field_novalue' => $cp->vars['field_novalue'], + 'field_default_value' => $cp->vars['field_default_value'], + 'field_validation' => $cp->vars['field_validation'], + 'field_required' => $cp->vars['field_required'], + 'field_show_on_reg' => $cp->vars['field_show_on_reg'], + 'field_show_on_vt' => $cp->vars['field_show_on_vt'], + 'field_hide' => $cp->vars['field_hide'], + 'field_show_profile' => $cp->vars['field_show_profile'], + 'field_no_view' => $cp->vars['field_no_view'] + ); + + if ($action == 'create') + { + $profile_fields += array( + 'field_type' => $field_type, + 'field_ident' => $field_ident, + 'field_name' => $field_ident, + 'field_order' => $new_field_order + 1, + 'field_active' => 1 + ); + + $sql = 'INSERT INTO ' . PROFILE_FIELDS_TABLE . ' ' . $db->sql_build_array('INSERT', $profile_fields); + $db->sql_query($sql); + + $field_id = $db->sql_nextid(); + } + else + { + $sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $profile_fields) . " + WHERE field_id = $field_id"; + $db->sql_query($sql); + } + + if ($action == 'create') + { + $field_ident = 'pf_' . $field_ident; + $profile_sql[] = $this->add_field_ident($field_ident, $field_type); + } + + $sql_ary = array( + 'lang_name' => $cp->vars['lang_name'], + 'lang_explain' => $cp->vars['lang_explain'], + 'lang_default_value' => $cp->vars['lang_default_value'] + ); + + if ($action == 'create') + { + $sql_ary['field_id'] = $field_id; + $sql_ary['lang_id'] = $default_lang_id; + + $profile_sql[] = 'INSERT INTO ' . PROFILE_LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); + } + else + { + $this->update_insert(PROFILE_LANG_TABLE, $sql_ary, array('field_id' => $field_id, 'lang_id' => $default_lang_id)); + } + + if (is_array($cp->vars['l_lang_name']) && sizeof($cp->vars['l_lang_name'])) + { + foreach ($cp->vars['l_lang_name'] as $lang_id => $data) + { + if (($cp->vars['lang_name'] != '' && $cp->vars['l_lang_name'][$lang_id] == '') + || ($cp->vars['lang_explain'] != '' && $cp->vars['l_lang_explain'][$lang_id] == '') + || ($cp->vars['lang_default_value'] != '' && $cp->vars['l_lang_default_value'][$lang_id] == '')) + { + $empty_lang[$lang_id] = true; + break; + } + + if (!isset($empty_lang[$lang_id])) + { + $profile_lang[] = array( + 'field_id' => $field_id, + 'lang_id' => $lang_id, + 'lang_name' => $cp->vars['l_lang_name'][$lang_id], + 'lang_explain' => (isset($cp->vars['l_lang_explain'][$lang_id])) ? $cp->vars['l_lang_explain'][$lang_id] : '', + 'lang_default_value' => (isset($cp->vars['l_lang_default_value'][$lang_id])) ? $cp->vars['l_lang_default_value'][$lang_id] : '' + ); + } + } + + foreach ($empty_lang as $lang_id => $NULL) + { + $sql = 'DELETE FROM ' . PROFILE_LANG_TABLE . " + WHERE field_id = $field_id + AND lang_id = " . (int) $lang_id; + $db->sql_query($sql); + } + } + + // These are always arrays because the key is the language id... + $cp->vars['l_lang_name'] = utf8_normalize_nfc(request_var('l_lang_name', array(0 => ''), true)); + $cp->vars['l_lang_explain'] = utf8_normalize_nfc(request_var('l_lang_explain', array(0 => ''), true)); + $cp->vars['l_lang_default_value'] = utf8_normalize_nfc(request_var('l_lang_default_value', array(0 => ''), true)); + + if ($field_type != FIELD_BOOL) + { + $cp->vars['l_lang_options'] = utf8_normalize_nfc(request_var('l_lang_options', array(0 => ''), true)); + } + else + { + /** + * @todo check if this line is correct... + $cp->vars['l_lang_default_value'] = request_var('l_lang_default_value', array(0 => array('')), true); + */ + $cp->vars['l_lang_options'] = utf8_normalize_nfc(request_var('l_lang_options', array(0 => array('')), true)); + } + + if ($cp->vars['lang_options']) + { + if (!is_array($cp->vars['lang_options'])) + { + $cp->vars['lang_options'] = explode("\n", $cp->vars['lang_options']); + } + + if ($action != 'create') + { + $sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . " + WHERE field_id = $field_id + AND lang_id = " . (int) $default_lang_id; + $db->sql_query($sql); + } + + foreach ($cp->vars['lang_options'] as $option_id => $value) + { + $sql_ary = array( + 'field_type' => (int) $field_type, + 'lang_value' => $value + ); + + if ($action == 'create') + { + $sql_ary['field_id'] = $field_id; + $sql_ary['lang_id'] = $default_lang_id; + $sql_ary['option_id'] = (int) $option_id; + + $profile_sql[] = 'INSERT INTO ' . PROFILE_FIELDS_LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); + } + else + { + $this->update_insert(PROFILE_FIELDS_LANG_TABLE, $sql_ary, array( + 'field_id' => $field_id, + 'lang_id' => (int) $default_lang_id, + 'option_id' => (int) $option_id) + ); + } + } + } + + if (is_array($cp->vars['l_lang_options']) && sizeof($cp->vars['l_lang_options'])) + { + $empty_lang = array(); + + foreach ($cp->vars['l_lang_options'] as $lang_id => $lang_ary) + { + if (!is_array($lang_ary)) + { + $lang_ary = explode("\n", $lang_ary); + } + + if (sizeof($lang_ary) != sizeof($cp->vars['lang_options'])) + { + $empty_lang[$lang_id] = true; + } + + if (!isset($empty_lang[$lang_id])) + { + if ($action != 'create') + { + $sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . " + WHERE field_id = $field_id + AND lang_id = " . (int) $lang_id; + $db->sql_query($sql); + } + + foreach ($lang_ary as $option_id => $value) + { + $profile_lang_fields[] = array( + 'field_id' => (int) $field_id, + 'lang_id' => (int) $lang_id, + 'option_id' => (int) $option_id, + 'field_type' => (int) $field_type, + 'lang_value' => $value + ); + } + } + } + + foreach ($empty_lang as $lang_id => $NULL) + { + $sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . " + WHERE field_id = $field_id + AND lang_id = " . (int) $lang_id; + $db->sql_query($sql); + } + } + + foreach ($profile_lang as $sql) + { + if ($action == 'create') + { + $profile_sql[] = 'INSERT INTO ' . PROFILE_LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql); + } + else + { + $lang_id = $sql['lang_id']; + unset($sql['lang_id'], $sql['field_id']); + + $this->update_insert(PROFILE_LANG_TABLE, $sql, array('lang_id' => (int) $lang_id, 'field_id' => $field_id)); + } + } + + if (sizeof($profile_lang_fields)) + { + foreach ($profile_lang_fields as $sql) + { + if ($action == 'create') + { + $profile_sql[] = 'INSERT INTO ' . PROFILE_FIELDS_LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql); + } + else + { + $lang_id = $sql['lang_id']; + $option_id = $sql['option_id']; + unset($sql['lang_id'], $sql['field_id'], $sql['option_id']); + + $this->update_insert(PROFILE_FIELDS_LANG_TABLE, $sql, array( + 'lang_id' => $lang_id, + 'field_id' => $field_id, + 'option_id' => $option_id) + ); + } + } + } + + + $db->sql_transaction('begin'); + + if ($action == 'create') + { + foreach ($profile_sql as $sql) + { + $db->sql_query($sql); + } + } + + $db->sql_transaction('commit'); + + if ($action == 'edit') + { + add_log('admin', 'LOG_PROFILE_FIELD_EDIT', $cp->vars['field_ident'] . ':' . $cp->vars['lang_name']); + trigger_error($user->lang['CHANGED_PROFILE_FIELD'] . adm_back_link($this->u_action)); + } + else + { + add_log('admin', 'LOG_PROFILE_FIELD_CREATE', substr($field_ident, 3) . ':' . $cp->vars['lang_name']); + trigger_error($user->lang['ADDED_PROFILE_FIELD'] . adm_back_link($this->u_action)); + } + } + + /** + * Update, then insert if not successfull + */ + function update_insert($table, $sql_ary, $where_fields) + { + global $db; + + $where_sql = array(); + $check_key = ''; + + foreach ($where_fields as $key => $value) + { + $check_key = (!$check_key) ? $key : $check_key; + $where_sql[] = $key . ' = ' . ((is_string($value)) ? "'" . $db->sql_escape($value) . "'" : (int) $value); + } + + if (!sizeof($where_sql)) + { + return; + } + + $sql = "SELECT $check_key + FROM $table + WHERE " . implode(' AND ', $where_sql); + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + $sql_ary = array_merge($where_fields, $sql_ary); + + if (sizeof($sql_ary)) + { + $db->sql_query("INSERT INTO $table " . $db->sql_build_array('INSERT', $sql_ary)); + } + } + else + { + if (sizeof($sql_ary)) + { + $sql = "UPDATE $table SET " . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE ' . implode(' AND ', $where_sql); + $db->sql_query($sql); + } + } + } + + /** + * Return sql statement for adding a new field ident (profile field) to the profile fields data table + */ + function add_field_ident($field_ident, $field_type) + { + global $db; + + switch ($db->sql_layer) + { + case 'mysql': + case 'mysql4': + case 'mysqli': + + // We are defining the biggest common value, because of the possibility to edit the min/max values of each field. + $sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " ADD `$field_ident` "; + + switch ($field_type) + { + case FIELD_STRING: + $sql .= ' VARCHAR(255) '; + break; + + case FIELD_DATE: + $sql .= 'VARCHAR(10) '; + break; + + case FIELD_TEXT: + $sql .= "TEXT"; + // ADD {$field_ident}_bbcode_uid VARCHAR(5) NOT NULL, + // ADD {$field_ident}_bbcode_bitfield INT(11) UNSIGNED"; + break; + + case FIELD_BOOL: + $sql .= 'TINYINT(2) '; + break; + + case FIELD_DROPDOWN: + $sql .= 'MEDIUMINT(8) '; + break; + + case FIELD_INT: + $sql .= 'BIGINT(20) '; + break; + } + + break; + + case 'sqlite': + + switch ($field_type) + { + case FIELD_STRING: + $type = ' VARCHAR(255) '; + break; + + case FIELD_DATE: + $type = 'VARCHAR(10) '; + break; + + case FIELD_TEXT: + $type = "TEXT(65535)"; + // ADD {$field_ident}_bbcode_uid VARCHAR(5) NOT NULL, + // ADD {$field_ident}_bbcode_bitfield INT(11) UNSIGNED"; + break; + + case FIELD_BOOL: + $type = 'TINYINT(2) '; + break; + + case FIELD_DROPDOWN: + $type = 'MEDIUMINT(8) '; + break; + + case FIELD_INT: + $type = 'BIGINT(20) '; + break; + } + + // We are defining the biggest common value, because of the possibility to edit the min/max values of each field. + if (version_compare(sqlite_libversion(), '3.0') == -1) + { + $sql = "SELECT sql + FROM sqlite_master + WHERE type = 'table' + AND name = '" . PROFILE_FIELDS_DATA_TABLE . "' + ORDER BY type DESC, name;"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + // Create a temp table and populate it, destroy the existing one + $db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . PROFILE_FIELDS_DATA_TABLE . '"?#i', 'CREATE TEMPORARY TABLE ' . PROFILE_FIELDS_DATA_TABLE . '_temp', $row['sql'])); + $db->sql_query('INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . '_temp SELECT * FROM ' . PROFILE_FIELDS_DATA_TABLE); + $db->sql_query('DROP TABLE ' . PROFILE_FIELDS_DATA_TABLE); + + preg_match('#\((.*)\)#s', $row['sql'], $matches); + + $new_table_cols = trim($matches[1]); + $old_table_cols = explode(',', $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 = $field_ident . ' ' . $type . ',' . $new_table_cols; + + // create a new table and fill it up. destroy the temp one + $db->sql_query('CREATE TABLE ' . PROFILE_FIELDS_DATA_TABLE . ' (' . $new_table_cols . ');'); + $db->sql_query('INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . PROFILE_FIELDS_DATA_TABLE . '_temp;'); + $db->sql_query('DROP TABLE ' . PROFILE_FIELDS_DATA_TABLE . '_temp'); + } + else + { + $sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " ADD $field_ident [$type]"; + } + + break; + + case 'mssql': + case 'mssql_odbc': + + // We are defining the biggest common value, because of the possibility to edit the min/max values of each field. + $sql = 'ALTER TABLE [' . PROFILE_FIELDS_DATA_TABLE . "] ADD [$field_ident] "; + + switch ($field_type) + { + case FIELD_STRING: + $sql .= ' [VARCHAR] (255) '; + break; + + case FIELD_DATE: + $sql .= '[VARCHAR] (10) '; + break; + + case FIELD_TEXT: + $sql .= "[TEXT]"; + // ADD {$field_ident}_bbcode_uid [VARCHAR] (5) NOT NULL, + // ADD {$field_ident}_bbcode_bitfield [INT] UNSIGNED"; + break; + + case FIELD_BOOL: + case FIELD_DROPDOWN: + $sql .= '[INT] '; + break; + + case FIELD_INT: + $sql .= '[FLOAT] '; + break; + } + + break; + + case 'postgres': + + // We are defining the biggest common value, because of the possibility to edit the min/max values of each field. + $sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " ADD COLUMN \"$field_ident\" "; + + switch ($field_type) + { + case FIELD_STRING: + $sql .= ' VARCHAR(255) '; + break; + + case FIELD_DATE: + $sql .= 'VARCHAR(10) '; + break; + + case FIELD_TEXT: + $sql .= "TEXT"; + // ADD {$field_ident}_bbcode_uid VARCHAR(5) NOT NULL, + // ADD {$field_ident}_bbcode_bitfield INT4 UNSIGNED"; + break; + + case FIELD_BOOL: + $sql .= 'INT2 '; + break; + + case FIELD_DROPDOWN: + $sql .= 'INT4 '; + break; + + case FIELD_INT: + $sql .= 'INT8 '; + break; + } + + break; + + case 'firebird': + + // We are defining the biggest common value, because of the possibility to edit the min/max values of each field. + $sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . ' ADD "' . strtoupper($field_ident) . '" '; + + switch ($field_type) + { + case FIELD_STRING: + $sql .= ' VARCHAR(255) '; + break; + + case FIELD_DATE: + $sql .= 'VARCHAR(10) '; + break; + + case FIELD_TEXT: + $sql .= "BLOB SUB_TYPE TEXT"; + // ADD {$field_ident}_bbcode_uid VARCHAR(5) NOT NULL, + // ADD {$field_ident}_bbcode_bitfield INTEGER UNSIGNED"; + break; + + case FIELD_BOOL: + case FIELD_DROPDOWN: + $sql .= 'INTEGER '; + break; + + case FIELD_INT: + $sql .= 'DOUBLE PRECISION '; + break; + } + + break; + + case 'oracle': + + // We are defining the biggest common value, because of the possibility to edit the min/max values of each field. + $sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " ADD $field_ident "; + + switch ($field_type) + { + case FIELD_STRING: + $sql .= ' VARCHAR2(255) '; + break; + + case FIELD_DATE: + $sql .= 'VARCHAR2(10) '; + break; + + case FIELD_TEXT: + $sql .= "CLOB"; + // ADD {$field_ident}_bbcode_uid VARCHAR2(5) NOT NULL, + // ADD {$field_ident}_bbcode_bitfield NUMBER(11) UNSIGNED"; + break; + + case FIELD_BOOL: + $sql .= 'NUMBER(2) '; + break; + + case FIELD_DROPDOWN: + $sql .= 'NUMBER(8) '; + break; + + case FIELD_INT: + $sql .= 'NUMBER(20) '; + break; + } + + break; + } + + return $sql; + } +} + +?> diff --git a/phpBB/includes/acp/acp_prune.php b/phpBB/includes/acp/acp_prune.php new file mode 100644 index 0000000000..7eeb37133f --- /dev/null +++ b/phpBB/includes/acp/acp_prune.php @@ -0,0 +1,466 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_prune +{ + var $u_action; + + function main($id, $mode) + { + global $user, $phpEx, $phpbb_admin_path, $phpbb_root_path; + + $user->add_lang('acp/prune'); + include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); + + switch ($mode) + { + case 'forums': + $this->tpl_name = 'acp_prune_forums'; + $this->page_title = 'ACP_PRUNE_FORUMS'; + $this->prune_forums($id, $mode); + break; + + case 'users': + $this->tpl_name = 'acp_prune_users'; + $this->page_title = 'ACP_PRUNE_USERS'; + $this->prune_users($id, $mode); + break; + } + } + + /** + * Prune forums + */ + function prune_forums($id, $mode) + { + global $db, $user, $auth, $template, $cache; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + $all_forums = request_var('all_forums', 0); + $forum_id = request_var('f', array(0)); + $submit = (isset($_POST['submit'])) ? true : false; + + if ($all_forums) + { + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE . ' + ORDER BY left_id'; + $result = $db->sql_query($sql); + + $forum_id = array(); + while ($row = $db->sql_fetchrow($result)) + { + $forum_id[] = $row['forum_id']; + } + $db->sql_freeresult($result); + } + + if ($submit) + { + if (confirm_box(true)) + { + $prune_posted = request_var('prune_days', 0); + $prune_viewed = request_var('prune_vieweddays', 0); + $prune_all = (!$prune_posted && !$prune_viewed) ? true : false; + + $prune_flags = 0; + $prune_flags += (request_var('prune_old_polls', 0)) ? 2 : 0; + $prune_flags += (request_var('prune_announce', 0)) ? 4 : 0; + $prune_flags += (request_var('prune_sticky', 0)) ? 8 : 0; + + // Convert days to seconds for timestamp functions... + $prunedate_posted = time() - ($prune_posted * 86400); + $prunedate_viewed = time() - ($prune_viewed * 86400); + + $template->assign_vars(array( + 'S_PRUNED' => true) + ); + + $sql_forum = (sizeof($forum_id)) ? ' AND ' . $db->sql_in_set('forum_id', $forum_id) : ''; + + // Get a list of forum's or the data for the forum that we are pruning. + $sql = 'SELECT forum_id, forum_name + FROM ' . FORUMS_TABLE . ' + WHERE forum_type = ' . FORUM_POST . " + $sql_forum + ORDER BY left_id ASC"; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + $prune_ids = array(); + $p_result['topics'] = 0; + $p_result['posts'] = 0; + $log_data = ''; + + do + { + if (!$auth->acl_get('f_list', $row['forum_id'])) + { + continue; + } + + if ($prune_all) + { + $p_result = prune($row['forum_id'], 'posted', time(), $prune_flags, false); + } + else + { + if ($prune_posted) + { + $return = prune($row['forum_id'], 'posted', $prunedate_posted, $prune_flags, false); + $p_result['topics'] += $return['topics']; + $p_result['posts'] += $return['posts']; + } + + if ($prune_viewed) + { + $return = prune($row['forum_id'], 'viewed', $prunedate_viewed, $prune_flags, false); + $p_result['topics'] += $return['topics']; + $p_result['posts'] += $return['posts']; + } + } + + $prune_ids[] = $row['forum_id']; + + $template->assign_block_vars('pruned', array( + 'FORUM_NAME' => $row['forum_name'], + 'NUM_TOPICS' => $p_result['topics'], + 'NUM_POSTS' => $p_result['posts']) + ); + + $log_data .= (($log_data != '') ? ', ' : '') . $row['forum_name']; + } + while ($row = $db->sql_fetchrow($result)); + + // Sync all pruned forums at once + sync('forum', 'forum_id', $prune_ids, true, true); + add_log('admin', 'LOG_PRUNE', $log_data); + } + $db->sql_freeresult($result); + + return; + } + else + { + confirm_box(false, $user->lang['PRUNE_FORUM_CONFIRM'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'submit' => 1, + 'all_forums' => $all_forums, + 'f' => $forum_id, + + 'prune_days' => request_var('prune_days', 0), + 'prune_vieweddays' => request_var('prune_vieweddays', 0), + 'prune_old_polls' => request_var('prune_old_polls', 0), + 'prune_announce' => request_var('prune_announce', 0), + 'prune_sticky' => request_var('prune_sticky', 0), + ))); + } + } + + // If they haven't selected a forum for pruning yet then + // display a select box to use for pruning. + if (!sizeof($forum_id)) + { + $template->assign_vars(array( + 'U_ACTION' => $this->u_action, + 'S_SELECT_FORUM' => true, + 'S_FORUM_OPTIONS' => make_forum_select(false, false, false)) + ); + } + else + { + $sql = 'SELECT forum_id, forum_name + FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_id); + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + + if (!$row) + { + $db->sql_freeresult($result); + trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $forum_list = $s_hidden_fields = ''; + do + { + $forum_list .= (($forum_list != '') ? ', ' : '') . '<b>' . $row['forum_name'] . '</b>'; + $s_hidden_fields .= '<input type="hidden" name="f[]" value="' . $row['forum_id'] . '" />'; + } + while ($row = $db->sql_fetchrow($result)); + + $db->sql_freeresult($result); + + $l_selected_forums = (sizeof($forum_id) == 1) ? 'SELECTED_FORUM' : 'SELECTED_FORUMS'; + + $template->assign_vars(array( + 'L_SELECTED_FORUMS' => $user->lang[$l_selected_forums], + 'U_ACTION' => $this->u_action, + 'U_BACK' => $this->u_action, + 'FORUM_LIST' => $forum_list, + 'S_HIDDEN_FIELDS' => $s_hidden_fields) + ); + } + } + + /** + * Prune users + */ + function prune_users($id, $mode) + { + global $db, $user, $auth, $template, $cache; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + $user->add_lang('memberlist'); + + $prune = (isset($_POST['prune'])) ? true : false; + + if ($prune) + { + $action = request_var('action', 'deactivate'); + $deleteposts = request_var('deleteposts', 0); + + if (confirm_box(true)) + { + $user_ids = $usernames = array(); + $this->get_prune_users($user_ids, $usernames); + + if (sizeof($user_ids)) + { + if ($action == 'deactivate') + { + user_active_flip('deactivate', $user_ids); + $l_log = 'LOG_PRUNE_USER_DEAC'; + } + else if ($action == 'delete') + { + if ($deleteposts) + { + foreach ($user_ids as $user_id) + { + user_delete('remove', $user_id); + } + + $l_log = 'LOG_PRUNE_USER_DEL_DEL'; + } + else + { + foreach ($user_ids as $user_id) + { + user_delete('retain', $user_id, $usernames[$user_id]); + } + + $l_log = 'LOG_PRUNE_USER_DEL_ANON'; + } + } + + add_log('admin', $l_log, implode(', ', $usernames)); + $msg = $user->lang['USER_' . strtoupper($action) . '_SUCCESS']; + } + else + { + $msg = $user->lang['USER_PRUNE_FAILURE']; + } + + trigger_error($msg . adm_back_link($this->u_action)); + } + else + { + // We list the users which will be pruned... + $user_ids = $usernames = array(); + $this->get_prune_users($user_ids, $usernames); + + if (!sizeof($user_ids)) + { + trigger_error($user->lang['USER_PRUNE_FAILURE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Assign to template + foreach ($user_ids as $user_id) + { + $template->assign_block_vars('users', array( + 'USERNAME' => $usernames[$user_id], + 'U_PROFILE' => append_sid($phpbb_root_path . 'memberlist.' . $phpEx, 'mode=viewprofile&u=' . $user_id), + 'U_USER_ADMIN' => ($auth->acl_get('a_user')) ? append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&mode=overview&u=' . $user_id, true, $user->session_id) : '', + )); + } + + $template->assign_vars(array( + 'S_DEACTIVATE' => ($action == 'deactivate') ? true : false, + 'S_DELETE' => ($action == 'delete') ? true : false, + )); + + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'prune' => 1, + + 'users' => request_var('users', '', true), + 'username' => request_var('username', '', true), + 'email' => request_var('email', ''), + 'joined_select' => request_var('joined_select', ''), + 'joined' => request_var('joined', ''), + 'active_select' => request_var('active_select', ''), + 'active' => request_var('active', ''), + 'count_select' => request_var('count_select', ''), + 'count' => request_var('count', ''), + 'deleteposts' => request_var('deleteposts', 0), + + 'action' => request_var('action', ''), + )), 'confirm_body_prune.html'); + } + } + + $find_count = array('lt' => $user->lang['LESS_THAN'], 'eq' => $user->lang['EQUAL_TO'], 'gt' => $user->lang['MORE_THAN']); + $s_find_count = ''; + + foreach ($find_count as $key => $value) + { + $selected = ($key == 'eq') ? ' selected="selected"' : ''; + $s_find_count .= '<option value="' . $key . '"' . $selected . '>' . $value . '</option>'; + } + + $find_time = array('lt' => $user->lang['BEFORE'], 'gt' => $user->lang['AFTER']); + $s_find_join_time = ''; + foreach ($find_time as $key => $value) + { + $s_find_join_time .= '<option value="' . $key . '">' . $value . '</option>'; + } + + $s_find_active_time = ''; + foreach ($find_time as $key => $value) + { + $s_find_active_time .= '<option value="' . $key . '">' . $value . '</option>'; + } + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action, + 'S_JOINED_OPTIONS' => $s_find_join_time, + 'S_ACTIVE_OPTIONS' => $s_find_active_time, + 'S_COUNT_OPTIONS' => $s_find_count, + 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=acp_prune&field=users'), + )); + } + + /** + * Get user_ids/usernames from those being pruned + */ + function get_prune_users(&$user_ids, &$usernames) + { + global $user, $db; + + $users = request_var('users', '', true); + + if ($users) + { + $users = explode("\n", $users); + $where_sql = ' AND ' . $db->sql_in_set('username_clean', array_map('utf8_clean_string', $users)); + } + else + { + $username = request_var('username', '', true); + $email = request_var('email', ''); + + $joined_select = request_var('joined_select', 'lt'); + $active_select = request_var('active_select', 'lt'); + $count_select = request_var('count_select', 'eq'); + $joined = request_var('joined', ''); + $active = request_var('active', ''); + + $active = ($active) ? explode('-', $active) : array(); + $joined = ($joined) ? explode('-', $joined) : array(); + + if ((sizeof($active) && sizeof($active) != 3) || (sizeof($joined) && sizeof($joined) != 3)) + { + trigger_error($user->lang['WRONG_ACTIVE_JOINED_DATE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $count = request_var('count', ''); + + $key_match = array('lt' => '<', 'gt' => '>', 'eq' => '='); + $sort_by_types = array('username', 'user_email', 'user_posts', 'user_regdate', 'user_lastvisit'); + + $where_sql = ''; + $where_sql .= ($username) ? ' AND username_clean ' . $db->sql_like_expression(str_replace('*', $db->any_char, utf8_clean_string($username))) : ''; + $where_sql .= ($email) ? ' AND user_email ' . $db->sql_like_expression(str_replace('*', $db->any_char, $email)) . ' ' : ''; + $where_sql .= (sizeof($joined)) ? " AND user_regdate " . $key_match[$joined_select] . ' ' . gmmktime(0, 0, 0, (int) $joined[1], (int) $joined[2], (int) $joined[0]) : ''; + $where_sql .= ($count !== '') ? " AND user_posts " . $key_match[$count_select] . ' ' . (int) $count . ' ' : ''; + + // First handle pruning of users who never logged in, last active date is 0000-00-00 + if (sizeof($active) && (int) $active[0] == 0 && (int) $active[1] == 0 && (int) $active[2] == 0) + { + $where_sql .= ' AND user_lastvisit = 0'; + } + else if (sizeof($active) && $active_select != 'lt') + { + $where_sql .= ' AND user_lastvisit ' . $key_match[$active_select] . ' ' . gmmktime(0, 0, 0, (int) $active[1], (int) $active[2], (int) $active[0]); + } + else if (sizeof($active)) + { + $where_sql .= ' AND (user_lastvisit > 0 AND user_lastvisit < ' . gmmktime(0, 0, 0, (int) $active[1], (int) $active[2], (int) $active[0]) . ')'; + } + } + + // Protect the admin, do not prune if no options are given... + if (!$where_sql) + { + return; + } + + // Get bot ids + $sql = 'SELECT user_id + FROM ' . BOTS_TABLE; + $result = $db->sql_query($sql); + + $bot_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $bot_ids[] = $row['user_id']; + } + $db->sql_freeresult($result); + + // Do not prune founder members + $sql = 'SELECT user_id, username + FROM ' . USERS_TABLE . ' + WHERE user_id <> ' . ANONYMOUS . ' + AND user_type <> ' . USER_FOUNDER . " + $where_sql"; + $result = $db->sql_query($sql); + + $where_sql = ''; + $user_ids = $usernames = array(); + + while ($row = $db->sql_fetchrow($result)) + { + // Do not prune bots and the user currently pruning. + if ($row['user_id'] != $user->data['user_id'] && !in_array($row['user_id'], $bot_ids)) + { + $user_ids[] = $row['user_id']; + $usernames[$row['user_id']] = $row['username']; + } + } + $db->sql_freeresult($result); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_ranks.php b/phpBB/includes/acp/acp_ranks.php new file mode 100644 index 0000000000..fcfef2a61e --- /dev/null +++ b/phpBB/includes/acp/acp_ranks.php @@ -0,0 +1,240 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_ranks +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + $user->add_lang('acp/posting'); + + // Set up general vars + $action = request_var('action', ''); + $action = (isset($_POST['add'])) ? 'add' : $action; + $action = (isset($_POST['save'])) ? 'save' : $action; + $rank_id = request_var('id', 0); + + $this->tpl_name = 'acp_ranks'; + $this->page_title = 'ACP_MANAGE_RANKS'; + + $form_name = 'acp_ranks'; + add_form_key($form_name); + + switch ($action) + { + case 'save': + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); + } + $rank_title = utf8_normalize_nfc(request_var('title', '', true)); + $special_rank = request_var('special_rank', 0); + $min_posts = ($special_rank) ? 0 : request_var('min_posts', 0); + $rank_image = request_var('rank_image', ''); + + // The rank image has to be a jpg, gif or png + if ($rank_image != '' && !preg_match('#(\.gif|\.png|\.jpg|\.jpeg)$#i', $rank_image)) + { + $rank_image = ''; + } + + if (!$rank_title) + { + trigger_error($user->lang['NO_RANK_TITLE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql_ary = array( + 'rank_title' => $rank_title, + 'rank_special' => $special_rank, + 'rank_min' => $min_posts, + 'rank_image' => htmlspecialchars_decode($rank_image) + ); + + if ($rank_id) + { + $sql = 'UPDATE ' . RANKS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " WHERE rank_id = $rank_id"; + $message = $user->lang['RANK_UPDATED']; + + add_log('admin', 'LOG_RANK_UPDATED', $rank_title); + } + else + { + $sql = 'INSERT INTO ' . RANKS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); + $message = $user->lang['RANK_ADDED']; + + add_log('admin', 'LOG_RANK_ADDED', $rank_title); + } + $db->sql_query($sql); + + $cache->destroy('_ranks'); + + trigger_error($message . adm_back_link($this->u_action)); + + break; + + case 'delete': + + if (!$rank_id) + { + trigger_error($user->lang['MUST_SELECT_RANK'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (confirm_box(true)) + { + $sql = 'SELECT rank_title + FROM ' . RANKS_TABLE . ' + WHERE rank_id = ' . $rank_id; + $result = $db->sql_query($sql); + $rank_title = (string) $db->sql_fetchfield('rank_title'); + $db->sql_freeresult($result); + + $sql = 'DELETE FROM ' . RANKS_TABLE . " + WHERE rank_id = $rank_id"; + $db->sql_query($sql); + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_rank = 0 + WHERE user_rank = $rank_id"; + $db->sql_query($sql); + + $cache->destroy('_ranks'); + + add_log('admin', 'LOG_RANK_REMOVED', $rank_title); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'rank_id' => $rank_id, + 'action' => 'delete', + ))); + } + + break; + + case 'edit': + case 'add': + + $data = $ranks = $existing_imgs = array(); + + $sql = 'SELECT * + FROM ' . RANKS_TABLE . ' + ORDER BY rank_min ASC, rank_special ASC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $existing_imgs[] = $row['rank_image']; + + if ($action == 'edit' && $rank_id == $row['rank_id']) + { + $ranks = $row; + } + } + $db->sql_freeresult($result); + + $imglist = filelist($phpbb_root_path . $config['ranks_path'], ''); + $edit_img = $filename_list = ''; + + foreach ($imglist as $path => $img_ary) + { + sort($img_ary); + + foreach ($img_ary as $img) + { + $img = $path . $img; + + if ($ranks && $img == $ranks['rank_image']) + { + $selected = ' selected="selected"'; + $edit_img = $img; + } + else + { + $selected = ''; + } + + if (strlen($img) > 255) + { + continue; + } + + $filename_list .= '<option value="' . htmlspecialchars($img) . '"' . $selected . '>' . $img . ((in_array($img, $existing_imgs)) ? ' ' . $user->lang['RANK_IMAGE_IN_USE'] : '') . '</option>'; + } + } + + $filename_list = '<option value=""' . (($edit_img == '') ? ' selected="selected"' : '') . '>----------</option>' . $filename_list; + unset($existing_imgs, $imglist); + + $template->assign_vars(array( + 'S_EDIT' => true, + 'U_BACK' => $this->u_action, + 'RANKS_PATH' => $phpbb_root_path . $config['ranks_path'], + 'U_ACTION' => $this->u_action . '&id=' . $rank_id, + + 'RANK_TITLE' => (isset($ranks['rank_title'])) ? $ranks['rank_title'] : '', + 'S_FILENAME_LIST' => $filename_list, + 'RANK_IMAGE' => ($edit_img) ? $phpbb_root_path . $config['ranks_path'] . '/' . $edit_img : $phpbb_admin_path . 'images/spacer.gif', + 'S_SPECIAL_RANK' => (!isset($ranks['rank_special']) || $ranks['rank_special']) ? true : false, + 'MIN_POSTS' => (isset($ranks['rank_min']) && !$ranks['rank_special']) ? $ranks['rank_min'] : 0) + ); + + + return; + + break; + } + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action) + ); + + $sql = 'SELECT * + FROM ' . RANKS_TABLE . ' + ORDER BY rank_special DESC, rank_min ASC, rank_title ASC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $template->assign_block_vars('ranks', array( + 'S_RANK_IMAGE' => ($row['rank_image']) ? true : false, + 'S_SPECIAL_RANK' => ($row['rank_special']) ? true : false, + + 'RANK_IMAGE' => $phpbb_root_path . $config['ranks_path'] . '/' . $row['rank_image'], + 'RANK_TITLE' => $row['rank_title'], + 'MIN_POSTS' => $row['rank_min'], + + 'U_EDIT' => $this->u_action . '&action=edit&id=' . $row['rank_id'], + 'U_DELETE' => $this->u_action . '&action=delete&id=' . $row['rank_id']) + ); + } + $db->sql_freeresult($result); + + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_reasons.php b/phpBB/includes/acp/acp_reasons.php new file mode 100644 index 0000000000..8d7bc88769 --- /dev/null +++ b/phpBB/includes/acp/acp_reasons.php @@ -0,0 +1,374 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_reasons +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + $user->add_lang(array('mcp', 'acp/posting')); + + // Set up general vars + $action = request_var('action', ''); + $submit = (isset($_POST['submit'])) ? true : false; + $reason_id = request_var('id', 0); + + $this->tpl_name = 'acp_reasons'; + $this->page_title = 'ACP_REASONS'; + + $form_name = 'acp_reason'; + add_form_key('acp_reason'); + + $error = array(); + + switch ($action) + { + case 'add': + case 'edit': + + $reason_row = array( + 'reason_title' => utf8_normalize_nfc(request_var('reason_title', '', true)), + 'reason_description' => utf8_normalize_nfc(request_var('reason_description', '', true)), + ); + + if ($submit) + { + if (!check_form_key($form_name)) + { + $error[] = $user->lang['FORM_INVALID']; + } + // Reason specified? + if (!$reason_row['reason_title'] || !$reason_row['reason_description']) + { + $error[] = $user->lang['NO_REASON_INFO']; + } + + $check_double = ($action == 'add') ? true : false; + + if ($action == 'edit') + { + $sql = 'SELECT reason_title + FROM ' . REPORTS_REASONS_TABLE . " + WHERE reason_id = $reason_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (strtolower($row['reason_title']) == 'other' || strtolower($reason_row['reason_title']) == 'other') + { + $reason_row['reason_title'] = 'other'; + } + + if ($row['reason_title'] != $reason_row['reason_title']) + { + $check_double = true; + } + } + + // Check for same reason if adding it... + if ($check_double) + { + $sql = 'SELECT reason_id + FROM ' . REPORTS_REASONS_TABLE . " + WHERE reason_title = '" . $db->sql_escape($reason_row['reason_title']) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row || ($action == 'add' && strtolower($reason_row['reason_title']) == 'other')) + { + $error[] = $user->lang['REASON_ALREADY_EXIST']; + } + } + + if (!sizeof($error)) + { + // New reason? + if ($action == 'add') + { + // Get new order... + $sql = 'SELECT MAX(reason_order) as max_reason_order + FROM ' . REPORTS_REASONS_TABLE; + $result = $db->sql_query($sql); + $max_order = (int) $db->sql_fetchfield('max_reason_order'); + $db->sql_freeresult($result); + + $sql_ary = array( + 'reason_title' => (string) $reason_row['reason_title'], + 'reason_description' => (string) $reason_row['reason_description'], + 'reason_order' => $max_order + 1 + ); + + $db->sql_query('INSERT INTO ' . REPORTS_REASONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + + $log = 'ADDED'; + } + else if ($reason_id) + { + $sql_ary = array( + 'reason_title' => (string) $reason_row['reason_title'], + 'reason_description' => (string) $reason_row['reason_description'], + ); + + $db->sql_query('UPDATE ' . REPORTS_REASONS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE reason_id = ' . $reason_id); + + $log = 'UPDATED'; + } + + add_log('admin', 'LOG_REASON_' . $log, $reason_row['reason_title']); + trigger_error($user->lang['REASON_' . $log] . adm_back_link($this->u_action)); + } + } + else if ($reason_id) + { + $sql = 'SELECT * + FROM ' . REPORTS_REASONS_TABLE . ' + WHERE reason_id = ' . $reason_id; + $result = $db->sql_query($sql); + $reason_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$reason_row) + { + trigger_error($user->lang['NO_REASON'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + + $l_title = ($action == 'edit') ? 'EDIT' : 'ADD'; + + $translated = false; + + // If the reason is defined within the language file, we will use the localized version, else just use the database entry... + if (isset($user->lang['report_reasons']['TITLE'][strtoupper($reason_row['reason_title'])]) && isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($reason_row['reason_title'])])) + { + $translated = true; + } + + $template->assign_vars(array( + 'L_TITLE' => $user->lang['REASON_' . $l_title], + 'U_ACTION' => $this->u_action . "&id=$reason_id&action=$action", + 'U_BACK' => $this->u_action, + 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + + 'REASON_TITLE' => $reason_row['reason_title'], + 'REASON_DESCRIPTION' => $reason_row['reason_description'], + + 'TRANSLATED_TITLE' => ($translated) ? $user->lang['report_reasons']['TITLE'][strtoupper($reason_row['reason_title'])] : '', + 'TRANSLATED_DESCRIPTION'=> ($translated) ? $user->lang['report_reasons']['DESCRIPTION'][strtoupper($reason_row['reason_title'])] : '', + + 'S_AVAILABLE_TITLES' => implode(', ', array_map('htmlspecialchars', array_keys($user->lang['report_reasons']['TITLE']))), + 'S_EDIT_REASON' => true, + 'S_TRANSLATED' => $translated, + 'S_ERROR' => (sizeof($error)) ? true : false, + ) + ); + + return; + break; + + case 'delete': + + $sql = 'SELECT * + FROM ' . REPORTS_REASONS_TABLE . ' + WHERE reason_id = ' . $reason_id; + $result = $db->sql_query($sql); + $reason_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$reason_row) + { + trigger_error($user->lang['NO_REASON'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (strtolower($reason_row['reason_title']) == 'other') + { + trigger_error($user->lang['NO_REMOVE_DEFAULT_REASON'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Let the deletion be confirmed... + if (confirm_box(true)) + { + $sql = 'SELECT reason_id + FROM ' . REPORTS_REASONS_TABLE . " + WHERE LOWER(reason_title) = 'other'"; + $result = $db->sql_query($sql); + $other_reason_id = (int) $db->sql_fetchfield('reason_id'); + $db->sql_freeresult($result); + + switch ($db->sql_layer) + { + // The ugly one! + case 'mysqli': + case 'mysql4': + case 'mysql': + // Change the reports using this reason to 'other' + $sql = 'UPDATE ' . REPORTS_TABLE . ' + SET reason_id = ' . $other_reason_id . ", report_text = CONCAT('" . $db->sql_escape($reason_row['reason_description']) . "\n\n', report_text) + WHERE reason_id = $reason_id"; + break; + + // Standard? What's that? + case 'mssql': + case 'mssql_odbc': + // Change the reports using this reason to 'other' + $sql = "DECLARE @ptrval binary(16) + + SELECT @ptrval = TEXTPTR(report_text) + FROM " . REPORTS_TABLE . " + WHERE reason_id = " . $reason_id . " + + UPDATETEXT " . REPORTS_TABLE . ".report_text @ptrval 0 0 '" . $db->sql_escape($reason_row['reason_description']) . "\n\n' + + UPDATE " . REPORTS_TABLE . ' + SET reason_id = ' . $other_reason_id . " + WHERE reason_id = $reason_id"; + break; + + // Teh standard + case 'postgres': + case 'oracle': + case 'firebird': + case 'sqlite': + // Change the reports using this reason to 'other' + $sql = 'UPDATE ' . REPORTS_TABLE . ' + SET reason_id = ' . $other_reason_id . ", report_text = '" . $db->sql_escape($reason_row['reason_description']) . "\n\n' || report_text + WHERE reason_id = $reason_id"; + break; + } + $db->sql_query($sql); + + $db->sql_query('DELETE FROM ' . REPORTS_REASONS_TABLE . ' WHERE reason_id = ' . $reason_id); + + add_log('admin', 'LOG_REASON_REMOVED', $reason_row['reason_title']); + trigger_error($user->lang['REASON_REMOVED'] . adm_back_link($this->u_action)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'id' => $reason_id)) + ); + } + + break; + + case 'move_up': + case 'move_down': + + $order = request_var('order', 0); + $order_total = $order * 2 + (($action == 'move_up') ? -1 : 1); + + $sql = 'UPDATE ' . REPORTS_REASONS_TABLE . ' + SET reason_order = ' . $order_total . ' - reason_order + WHERE reason_order IN (' . $order . ', ' . (($action == 'move_up') ? $order - 1 : $order + 1) . ')'; + $db->sql_query($sql); + + break; + } + + // By default, check that order is valid and fix it if necessary + $sql = 'SELECT reason_id, reason_order + FROM ' . REPORTS_REASONS_TABLE . ' + ORDER BY reason_order'; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + $order = 0; + do + { + ++$order; + + if ($row['reason_order'] != $order) + { + $sql = 'UPDATE ' . REPORTS_REASONS_TABLE . " + SET reason_order = $order + WHERE reason_id = {$row['reason_id']}"; + $db->sql_query($sql); + } + } + while ($row = $db->sql_fetchrow($result)); + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action, + ) + ); + + // Reason count + $sql = 'SELECT reason_id, COUNT(reason_id) AS reason_count + FROM ' . REPORTS_TABLE . ' + GROUP BY reason_id'; + $result = $db->sql_query($sql); + + $reason_count = array(); + while ($row = $db->sql_fetchrow($result)) + { + $reason_count[$row['reason_id']] = $row['reason_count']; + } + $db->sql_freeresult($result); + + $sql = 'SELECT * + FROM ' . REPORTS_REASONS_TABLE . ' + ORDER BY reason_order ASC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $translated = false; + $other_reason = ($row['reason_title'] == 'other') ? true : false; + + // If the reason is defined within the language file, we will use the localized version, else just use the database entry... + if (isset($user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]) && isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])])) + { + $row['reason_description'] = $user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])]; + $row['reason_title'] = $user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]; + + $translated = true; + } + + $template->assign_block_vars('reasons', array( + 'REASON_TITLE' => $row['reason_title'], + 'REASON_DESCRIPTION' => $row['reason_description'], + 'REASON_COUNT' => (isset($reason_count[$row['reason_id']])) ? $reason_count[$row['reason_id']] : 0, + + 'S_TRANSLATED' => $translated, + 'S_OTHER_REASON' => $other_reason, + + 'U_EDIT' => $this->u_action . '&action=edit&id=' . $row['reason_id'], + 'U_DELETE' => (!$other_reason) ? $this->u_action . '&action=delete&id=' . $row['reason_id'] : '', + 'U_MOVE_UP' => $this->u_action . '&action=move_up&order=' . $row['reason_order'], + 'U_MOVE_DOWN' => $this->u_action . '&action=move_down&order=' . $row['reason_order']) + ); + } + $db->sql_freeresult($result); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php new file mode 100644 index 0000000000..930c8d2a26 --- /dev/null +++ b/phpBB/includes/acp/acp_search.php @@ -0,0 +1,629 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_search +{ + var $u_action; + var $state; + var $search; + var $max_post_id; + var $batch_size = 100; + + function main($id, $mode) + { + global $user; + + $user->add_lang('acp/search'); + + // For some this may be of help... + @ini_set('memory_limit', '128M'); + + switch ($mode) + { + case 'settings': + $this->settings($id, $mode); + break; + + case 'index': + $this->index($id, $mode); + break; + } + } + + function settings($id, $mode) + { + global $db, $user, $auth, $template, $cache; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + $submit = (isset($_POST['submit'])) ? true : false; + + $search_types = $this->get_search_types(); + + $settings = array( + 'search_interval' => 'float', + 'search_anonymous_interval' => 'float', + 'load_search' => 'bool', + 'limit_search_load' => 'float', + 'min_search_author_chars' => 'integer', + 'max_num_search_keywords' => 'integer', + 'search_store_results' => 'integer', + ); + + $search = null; + $error = false; + $search_options = ''; + foreach ($search_types as $type) + { + if ($this->init_search($type, $search, $error)) + { + continue; + } + + $name = ucfirst(strtolower(str_replace('_', ' ', $type))); + $selected = ($config['search_type'] == $type) ? ' selected="selected"' : ''; + $search_options .= '<option value="' . $type . '"' . $selected . '>' . $name . '</option>'; + + if (method_exists($search, 'acp')) + { + $vars = $search->acp(); + + if (!$submit) + { + $template->assign_block_vars('backend', array( + 'NAME' => $name, + 'SETTINGS' => $vars['tpl']) + ); + } + else if (is_array($vars['config'])) + { + $settings = array_merge($settings, $vars['config']); + } + } + } + unset($search); + unset($error); + + $cfg_array = (isset($_REQUEST['config'])) ? request_var('config', array('' => ''), true) : array(); + $updated = request_var('updated', false); + + foreach ($settings as $config_name => $var_type) + { + if (!isset($cfg_array[$config_name])) + { + continue; + } + + // e.g. integer:4:12 (min 4, max 12) + $var_type = explode(':', $var_type); + + $config_value = $cfg_array[$config_name]; + settype($config_value, $var_type[0]); + + if (isset($var_type[1])) + { + $config_value = max($var_type[1], $config_value); + } + + if (isset($var_type[2])) + { + $config_value = min($var_type[2], $config_value); + } + + // only change config if anything was actually changed + if ($submit && ($config[$config_name] != $config_value)) + { + set_config($config_name, $config_value); + $updated = true; + } + } + + if ($submit) + { + $extra_message = ''; + if ($updated) + { + add_log('admin', 'LOG_CONFIG_SEARCH'); + } + + if (isset($cfg_array['search_type']) && in_array($cfg_array['search_type'], $search_types, true) && ($cfg_array['search_type'] != $config['search_type'])) + { + $search = null; + $error = false; + + if (!$this->init_search($cfg_array['search_type'], $search, $error)) + { + if (confirm_box(true)) + { + if (!method_exists($search, 'init') || !($error = $search->init())) + { + set_config('search_type', $cfg_array['search_type']); + + if (!$updated) + { + add_log('admin', 'LOG_CONFIG_SEARCH'); + } + $extra_message = '<br />' . $user->lang['SWITCHED_SEARCH_BACKEND'] . '<br /><a href="' . append_sid("{$phpbb_admin_path}index.$phpEx", 'i=search&mode=index') . '">» ' . $user->lang['GO_TO_SEARCH_INDEX'] . '</a>'; + } + else + { + trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); + } + } + else + { + confirm_box(false, $user->lang['CONFIRM_SEARCH_BACKEND'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'submit' => true, + 'updated' => $updated, + 'config' => array('search_type' => $cfg_array['search_type']), + ))); + } + } + else + { + trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); + } + } + + $search = null; + $error = false; + if (!$this->init_search($config['search_type'], $search, $error)) + { + if ($updated) + { + if (method_exists($search, 'config_updated')) + { + if ($search->config_updated()) + { + trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); + } + } + } + } + else + { + trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); + } + + trigger_error($user->lang['CONFIG_UPDATED'] . $extra_message . adm_back_link($this->u_action)); + } + unset($cfg_array); + + $this->tpl_name = 'acp_search'; + $this->page_title = 'ACP_SEARCH_SETTINGS'; + + $template->assign_vars(array( + 'LIMIT_SEARCH_LOAD' => (float) $config['limit_search_load'], + 'MIN_SEARCH_AUTHOR_CHARS' => (int) $config['min_search_author_chars'], + 'SEARCH_INTERVAL' => (float) $config['search_interval'], + 'SEARCH_GUEST_INTERVAL' => (float) $config['search_anonymous_interval'], + 'SEARCH_STORE_RESULTS' => (int) $config['search_store_results'], + 'MAX_NUM_SEARCH_KEYWORDS' => (int) $config['max_num_search_keywords'], + + 'S_SEARCH_TYPES' => $search_options, + 'S_YES_SEARCH' => (bool) $config['load_search'], + 'S_SETTINGS' => true, + + 'U_ACTION' => $this->u_action) + ); + } + + function index($id, $mode) + { + global $db, $user, $auth, $template, $cache; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + if (isset($_REQUEST['action']) && is_array($_REQUEST['action'])) + { + $action = request_var('action', array('' => false)); + $action = key($action); + } + else + { + $action = request_var('action', ''); + } + $this->state = explode(',', $config['search_indexing_state']); + + if (isset($_POST['cancel'])) + { + $action = ''; + $this->state = array(); + $this->save_state(); + } + + if ($action) + { + switch ($action) + { + case 'progress_bar': + $type = request_var('type', ''); + $this->display_progress_bar($type); + break; + + case 'delete': + $this->state[1] = 'delete'; + break; + + case 'create': + $this->state[1] = 'create'; + break; + + default: + trigger_error('NO_ACTION', E_USER_ERROR); + break; + } + + if (empty($this->state[0])) + { + $this->state[0] = request_var('search_type', ''); + } + + $this->search = null; + $error = false; + if ($this->init_search($this->state[0], $this->search, $error)) + { + trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); + } + $name = ucfirst(strtolower(str_replace('_', ' ', $this->state[0]))); + + $action = &$this->state[1]; + + $this->max_post_id = $this->get_max_post_id(); + + $post_counter = (isset($this->state[2])) ? $this->state[2] : 0; + $this->state[2] = &$post_counter; + $this->save_state(); + + switch ($action) + { + case 'delete': + if (method_exists($this->search, 'delete_index')) + { + // pass a reference to myself so the $search object can make use of save_state() and attributes + if ($error = $this->search->delete_index($this, append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=delete", false))) + { + $this->state = array(''); + $this->save_state(); + trigger_error($error . adm_back_link($this->u_action) . $this->close_popup_js(), E_USER_WARNING); + } + } + else + { + $starttime = explode(' ', microtime()); + $starttime = $starttime[1] + $starttime[0]; + $row_count = 0; + while (still_on_time() && $post_counter <= $this->max_post_id) + { + $sql = 'SELECT post_id, poster_id, forum_id + FROM ' . POSTS_TABLE . ' + WHERE post_id >= ' . (int) ($post_counter + 1) . ' + AND post_id <= ' . (int) ($post_counter + $this->batch_size); + $result = $db->sql_query($sql); + + $ids = $posters = $forum_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $ids[] = $row['post_id']; + $posters[] = $row['poster_id']; + $forum_ids[] = $row['forum_id']; + } + $db->sql_freeresult($result); + $row_count += sizeof($ids); + + if (sizeof($ids)) + { + $this->search->index_remove($ids, $posters, $forum_ids); + } + + $post_counter += $this->batch_size; + } + // save the current state + $this->save_state(); + + if ($post_counter <= $this->max_post_id) + { + $mtime = explode(' ', microtime()); + $totaltime = $mtime[0] + $mtime[1] - $starttime; + $rows_per_second = $row_count / $totaltime; + meta_refresh(1, append_sid($this->u_action . '&action=delete&skip_rows=' . $post_counter)); + trigger_error(sprintf($user->lang['SEARCH_INDEX_DELETE_REDIRECT'], $post_counter, $row_count, $rows_per_second)); + } + } + + $this->search->tidy(); + + $this->state = array(''); + $this->save_state(); + + add_log('admin', 'LOG_SEARCH_INDEX_REMOVED', $name); + trigger_error($user->lang['SEARCH_INDEX_REMOVED'] . adm_back_link($this->u_action) . $this->close_popup_js()); + break; + + case 'create': + if (method_exists($this->search, 'create_index')) + { + // pass a reference to acp_search so the $search object can make use of save_state() and attributes + if ($error = $this->search->create_index($this, append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=create", false))) + { + $this->state = array(''); + $this->save_state(); + trigger_error($error . adm_back_link($this->u_action) . $this->close_popup_js(), E_USER_WARNING); + } + } + else + { + $sql = 'SELECT forum_id, enable_indexing + FROM ' . FORUMS_TABLE; + $result = $db->sql_query($sql, 3600); + + while ($row = $db->sql_fetchrow($result)) + { + $forums[$row['forum_id']] = (bool) $row['enable_indexing']; + } + $db->sql_freeresult($result); + + $starttime = explode(' ', microtime()); + $starttime = $starttime[1] + $starttime[0]; + $row_count = 0; + while (still_on_time() && $post_counter <= $this->max_post_id) + { + $sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id + FROM ' . POSTS_TABLE . ' + WHERE post_id >= ' . (int) ($post_counter + 1) . ' + AND post_id <= ' . (int) ($post_counter + $this->batch_size); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + // Indexing enabled for this forum or global announcement? + // Global announcements get indexed by default. + if (!$row['forum_id'] || (isset($forums[$row['forum_id']]) && $forums[$row['forum_id']])) + { + $this->search->index('post', $row['post_id'], $row['post_text'], $row['post_subject'], $row['poster_id'], $row['forum_id']); + } + $row_count++; + } + $db->sql_freeresult($result); + + $post_counter += $this->batch_size; + } + // save the current state + $this->save_state(); + + // pretend the number of posts was as big as the number of ids we indexed so far + // just an estimation as it includes deleted posts + $num_posts = $config['num_posts']; + $config['num_posts'] = min($config['num_posts'], $post_counter); + $this->search->tidy(); + $config['num_posts'] = $num_posts; + + if ($post_counter <= $this->max_post_id) + { + $mtime = explode(' ', microtime()); + $totaltime = $mtime[0] + $mtime[1] - $starttime; + $rows_per_second = $row_count / $totaltime; + meta_refresh(1, append_sid($this->u_action . '&action=create&skip_rows=' . $post_counter)); + trigger_error(sprintf($user->lang['SEARCH_INDEX_CREATE_REDIRECT'], $post_counter, $row_count, $rows_per_second)); + } + } + + $this->search->tidy(); + + $this->state = array(''); + $this->save_state(); + + add_log('admin', 'LOG_SEARCH_INDEX_CREATED', $name); + trigger_error($user->lang['SEARCH_INDEX_CREATED'] . adm_back_link($this->u_action) . $this->close_popup_js()); + break; + } + } + + $search_types = $this->get_search_types(); + + $search = null; + $error = false; + $search_options = ''; + foreach ($search_types as $type) + { + if ($this->init_search($type, $search, $error) || !method_exists($search, 'index_created')) + { + continue; + } + + $name = ucfirst(strtolower(str_replace('_', ' ', $type))); + + $data = array(); + if (method_exists($search, 'index_stats')) + { + $data = $search->index_stats(); + } + + $statistics = array(); + foreach ($data as $statistic => $value) + { + $n = sizeof($statistics); + if ($n && sizeof($statistics[$n - 1]) < 3) + { + $statistics[$n - 1] += array('statistic_2' => $statistic, 'value_2' => $value); + } + else + { + $statistics[] = array('statistic_1' => $statistic, 'value_1' => $value); + } + } + + $template->assign_block_vars('backend', array( + 'L_NAME' => $name, + 'NAME' => $type, + + 'S_ACTIVE' => ($type == $config['search_type']) ? true : false, + 'S_HIDDEN_FIELDS' => build_hidden_fields(array('search_type' => $type)), + 'S_INDEXED' => (bool) $search->index_created(), + 'S_STATS' => (bool) sizeof($statistics)) + ); + + foreach ($statistics as $statistic) + { + $template->assign_block_vars('backend.data', array( + 'STATISTIC_1' => $statistic['statistic_1'], + 'VALUE_1' => $statistic['value_1'], + 'STATISTIC_2' => (isset($statistic['statistic_2'])) ? $statistic['statistic_2'] : '', + 'VALUE_2' => (isset($statistic['value_2'])) ? $statistic['value_2'] : '') + ); + } + } + unset($search); + unset($error); + unset($statistics); + unset($data); + + $this->tpl_name = 'acp_search'; + $this->page_title = 'ACP_SEARCH_INDEX'; + + $template->assign_vars(array( + 'S_INDEX' => true, + 'U_ACTION' => $this->u_action, + 'U_PROGRESS_BAR' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=progress_bar"), + 'UA_PROGRESS_BAR' => addslashes(append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=progress_bar")), + )); + + if (isset($this->state[1])) + { + $template->assign_vars(array( + 'S_CONTINUE_INDEXING' => $this->state[1], + 'U_CONTINUE_INDEXING' => $this->u_action . '&action=' . $this->state[1], + 'L_CONTINUE' => ($this->state[1] == 'create') ? $user->lang['CONTINUE_INDEXING'] : $user->lang['CONTINUE_DELETING_INDEX'], + 'L_CONTINUE_EXPLAIN' => ($this->state[1] == 'create') ? $user->lang['CONTINUE_INDEXING_EXPLAIN'] : $user->lang['CONTINUE_DELETING_INDEX_EXPLAIN']) + ); + } + } + + function display_progress_bar($type) + { + global $template, $user; + + $l_type = ($type == 'create') ? 'INDEXING_IN_PROGRESS' : 'DELETING_INDEX_IN_PROGRESS'; + + adm_page_header($user->lang[$l_type]); + + $template->set_filenames(array( + 'body' => 'progress_bar.html') + ); + + $template->assign_vars(array( + 'L_PROGRESS' => $user->lang[$l_type], + 'L_PROGRESS_EXPLAIN' => $user->lang[$l_type . '_EXPLAIN']) + ); + + adm_page_footer(); + } + + function close_popup_js() + { + return "<script type=\"text/javascript\">\n" . + "// <![CDATA[\n" . + " close_waitscreen = 1;\n" . + "// ]]>\n" . + "</script>\n"; + } + + function get_search_types() + { + global $phpbb_root_path, $phpEx; + + $search_types = array(); + + $dp = @opendir($phpbb_root_path . 'includes/search'); + + if ($dp) + { + while (($file = readdir($dp)) !== false) + { + if ((preg_match('#\.' . $phpEx . '$#', $file)) && ($file != "search.$phpEx")) + { + $search_types[] = preg_replace('#^(.*?)\.' . $phpEx . '$#', '\1', $file); + } + } + closedir($dp); + + sort($search_types); + } + + return $search_types; + } + + function get_max_post_id() + { + global $db; + + $sql = 'SELECT MAX(post_id) as max_post_id + FROM '. POSTS_TABLE; + $result = $db->sql_query($sql); + $max_post_id = (int) $db->sql_fetchfield('max_post_id'); + $db->sql_freeresult($result); + + return $max_post_id; + } + + function save_state($state = false) + { + if ($state) + { + $this->state = $state; + } + + ksort($this->state); + + set_config('search_indexing_state', implode(',', $this->state), true); + } + + /** + * Initialises a search backend object + * + * @return false if no error occurred else an error message + */ + function init_search($type, &$search, &$error) + { + global $phpbb_root_path, $phpEx, $user; + + if (!preg_match('#^\w+$#', $type) || !file_exists("{$phpbb_root_path}includes/search/$type.$phpEx")) + { + $error = $user->lang['NO_SUCH_SEARCH_MODULE']; + return $error; + } + + include_once("{$phpbb_root_path}includes/search/$type.$phpEx"); + + if (!class_exists($type)) + { + $error = $user->lang['NO_SUCH_SEARCH_MODULE']; + return $error; + } + + $error = false; + $search = new $type($error); + + return $error; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_send_statistics.php b/phpBB/includes/acp/acp_send_statistics.php new file mode 100644 index 0000000000..b3baf54983 --- /dev/null +++ b/phpBB/includes/acp/acp_send_statistics.php @@ -0,0 +1,90 @@ +<?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; +} + +include($phpbb_root_path . 'includes/questionnaire/questionnaire.' . $phpEx); + +/** +* @package acp +*/ +class acp_send_statistics +{ + var $u_action; + + function main($id, $mode) + { + global $config, $template, $phpbb_admin_path, $phpEx; + + $collect_url = "http://www.phpbb.com/stats/receive_stats.php"; + + $this->tpl_name = 'acp_send_statistics'; + $this->page_title = 'ACP_SEND_STATISTICS'; + + // generate a unique id if necessary + if (!isset($config['questionnaire_unique_id'])) + { + $install_id = unique_id(); + set_config('questionnaire_unique_id', $install_id); + } + else + { + $install_id = $config['questionnaire_unique_id']; + } + + $collector = new phpbb_questionnaire_data_collector($install_id); + + // Add data provider + $collector->add_data_provider(new phpbb_questionnaire_php_data_provider()); + $collector->add_data_provider(new phpbb_questionnaire_system_data_provider()); + $collector->add_data_provider(new phpbb_questionnaire_phpbb_data_provider($config)); + + $template->assign_vars(array( + 'U_COLLECT_STATS' => $collect_url, + 'RAW_DATA' => $collector->get_data_for_form(), + 'U_ACP_MAIN' => append_sid("{$phpbb_admin_path}index.$phpEx"), + )); + + $raw = $collector->get_data_raw(); + + foreach ($raw as $provider => $data) + { + if ($provider == 'install_id') + { + $data = array($provider => $data); + } + + $template->assign_block_vars('providers', array( + 'NAME' => htmlspecialchars($provider), + )); + + foreach ($data as $key => $value) + { + if (is_array($value)) + { + $value = utf8_wordwrap(serialize($value), 75, "\n", true); + } + + $template->assign_block_vars('providers.values', array( + 'KEY' => utf8_htmlspecialchars($key), + 'VALUE' => utf8_htmlspecialchars($value), + )); + } + } + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php new file mode 100644 index 0000000000..fbf3eadcb2 --- /dev/null +++ b/phpBB/includes/acp/acp_styles.php @@ -0,0 +1,3768 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_styles +{ + var $u_action; + + var $style_cfg; + var $template_cfg; + var $theme_cfg; + var $imageset_cfg; + var $imageset_keys; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + // Hardcoded template bitfield to add for new templates + $bitfield = new bitfield(); + $bitfield->set(0); + $bitfield->set(1); + $bitfield->set(2); + $bitfield->set(3); + $bitfield->set(4); + $bitfield->set(8); + $bitfield->set(9); + $bitfield->set(11); + $bitfield->set(12); + define('TEMPLATE_BITFIELD', $bitfield->get_base64()); + unset($bitfield); + + $user->add_lang('acp/styles'); + + $this->tpl_name = 'acp_styles'; + $this->page_title = 'ACP_CAT_STYLES'; + + $action = request_var('action', ''); + $action = (isset($_POST['add'])) ? 'add' : $action; + $style_id = request_var('id', 0); + + // Fill the configuration variables + $this->style_cfg = $this->template_cfg = $this->theme_cfg = $this->imageset_cfg = ' +# +# phpBB {MODE} configuration file +# +# @package phpBB3 +# @copyright (c) 2005 phpBB Group +# @license http://opensource.org/licenses/gpl-license.php GNU Public License +# +# +# At the left is the name, please do not change this +# At the right the value is entered +# For on/off options the valid values are on, off, 1, 0, true and false +# +# Values get trimmed, if you want to add a space in front or at the end of +# the value, then enclose the value with single or double quotes. +# Single and double quotes do not need to be escaped. +# +# + +# General Information about this {MODE} +name = {NAME} +copyright = {COPYRIGHT} +version = {VERSION} +'; + + $this->theme_cfg .= ' +# Some configuration options + +# +# You have to turn this option on if you want to use the +# path template variables ({T_IMAGESET_PATH} for example) within +# your css file. +# This is mostly the case if you want to use language specific +# images within your css file. +# +parse_css_file = {PARSE_CSS_FILE} +'; + + $this->template_cfg .= ' +# Some configuration options + +# +# You can use this function to inherit templates from another template. +# The template of the given name has to be installed. +# Templates cannot inherit from inheriting templates. +#'; + + $this->imageset_keys = array( + 'logos' => array( + 'site_logo', + ), + 'buttons' => array( + 'icon_back_top', 'icon_contact_aim', 'icon_contact_email', 'icon_contact_icq', 'icon_contact_jabber', 'icon_contact_msnm', 'icon_contact_pm', 'icon_contact_yahoo', 'icon_contact_www', 'icon_post_delete', 'icon_post_edit', 'icon_post_info', 'icon_post_quote', 'icon_post_report', 'icon_user_online', 'icon_user_offline', 'icon_user_profile', 'icon_user_search', 'icon_user_warn', 'button_pm_forward', 'button_pm_new', 'button_pm_reply', 'button_topic_locked', 'button_topic_new', 'button_topic_reply', + ), + 'icons' => array( + 'icon_post_target', 'icon_post_target_unread', 'icon_topic_attach', 'icon_topic_latest', 'icon_topic_newest', 'icon_topic_reported', 'icon_topic_unapproved', 'icon_friend', 'icon_foe', + ), + 'forums' => array( + 'forum_link', 'forum_read', 'forum_read_locked', 'forum_read_subforum', 'forum_unread', 'forum_unread_locked', 'forum_unread_subforum', 'subforum_read', 'subforum_unread' + ), + 'folders' => array( + 'topic_moved', 'topic_read', 'topic_read_mine', 'topic_read_hot', 'topic_read_hot_mine', 'topic_read_locked', 'topic_read_locked_mine', 'topic_unread', 'topic_unread_mine', 'topic_unread_hot', 'topic_unread_hot_mine', 'topic_unread_locked', 'topic_unread_locked_mine', 'sticky_read', 'sticky_read_mine', 'sticky_read_locked', 'sticky_read_locked_mine', 'sticky_unread', 'sticky_unread_mine', 'sticky_unread_locked', 'sticky_unread_locked_mine', 'announce_read', 'announce_read_mine', 'announce_read_locked', 'announce_read_locked_mine', 'announce_unread', 'announce_unread_mine', 'announce_unread_locked', 'announce_unread_locked_mine', 'global_read', 'global_read_mine', 'global_read_locked', 'global_read_locked_mine', 'global_unread', 'global_unread_mine', 'global_unread_locked', 'global_unread_locked_mine', 'pm_read', 'pm_unread', + ), + 'polls' => array( + 'poll_left', 'poll_center', 'poll_right', + ), + 'ui' => array( + 'upload_bar', + ), + 'user' => array( + 'user_icon1', 'user_icon2', 'user_icon3', 'user_icon4', 'user_icon5', 'user_icon6', 'user_icon7', 'user_icon8', 'user_icon9', 'user_icon10', + ), + ); + + // Execute overall actions + switch ($action) + { + case 'delete': + if ($style_id) + { + $this->remove($mode, $style_id); + return; + } + break; + + case 'export': + if ($style_id) + { + $this->export($mode, $style_id); + return; + } + break; + + case 'install': + $this->install($mode); + return; + break; + + case 'add': + $this->add($mode); + return; + break; + + case 'details': + if ($style_id) + { + $this->details($mode, $style_id); + return; + } + break; + + case 'edit': + if ($style_id) + { + switch ($mode) + { + case 'imageset': + return $this->edit_imageset($style_id); + case 'template': + return $this->edit_template($style_id); + case 'theme': + return $this->edit_theme($style_id); + } + } + break; + + case 'cache': + if ($style_id) + { + switch ($mode) + { + case 'template': + return $this->template_cache($style_id); + } + } + break; + } + + switch ($mode) + { + case 'style': + + switch ($action) + { + case 'activate': + case 'deactivate': + + if ($style_id == $config['default_style']) + { + trigger_error($user->lang['DEACTIVATE_DEFAULT'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (($action == 'deactivate' && confirm_box(true)) || $action == 'activate') + { + $sql = 'UPDATE ' . STYLES_TABLE . ' + SET style_active = ' . (($action == 'activate') ? 1 : 0) . ' + WHERE style_id = ' . $style_id; + $db->sql_query($sql); + + // Set style to default for any member using deactivated style + if ($action == 'deactivate') + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_style = ' . $config['default_style'] . " + WHERE user_style = $style_id"; + $db->sql_query($sql); + + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET forum_style = 0 + WHERE forum_style = ' . $style_id; + $db->sql_query($sql); + } + } + else if ($action == 'deactivate') + { + $s_hidden_fields = array( + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'style_id' => $style_id, + ); + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($s_hidden_fields)); + } + break; + } + + $this->frontend('style', array('details'), array('export', 'delete')); + break; + + case 'template': + + switch ($action) + { + // Refresh template data stored in db and clear cache + case 'refresh': + + $sql = 'SELECT * + FROM ' . STYLES_TEMPLATE_TABLE . " + WHERE template_id = $style_id"; + $result = $db->sql_query($sql); + $template_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$template_row) + { + trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (confirm_box(true)) + { + $template_refreshed = ''; + + // Only refresh database if the template is stored in the database + if ($template_row['template_storedb'] && file_exists("{$phpbb_root_path}styles/{$template_row['template_path']}/template/")) + { + $filelist = array('' => array()); + + $sql = 'SELECT template_filename, template_mtime + FROM ' . STYLES_TEMPLATE_DATA_TABLE . " + WHERE template_id = $style_id"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { +// if (@filemtime("{$phpbb_root_path}styles/{$template_row['template_path']}/template/" . $row['template_filename']) > $row['template_mtime']) +// { + // get folder info from the filename + if (($slash_pos = strrpos($row['template_filename'], '/')) === false) + { + $filelist[''][] = $row['template_filename']; + } + else + { + $filelist[substr($row['template_filename'], 0, $slash_pos + 1)][] = substr($row['template_filename'], $slash_pos + 1, strlen($row['template_filename']) - $slash_pos - 1); + } +// } + } + $db->sql_freeresult($result); + + $this->store_templates('update', $style_id, $template_row['template_path'], $filelist); + unset($filelist); + + $template_refreshed = $user->lang['TEMPLATE_REFRESHED'] . '<br />'; + add_log('admin', 'LOG_TEMPLATE_REFRESHED', $template_row['template_name']); + } + + $this->clear_template_cache($template_row); + + trigger_error($template_refreshed . $user->lang['TEMPLATE_CACHE_CLEARED'] . adm_back_link($this->u_action)); + } + else + { + confirm_box(false, ($template_row['template_storedb']) ? $user->lang['CONFIRM_TEMPLATE_REFRESH'] : $user->lang['CONFIRM_TEMPLATE_CLEAR_CACHE'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'id' => $style_id + ))); + } + + break; + } + + $this->frontend('template', array('edit', 'cache', 'details'), array('refresh', 'export', 'delete')); + break; + + case 'theme': + + switch ($action) + { + // Refresh theme data stored in the database + case 'refresh': + + $sql = 'SELECT * + FROM ' . STYLES_THEME_TABLE . " + WHERE theme_id = $style_id"; + $result = $db->sql_query($sql); + $theme_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$theme_row) + { + trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (!$theme_row['theme_storedb']) + { + trigger_error($user->lang['THEME_ERR_REFRESH_FS'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (confirm_box(true)) + { + if ($theme_row['theme_storedb'] && file_exists("{$phpbb_root_path}styles/{$theme_row['theme_path']}/theme/stylesheet.css")) + { + // Save CSS contents + $sql_ary = array( + 'theme_mtime' => (int) filemtime("{$phpbb_root_path}styles/{$theme_row['theme_path']}/theme/stylesheet.css"), + 'theme_data' => $this->db_theme_data($theme_row) + ); + + $sql = 'UPDATE ' . STYLES_THEME_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE theme_id = $style_id"; + $db->sql_query($sql); + + $cache->destroy('sql', STYLES_THEME_TABLE); + + add_log('admin', 'LOG_THEME_REFRESHED', $theme_row['theme_name']); + trigger_error($user->lang['THEME_REFRESHED'] . adm_back_link($this->u_action)); + } + } + else + { + confirm_box(false, $user->lang['CONFIRM_THEME_REFRESH'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'id' => $style_id + ))); + } + break; + } + + $this->frontend('theme', array('edit', 'details'), array('refresh', 'export', 'delete')); + break; + + case 'imageset': + + switch ($action) + { + case 'refresh': + + $sql = 'SELECT * + FROM ' . STYLES_IMAGESET_TABLE . " + WHERE imageset_id = $style_id"; + $result = $db->sql_query($sql); + $imageset_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$imageset_row) + { + trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (confirm_box(true)) + { + $sql_ary = array(); + + $imageset_definitions = array(); + foreach ($this->imageset_keys as $topic => $key_array) + { + $imageset_definitions = array_merge($imageset_definitions, $key_array); + } + + $cfg_data_imageset = parse_cfg_file("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/imageset.cfg"); + + $db->sql_transaction('begin'); + + $sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . ' + WHERE imageset_id = ' . $style_id; + $result = $db->sql_query($sql); + + foreach ($cfg_data_imageset 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); + if (in_array($image_name, $imageset_definitions)) + { + $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) $style_id, + 'image_lang' => '', + ); + } + } + } + + $sql = 'SELECT lang_dir + FROM ' . LANG_TABLE; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if (@file_exists("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/{$row['lang_dir']}/imageset.cfg")) + { + $cfg_data_imageset_data = parse_cfg_file("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/{$row['lang_dir']}/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); + if (in_array($image_name, $imageset_definitions)) + { + $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) $style_id, + 'image_lang' => (string) $row['lang_dir'], + ); + } + } + } + } + } + $db->sql_freeresult($result); + + $db->sql_multi_insert(STYLES_IMAGESET_DATA_TABLE, $sql_ary); + + $db->sql_transaction('commit'); + + $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE); + + add_log('admin', 'LOG_IMAGESET_REFRESHED', $imageset_row['imageset_name']); + trigger_error($user->lang['IMAGESET_REFRESHED'] . adm_back_link($this->u_action)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_IMAGESET_REFRESH'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'id' => $style_id + ))); + } + break; + } + + $this->frontend('imageset', array('edit', 'details'), array('refresh', 'export', 'delete')); + break; + } + } + + /** + * Build Frontend with supplied options + */ + function frontend($mode, $options, $actions) + { + global $user, $template, $db, $config, $phpbb_root_path, $phpEx; + + $sql_from = ''; + $style_count = array(); + + switch ($mode) + { + case 'style': + $sql_from = STYLES_TABLE; + + $sql = 'SELECT user_style, COUNT(user_style) AS style_count + FROM ' . USERS_TABLE . ' + GROUP BY user_style'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $style_count[$row['user_style']] = $row['style_count']; + } + $db->sql_freeresult($result); + + break; + + case 'template': + $sql_from = STYLES_TEMPLATE_TABLE; + break; + + case 'theme': + $sql_from = STYLES_THEME_TABLE; + break; + + case 'imageset': + $sql_from = STYLES_IMAGESET_TABLE; + break; + } + + $l_prefix = strtoupper($mode); + + $this->page_title = 'ACP_' . $l_prefix . 'S'; + + $template->assign_vars(array( + 'S_FRONTEND' => true, + 'S_STYLE' => ($mode == 'style') ? true : false, + + 'L_TITLE' => $user->lang[$this->page_title], + 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], + 'L_NAME' => $user->lang[$l_prefix . '_NAME'], + 'L_INSTALLED' => $user->lang['INSTALLED_' . $l_prefix], + 'L_UNINSTALLED' => $user->lang['UNINSTALLED_' . $l_prefix], + 'L_NO_UNINSTALLED' => $user->lang['NO_UNINSTALLED_' . $l_prefix], + 'L_CREATE' => $user->lang['CREATE_' . $l_prefix], + + 'U_ACTION' => $this->u_action, + ) + ); + + $sql = "SELECT * + FROM $sql_from"; + $result = $db->sql_query($sql); + + $installed = array(); + + $basis_options = '<option class="sep" value="">' . $user->lang['OPTIONAL_BASIS'] . '</option>'; + while ($row = $db->sql_fetchrow($result)) + { + $installed[] = $row[$mode . '_name']; + $basis_options .= '<option value="' . $row[$mode . '_id'] . '">' . $row[$mode . '_name'] . '</option>'; + + $stylevis = ($mode == 'style' && !$row['style_active']) ? 'activate' : 'deactivate'; + + $s_options = array(); + foreach ($options as $option) + { + $s_options[] = '<a href="' . $this->u_action . "&action=$option&id=" . $row[$mode . '_id'] . '">' . $user->lang[strtoupper($option)] . '</a>'; + } + + $s_actions = array(); + foreach ($actions as $option) + { + $s_actions[] = '<a href="' . $this->u_action . "&action=$option&id=" . $row[$mode . '_id'] . '">' . $user->lang[strtoupper($option)] . '</a>'; + } + + $template->assign_block_vars('installed', array( + 'S_DEFAULT_STYLE' => ($mode == 'style' && $row['style_id'] == $config['default_style']) ? true : false, + 'U_EDIT' => $this->u_action . '&action=' . (($mode == 'style') ? 'details' : 'edit') . '&id=' . $row[$mode . '_id'], + 'U_STYLE_ACT_DEACT' => $this->u_action . '&action=' . $stylevis . '&id=' . $row[$mode . '_id'], + 'L_STYLE_ACT_DEACT' => $user->lang['STYLE_' . strtoupper($stylevis)], + 'S_OPTIONS' => implode(' | ', $s_options), + 'S_ACTIONS' => implode(' | ', $s_actions), + 'U_PREVIEW' => ($mode == 'style') ? append_sid("{$phpbb_root_path}index.$phpEx", "$mode=" . $row[$mode . '_id']) : '', + + 'NAME' => $row[$mode . '_name'], + 'STYLE_COUNT' => ($mode == 'style' && isset($style_count[$row['style_id']])) ? $style_count[$row['style_id']] : 0, + ) + ); + } + $db->sql_freeresult($result); + + // Grab uninstalled items + $new_ary = $cfg = array(); + + $dp = @opendir("{$phpbb_root_path}styles"); + + if ($dp) + { + while (($file = readdir($dp)) !== false) + { + $subpath = ($mode != 'style') ? "$mode/" : ''; + if ($file[0] != '.' && file_exists("{$phpbb_root_path}styles/$file/$subpath$mode.cfg")) + { + if ($cfg = file("{$phpbb_root_path}styles/$file/$subpath$mode.cfg")) + { + $items = parse_cfg_file('', $cfg); + $name = (isset($items['name'])) ? trim($items['name']) : false; + + if ($name && !in_array($name, $installed)) + { + $new_ary[] = array( + 'path' => $file, + 'name' => $name, + 'copyright' => $items['copyright'], + ); + } + } + } + } + closedir($dp); + } + + unset($installed); + + if (sizeof($new_ary)) + { + foreach ($new_ary as $cfg) + { + $template->assign_block_vars('uninstalled', array( + 'NAME' => $cfg['name'], + 'COPYRIGHT' => $cfg['copyright'], + 'U_INSTALL' => $this->u_action . '&action=install&path=' . urlencode($cfg['path'])) + ); + } + } + unset($new_ary); + + $template->assign_vars(array( + 'S_BASIS_OPTIONS' => $basis_options) + ); + + } + + /** + * Provides a template editor which allows saving changes to template files on the filesystem or in the database. + * + * @param int $template_id specifies which template set is being edited + */ + function edit_template($template_id) + { + global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template, $safe_mode; + + if (defined('PHPBB_DISABLE_ACP_EDITOR')) + { + trigger_error($user->lang['EDITOR_DISABLED'] . adm_back_link($this->u_action)); + } + + $this->page_title = 'EDIT_TEMPLATE'; + + $filelist = $filelist_cats = array(); + + $template_data = utf8_normalize_nfc(request_var('template_data', '', true)); + $template_data = htmlspecialchars_decode($template_data); + $template_file = utf8_normalize_nfc(request_var('template_file', '', true)); + $text_rows = max(5, min(999, request_var('text_rows', 20))); + $save_changes = (isset($_POST['save'])) ? true : false; + + // make sure template_file path doesn't go upwards + $template_file = str_replace('..', '.', $template_file); + + // Retrieve some information about the template + $sql = 'SELECT template_storedb, template_path, template_name + FROM ' . STYLES_TEMPLATE_TABLE . " + WHERE template_id = $template_id"; + $result = $db->sql_query($sql); + $template_info = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$template_info) + { + trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if ($save_changes && !check_form_key('acp_styles')) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + else if (!$save_changes) + { + add_form_key('acp_styles'); + } + + // save changes to the template if the user submitted any + if ($save_changes && $template_file) + { + // Get the filesystem location of the current file + $file = "{$phpbb_root_path}styles/{$template_info['template_path']}/template/$template_file"; + $additional = ''; + + // If the template is stored on the filesystem try to write the file else store it in the database + if (!$safe_mode && !$template_info['template_storedb'] && file_exists($file) && @is_writable($file)) + { + if (!($fp = @fopen($file, 'wb'))) + { + // File exists and is writeable, but still not able to be written to + trigger_error(sprintf($user->lang['TEMPLATE_FILE_NOT_WRITABLE'], htmlspecialchars($template_file)) . adm_back_link($this->u_action), E_USER_WARNING); + } + fwrite($fp, $template_data); + fclose($fp); + } + else + { + $db->sql_transaction('begin'); + + // If it's not stored in the db yet, then update the template setting and store all template files in the db + if (!$template_info['template_storedb']) + { + if ($super = $this->get_super('template', $template_id)) + { + $this->store_in_db('template', $super['template_id']); + } + else + { + $this->store_in_db('template', $template_id); + } + + add_log('admin', 'LOG_TEMPLATE_EDIT_DETAILS', $template_info['template_name']); + $additional .= '<br />' . $user->lang['EDIT_TEMPLATE_STORED_DB']; + } + + // Update the template_data table entry for this template file + $sql = 'UPDATE ' . STYLES_TEMPLATE_DATA_TABLE . " + SET template_data = '" . $db->sql_escape($template_data) . "', template_mtime = " . time() . " + WHERE template_id = $template_id + AND template_filename = '" . $db->sql_escape($template_file) . "'"; + $db->sql_query($sql); + + $db->sql_transaction('commit'); + } + + // destroy the cached version of the template (filename without extension) + $this->clear_template_cache($template_info, array(substr($template_file, 0, -5))); + + $cache->destroy('sql', STYLES_TABLE); + + add_log('admin', 'LOG_TEMPLATE_EDIT', $template_info['template_name'], $template_file); + trigger_error($user->lang['TEMPLATE_FILE_UPDATED'] . $additional . adm_back_link($this->u_action . "&action=edit&id=$template_id&text_rows=$text_rows&template_file=$template_file")); + } + + // Generate a category array containing template filenames + if (!$template_info['template_storedb']) + { + $template_path = "{$phpbb_root_path}styles/{$template_info['template_path']}/template"; + + $filelist = filelist($template_path, '', 'html'); + $filelist[''] = array_diff($filelist[''], array('bbcode.html')); + + if ($template_file) + { + if (!file_exists($template_path . "/$template_file") || !($template_data = file_get_contents($template_path . "/$template_file"))) + { + trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + } + else + { + $sql = 'SELECT * + FROM ' . STYLES_TEMPLATE_DATA_TABLE . " + WHERE template_id = $template_id"; + $result = $db->sql_query($sql); + + $filelist = array('' => array()); + while ($row = $db->sql_fetchrow($result)) + { + $file_info = pathinfo($row['template_filename']); + + if (($file_info['basename'] != 'bbcode') && ($file_info['extension'] == 'html')) + { + if (($file_info['dirname'] == '.') || empty($file_info['dirname'])) + { + $filelist[''][] = $row['template_filename']; + } + else + { + $filelist[$file_info['dirname'] . '/'][] = $file_info['basename']; + } + } + + if ($row['template_filename'] == $template_file) + { + $template_data = $row['template_data']; + } + } + $db->sql_freeresult($result); + unset($file_info); + } + + if (empty($filelist[''])) + { + trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Now create the categories + $filelist_cats[''] = array(); + foreach ($filelist as $pathfile => $file_ary) + { + // Use the directory name as category name + if (!empty($pathfile)) + { + $filelist_cats[$pathfile] = array(); + foreach ($file_ary as $file) + { + $filelist_cats[$pathfile][$pathfile . $file] = $file; + } + } + // or if it's in the main category use the word before the first underscore to group files + else + { + $cats = array(); + foreach ($file_ary as $file) + { + $cats[] = substr($file, 0, strpos($file, '_')); + $filelist_cats[substr($file, 0, strpos($file, '_'))][$file] = $file; + } + + $cats = array_values(array_unique($cats)); + + // we don't need any single element categories so put them into the misc '' category + for ($i = 0, $n = sizeof($cats); $i < $n; $i++) + { + if (sizeof($filelist_cats[$cats[$i]]) == 1 && $cats[$i] !== '') + { + $filelist_cats[''][key($filelist_cats[$cats[$i]])] = current($filelist_cats[$cats[$i]]); + unset($filelist_cats[$cats[$i]]); + } + } + unset($cats); + } + } + unset($filelist); + + // Generate list of categorised template files + $tpl_options = ''; + ksort($filelist_cats); + foreach ($filelist_cats as $category => $tpl_ary) + { + ksort($tpl_ary); + + if (!empty($category)) + { + $tpl_options .= '<option class="sep" value="">' . $category . '</option>'; + } + + foreach ($tpl_ary as $filename => $file) + { + $selected = ($template_file == $filename) ? ' selected="selected"' : ''; + $tpl_options .= '<option value="' . $filename . '"' . $selected . '>' . $file . '</option>'; + } + } + + $template->assign_vars(array( + 'S_EDIT_TEMPLATE' => true, + 'S_HIDDEN_FIELDS' => build_hidden_fields(array('template_file' => $template_file)), + 'S_TEMPLATES' => $tpl_options, + + 'U_ACTION' => $this->u_action . "&action=edit&id=$template_id&text_rows=$text_rows", + 'U_BACK' => $this->u_action, + + 'L_EDIT' => $user->lang['EDIT_TEMPLATE'], + 'L_EDIT_EXPLAIN' => $user->lang['EDIT_TEMPLATE_EXPLAIN'], + 'L_EDITOR' => $user->lang['TEMPLATE_EDITOR'], + 'L_EDITOR_HEIGHT' => $user->lang['TEMPLATE_EDITOR_HEIGHT'], + 'L_FILE' => $user->lang['TEMPLATE_FILE'], + 'L_SELECT' => $user->lang['SELECT_TEMPLATE'], + 'L_SELECTED' => $user->lang['SELECTED_TEMPLATE'], + 'L_SELECTED_FILE' => $user->lang['SELECTED_TEMPLATE_FILE'], + + 'SELECTED_TEMPLATE' => $template_info['template_name'], + 'TEMPLATE_FILE' => $template_file, + 'TEMPLATE_DATA' => utf8_htmlspecialchars($template_data), + 'TEXT_ROWS' => $text_rows) + ); + } + + /** + * Allows the admin to view cached versions of template files and clear single template cache files + * + * @param int $template_id specifies which template's cache is shown + */ + function template_cache($template_id) + { + global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template; + + $source = str_replace('/', '.', request_var('source', '')); + $file_ary = array_diff(request_var('delete', array('')), array('')); + $submit = isset($_POST['submit']) ? true : false; + + $sql = 'SELECT * + FROM ' . STYLES_TEMPLATE_TABLE . " + WHERE template_id = $template_id"; + $result = $db->sql_query($sql); + $template_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$template_row) + { + trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // User wants to delete one or more files ... + if ($submit && $file_ary) + { + $this->clear_template_cache($template_row, $file_ary); + trigger_error($user->lang['TEMPLATE_CACHE_CLEARED'] . adm_back_link($this->u_action . "&action=cache&id=$template_id")); + } + + $cache_prefix = 'tpl_' . str_replace('_', '-', $template_row['template_path']); + + // Someone wants to see the cached source ... so we'll highlight it, + // add line numbers and indent it appropriately. This could be nasty + // on larger source files ... + if ($source && file_exists("{$phpbb_root_path}cache/{$cache_prefix}_$source.html.$phpEx")) + { + adm_page_header($user->lang['TEMPLATE_CACHE']); + + $template->set_filenames(array( + 'body' => 'viewsource.html') + ); + + $template->assign_vars(array( + 'FILENAME' => str_replace('.', '/', $source) . '.html') + ); + + $code = str_replace(array("\r\n", "\r"), array("\n", "\n"), file_get_contents("{$phpbb_root_path}cache/{$cache_prefix}_$source.html.$phpEx")); + + $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)); + } + + $marker = 'MARKER' . time(); + $code = highlight_string(str_replace("\n", $marker, $code), true); + $code = str_replace($marker, "\n", $code); + $str_from = array('<span style="color: ', '<font color="syntax', '</font>', '<code>', '</code>','[', ']', '.', ':'); + $str_to = array('<span class="', '<span class="syntax', '</span>', '', '', '[', ']', '.', ':'); + + $code = str_replace($str_from, $str_to, $code); + $code = preg_replace('#^(<span class="[a-z_]+">)\n?(.*?)\n?(</span>)$#ism', '$1$2$3', $code); + $code = substr($code, strlen('<span class="syntaxhtml">')); + $code = substr($code, 0, -1 * strlen('</ span>')); + $code = explode("\n", $code); + + foreach ($code as $key => $line) + { + $template->assign_block_vars('source', array( + 'LINENUM' => $key + 1, + 'LINE' => preg_replace('#([^ ;]) ([^ &])#', '$1 $2', $line)) + ); + unset($code[$key]); + } + + adm_page_footer(); + } + + $filemtime = array(); + if ($template_row['template_storedb']) + { + $ids = array(); + if (isset($template_row['template_inherits_id']) && $template_row['template_inherits_id']) + { + $ids[] = $template_row['template_inherits_id']; + } + $ids[] = $template_row['template_id']; + + $filemtime = array(); + $file_template_db = array(); + + foreach ($ids as $id) + { + $sql = 'SELECT template_filename, template_mtime + FROM ' . STYLES_TEMPLATE_DATA_TABLE . " + WHERE template_id = $id"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $filemtime[$row['template_filename']] = $row['template_mtime']; + $file_template_db[$row['template_filename']] = $id; + } + $db->sql_freeresult($result); + } + } + + // Get a list of cached template files and then retrieve additional information about them + $file_ary = $this->template_cache_filelist($template_row['template_path']); + + foreach ($file_ary as $file) + { + $file = str_replace('/', '.', $file); + + // perform some dirty guessing to get the path right. + // We assume that three dots in a row were '../' + $tpl_file = str_replace('.', '/', $file); + $tpl_file = str_replace('///', '../', $tpl_file); + + $filename = "{$cache_prefix}_$file.html.$phpEx"; + + if (!file_exists("{$phpbb_root_path}cache/$filename")) + { + continue; + } + + $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_path']}/template/$tpl_file.html"; + $inherited = false; + + if (isset($template_row['template_inherits_id']) && $template_row['template_inherits_id']) + { + if (!$template_row['template_storedb']) + { + if (!file_exists($file_tpl)) + { + $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_inherit_path']}/template/$tpl_file.html"; + $inherited = true; + } + } + else + { + if ($file_template_db[$file . '.html'] == $template_row['template_inherits_id']) + { + $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_inherit_path']}/template/$tpl_file.html"; + $inherited = true; + } + } + } + + // Correct the filename if it is stored in database and the file is in a subfolder. + if ($template_row['template_storedb']) + { + $file = str_replace('.', '/', $file); + } + + $template->assign_block_vars('file', array( + 'U_VIEWSOURCE' => $this->u_action . "&action=cache&id=$template_id&source=$file", + + 'CACHED' => $user->format_date(filemtime("{$phpbb_root_path}cache/$filename")), + 'FILENAME' => $file, + 'FILENAME_PATH' => $file_tpl, + 'FILESIZE' => get_formatted_filesize(filesize("{$phpbb_root_path}cache/$filename")), + 'MODIFIED' => $user->format_date((!$template_row['template_storedb']) ? filemtime($file_tpl) : $filemtime[$file . '.html'])) + ); + } + unset($filemtime); + + $template->assign_vars(array( + 'S_CACHE' => true, + 'S_TEMPLATE' => true, + + 'U_ACTION' => $this->u_action . "&action=cache&id=$template_id", + 'U_BACK' => $this->u_action) + ); + } + + /** + * Provides a css editor and a basic easier to use stylesheet editing tool for less experienced (or lazy) users + * + * @param int $theme_id specifies which theme is being edited + */ + function edit_theme($theme_id) + { + global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template, $safe_mode; + + $this->page_title = 'EDIT_THEME'; + + $filelist = $filelist_cats = array(); + + $theme_data = utf8_normalize_nfc(request_var('template_data', '', true)); + $theme_data = htmlspecialchars_decode($theme_data); + $theme_file = utf8_normalize_nfc(request_var('template_file', '', true)); + $text_rows = max(5, min(999, request_var('text_rows', 20))); + $save_changes = (isset($_POST['save'])) ? true : false; + + // make sure theme_file path doesn't go upwards + $theme_file = str_replace('..', '.', $theme_file); + + // Retrieve some information about the theme + $sql = 'SELECT theme_storedb, theme_path, theme_name, theme_data + FROM ' . STYLES_THEME_TABLE . " + WHERE theme_id = $theme_id"; + $result = $db->sql_query($sql); + + if (!($theme_info = $db->sql_fetchrow($result))) + { + trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING); + } + $db->sql_freeresult($result); + + // save changes to the theme if the user submitted any + if ($save_changes) + { + // Get the filesystem location of the current file + $file = "{$phpbb_root_path}styles/{$theme_info['theme_path']}/theme/$theme_file"; + $additional = ''; + $message = $user->lang['THEME_UPDATED']; + + // If the theme is stored on the filesystem try to write the file else store it in the database + if (!$safe_mode && !$theme_info['theme_storedb'] && file_exists($file) && @is_writable($file)) + { + if (!($fp = @fopen($file, 'wb'))) + { + trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING); + } + fwrite($fp, $theme_data); + fclose($fp); + } + else + { + // Write stylesheet to db + $sql_ary = array( + 'theme_mtime' => time(), + 'theme_storedb' => 1, + 'theme_data' => $this->db_theme_data($theme_info, $theme_data), + ); + $sql = 'UPDATE ' . STYLES_THEME_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE theme_id = ' . $theme_id; + $db->sql_query($sql); + + $cache->destroy('sql', STYLES_THEME_TABLE); + + // notify the user if the theme was not stored in the db before his modification + if (!$theme_info['theme_storedb']) + { + add_log('admin', 'LOG_THEME_EDIT_DETAILS', $theme_info['theme_name']); + $message .= '<br />' . $user->lang['EDIT_THEME_STORED_DB']; + } + } + $cache->destroy('sql', STYLES_THEME_TABLE); + add_log('admin', (!$theme_info['theme_storedb']) ? 'LOG_THEME_EDIT_FILE' : 'LOG_THEME_EDIT', $theme_info['theme_name'], (!$theme_info['theme_storedb']) ? $theme_file : ''); + + trigger_error($message . adm_back_link($this->u_action . "&action=edit&id=$theme_id&template_file=$theme_file&text_rows=$text_rows")); + } + + // Generate a category array containing theme filenames + if (!$theme_info['theme_storedb']) + { + $theme_path = "{$phpbb_root_path}styles/{$theme_info['theme_path']}/theme"; + + $filelist = filelist($theme_path, '', 'css'); + + if ($theme_file) + { + if (!file_exists($theme_path . "/$theme_file") || !($theme_data = file_get_contents($theme_path . "/$theme_file"))) + { + trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + } + else + { + $theme_data = &$theme_info['theme_data']; + } + + // Now create the categories + $filelist_cats[''] = array(); + foreach ($filelist as $pathfile => $file_ary) + { + // Use the directory name as category name + if (!empty($pathfile)) + { + $filelist_cats[$pathfile] = array(); + foreach ($file_ary as $file) + { + $filelist_cats[$pathfile][$pathfile . $file] = $file; + } + } + // or if it's in the main category use the word before the first underscore to group files + else + { + $cats = array(); + foreach ($file_ary as $file) + { + $cats[] = substr($file, 0, strpos($file, '_')); + $filelist_cats[substr($file, 0, strpos($file, '_'))][$file] = $file; + } + + $cats = array_values(array_unique($cats)); + + // we don't need any single element categories so put them into the misc '' category + for ($i = 0, $n = sizeof($cats); $i < $n; $i++) + { + if (sizeof($filelist_cats[$cats[$i]]) == 1 && $cats[$i] !== '') + { + $filelist_cats[''][key($filelist_cats[$cats[$i]])] = current($filelist_cats[$cats[$i]]); + unset($filelist_cats[$cats[$i]]); + } + } + unset($cats); + } + } + unset($filelist); + + // Generate list of categorised theme files + $tpl_options = ''; + ksort($filelist_cats); + foreach ($filelist_cats as $category => $tpl_ary) + { + ksort($tpl_ary); + + if (!empty($category)) + { + $tpl_options .= '<option class="sep" value="">' . $category . '</option>'; + } + + foreach ($tpl_ary as $filename => $file) + { + $selected = ($theme_file == $filename) ? ' selected="selected"' : ''; + $tpl_options .= '<option value="' . $filename . '"' . $selected . '>' . $file . '</option>'; + } + } + + $template->assign_vars(array( + 'S_EDIT_THEME' => true, + 'S_HIDDEN_FIELDS' => build_hidden_fields(array('template_file' => $theme_file)), + 'S_THEME_IN_DB' => $theme_info['theme_storedb'], + 'S_TEMPLATES' => $tpl_options, + + 'U_ACTION' => $this->u_action . "&action=edit&id=$theme_id&text_rows=$text_rows", + 'U_BACK' => $this->u_action, + + 'L_EDIT' => $user->lang['EDIT_THEME'], + 'L_EDIT_EXPLAIN' => $user->lang['EDIT_THEME_EXPLAIN'], + 'L_EDITOR' => $user->lang['THEME_EDITOR'], + 'L_EDITOR_HEIGHT' => $user->lang['THEME_EDITOR_HEIGHT'], + 'L_FILE' => $user->lang['THEME_FILE'], + 'L_SELECT' => $user->lang['SELECT_THEME'], + 'L_SELECTED' => $user->lang['SELECTED_THEME'], + 'L_SELECTED_FILE' => $user->lang['SELECTED_THEME_FILE'], + + 'SELECTED_TEMPLATE' => $theme_info['theme_name'], + 'TEMPLATE_FILE' => $theme_file, + 'TEMPLATE_DATA' => utf8_htmlspecialchars($theme_data), + 'TEXT_ROWS' => $text_rows) + ); + } + + /** + * Edit imagesets + * + * @param int $imageset_id specifies which imageset is being edited + */ + function edit_imageset($imageset_id) + { + global $db, $user, $phpbb_root_path, $cache, $template; + + $this->page_title = 'EDIT_IMAGESET'; + + if (!$imageset_id) + { + trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $update = (isset($_POST['update'])) ? true : false; + + $imgname = request_var('imgname', 'site_logo'); + $imgname = preg_replace('#[^a-z0-9\-+_]#i', '', $imgname); + $sql_extra = $imgnamelang = ''; + + $sql = 'SELECT imageset_path, imageset_name + FROM ' . STYLES_IMAGESET_TABLE . " + WHERE imageset_id = $imageset_id"; + $result = $db->sql_query($sql); + $imageset_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$imageset_row) + { + trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $imageset_path = $imageset_row['imageset_path']; + $imageset_name = $imageset_row['imageset_name']; + + if (strpos($imgname, '-') !== false) + { + list($imgname, $imgnamelang) = explode('-', $imgname); + $sql_extra = " AND image_lang IN ('" . $db->sql_escape($imgnamelang) . "', '')"; + } + + $sql = 'SELECT image_filename, image_width, image_height, image_lang, image_id + FROM ' . STYLES_IMAGESET_DATA_TABLE . " + WHERE imageset_id = $imageset_id + AND image_name = '" . $db->sql_escape($imgname) . "'$sql_extra"; + $result = $db->sql_query($sql); + $imageset_data_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $image_filename = $imageset_data_row['image_filename']; + $image_width = $imageset_data_row['image_width']; + $image_height = $imageset_data_row['image_height']; + $image_lang = $imageset_data_row['image_lang']; + $image_id = $imageset_data_row['image_id']; + $imgsize = ($imageset_data_row['image_width'] && $imageset_data_row['image_height']) ? 1 : 0; + + // Check to see whether the selected image exists in the table + $valid_name = ($update) ? false : true; + + foreach ($this->imageset_keys as $category => $img_ary) + { + if (in_array($imgname, $img_ary)) + { + $valid_name = true; + break; + } + } + + if ($update && isset($_POST['imgpath']) && $valid_name) + { + // If imgwidth and imgheight are non-zero grab the actual size + // from the image itself ... we ignore width settings for the poll center image + $imgwidth = request_var('imgwidth', 0); + $imgheight = request_var('imgheight', 0); + $imgsize = request_var('imgsize', 0); + $imgpath = request_var('imgpath', ''); + $imgpath = str_replace('..', '.', $imgpath); + + // If no dimensions selected, we reset width and height to 0 ;) + if (!$imgsize) + { + $imgwidth = $imgheight = 0; + } + + $imglang = ''; + + if ($imgpath && !file_exists("{$phpbb_root_path}styles/$imageset_path/imageset/$imgpath")) + { + trigger_error($user->lang['NO_IMAGE_ERROR'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Determine width/height. If dimensions included and no width/height given, we detect them automatically... + if ($imgsize && $imgpath) + { + if (!$imgwidth || !$imgheight) + { + list($imgwidth_file, $imgheight_file) = getimagesize("{$phpbb_root_path}styles/$imageset_path/imageset/$imgpath"); + $imgwidth = ($imgwidth) ? $imgwidth : $imgwidth_file; + $imgheight = ($imgheight) ? $imgheight : $imgheight_file; + } + $imgwidth = ($imgname != 'poll_center') ? (int) $imgwidth : 0; + $imgheight = (int) $imgheight; + } + + if (strpos($imgpath, '/') !== false) + { + list($imglang, $imgfilename) = explode('/', $imgpath); + } + else + { + $imgfilename = $imgpath; + } + + $sql_ary = array( + 'image_filename' => (string) $imgfilename, + 'image_width' => (int) $imgwidth, + 'image_height' => (int) $imgheight, + 'image_lang' => (string) $imglang, + ); + + // already exists + if ($imageset_data_row) + { + $sql = 'UPDATE ' . STYLES_IMAGESET_DATA_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE image_id = $image_id"; + $db->sql_query($sql); + } + // does not exist + else if (!$imageset_data_row) + { + $sql_ary['image_name'] = $imgname; + $sql_ary['imageset_id'] = (int) $imageset_id; + $db->sql_query('INSERT INTO ' . STYLES_IMAGESET_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + } + + $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE); + + add_log('admin', 'LOG_IMAGESET_EDIT', $imageset_name); + + $template->assign_var('SUCCESS', true); + + $image_filename = $imgfilename; + $image_width = $imgwidth; + $image_height = $imgheight; + $image_lang = $imglang; + } + + $imglang = ''; + $imagesetlist = array('nolang' => array(), 'lang' => array()); + $langs = array(); + + $dir = "{$phpbb_root_path}styles/$imageset_path/imageset"; + $dp = @opendir($dir); + + if ($dp) + { + while (($file = readdir($dp)) !== false) + { + if ($file[0] != '.' && strtoupper($file) != 'CVS' && !is_file($dir . '/' . $file) && !is_link($dir . '/' . $file)) + { + $langs[] = $file; + } + else if (preg_match('#\.(?:gif|jpg|png)$#', $file)) + { + $imagesetlist['nolang'][] = $file; + } + } + + if ($sql_extra) + { + $dp2 = @opendir("$dir/$imgnamelang"); + + if ($dp2) + { + while (($file2 = readdir($dp2)) !== false) + { + if (preg_match('#\.(?:gif|jpg|png)$#', $file2)) + { + $imagesetlist['lang'][] = "$imgnamelang/$file2"; + } + } + closedir($dp2); + } + } + closedir($dp); + } + + // Generate list of image options + $img_options = ''; + foreach ($this->imageset_keys as $category => $img_ary) + { + $template->assign_block_vars('category', array( + 'NAME' => $user->lang['IMG_CAT_' . strtoupper($category)] + )); + + foreach ($img_ary as $img) + { + if ($category == 'buttons') + { + foreach ($langs as $language) + { + $template->assign_block_vars('category.images', array( + 'SELECTED' => ($img == $imgname && $language == $imgnamelang), + 'VALUE' => $img . '-' . $language, + 'TEXT' => $user->lang['IMG_' . strtoupper($img)] . ' [ ' . $language . ' ]' + )); + } + } + else + { + $template->assign_block_vars('category.images', array( + 'SELECTED' => ($img == $imgname), + 'VALUE' => $img, + 'TEXT' => (($category == 'custom') ? $img : $user->lang['IMG_' . strtoupper($img)]) + )); + } + } + } + + // Make sure the list of possible images is sorted alphabetically + sort($imagesetlist['lang']); + sort($imagesetlist['nolang']); + + $image_found = false; + $img_val = ''; + foreach ($imagesetlist as $type => $img_ary) + { + if ($type !== 'lang' || $sql_extra) + { + $template->assign_block_vars('imagesetlist', array( + 'TYPE' => ($type == 'lang') + )); + } + + foreach ($img_ary as $img) + { + $imgtext = preg_replace('/^([^\/]+\/)/', '', $img); + $selected = (!empty($imgname) && strpos($image_filename, $imgtext) !== false); + if ($selected) + { + $image_found = true; + $img_val = htmlspecialchars($img); + } + $template->assign_block_vars('imagesetlist.images', array( + 'SELECTED' => $selected, + 'TEXT' => $imgtext, + 'VALUE' => htmlspecialchars($img) + )); + } + } + + $imgsize_bool = (!empty($imgname) && $image_width && $image_height) ? true : false; + $image_request = '../styles/' . $imageset_path . '/imageset/' . ($image_lang ? $imgnamelang . '/' : '') . $image_filename; + + $template->assign_vars(array( + 'S_EDIT_IMAGESET' => true, + 'L_TITLE' => $user->lang[$this->page_title], + 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], + 'IMAGE_OPTIONS' => $img_options, + 'IMAGE_SIZE' => $image_width, + 'IMAGE_HEIGHT' => $image_height, + 'IMAGE_REQUEST' => (empty($image_filename)) ? 'images/no_image.png' : $image_request, + 'U_ACTION' => $this->u_action . "&action=edit&id=$imageset_id", + 'U_BACK' => $this->u_action, + 'NAME' => $imageset_name, + 'A_NAME' => addslashes($imageset_name), + 'PATH' => $imageset_path, + 'A_PATH' => addslashes($imageset_path), + 'ERROR' => !$valid_name, + 'IMG_SRC' => ($image_found) ? '../styles/' . $imageset_path . '/imageset/' . $img_val : 'images/no_image.png', + 'IMAGE_SELECT' => $image_found + )); + } + + /** + * Remove style/template/theme/imageset + */ + function remove($mode, $style_id) + { + global $db, $template, $user, $phpbb_root_path, $cache, $config; + + $new_id = request_var('new_id', 0); + $update = (isset($_POST['update'])) ? true : false; + $sql_where = ''; + + switch ($mode) + { + case 'style': + $sql_from = STYLES_TABLE; + $sql_select = 'style_name'; + $sql_where = 'AND style_active = 1'; + break; + + case 'template': + $sql_from = STYLES_TEMPLATE_TABLE; + $sql_select = 'template_name, template_path, template_storedb'; + break; + + case 'theme': + $sql_from = STYLES_THEME_TABLE; + $sql_select = 'theme_name, theme_path, theme_storedb'; + break; + + case 'imageset': + $sql_from = STYLES_IMAGESET_TABLE; + $sql_select = 'imageset_name, imageset_path'; + break; + } + + if ($mode === 'template' && ($conflicts = $this->check_inheritance($mode, $style_id))) + { + $l_type = strtoupper($mode); + $msg = $user->lang[$l_type . '_DELETE_DEPENDENT']; + foreach ($conflicts as $id => $values) + { + $msg .= '<br />' . $values['template_name']; + } + + trigger_error($msg . adm_back_link($this->u_action), E_USER_WARNING); + } + + $l_prefix = strtoupper($mode); + + $sql = "SELECT $sql_select + FROM $sql_from + WHERE {$mode}_id = $style_id"; + $result = $db->sql_query($sql); + $style_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$style_row) + { + trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = "SELECT {$mode}_id, {$mode}_name + FROM $sql_from + WHERE {$mode}_id <> $style_id + $sql_where + ORDER BY {$mode}_name ASC"; + $result = $db->sql_query($sql); + + $s_options = ''; + + if ($row = $db->sql_fetchrow($result)) + { + do + { + $s_options .= '<option value="' . $row[$mode . '_id'] . '">' . $row[$mode . '_name'] . '</option>'; + } + while ($row = $db->sql_fetchrow($result)); + } + else + { + trigger_error($user->lang['ONLY_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING); + } + $db->sql_freeresult($result); + + if ($update) + { + $sql = "DELETE FROM $sql_from + WHERE {$mode}_id = $style_id"; + $db->sql_query($sql); + + if ($mode == 'style') + { + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_style = $new_id + WHERE user_style = $style_id"; + $db->sql_query($sql); + + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET forum_style = $new_id + WHERE forum_style = $style_id"; + $db->sql_query($sql); + + if ($style_id == $config['default_style']) + { + set_config('default_style', $new_id); + } + } + else + { + if ($mode == 'imageset') + { + $sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . " + WHERE imageset_id = $style_id"; + $db->sql_query($sql); + } + $sql = 'UPDATE ' . STYLES_TABLE . " + SET {$mode}_id = $new_id + WHERE {$mode}_id = $style_id"; + $db->sql_query($sql); + } + + $cache->destroy('sql', STYLES_TABLE); + + add_log('admin', 'LOG_' . $l_prefix . '_DELETE', $style_row[$mode . '_name']); + $message = ($mode != 'style') ? $l_prefix . '_DELETED_FS' : $l_prefix . '_DELETED'; + trigger_error($user->lang[$message] . adm_back_link($this->u_action)); + } + + $this->page_title = 'DELETE_' . $l_prefix; + + $template->assign_vars(array( + 'S_DELETE' => true, + 'S_REPLACE_OPTIONS' => $s_options, + + 'L_TITLE' => $user->lang[$this->page_title], + 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], + 'L_NAME' => $user->lang[$l_prefix . '_NAME'], + 'L_REPLACE' => $user->lang['REPLACE_' . $l_prefix], + 'L_REPLACE_EXPLAIN' => $user->lang['REPLACE_' . $l_prefix . '_EXPLAIN'], + + 'U_ACTION' => $this->u_action . "&action=delete&id=$style_id", + 'U_BACK' => $this->u_action, + + 'NAME' => $style_row[$mode . '_name'], + ) + ); + } + + /** + * Export style or style elements + */ + function export($mode, $style_id) + { + global $db, $template, $user, $phpbb_root_path, $cache, $phpEx, $config; + + $update = (isset($_POST['update'])) ? true : false; + + $inc_template = request_var('inc_template', 0); + $inc_theme = request_var('inc_theme', 0); + $inc_imageset = request_var('inc_imageset', 0); + $store = request_var('store', 0); + $format = request_var('format', ''); + + $error = array(); + $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; + } + + if (!in_array($format, $methods)) + { + $format = 'tar'; + } + + switch ($mode) + { + case 'style': + if ($update && ($inc_template + $inc_theme + $inc_imageset) < 1) + { + $error[] = $user->lang['STYLE_ERR_MORE_ELEMENTS']; + } + + $name = 'style_name'; + + $sql_select = 's.style_id, s.style_name, s.style_copyright'; + $sql_select .= ($inc_template) ? ', t.*' : ', t.template_name'; + $sql_select .= ($inc_theme) ? ', c.*' : ', c.theme_name'; + $sql_select .= ($inc_imageset) ? ', i.*' : ', i.imageset_name'; + $sql_from = STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . ' c, ' . STYLES_IMAGESET_TABLE . ' i'; + $sql_where = "s.style_id = $style_id AND t.template_id = s.template_id AND c.theme_id = s.theme_id AND i.imageset_id = s.imageset_id"; + + $l_prefix = 'STYLE'; + break; + + case 'template': + $name = 'template_name'; + + $sql_select = '*'; + $sql_from = STYLES_TEMPLATE_TABLE; + $sql_where = "template_id = $style_id"; + + $l_prefix = 'TEMPLATE'; + break; + + case 'theme': + $name = 'theme_name'; + + $sql_select = '*'; + $sql_from = STYLES_THEME_TABLE; + $sql_where = "theme_id = $style_id"; + + $l_prefix = 'THEME'; + break; + + case 'imageset': + $name = 'imageset_name'; + + $sql_select = '*'; + $sql_from = STYLES_IMAGESET_TABLE; + $sql_where = "imageset_id = $style_id"; + + $l_prefix = 'IMAGESET'; + break; + } + + if ($update && !sizeof($error)) + { + $sql = "SELECT $sql_select + FROM $sql_from + WHERE $sql_where"; + $result = $db->sql_query($sql); + $style_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$style_row) + { + trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $var_ary = array('style_id', 'style_name', 'style_copyright', 'template_id', 'template_name', 'template_path', 'template_copyright', 'template_storedb', 'template_inherits_id', 'bbcode_bitfield', 'theme_id', 'theme_name', 'theme_path', 'theme_copyright', 'theme_storedb', 'theme_mtime', 'theme_data', 'imageset_id', 'imageset_name', 'imageset_path', 'imageset_copyright'); + + foreach ($var_ary as $var) + { + if (!isset($style_row[$var])) + { + $style_row[$var] = ''; + } + } + + $files = $data = array(); + + if ($mode == 'style') + { + $style_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['style_name'], $style_row['style_copyright'], $config['version']), $this->style_cfg); + + $style_cfg .= (!$inc_template) ? "\nrequired_template = {$style_row['template_name']}" : ''; + $style_cfg .= (!$inc_theme) ? "\nrequired_theme = {$style_row['theme_name']}" : ''; + $style_cfg .= (!$inc_imageset) ? "\nrequired_imageset = {$style_row['imageset_name']}" : ''; + + $data[] = array( + 'src' => $style_cfg, + 'prefix' => 'style.cfg' + ); + + unset($style_cfg); + } + + // Export template core code + if ($mode == 'template' || $inc_template) + { + $template_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['template_name'], $style_row['template_copyright'], $config['version']), $this->template_cfg); + + $use_template_name = ''; + + // Add the inherit from variable, depending on it's use... + if ($style_row['template_inherits_id']) + { + // Get the template name + $sql = 'SELECT template_name + FROM ' . STYLES_TEMPLATE_TABLE . ' + WHERE template_id = ' . (int) $style_row['template_inherits_id']; + $result = $db->sql_query($sql); + $use_template_name = (string) $db->sql_fetchfield('template_name'); + $db->sql_freeresult($result); + } + + $template_cfg .= ($use_template_name) ? "\ninherit_from = $use_template_name" : "\n#inherit_from = "; + $template_cfg .= "\n\nbbcode_bitfield = {$style_row['bbcode_bitfield']}"; + + $data[] = array( + 'src' => $template_cfg, + 'prefix' => 'template/template.cfg' + ); + + // This is potentially nasty memory-wise ... + if (!$style_row['template_storedb']) + { + $files[] = array( + 'src' => "styles/{$style_row['template_path']}/template/", + 'prefix-' => "styles/{$style_row['template_path']}/", + 'prefix+' => false, + 'exclude' => 'template.cfg' + ); + } + else + { + $sql = 'SELECT template_filename, template_data + FROM ' . STYLES_TEMPLATE_DATA_TABLE . " + WHERE template_id = {$style_row['template_id']}"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $data[] = array( + 'src' => $row['template_data'], + 'prefix' => 'template/' . $row['template_filename'] + ); + } + $db->sql_freeresult($result); + } + unset($template_cfg); + } + + // Export theme core code + if ($mode == 'theme' || $inc_theme) + { + $theme_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['theme_name'], $style_row['theme_copyright'], $config['version']), $this->theme_cfg); + + // Read old cfg file + $items = $cache->obtain_cfg_items($style_row); + $items = $items['theme']; + + if (!isset($items['parse_css_file'])) + { + $items['parse_css_file'] = 'off'; + } + + $theme_cfg = str_replace(array('{PARSE_CSS_FILE}'), array($items['parse_css_file']), $theme_cfg); + + $files[] = array( + 'src' => "styles/{$style_row['theme_path']}/theme/", + 'prefix-' => "styles/{$style_row['theme_path']}/", + 'prefix+' => false, + 'exclude' => ($style_row['theme_storedb']) ? 'stylesheet.css,theme.cfg' : 'theme.cfg' + ); + + $data[] = array( + 'src' => $theme_cfg, + 'prefix' => 'theme/theme.cfg' + ); + + if ($style_row['theme_storedb']) + { + $data[] = array( + 'src' => $style_row['theme_data'], + 'prefix' => 'theme/stylesheet.css' + ); + } + + unset($items, $theme_cfg); + } + + // Export imageset core code + if ($mode == 'imageset' || $inc_imageset) + { + $imageset_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['imageset_name'], $style_row['imageset_copyright'], $config['version']), $this->imageset_cfg); + + $imageset_main = array(); + + $sql = 'SELECT image_filename, image_name, image_height, image_width + FROM ' . STYLES_IMAGESET_DATA_TABLE . " + WHERE imageset_id = $style_id + AND image_lang = ''"; + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + $imageset_main[$row['image_name']] = $row['image_filename'] . ($row['image_height'] ? '*' . $row['image_height']: '') . ($row['image_width'] ? '*' . $row['image_width']: ''); + } + $db->sql_freeresult($result); + + foreach ($this->imageset_keys as $topic => $key_array) + { + foreach ($key_array as $key) + { + if (isset($imageset_main[$key])) + { + $imageset_cfg .= "\nimg_" . $key . ' = ' . str_replace("styles/{$style_row['imageset_path']}/imageset/", '{PATH}', $imageset_main[$key]); + } + } + } + + $files[] = array( + 'src' => "styles/{$style_row['imageset_path']}/imageset/", + 'prefix-' => "styles/{$style_row['imageset_path']}/", + 'prefix+' => false, + 'exclude' => 'imageset.cfg' + ); + + $data[] = array( + 'src' => trim($imageset_cfg), + 'prefix' => 'imageset/imageset.cfg' + ); + + end($data); + + $imageset_root = "{$phpbb_root_path}styles/{$style_row['imageset_path']}/imageset/"; + + if ($dh = @opendir($imageset_root)) + { + while (($fname = readdir($dh)) !== false) + { + if ($fname[0] != '.' && $fname != 'CVS' && is_dir("$imageset_root$fname")) + { + $files[key($files)]['exclude'] .= ',' . $fname . '/imageset.cfg'; + } + } + closedir($dh); + } + + $imageset_lang = array(); + + $sql = 'SELECT image_filename, image_name, image_height, image_width, image_lang + FROM ' . STYLES_IMAGESET_DATA_TABLE . " + WHERE imageset_id = $style_id + AND image_lang <> ''"; + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + $imageset_lang[$row['image_lang']][$row['image_name']] = $row['image_filename'] . ($row['image_height'] ? '*' . $row['image_height']: '') . ($row['image_width'] ? '*' . $row['image_width']: ''); + } + $db->sql_freeresult($result); + + foreach ($imageset_lang as $lang => $imageset_localized) + { + $imageset_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['imageset_name'], $style_row['imageset_copyright'], $config['version']), $this->imageset_cfg); + + foreach ($this->imageset_keys as $topic => $key_array) + { + foreach ($key_array as $key) + { + if (isset($imageset_localized[$key])) + { + $imageset_cfg .= "\nimg_" . $key . ' = ' . str_replace("styles/{$style_row['imageset_path']}/imageset/", '{PATH}', $imageset_localized[$key]); + } + } + } + + $data[] = array( + 'src' => trim($imageset_cfg), + 'prefix' => 'imageset/' . $lang . '/imageset.cfg' + ); + } + + unset($imageset_cfg); + } + + switch ($format) + { + case 'tar': + $ext = '.tar'; + $mimetype = 'x-tar'; + $compress = 'compress_tar'; + break; + + case 'zip': + $ext = '.zip'; + $mimetype = 'zip'; + break; + + case 'tar.gz': + $ext = '.tar.gz'; + $mimetype = 'x-gzip'; + break; + + case 'tar.bz2': + $ext = '.tar.bz2'; + $mimetype = 'x-bzip2'; + break; + + default: + $error[] = $user->lang[$l_prefix . '_ERR_ARCHIVE']; + } + + if (!sizeof($error)) + { + include($phpbb_root_path . 'includes/functions_compress.' . $phpEx); + + if ($mode == 'style') + { + $path = preg_replace('#[^\w-]+#', '_', $style_row['style_name']); + } + else + { + $path = $style_row[$mode . '_path']; + } + + if ($format == 'zip') + { + $compress = new compress_zip('w', $phpbb_root_path . "store/$path$ext"); + } + else + { + $compress = new compress_tar('w', $phpbb_root_path . "store/$path$ext", $ext); + } + + if (sizeof($files)) + { + foreach ($files as $file_ary) + { + $compress->add_file($file_ary['src'], $file_ary['prefix-'], $file_ary['prefix+'], $file_ary['exclude']); + } + } + + if (sizeof($data)) + { + foreach ($data as $data_ary) + { + $compress->add_data($data_ary['src'], $data_ary['prefix']); + } + } + + $compress->close(); + + add_log('admin', 'LOG_' . $l_prefix . '_EXPORT', $style_row[$mode . '_name']); + + if (!$store) + { + $compress->download($path); + @unlink("{$phpbb_root_path}store/$path$ext"); + exit; + } + + trigger_error(sprintf($user->lang[$l_prefix . '_EXPORTED'], "store/$path$ext") . adm_back_link($this->u_action)); + } + } + + $sql = "SELECT {$mode}_id, {$mode}_name + FROM " . (($mode == 'style') ? STYLES_TABLE : $sql_from) . " + WHERE {$mode}_id = $style_id"; + $result = $db->sql_query($sql); + $style_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$style_row) + { + trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $this->page_title = $l_prefix . '_EXPORT'; + + $format_buttons = ''; + foreach ($methods as $method) + { + $format_buttons .= '<label><input type="radio"' . ((!$format_buttons) ? ' id="format"' : '') . ' class="radio" value="' . $method . '" name="format"' . (($method == $format) ? ' checked="checked"' : '') . ' /> ' . $method . '</label>'; + } + + $template->assign_vars(array( + 'S_EXPORT' => true, + 'S_ERROR_MSG' => (sizeof($error)) ? true : false, + 'S_STYLE' => ($mode == 'style') ? true : false, + + 'L_TITLE' => $user->lang[$this->page_title], + 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], + 'L_NAME' => $user->lang[$l_prefix . '_NAME'], + + 'U_ACTION' => $this->u_action . '&action=export&id=' . $style_id, + 'U_BACK' => $this->u_action, + + 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + 'NAME' => $style_row[$mode . '_name'], + 'FORMAT_BUTTONS' => $format_buttons) + ); + } + + /** + * Display details + */ + function details($mode, $style_id) + { + global $template, $db, $config, $user, $safe_mode, $cache, $phpbb_root_path; + + $update = (isset($_POST['update'])) ? true : false; + $l_type = strtoupper($mode); + + $error = array(); + $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE, 'imageset' => STYLES_IMAGESET_TABLE); + + switch ($mode) + { + case 'style': + $sql_from = STYLES_TABLE; + break; + + case 'template': + $sql_from = STYLES_TEMPLATE_TABLE; + break; + + case 'theme': + $sql_from = STYLES_THEME_TABLE; + break; + + case 'imageset': + $sql_from = STYLES_IMAGESET_TABLE; + break; + } + + $sql = "SELECT * + FROM $sql_from + WHERE {$mode}_id = $style_id"; + $result = $db->sql_query($sql); + $style_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$style_row) + { + trigger_error($user->lang['NO_' . $l_type] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $style_row['style_default'] = ($mode == 'style' && $config['default_style'] == $style_id) ? 1 : 0; + + if ($update) + { + $name = utf8_normalize_nfc(request_var('name', '', true)); + $copyright = utf8_normalize_nfc(request_var('copyright', '', true)); + + $template_id = request_var('template_id', 0); + $theme_id = request_var('theme_id', 0); + $imageset_id = request_var('imageset_id', 0); + + $style_active = request_var('style_active', 0); + $style_default = request_var('style_default', 0); + $store_db = request_var('store_db', 0); + + // If the admin selected the style to be the default style, but forgot to activate it... we will do it for him + if ($style_default) + { + $style_active = 1; + } + + $sql = "SELECT {$mode}_id, {$mode}_name + FROM $sql_from + WHERE {$mode}_id <> $style_id + AND LOWER({$mode}_name) = '" . $db->sql_escape(strtolower($name)) . "'"; + $result = $db->sql_query($sql); + $conflict = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($mode == 'style' && (!$template_id || !$theme_id || !$imageset_id)) + { + $error[] = $user->lang['STYLE_ERR_NO_IDS']; + } + + if ($mode == 'style' && $style_row['style_active'] && !$style_active && $config['default_style'] == $style_id) + { + $error[] = $user->lang['DEACTIVATE_DEFAULT']; + } + + if (!$name || $conflict) + { + $error[] = $user->lang[$l_type . '_ERR_STYLE_NAME']; + } + + if ($mode === 'theme' || $mode === 'template') + { + // a rather elaborate check we have to do here once to avoid trouble later + $check = "{$phpbb_root_path}styles/" . $style_row["{$mode}_path"] . (($mode === 'theme') ? '/theme/stylesheet.css' : '/template'); + if (($style_row["{$mode}_storedb"] != $store_db) && !$store_db && ($safe_mode || !@is_writable($check))) + { + $error[] = $user->lang['EDIT_' . strtoupper($mode) . '_STORED_DB']; + $store_db = 1; + } + + // themes which have to be parsed have to go into db + if ($mode == 'theme') + { + $cfg = parse_cfg_file("{$phpbb_root_path}styles/" . $style_row["{$mode}_path"] . "/theme/theme.cfg"); + + if (isset($cfg['parse_css_file']) && $cfg['parse_css_file'] && !$store_db) + { + $error[] = $user->lang['EDIT_THEME_STORE_PARSED']; + $store_db = 1; + } + } + } + + if (!sizeof($error)) + { + // Check length settings + if (utf8_strlen($name) > 30) + { + $error[] = $user->lang[$l_type . '_ERR_NAME_LONG']; + } + + if (utf8_strlen($copyright) > 60) + { + $error[] = $user->lang[$l_type . '_ERR_COPY_LONG']; + } + } + } + + if ($update && sizeof($error)) + { + $style_row = array_merge($style_row, array( + 'template_id' => $template_id, + 'theme_id' => $theme_id, + 'imageset_id' => $imageset_id, + 'style_active' => $style_active, + $mode . '_storedb' => $store_db, + $mode . '_name' => $name, + $mode . '_copyright' => $copyright) + ); + } + + // User has submitted form and no errors have occurred + if ($update && !sizeof($error)) + { + $sql_ary = array( + $mode . '_name' => $name, + $mode . '_copyright' => $copyright + ); + + switch ($mode) + { + case 'style': + + $sql_ary += array( + 'template_id' => (int) $template_id, + 'theme_id' => (int) $theme_id, + 'imageset_id' => (int) $imageset_id, + 'style_active' => (int) $style_active, + ); + break; + + case 'imageset': + break; + + case 'theme': + + if ($style_row['theme_storedb'] != $store_db) + { + $theme_data = ''; + + if (!$style_row['theme_storedb']) + { + $theme_data = $this->db_theme_data($style_row); + } + else if (!$store_db && !$safe_mode && @is_writable("{$phpbb_root_path}styles/{$style_row['theme_path']}/theme/stylesheet.css")) + { + $store_db = 1; + $theme_data = $style_row['theme_data']; + + if ($fp = @fopen("{$phpbb_root_path}styles/{$style_row['theme_path']}/theme/stylesheet.css", 'wb')) + { + $store_db = (@fwrite($fp, str_replace("styles/{$style_row['theme_path']}/theme/", './', $theme_data))) ? 0 : 1; + } + fclose($fp); + } + + $sql_ary += array( + 'theme_mtime' => ($store_db) ? filemtime("{$phpbb_root_path}styles/{$style_row['theme_path']}/theme/stylesheet.css") : 0, + 'theme_storedb' => $store_db, + 'theme_data' => ($store_db) ? $theme_data : '', + ); + } + break; + + case 'template': + + if ($style_row['template_storedb'] != $store_db) + { + if ($super = $this->get_super($mode, $style_row['template_id'])) + { + $error[] = (sprintf($user->lang["{$l_type}_INHERITS"], $super['template_name'])); + $sql_ary = array(); + } + else + { + if (!$store_db && !$safe_mode && @is_writable("{$phpbb_root_path}styles/{$style_row['template_path']}/template")) + { + $err = $this->store_in_fs('template', $style_row['template_id']); + if ($err) + { + $error += $err; + } + } + else if ($store_db) + { + $this->store_in_db('template', $style_row['template_id']); + } + else + { + // We no longer store within the db, but are also not able to update the file structure + // Since the admin want to switch this, we adhere to his decision. But we also need to remove the cache + $sql = 'DELETE FROM ' . STYLES_TEMPLATE_DATA_TABLE . " + WHERE template_id = $style_id"; + $db->sql_query($sql); + } + + $sql_ary += array( + 'template_storedb' => $store_db, + ); + } + } + break; + } + + if (sizeof($sql_ary)) + { + $sql = "UPDATE $sql_from + SET " . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE {$mode}_id = $style_id"; + $db->sql_query($sql); + + // Making this the default style? + if ($mode == 'style' && $style_default) + { + set_config('default_style', $style_id); + } + } + + $cache->destroy('sql', STYLES_TABLE); + + add_log('admin', 'LOG_' . $l_type . '_EDIT_DETAILS', $name); + if (sizeof($error)) + { + trigger_error(implode('<br />', $error) . adm_back_link($this->u_action), E_USER_WARNING); + } + else + { + trigger_error($user->lang[$l_type . '_DETAILS_UPDATED'] . adm_back_link($this->u_action)); + } + } + + if ($mode == 'style') + { + foreach ($element_ary as $element => $table) + { + $sql = "SELECT {$element}_id, {$element}_name + FROM $table + ORDER BY {$element}_id ASC"; + $result = $db->sql_query($sql); + + ${$element . '_options'} = ''; + while ($row = $db->sql_fetchrow($result)) + { + $selected = ($row[$element . '_id'] == $style_row[$element . '_id']) ? ' selected="selected"' : ''; + ${$element . '_options'} .= '<option value="' . $row[$element . '_id'] . '"' . $selected . '>' . $row[$element . '_name'] . '</option>'; + } + $db->sql_freeresult($result); + } + } + + if ($mode == 'template') + { + $super = array(); + if (isset($style_row[$mode . '_inherits_id']) && $style_row['template_inherits_id']) + { + $super = $this->get_super($mode, $style_row['template_id']); + } + } + + $this->page_title = 'EDIT_DETAILS_' . $l_type; + + $template->assign_vars(array( + 'S_DETAILS' => true, + 'S_ERROR_MSG' => (sizeof($error)) ? true : false, + 'S_STYLE' => ($mode == 'style') ? true : false, + 'S_TEMPLATE' => ($mode == 'template') ? true : false, + 'S_THEME' => ($mode == 'theme') ? true : false, + 'S_IMAGESET' => ($mode == 'imageset') ? true : false, + 'S_STORE_DB' => (isset($style_row[$mode . '_storedb'])) ? $style_row[$mode . '_storedb'] : 0, + 'S_STORE_DB_DISABLED' => (isset($style_row[$mode . '_inherits_id'])) ? $style_row[$mode . '_inherits_id'] : 0, + 'S_STYLE_ACTIVE' => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0, + 'S_STYLE_DEFAULT' => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0, + 'S_SUPERTEMPLATE' => (isset($style_row[$mode . '_inherits_id']) && $style_row[$mode . '_inherits_id']) ? $super['template_name'] : 0, + + 'S_TEMPLATE_OPTIONS' => ($mode == 'style') ? $template_options : '', + 'S_THEME_OPTIONS' => ($mode == 'style') ? $theme_options : '', + 'S_IMAGESET_OPTIONS' => ($mode == 'style') ? $imageset_options : '', + + 'U_ACTION' => $this->u_action . '&action=details&id=' . $style_id, + 'U_BACK' => $this->u_action, + + 'L_TITLE' => $user->lang[$this->page_title], + 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], + 'L_NAME' => $user->lang[$l_type . '_NAME'], + 'L_LOCATION' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION'] : '', + 'L_LOCATION_EXPLAIN' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION_EXPLAIN'] : '', + + 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + 'NAME' => $style_row[$mode . '_name'], + 'COPYRIGHT' => $style_row[$mode . '_copyright'], + ) + ); + } + + /** + * Load css file contents + */ + function load_css_file($path, $filename) + { + global $phpbb_root_path; + + $file = "{$phpbb_root_path}styles/$path/theme/$filename"; + + if (file_exists($file) && ($content = file_get_contents($file))) + { + $content = trim($content); + } + else + { + $content = ''; + } + if (defined('DEBUG')) + { + $content = "/* BEGIN @include $filename */ \n $content \n /* END @include $filename */ \n"; + } + + return $content; + } + + /** + * Returns a string containing the value that should be used for the theme_data column in the theme database table. + * Includes contents of files loaded via @import + * + * @param array $theme_row is an associative array containing the theme's current database entry + * @param mixed $stylesheet can either be the new content for the stylesheet or false to load from the standard file + * @param string $root_path should only be used in case you want to use a different root path than "{$phpbb_root_path}styles/{$theme_row['theme_path']}" + * + * @return string Stylesheet data for theme_data column in the theme table + */ + function db_theme_data($theme_row, $stylesheet = false, $root_path = '') + { + global $phpbb_root_path; + + if (!$root_path) + { + $root_path = $phpbb_root_path . 'styles/' . $theme_row['theme_path']; + } + + if (!$stylesheet) + { + $stylesheet = ''; + if (file_exists($root_path . '/theme/stylesheet.css')) + { + $stylesheet = file_get_contents($root_path . '/theme/stylesheet.css'); + } + } + + // Match CSS imports + $matches = array(); + preg_match_all('/@import url\(["\'](.*)["\']\);/i', $stylesheet, $matches); + + if (sizeof($matches)) + { + foreach ($matches[0] as $idx => $match) + { + $stylesheet = str_replace($match, acp_styles::load_css_file($theme_row['theme_path'], $matches[1][$idx]), $stylesheet); + } + } + + // adjust paths + return str_replace('./', 'styles/' . $theme_row['theme_path'] . '/theme/', $stylesheet); + } + + /** + * Store template files into db + */ + function store_templates($mode, $style_id, $template_path, $filelist) + { + global $phpbb_root_path, $phpEx, $db; + + $template_path = $template_path . '/template/'; + $includes = array(); + foreach ($filelist as $pathfile => $file_ary) + { + foreach ($file_ary as $file) + { + if (!($fp = @fopen("{$phpbb_root_path}styles/$template_path$pathfile$file", 'r'))) + { + trigger_error("Could not open {$phpbb_root_path}styles/$template_path$pathfile$file", E_USER_ERROR); + } + + $filesize = filesize("{$phpbb_root_path}styles/$template_path$pathfile$file"); + + if ($filesize) + { + $template_data = fread($fp, $filesize); + } + + fclose($fp); + + if (!$filesize) + { + // File is empty + continue; + } + + if (preg_match_all('#<!-- INCLUDE (.*?\.html) -->#is', $template_data, $matches)) + { + foreach ($matches[1] as $match) + { + $includes[trim($match)][] = $file; + } + } + } + } + + foreach ($filelist as $pathfile => $file_ary) + { + foreach ($file_ary as $file) + { + // Skip index. + if (strpos($file, 'index.') === 0) + { + continue; + } + + // We could do this using extended inserts ... but that could be one + // heck of a lot of data ... + $sql_ary = array( + 'template_id' => (int) $style_id, + 'template_filename' => "$pathfile$file", + 'template_included' => (isset($includes[$file])) ? implode(':', $includes[$file]) . ':' : '', + 'template_mtime' => (int) filemtime("{$phpbb_root_path}styles/$template_path$pathfile$file"), + 'template_data' => (string) file_get_contents("{$phpbb_root_path}styles/$template_path$pathfile$file"), + ); + + if ($mode == 'insert') + { + $sql = 'INSERT INTO ' . STYLES_TEMPLATE_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); + } + else + { + $sql = 'UPDATE ' . STYLES_TEMPLATE_DATA_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE template_id = $style_id + AND template_filename = '" . $db->sql_escape("$pathfile$file") . "'"; + } + $db->sql_query($sql); + } + } + } + + /** + * Returns an array containing all template filenames for one template that are currently cached. + * + * @param string $template_path contains the name of the template's folder in /styles/ + * + * @return array of filenames that exist in /styles/$template_path/template/ (without extension!) + */ + function template_cache_filelist($template_path) + { + global $phpbb_root_path, $phpEx, $user; + + $cache_prefix = 'tpl_' . str_replace('_', '-', $template_path); + + if (!($dp = @opendir("{$phpbb_root_path}cache"))) + { + trigger_error($user->lang['TEMPLATE_ERR_CACHE_READ'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $file_ary = array(); + while ($file = readdir($dp)) + { + if ($file[0] == '.') + { + continue; + } + + if (is_file($phpbb_root_path . 'cache/' . $file) && (strpos($file, $cache_prefix) === 0)) + { + $file_ary[] = str_replace('.', '/', preg_replace('#^' . preg_quote($cache_prefix, '#') . '_(.*?)\.html\.' . $phpEx . '$#i', '\1', $file)); + } + } + closedir($dp); + + return $file_ary; + } + + /** + * Destroys cached versions of template files + * + * @param array $template_row contains the template's row in the STYLES_TEMPLATE_TABLE database table + * @param mixed $file_ary is optional and may contain an array of template file names which should be refreshed in the cache. + * The file names should be the original template file names and not the cache file names. + */ + function clear_template_cache($template_row, $file_ary = false) + { + global $phpbb_root_path, $phpEx, $user; + + $cache_prefix = 'tpl_' . str_replace('_', '-', $template_row['template_path']); + + if (!$file_ary || !is_array($file_ary)) + { + $file_ary = $this->template_cache_filelist($template_row['template_path']); + $log_file_list = $user->lang['ALL_FILES']; + } + else + { + $log_file_list = implode(', ', $file_ary); + } + + foreach ($file_ary as $file) + { + $file = str_replace('/', '.', $file); + + $file = "{$phpbb_root_path}cache/{$cache_prefix}_$file.html.$phpEx"; + if (file_exists($file) && is_file($file)) + { + @unlink($file); + } + } + unset($file_ary); + + add_log('admin', 'LOG_TEMPLATE_CACHE_CLEARED', $template_row['template_name'], $log_file_list); + } + + /** + * Install Style/Template/Theme/Imageset + */ + function install($mode) + { + global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template; + + $l_type = strtoupper($mode); + + $error = $installcfg = $style_row = array(); + $root_path = $cfg_file = ''; + $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE, 'imageset' => STYLES_IMAGESET_TABLE); + + $install_path = request_var('path', ''); + $update = (isset($_POST['update'])) ? true : false; + + // Installing, obtain cfg file contents + if ($install_path) + { + $root_path = $phpbb_root_path . 'styles/' . $install_path . '/'; + $cfg_file = ($mode == 'style') ? "$root_path$mode.cfg" : "$root_path$mode/$mode.cfg"; + + if (!file_exists($cfg_file)) + { + $error[] = $user->lang[$l_type . '_ERR_NOT_' . $l_type]; + } + else + { + $installcfg = parse_cfg_file($cfg_file); + } + } + + // Installing + if (sizeof($installcfg)) + { + $name = $installcfg['name']; + $copyright = $installcfg['copyright']; + $version = $installcfg['version']; + + $style_row = array( + $mode . '_id' => 0, + $mode . '_name' => '', + $mode . '_copyright' => '' + ); + + switch ($mode) + { + case 'style': + + $style_row = array( + 'style_id' => 0, + 'style_name' => $installcfg['name'], + 'style_copyright' => $installcfg['copyright'] + ); + + $reqd_template = (isset($installcfg['required_template'])) ? $installcfg['required_template'] : false; + $reqd_theme = (isset($installcfg['required_theme'])) ? $installcfg['required_theme'] : false; + $reqd_imageset = (isset($installcfg['required_imageset'])) ? $installcfg['required_imageset'] : false; + + // Check to see if each element is already installed, if it is grab the id + foreach ($element_ary as $element => $table) + { + $style_row = array_merge($style_row, array( + $element . '_id' => 0, + $element . '_name' => '', + $element . '_copyright' => '') + ); + + $this->test_installed($element, $error, (${'reqd_' . $element}) ? $phpbb_root_path . 'styles/' . $reqd_template . '/' : $root_path, ${'reqd_' . $element}, $style_row[$element . '_id'], $style_row[$element . '_name'], $style_row[$element . '_copyright']); + + if (!$style_row[$element . '_name']) + { + $style_row[$element . '_name'] = $reqd_template; + } + + // Merge other information to installcfg... if present + $cfg_file = $phpbb_root_path . 'styles/' . $install_path . '/' . $element . '/' . $element . '.cfg'; + + if (file_exists($cfg_file)) + { + $cfg_contents = parse_cfg_file($cfg_file); + + // Merge only specific things. We may need them later. + foreach (array('inherit_from', 'parse_css_file') as $key) + { + if (!empty($cfg_contents[$key]) && !isset($installcfg[$key])) + { + $installcfg[$key] = $cfg_contents[$key]; + } + } + } + } + + break; + + case 'template': + $this->test_installed('template', $error, $root_path, false, $style_row['template_id'], $style_row['template_name'], $style_row['template_copyright']); + break; + + case 'theme': + $this->test_installed('theme', $error, $root_path, false, $style_row['theme_id'], $style_row['theme_name'], $style_row['theme_copyright']); + break; + + case 'imageset': + $this->test_installed('imageset', $error, $root_path, false, $style_row['imageset_id'], $style_row['imageset_name'], $style_row['imageset_copyright']); + break; + } + } + else + { + trigger_error($user->lang['NO_' . $l_type] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $style_row['store_db'] = request_var('store_db', 0); + $style_row['style_active'] = request_var('style_active', 1); + $style_row['style_default'] = request_var('style_default', 0); + + // User has submitted form and no errors have occurred + if ($update && !sizeof($error)) + { + if ($mode == 'style') + { + foreach ($element_ary as $element => $table) + { + ${$element . '_root_path'} = (${'reqd_' . $element}) ? $phpbb_root_path . 'styles/' . ${'reqd_' . $element} . '/' : false; + ${$element . '_path'} = (${'reqd_' . $element}) ? ${'reqd_' . $element} : false; + } + $this->install_style($error, 'install', $root_path, $style_row['style_id'], $style_row['style_name'], $install_path, $style_row['style_copyright'], $style_row['style_active'], $style_row['style_default'], $style_row, $template_root_path, $template_path, $theme_root_path, $theme_path, $imageset_root_path, $imageset_path); + } + else + { + $style_row['store_db'] = $this->install_element($mode, $error, 'install', $root_path, $style_row[$mode . '_id'], $style_row[$mode . '_name'], $install_path, $style_row[$mode . '_copyright'], $style_row['store_db']); + } + + if (!sizeof($error)) + { + $cache->destroy('sql', STYLES_TABLE); + + $message = ($style_row['store_db']) ? '_ADDED_DB' : '_ADDED'; + trigger_error($user->lang[$l_type . $message] . adm_back_link($this->u_action)); + } + } + + $this->page_title = 'INSTALL_' . $l_type; + + $template->assign_vars(array( + 'S_DETAILS' => true, + 'S_INSTALL' => true, + 'S_ERROR_MSG' => (sizeof($error)) ? true : false, + 'S_LOCATION' => (isset($installcfg['inherit_from']) && $installcfg['inherit_from']) ? false : true, + 'S_STYLE' => ($mode == 'style') ? true : false, + 'S_TEMPLATE' => ($mode == 'template') ? true : false, + 'S_SUPERTEMPLATE' => (isset($installcfg['inherit_from'])) ? $installcfg['inherit_from'] : '', + 'S_THEME' => ($mode == 'theme') ? true : false, + + 'S_STORE_DB' => (isset($style_row[$mode . '_storedb'])) ? $style_row[$mode . '_storedb'] : 0, + 'S_STYLE_ACTIVE' => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0, + 'S_STYLE_DEFAULT' => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0, + + 'U_ACTION' => $this->u_action . "&action=install&path=" . urlencode($install_path), + 'U_BACK' => $this->u_action, + + 'L_TITLE' => $user->lang[$this->page_title], + 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], + 'L_NAME' => $user->lang[$l_type . '_NAME'], + 'L_LOCATION' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION'] : '', + 'L_LOCATION_EXPLAIN' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION_EXPLAIN'] : '', + + 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + 'NAME' => $style_row[$mode . '_name'], + 'COPYRIGHT' => $style_row[$mode . '_copyright'], + 'TEMPLATE_NAME' => ($mode == 'style') ? $style_row['template_name'] : '', + 'THEME_NAME' => ($mode == 'style') ? $style_row['theme_name'] : '', + 'IMAGESET_NAME' => ($mode == 'style') ? $style_row['imageset_name'] : '') + ); + } + + /** + * Add new style + */ + function add($mode) + { + global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template; + + $l_type = strtoupper($mode); + $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE, 'imageset' => STYLES_IMAGESET_TABLE); + $error = array(); + + $style_row = array( + $mode . '_name' => utf8_normalize_nfc(request_var('name', '', true)), + $mode . '_copyright' => utf8_normalize_nfc(request_var('copyright', '', true)), + 'template_id' => 0, + 'theme_id' => 0, + 'imageset_id' => 0, + 'store_db' => request_var('store_db', 0), + 'style_active' => request_var('style_active', 1), + 'style_default' => request_var('style_default', 0), + ); + + $basis = request_var('basis', 0); + $update = (isset($_POST['update'])) ? true : false; + + if ($basis) + { + switch ($mode) + { + case 'style': + $sql_select = 'template_id, theme_id, imageset_id'; + $sql_from = STYLES_TABLE; + break; + + case 'template': + $sql_select = 'template_id'; + $sql_from = STYLES_TEMPLATE_TABLE; + break; + + case 'theme': + $sql_select = 'theme_id'; + $sql_from = STYLES_THEME_TABLE; + break; + + case 'imageset': + $sql_select = 'imageset_id'; + $sql_from = STYLES_IMAGESET_TABLE; + break; + } + + $sql = "SELECT $sql_select + FROM $sql_from + WHERE {$mode}_id = $basis"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + $error[] = $user->lang['NO_' . $l_type]; + } + + if (!sizeof($error)) + { + $style_row['template_id'] = (isset($row['template_id'])) ? $row['template_id'] : $style_row['template_id']; + $style_row['theme_id'] = (isset($row['theme_id'])) ? $row['theme_id'] : $style_row['theme_id']; + $style_row['imageset_id'] = (isset($row['imageset_id'])) ? $row['imageset_id'] : $style_row['imageset_id']; + } + } + + if ($update) + { + $style_row['template_id'] = request_var('template_id', $style_row['template_id']); + $style_row['theme_id'] = request_var('theme_id', $style_row['theme_id']); + $style_row['imageset_id'] = request_var('imageset_id', $style_row['imageset_id']); + + if ($mode == 'style' && (!$style_row['template_id'] || !$style_row['theme_id'] || !$style_row['imageset_id'])) + { + $error[] = $user->lang['STYLE_ERR_NO_IDS']; + } + } + + // User has submitted form and no errors have occurred + if ($update && !sizeof($error)) + { + if ($mode == 'style') + { + $style_row['style_id'] = 0; + + $this->install_style($error, 'add', '', $style_row['style_id'], $style_row['style_name'], '', $style_row['style_copyright'], $style_row['style_active'], $style_row['style_default'], $style_row); + } + + if (!sizeof($error)) + { + $cache->destroy('sql', STYLES_TABLE); + + $message = ($style_row['store_db']) ? '_ADDED_DB' : '_ADDED'; + trigger_error($user->lang[$l_type . $message] . adm_back_link($this->u_action)); + } + } + + if ($mode == 'style') + { + foreach ($element_ary as $element => $table) + { + $sql = "SELECT {$element}_id, {$element}_name + FROM $table + ORDER BY {$element}_id ASC"; + $result = $db->sql_query($sql); + + ${$element . '_options'} = ''; + while ($row = $db->sql_fetchrow($result)) + { + $selected = ($row[$element . '_id'] == $style_row[$element . '_id']) ? ' selected="selected"' : ''; + ${$element . '_options'} .= '<option value="' . $row[$element . '_id'] . '"' . $selected . '>' . $row[$element . '_name'] . '</option>'; + } + $db->sql_freeresult($result); + } + } + + $this->page_title = 'ADD_' . $l_type; + + $template->assign_vars(array( + 'S_DETAILS' => true, + 'S_ADD' => true, + 'S_ERROR_MSG' => (sizeof($error)) ? true : false, + 'S_STYLE' => ($mode == 'style') ? true : false, + 'S_TEMPLATE' => ($mode == 'template') ? true : false, + 'S_THEME' => ($mode == 'theme') ? true : false, + 'S_BASIS' => ($basis) ? true : false, + + 'S_STORE_DB' => (isset($style_row['storedb'])) ? $style_row['storedb'] : 0, + 'S_STYLE_ACTIVE' => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0, + 'S_STYLE_DEFAULT' => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0, + 'S_TEMPLATE_OPTIONS' => ($mode == 'style') ? $template_options : '', + 'S_THEME_OPTIONS' => ($mode == 'style') ? $theme_options : '', + 'S_IMAGESET_OPTIONS' => ($mode == 'style') ? $imageset_options : '', + + 'U_ACTION' => $this->u_action . '&action=add&basis=' . $basis, + 'U_BACK' => $this->u_action, + + 'L_TITLE' => $user->lang[$this->page_title], + 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], + 'L_NAME' => $user->lang[$l_type . '_NAME'], + 'L_LOCATION' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION'] : '', + 'L_LOCATION_EXPLAIN' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION_EXPLAIN'] : '', + + 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + 'NAME' => $style_row[$mode . '_name'], + 'COPYRIGHT' => $style_row[$mode . '_copyright']) + ); + + } + + /** + + $reqd_template = (isset($installcfg['required_template'])) ? $installcfg['required_template'] : false; + $reqd_theme = (isset($installcfg['required_theme'])) ? $installcfg['required_theme'] : false; + $reqd_imageset = (isset($installcfg['required_imageset'])) ? $installcfg['required_imageset'] : false; + + // Check to see if each element is already installed, if it is grab the id + foreach ($element_ary as $element => $table) + { + $style_row = array_merge($style_row, array( + $element . '_id' => 0, + $element . '_name' => '', + $element . '_copyright' => '') + ); + + $this->test_installed($element, $error, $root_path, ${'reqd_' . $element}, $style_row[$element . '_id'], $style_row[$element . '_name'], $style_row[$element . '_copyright']); + * Is this element installed? If not, grab its cfg details + */ + function test_installed($element, &$error, $root_path, $reqd_name, &$id, &$name, &$copyright) + { + global $db, $user; + + switch ($element) + { + case 'template': + $sql_from = STYLES_TEMPLATE_TABLE; + break; + + case 'theme': + $sql_from = STYLES_THEME_TABLE; + break; + + case 'imageset': + $sql_from = STYLES_IMAGESET_TABLE; + break; + } + + $l_element = strtoupper($element); + + $chk_name = ($reqd_name !== false) ? $reqd_name : $name; + + $sql = "SELECT {$element}_id, {$element}_name + FROM $sql_from + WHERE {$element}_name = '" . $db->sql_escape($chk_name) . "'"; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + $name = $row[$element . '_name']; + $id = $row[$element . '_id']; + } + else + { + if (!($cfg = @file("$root_path$element/$element.cfg"))) + { + $error[] = sprintf($user->lang['REQUIRES_' . $l_element], $reqd_name); + return false; + } + + $cfg = parse_cfg_file("$root_path$element/$element.cfg", $cfg); + + $name = $cfg['name']; + $copyright = $cfg['copyright']; + $id = 0; + + unset($cfg); + } + $db->sql_freeresult($result); + } + + /** + * Install/Add style + */ + function install_style(&$error, $action, $root_path, &$id, $name, $path, $copyright, $active, $default, &$style_row, $template_root_path = false, $template_path = false, $theme_root_path = false, $theme_path = false, $imageset_root_path = false, $imageset_path = false) + { + global $config, $db, $user; + + $element_ary = array('template', 'theme', 'imageset'); + + if (!$name) + { + $error[] = $user->lang['STYLE_ERR_STYLE_NAME']; + } + + // Check length settings + if (utf8_strlen($name) > 30) + { + $error[] = $user->lang['STYLE_ERR_NAME_LONG']; + } + + if (utf8_strlen($copyright) > 60) + { + $error[] = $user->lang['STYLE_ERR_COPY_LONG']; + } + + // Check if the name already exist + $sql = 'SELECT style_id + FROM ' . STYLES_TABLE . " + WHERE style_name = '" . $db->sql_escape($name) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + $error[] = $user->lang['STYLE_ERR_NAME_EXIST']; + } + + if (sizeof($error)) + { + return false; + } + + foreach ($element_ary as $element) + { + // Zero id value ... need to install element ... run usual checks + // and do the install if necessary + if (!$style_row[$element . '_id']) + { + $this->install_element($element, $error, $action, (${$element . '_root_path'}) ? ${$element . '_root_path'} : $root_path, $style_row[$element . '_id'], $style_row[$element . '_name'], (${$element . '_path'}) ? ${$element . '_path'} : $path, $style_row[$element . '_copyright']); + } + } + + if (!$style_row['template_id'] || !$style_row['theme_id'] || !$style_row['imageset_id']) + { + $error[] = $user->lang['STYLE_ERR_NO_IDS']; + } + + if (sizeof($error)) + { + return false; + } + + $db->sql_transaction('begin'); + + $sql_ary = array( + 'style_name' => $name, + 'style_copyright' => $copyright, + 'style_active' => (int) $active, + 'template_id' => (int) $style_row['template_id'], + 'theme_id' => (int) $style_row['theme_id'], + 'imageset_id' => (int) $style_row['imageset_id'], + ); + + $sql = 'INSERT INTO ' . STYLES_TABLE . ' + ' . $db->sql_build_array('INSERT', $sql_ary); + $db->sql_query($sql); + + $id = $db->sql_nextid(); + + if ($default) + { + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_style = $id + WHERE user_style = " . $config['default_style']; + $db->sql_query($sql); + + set_config('default_style', $id); + } + + $db->sql_transaction('commit'); + + add_log('admin', 'LOG_STYLE_ADD', $name); + } + + /** + * Install/add an element, doing various checks as we go + */ + function install_element($mode, &$error, $action, $root_path, &$id, $name, $path, $copyright, $store_db = 0) + { + global $phpbb_root_path, $db, $user; + + // we parse the cfg here (again) + $cfg_data = parse_cfg_file("$root_path$mode/$mode.cfg"); + + switch ($mode) + { + case 'template': + $sql_from = STYLES_TEMPLATE_TABLE; + break; + + case 'theme': + $sql_from = STYLES_THEME_TABLE; + break; + + case 'imageset': + $sql_from = STYLES_IMAGESET_TABLE; + break; + } + + $l_type = strtoupper($mode); + + if (!$name) + { + $error[] = $user->lang[$l_type . '_ERR_STYLE_NAME']; + } + + // Check length settings + if (utf8_strlen($name) > 30) + { + $error[] = $user->lang[$l_type . '_ERR_NAME_LONG']; + } + + if (utf8_strlen($copyright) > 60) + { + $error[] = $user->lang[$l_type . '_ERR_COPY_LONG']; + } + + // Check if the name already exist + $sql = "SELECT {$mode}_id + FROM $sql_from + WHERE {$mode}_name = '" . $db->sql_escape($name) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + // If it exist, we just use the style on installation + if ($action == 'install') + { + $id = $row[$mode . '_id']; + return false; + } + + $error[] = $user->lang[$l_type . '_ERR_NAME_EXIST']; + } + + if (isset($cfg_data['inherit_from']) && $cfg_data['inherit_from']) + { + if ($mode === 'template') + { + $select_bf = ', bbcode_bitfield'; + } + else + { + $select_bf = ''; + } + + $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path, {$mode}_storedb $select_bf + FROM $sql_from + WHERE {$mode}_name = '" . $db->sql_escape($cfg_data['inherit_from']) . "' + AND {$mode}_inherits_id = 0"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + if (!$row) + { + $error[] = sprintf($user->lang[$l_type . '_ERR_REQUIRED_OR_INCOMPLETE'], $cfg_data['inherit_from']); + } + else + { + $inherit_id = $row["{$mode}_id"]; + $inherit_path = $row["{$mode}_path"]; + $inherit_bf = ($mode === 'template') ? $row["bbcode_bitfield"] : false; + $cfg_data['store_db'] = $row["{$mode}_storedb"]; + $store_db = $row["{$mode}_storedb"]; + } + } + else + { + $inherit_id = 0; + $inherit_path = ''; + $inherit_bf = false; + } + + if (sizeof($error)) + { + return false; + } + + $sql_ary = array( + $mode . '_name' => $name, + $mode . '_copyright' => $copyright, + $mode . '_path' => $path, + ); + + switch ($mode) + { + case 'template': + // We check if the template author defined a different bitfield + if (!empty($cfg_data['template_bitfield'])) + { + $sql_ary['bbcode_bitfield'] = $cfg_data['template_bitfield']; + } + else if ($inherit_bf) + { + $sql_ary['bbcode_bitfield'] = $inherit_bf; + } + else + { + $sql_ary['bbcode_bitfield'] = TEMPLATE_BITFIELD; + } + + // We set a pre-defined bitfield here which we may use further in 3.2 + $sql_ary += array( + 'template_storedb' => $store_db, + ); + if (isset($cfg_data['inherit_from']) && $cfg_data['inherit_from']) + { + $sql_ary += array( + 'template_inherits_id' => $inherit_id, + 'template_inherit_path' => $inherit_path, + ); + } + break; + + case 'theme': + // We are only interested in the theme configuration for now + + if (isset($cfg_data['parse_css_file']) && $cfg_data['parse_css_file']) + { + $store_db = 1; + } + + $sql_ary += array( + 'theme_storedb' => $store_db, + 'theme_data' => ($store_db) ? $this->db_theme_data($sql_ary, false, $root_path) : '', + 'theme_mtime' => (int) filemtime("{$phpbb_root_path}styles/$path/theme/stylesheet.css") + ); + break; + + // all the heavy lifting is done later + case 'imageset': + break; + } + + $db->sql_transaction('begin'); + + $sql = "INSERT INTO $sql_from + " . $db->sql_build_array('INSERT', $sql_ary); + $db->sql_query($sql); + + $id = $db->sql_nextid(); + + if ($mode == 'template' && $store_db) + { + $filelist = filelist("{$root_path}template", '', 'html'); + $this->store_templates('insert', $id, $path, $filelist); + } + else if ($mode == 'imageset') + { + $cfg_data = parse_cfg_file("$root_path$mode/imageset.cfg"); + + $imageset_definitions = array(); + foreach ($this->imageset_keys as $topic => $key_array) + { + $imageset_definitions = array_merge($imageset_definitions, $key_array); + } + + foreach ($cfg_data as $key => $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($key, 'img_') === 0 && $image_filename) + { + $key = substr($key, 4); + if (in_array($key, $imageset_definitions)) + { + $sql_ary = array( + 'image_name' => $key, + 'image_filename' => str_replace('{PATH}', "styles/$path/imageset/", trim($image_filename)), + 'image_height' => (int) $image_height, + 'image_width' => (int) $image_width, + 'imageset_id' => (int) $id, + 'image_lang' => '', + ); + $db->sql_query('INSERT INTO ' . STYLES_IMAGESET_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + } + } + } + unset($cfg_data); + + $sql = 'SELECT lang_dir + FROM ' . LANG_TABLE; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if (@file_exists("$root_path$mode/{$row['lang_dir']}/imageset.cfg")) + { + $cfg_data_imageset_data = parse_cfg_file("$root_path$mode/{$row['lang_dir']}/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); + if (in_array($image_name, $imageset_definitions)) + { + $sql_ary = array( + 'image_name' => $image_name, + 'image_filename' => $image_filename, + 'image_height' => (int) $image_height, + 'image_width' => (int) $image_width, + 'imageset_id' => (int) $id, + 'image_lang' => $row['lang_dir'], + ); + $db->sql_query('INSERT INTO ' . STYLES_IMAGESET_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + } + } + } + unset($cfg_data_imageset_data); + } + } + $db->sql_freeresult($result); + } + + $db->sql_transaction('commit'); + + $log = ($store_db) ? 'LOG_' . $l_type . '_ADD_DB' : 'LOG_' . $l_type . '_ADD_FS'; + add_log('admin', $log, $name); + + // Return store_db in case it had to be altered + return $store_db; + } + + /** + * Checks downwards dependencies + * + * @access public + * @param string $mode The element type to check - only template is supported + * @param int $id The template id + * @returns false if no component inherits, array with name, path and id for each subtemplate otherwise + */ + function check_inheritance($mode, $id) + { + global $db; + + $l_type = strtoupper($mode); + + switch ($mode) + { + case 'template': + $sql_from = STYLES_TEMPLATE_TABLE; + break; + + case 'theme': + $sql_from = STYLES_THEME_TABLE; + break; + + case 'imageset': + $sql_from = STYLES_IMAGESET_TABLE; + break; + } + + $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path + FROM $sql_from + WHERE {$mode}_inherits_id = " . (int) $id; + $result = $db->sql_query($sql); + + $names = array(); + while ($row = $db->sql_fetchrow($result)) + { + + $names[$row["{$mode}_id"]] = array( + "{$mode}_id" => $row["{$mode}_id"], + "{$mode}_name" => $row["{$mode}_name"], + "{$mode}_path" => $row["{$mode}_path"], + ); + } + $db->sql_freeresult($result); + + if (sizeof($names)) + { + return $names; + } + else + { + return false; + } + } + + /** + * Checks upwards dependencies + * + * @access public + * @param string $mode The element type to check - only template is supported + * @param int $id The template id + * @returns false if the component does not inherit, array with name, path and id otherwise + */ + function get_super($mode, $id) + { + global $db; + + $l_type = strtoupper($mode); + + switch ($mode) + { + case 'template': + $sql_from = STYLES_TEMPLATE_TABLE; + break; + + case 'theme': + $sql_from = STYLES_THEME_TABLE; + break; + + case 'imageset': + $sql_from = STYLES_IMAGESET_TABLE; + break; + } + + $sql = "SELECT {$mode}_inherits_id + FROM $sql_from + WHERE {$mode}_id = " . (int) $id; + $result = $db->sql_query_limit($sql, 1); + + if ($row = $db->sql_fetchrow($result)) + { + $db->sql_freeresult($result); + } + else + { + return false; + } + + $super_id = $row["{$mode}_inherits_id"]; + + $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path + FROM $sql_from + WHERE {$mode}_id = " . (int) $super_id; + + $result = $db->sql_query_limit($sql, 1); + if ($row = $db->sql_fetchrow($result)) + { + $db->sql_freeresult($result); + return $row; + } + + return false; + } + + /** + * Moves a template set and its subtemplates to the database + * + * @access public + * @param string $mode The component to move - only template is supported + * @param int $id The template id + */ + function store_in_db($mode, $id) + { + global $db, $user; + + $error = array(); + $l_type = strtoupper($mode); + if ($super = $this->get_super($mode, $id)) + { + $error[] = (sprintf($user->lang["{$l_type}_INHERITS"], $super['template_name'])); + return $error; + } + + $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path + FROM " . STYLES_TEMPLATE_TABLE . ' + WHERE template_id = ' . (int) $id; + + $result = $db->sql_query_limit($sql, 1); + if ($row = $db->sql_fetchrow($result)) + { + $db->sql_freeresult($result); + $subs = $this->check_inheritance($mode, $id); + + $this->_store_in_db($mode, $id, $row["{$mode}_path"]); + if ($subs && sizeof($subs)) + { + foreach ($subs as $sub_id => $sub) + { + if ($err = $this->_store_in_db($mode, $sub["{$mode}_id"], $sub["{$mode}_path"])) + { + $error[] = $err; + } + } + } + } + if (sizeof($error)) + { + return $error; + } + + return false; + } + + /** + * Moves a template set to the database + * + * @access private + * @param string $mode The component to move - only template is supported + * @param int $id The template id + * @param string $path TThe path to the template files + */ + function _store_in_db($mode, $id, $path) + { + global $phpbb_root_path, $db; + + $filelist = filelist("{$phpbb_root_path}styles/{$path}/template", '', 'html'); + $this->store_templates('insert', $id, $path, $filelist); + + // Okay, we do the query here -shouldn't be triggered often. + $sql = 'UPDATE ' . STYLES_TEMPLATE_TABLE . ' + SET template_storedb = 1 + WHERE template_id = ' . $id; + $db->sql_query($sql); + } + + /** + * Moves a template set and its subtemplates to the filesystem + * + * @access public + * @param string $mode The component to move - only template is supported + * @param int $id The template id + */ + function store_in_fs($mode, $id) + { + global $db, $user; + + $error = array(); + $l_type = strtoupper($mode); + if ($super = $this->get_super($mode, $id)) + { + $error[] = (sprintf($user->lang["{$l_type}_INHERITS"], $super['template_name'])); + return($error); + } + + $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path + FROM " . STYLES_TEMPLATE_TABLE . ' + WHERE template_id = ' . (int) $id; + + $result = $db->sql_query_limit($sql, 1); + if ($row = $db->sql_fetchrow($result)) + { + $db->sql_freeresult($result); + if (!sizeof($error)) + { + $subs = $this->check_inheritance($mode, $id); + + $this->_store_in_fs($mode, $id, $row["{$mode}_path"]); + + if ($subs && sizeof($subs)) + { + foreach ($subs as $sub_id => $sub) + { + $this->_store_in_fs($mode, $sub["{$mode}_id"], $sub["{$mode}_path"]); + } + } + } + if (sizeof($error)) + { + $this->store_in_db($id, $mode); + return $error; + } + } + return false; + } + + /** + * Moves a template set to the filesystem + * + * @access private + * @param string $mode The component to move - only template is supported + * @param int $id The template id + * @param string $path The path to the template + */ + function _store_in_fs($mode, $id, $path) + { + global $phpbb_root_path, $db, $user, $safe_mode; + + $store_db = 0; + $error = array(); + if (!$safe_mode && @is_writable("{$phpbb_root_path}styles/{$path}/template")) + { + $sql = 'SELECT * + FROM ' . STYLES_TEMPLATE_DATA_TABLE . " + WHERE template_id = $id"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if (!($fp = @fopen("{$phpbb_root_path}styles/{$path}/template/" . $row['template_filename'], 'wb'))) + { + $store_db = 1; + $error[] = $user->lang['EDIT_TEMPLATE_STORED_DB']; + break; + } + + fwrite($fp, $row['template_data']); + fclose($fp); + } + $db->sql_freeresult($result); + + if (!$store_db) + { + $sql = 'DELETE FROM ' . STYLES_TEMPLATE_DATA_TABLE . " + WHERE template_id = $id"; + $db->sql_query($sql); + } + } + if (sizeof($error)) + { + return $error; + } + $sql = 'UPDATE ' . STYLES_TEMPLATE_TABLE . ' + SET template_storedb = 0 + WHERE template_id = ' . $id; + $db->sql_query($sql); + + return false; + } + +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_update.php b/phpBB/includes/acp/acp_update.php new file mode 100644 index 0000000000..3204e0204e --- /dev/null +++ b/phpBB/includes/acp/acp_update.php @@ -0,0 +1,83 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_update +{ + var $u_action; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $cache; + global $phpbb_root_path, $phpbb_admin_path, $phpEx; + + $user->add_lang('install'); + + $this->tpl_name = 'acp_update'; + $this->page_title = 'ACP_VERSION_CHECK'; + + // Get current and latest version + $errstr = ''; + $errno = 0; + + $info = obtain_latest_version_info(request_var('versioncheck_force', false), true); + + if ($info === false) + { + trigger_error('VERSIONCHECK_FAIL', E_USER_WARNING); + } + + $info = explode("\n", $info); + $latest_version = trim($info[0]); + + $announcement_url = trim($info[1]); + $announcement_url = (strpos($announcement_url, '&') === false) ? str_replace('&', '&', $announcement_url) : $announcement_url; + $update_link = append_sid($phpbb_root_path . 'install/index.' . $phpEx, 'mode=update'); + + // Determine automatic update... + $sql = 'SELECT config_value + FROM ' . CONFIG_TABLE . " + WHERE config_name = 'version_update_from'"; + $result = $db->sql_query($sql); + $version_update_from = (string) $db->sql_fetchfield('config_value'); + $db->sql_freeresult($result); + + $current_version = (!empty($version_update_from)) ? $version_update_from : $config['version']; + + $up_to_date_automatic = (version_compare(str_replace('rc', 'RC', strtolower($current_version)), str_replace('rc', 'RC', strtolower($latest_version)), '<')) ? false : true; + $up_to_date = (version_compare(str_replace('rc', 'RC', strtolower($config['version'])), str_replace('rc', 'RC', strtolower($latest_version)), '<')) ? false : true; + + $template->assign_vars(array( + 'S_UP_TO_DATE' => $up_to_date, + 'S_UP_TO_DATE_AUTO' => $up_to_date_automatic, + 'S_VERSION_CHECK' => true, + 'U_ACTION' => $this->u_action, + 'U_VERSIONCHECK_FORCE' => append_sid($this->u_action . '&versioncheck_force=1'), + + 'LATEST_VERSION' => $latest_version, + 'CURRENT_VERSION' => $config['version'], + 'AUTO_VERSION' => $version_update_from, + + 'UPDATE_INSTRUCTIONS' => sprintf($user->lang['UPDATE_INSTRUCTIONS'], $announcement_url, $update_link), + )); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php new file mode 100644 index 0000000000..afca056eb2 --- /dev/null +++ b/phpBB/includes/acp/acp_users.php @@ -0,0 +1,2358 @@ +<?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; +} + +/** +* @package acp +*/ +class acp_users +{ + var $u_action; + var $p_master; + + function acp_users(&$p_master) + { + $this->p_master = &$p_master; + } + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $cache; + global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix, $file_uploads; + + $user->add_lang(array('posting', 'ucp', 'acp/users')); + $this->tpl_name = 'acp_users'; + $this->page_title = 'ACP_USER_' . strtoupper($mode); + + $error = array(); + $username = utf8_normalize_nfc(request_var('username', '', true)); + $user_id = request_var('u', 0); + $action = request_var('action', ''); + + $submit = (isset($_POST['update']) && !isset($_POST['cancel'])) ? true : false; + + $form_name = 'acp_users'; + add_form_key($form_name); + + // Whois (special case) + if ($action == 'whois') + { + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + + $this->page_title = 'WHOIS'; + $this->tpl_name = 'simple_body'; + + $user_ip = request_var('user_ip', ''); + $domain = gethostbyaddr($user_ip); + $ipwhois = user_ipwhois($user_ip); + + $template->assign_vars(array( + 'MESSAGE_TITLE' => sprintf($user->lang['IP_WHOIS_FOR'], $domain), + 'MESSAGE_TEXT' => nl2br($ipwhois)) + ); + + return; + } + + // Show user selection mask + if (!$username && !$user_id) + { + $this->page_title = 'SELECT_USER'; + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action, + 'ANONYMOUS_USER_ID' => ANONYMOUS, + + 'S_SELECT_USER' => true, + 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=select_user&field=username&select_single=true'), + )); + + return; + } + + if (!$user_id) + { + $sql = 'SELECT user_id + FROM ' . USERS_TABLE . " + WHERE username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'"; + $result = $db->sql_query($sql); + $user_id = (int) $db->sql_fetchfield('user_id'); + $db->sql_freeresult($result); + + if (!$user_id) + { + trigger_error($user->lang['NO_USER'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + + // Generate content for all modes + $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 = ' . $user_id . ' + ORDER BY s.session_time DESC'; + $result = $db->sql_query($sql); + $user_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$user_row) + { + trigger_error($user->lang['NO_USER'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Generate overall "header" for user admin + $s_form_options = ''; + + // Build modes dropdown list + $sql = 'SELECT module_mode, module_auth + FROM ' . MODULES_TABLE . " + WHERE module_basename = 'users' + AND module_enabled = 1 + AND module_class = 'acp' + ORDER BY left_id, module_mode"; + $result = $db->sql_query($sql); + + $dropdown_modes = array(); + while ($row = $db->sql_fetchrow($result)) + { + if (!$this->p_master->module_auth($row['module_auth'])) + { + continue; + } + + $dropdown_modes[$row['module_mode']] = true; + } + $db->sql_freeresult($result); + + foreach ($dropdown_modes as $module_mode => $null) + { + $selected = ($mode == $module_mode) ? ' selected="selected"' : ''; + $s_form_options .= '<option value="' . $module_mode . '"' . $selected . '>' . $user->lang['ACP_USER_' . strtoupper($module_mode)] . '</option>'; + } + + $template->assign_vars(array( + 'U_BACK' => $this->u_action, + 'U_MODE_SELECT' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&u=$user_id"), + 'U_ACTION' => $this->u_action . '&u=' . $user_id, + 'S_FORM_OPTIONS' => $s_form_options, + 'MANAGED_USERNAME' => $user_row['username']) + ); + + // Prevent normal users/admins change/view founders if they are not a founder by themselves + if ($user->data['user_type'] != USER_FOUNDER && $user_row['user_type'] == USER_FOUNDER) + { + trigger_error($user->lang['NOT_MANAGE_FOUNDER'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + switch ($mode) + { + case 'overview': + + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + + $user->add_lang('acp/ban'); + + $delete = request_var('delete', 0); + $delete_type = request_var('delete_type', ''); + $ip = request_var('ip', 'ip'); + + if ($submit) + { + // You can't delete the founder + if ($delete && $user_row['user_type'] != USER_FOUNDER) + { + if (!$auth->acl_get('a_userdel')) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + // Check if the user wants to remove himself or the guest user account + if ($user_id == ANONYMOUS) + { + trigger_error($user->lang['CANNOT_REMOVE_ANONYMOUS'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if ($user_id == $user->data['user_id']) + { + trigger_error($user->lang['CANNOT_REMOVE_YOURSELF'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if (confirm_box(true)) + { + user_delete($delete_type, $user_id, $user_row['username']); + + add_log('admin', 'LOG_USER_DELETED', $user_row['username']); + trigger_error($user->lang['USER_DELETED'] . adm_back_link($this->u_action)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'u' => $user_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'update' => true, + 'delete' => 1, + 'delete_type' => $delete_type)) + ); + } + } + + // Handle quicktool actions + switch ($action) + { + case 'banuser': + case 'banemail': + case 'banip': + + if ($user_id == $user->data['user_id']) + { + trigger_error($user->lang['CANNOT_BAN_YOURSELF'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if ($user_row['user_type'] == USER_FOUNDER) + { + trigger_error($user->lang['CANNOT_BAN_FOUNDER'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + $ban = array(); + + switch ($action) + { + case 'banuser': + $ban[] = $user_row['username']; + $reason = 'USER_ADMIN_BAN_NAME_REASON'; + $log = 'LOG_USER_BAN_USER'; + break; + + case 'banemail': + $ban[] = $user_row['user_email']; + $reason = 'USER_ADMIN_BAN_EMAIL_REASON'; + $log = 'LOG_USER_BAN_EMAIL'; + break; + + case 'banip': + $ban[] = $user_row['user_ip']; + + $sql = 'SELECT DISTINCT poster_ip + FROM ' . POSTS_TABLE . " + WHERE poster_id = $user_id"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $ban[] = $row['poster_ip']; + } + $db->sql_freeresult($result); + + $reason = 'USER_ADMIN_BAN_IP_REASON'; + $log = 'LOG_USER_BAN_IP'; + break; + } + + $ban_reason = utf8_normalize_nfc(request_var('ban_reason', $user->lang[$reason], true)); + $ban_give_reason = utf8_normalize_nfc(request_var('ban_give_reason', '', true)); + + // Log not used at the moment, we simply utilize the ban function. + $result = user_ban(substr($action, 3), $ban, 0, 0, 0, $ban_reason, $ban_give_reason); + + trigger_error((($result === false) ? $user->lang['BAN_ALREADY_ENTERED'] : $user->lang['BAN_SUCCESSFUL']) . adm_back_link($this->u_action . '&u=' . $user_id)); + + break; + + case 'reactivate': + + if ($user_id == $user->data['user_id']) + { + trigger_error($user->lang['CANNOT_FORCE_REACT_YOURSELF'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if ($user_row['user_type'] == USER_FOUNDER) + { + trigger_error($user->lang['CANNOT_FORCE_REACT_FOUNDER'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if ($user_row['user_type'] == USER_IGNORE) + { + trigger_error($user->lang['CANNOT_FORCE_REACT_BOT'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if ($config['email_enable']) + { + include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + + $server_url = generate_board_url(); + + $user_actkey = gen_rand_string(10); + $key_len = 54 - (strlen($server_url)); + $key_len = ($key_len > 6) ? $key_len : 6; + $user_actkey = substr($user_actkey, 0, $key_len); + $email_template = ($user_row['user_type'] == USER_NORMAL) ? 'user_reactivate_account' : 'user_resend_inactive'; + + if ($user_row['user_type'] == USER_NORMAL) + { + user_active_flip('deactivate', $user_id, INACTIVE_REMIND); + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_actkey = '" . $db->sql_escape($user_actkey) . "' + WHERE user_id = $user_id"; + $db->sql_query($sql); + } + else + { + // Grabbing the last confirm key - we only send a reminder + $sql = 'SELECT user_actkey + FROM ' . USERS_TABLE . ' + WHERE user_id = ' . $user_id; + $result = $db->sql_query($sql); + $user_actkey = (string) $db->sql_fetchfield('user_actkey'); + $db->sql_freeresult($result); + } + + $messenger = new messenger(false); + + $messenger->template($email_template, $user_row['user_lang']); + + $messenger->to($user_row['user_email'], $user_row['username']); + + $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); + $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); + $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); + $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + + $messenger->assign_vars(array( + 'WELCOME_MSG' => htmlspecialchars_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename'])), + 'USERNAME' => htmlspecialchars_decode($user_row['username']), + 'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k=$user_actkey") + ); + + $messenger->send(NOTIFY_EMAIL); + + add_log('admin', 'LOG_USER_REACTIVATE', $user_row['username']); + add_log('user', $user_id, 'LOG_USER_REACTIVATE_USER'); + + trigger_error($user->lang['FORCE_REACTIVATION_SUCCESS'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + + break; + + case 'active': + + if ($user_id == $user->data['user_id']) + { + // It is only deactivation since the user is already activated (else he would not have reached this page) + trigger_error($user->lang['CANNOT_DEACTIVATE_YOURSELF'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if ($user_row['user_type'] == USER_FOUNDER) + { + trigger_error($user->lang['CANNOT_DEACTIVATE_FOUNDER'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if ($user_row['user_type'] == USER_IGNORE) + { + trigger_error($user->lang['CANNOT_DEACTIVATE_BOT'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + user_active_flip('flip', $user_id); + + if ($user_row['user_type'] == USER_INACTIVE) + { + if ($config['require_activation'] == USER_ACTIVATION_ADMIN) + { + include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + + $messenger = new messenger(false); + + $messenger->template('admin_welcome_activated', $user_row['user_lang']); + + $messenger->to($user_row['user_email'], $user_row['username']); + + $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); + $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); + $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); + $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($user_row['username'])) + ); + + $messenger->send(NOTIFY_EMAIL); + } + } + + $message = ($user_row['user_type'] == USER_INACTIVE) ? 'USER_ADMIN_ACTIVATED' : 'USER_ADMIN_DEACTIVED'; + $log = ($user_row['user_type'] == USER_INACTIVE) ? 'LOG_USER_ACTIVE' : 'LOG_USER_INACTIVE'; + + add_log('admin', $log, $user_row['username']); + add_log('user', $user_id, $log . '_USER'); + + trigger_error($user->lang[$message] . adm_back_link($this->u_action . '&u=' . $user_id)); + + break; + + case 'delsig': + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + $sql_ary = array( + 'user_sig' => '', + 'user_sig_bbcode_uid' => '', + 'user_sig_bbcode_bitfield' => '' + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE user_id = $user_id"; + $db->sql_query($sql); + + add_log('admin', 'LOG_USER_DEL_SIG', $user_row['username']); + add_log('user', $user_id, 'LOG_USER_DEL_SIG_USER'); + + trigger_error($user->lang['USER_ADMIN_SIG_REMOVED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + + break; + + case 'delavatar': + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + $sql_ary = array( + 'user_avatar' => '', + 'user_avatar_type' => 0, + 'user_avatar_width' => 0, + 'user_avatar_height' => 0, + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE user_id = $user_id"; + $db->sql_query($sql); + + // Delete old avatar if present + if ($user_row['user_avatar'] && $user_row['user_avatar_type'] != AVATAR_GALLERY) + { + avatar_delete('user', $user_row); + } + + add_log('admin', 'LOG_USER_DEL_AVATAR', $user_row['username']); + add_log('user', $user_id, 'LOG_USER_DEL_AVATAR_USER'); + + trigger_error($user->lang['USER_ADMIN_AVATAR_REMOVED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + break; + + case 'delposts': + + if (confirm_box(true)) + { + // Delete posts, attachments, etc. + delete_posts('poster_id', $user_id); + + add_log('admin', 'LOG_USER_DEL_POSTS', $user_row['username']); + trigger_error($user->lang['USER_POSTS_DELETED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'u' => $user_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'update' => true)) + ); + } + + break; + + case 'delattach': + + if (confirm_box(true)) + { + delete_attachments('user', $user_id); + + add_log('admin', 'LOG_USER_DEL_ATTACH', $user_row['username']); + trigger_error($user->lang['USER_ATTACHMENTS_REMOVED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'u' => $user_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'update' => true)) + ); + } + + break; + + case 'deloutbox': + + if (confirm_box(true)) + { + $msg_ids = array(); + $lang = 'EMPTY'; + + $sql = 'SELECT msg_id + FROM ' . PRIVMSGS_TO_TABLE . " + WHERE author_id = $user_id + AND folder_id = " . PRIVMSGS_OUTBOX; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + if (!function_exists('delete_pm')) + { + include($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx); + } + + do + { + $msg_ids[] = (int) $row['msg_id']; + } + while ($row = $db->sql_fetchrow($result)); + + $db->sql_freeresult($result); + + delete_pm($user_id, $msg_ids, PRIVMSGS_OUTBOX); + + add_log('admin', 'LOG_USER_DEL_OUTBOX', $user_row['username']); + + $lang = 'EMPTIED'; + } + $db->sql_freeresult($result); + + trigger_error($user->lang['USER_OUTBOX_' . $lang] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'u' => $user_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'update' => true)) + ); + } + break; + + case 'moveposts': + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + $user->add_lang('acp/forums'); + + $new_forum_id = request_var('new_f', 0); + + if (!$new_forum_id) + { + $this->page_title = 'USER_ADMIN_MOVE_POSTS'; + + $template->assign_vars(array( + 'S_SELECT_FORUM' => true, + 'U_ACTION' => $this->u_action . "&action=$action&u=$user_id", + 'U_BACK' => $this->u_action . "&u=$user_id", + 'S_FORUM_OPTIONS' => make_forum_select(false, false, false, true)) + ); + + return; + } + + // Is the new forum postable to? + $sql = 'SELECT forum_name, forum_type + FROM ' . FORUMS_TABLE . " + WHERE forum_id = $new_forum_id"; + $result = $db->sql_query($sql); + $forum_info = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$forum_info) + { + trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if ($forum_info['forum_type'] != FORUM_POST) + { + trigger_error($user->lang['MOVE_POSTS_NO_POSTABLE_FORUM'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + // Two stage? + // Move topics comprising only posts from this user + $topic_id_ary = $move_topic_ary = $move_post_ary = $new_topic_id_ary = array(); + $forum_id_ary = array($new_forum_id); + + $sql = 'SELECT topic_id, COUNT(post_id) AS total_posts + FROM ' . POSTS_TABLE . " + WHERE poster_id = $user_id + AND forum_id <> $new_forum_id + GROUP BY topic_id"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $topic_id_ary[$row['topic_id']] = $row['total_posts']; + } + $db->sql_freeresult($result); + + if (sizeof($topic_id_ary)) + { + $sql = 'SELECT topic_id, forum_id, topic_title, topic_replies, topic_replies_real, topic_attachment + FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', array_keys($topic_id_ary)); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if (max($row['topic_replies'], $row['topic_replies_real']) + 1 == $topic_id_ary[$row['topic_id']]) + { + $move_topic_ary[] = $row['topic_id']; + } + else + { + $move_post_ary[$row['topic_id']]['title'] = $row['topic_title']; + $move_post_ary[$row['topic_id']]['attach'] = ($row['topic_attachment']) ? 1 : 0; + } + + $forum_id_ary[] = $row['forum_id']; + } + $db->sql_freeresult($result); + } + + // Entire topic comprises posts by this user, move these topics + if (sizeof($move_topic_ary)) + { + move_topics($move_topic_ary, $new_forum_id, false); + } + + if (sizeof($move_post_ary)) + { + // Create new topic + // Update post_ids, report_ids, attachment_ids + foreach ($move_post_ary as $topic_id => $post_ary) + { + // Create new topic + $sql = 'INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', array( + 'topic_poster' => $user_id, + 'topic_time' => time(), + 'forum_id' => $new_forum_id, + 'icon_id' => 0, + 'topic_approved' => 1, + 'topic_title' => $post_ary['title'], + 'topic_first_poster_name' => $user_row['username'], + 'topic_type' => POST_NORMAL, + 'topic_time_limit' => 0, + 'topic_attachment' => $post_ary['attach']) + ); + $db->sql_query($sql); + + $new_topic_id = $db->sql_nextid(); + + // Move posts + $sql = 'UPDATE ' . POSTS_TABLE . " + SET forum_id = $new_forum_id, topic_id = $new_topic_id + WHERE topic_id = $topic_id + AND poster_id = $user_id"; + $db->sql_query($sql); + + if ($post_ary['attach']) + { + $sql = 'UPDATE ' . ATTACHMENTS_TABLE . " + SET topic_id = $new_topic_id + WHERE topic_id = $topic_id + AND poster_id = $user_id"; + $db->sql_query($sql); + } + + $new_topic_id_ary[] = $new_topic_id; + } + } + + $forum_id_ary = array_unique($forum_id_ary); + $topic_id_ary = array_unique(array_merge(array_keys($topic_id_ary), $new_topic_id_ary)); + + if (sizeof($topic_id_ary)) + { + sync('topic_reported', 'topic_id', $topic_id_ary); + sync('topic', 'topic_id', $topic_id_ary); + } + + if (sizeof($forum_id_ary)) + { + sync('forum', 'forum_id', $forum_id_ary, false, true); + } + + + add_log('admin', 'LOG_USER_MOVE_POSTS', $user_row['username'], $forum_info['forum_name']); + add_log('user', $user_id, 'LOG_USER_MOVE_POSTS_USER', $forum_info['forum_name']); + + trigger_error($user->lang['USER_POSTS_MOVED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + + break; + + case 'leave_nr': + + if (confirm_box(true)) + { + remove_newly_registered($user_id, $user_row); + + add_log('admin', 'LOG_USER_REMOVED_NR', $user_row['username']); + trigger_error($user->lang['USER_LIFTED_NR'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'u' => $user_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'update' => true)) + ); + } + + break; + } + + // Handle registration info updates + $data = array( + 'username' => utf8_normalize_nfc(request_var('user', $user_row['username'], true)), + 'user_founder' => request_var('user_founder', ($user_row['user_type'] == USER_FOUNDER) ? 1 : 0), + 'email' => strtolower(request_var('user_email', $user_row['user_email'])), + 'email_confirm' => strtolower(request_var('email_confirm', '')), + 'new_password' => request_var('new_password', '', true), + 'password_confirm' => request_var('password_confirm', '', true), + ); + + // Validation data - we do not check the password complexity setting here + $check_ary = array( + 'new_password' => array( + array('string', true, $config['min_pass_chars'], $config['max_pass_chars']), + array('password')), + 'password_confirm' => array('string', true, $config['min_pass_chars'], $config['max_pass_chars']), + ); + + // Check username if altered + if ($data['username'] != $user_row['username']) + { + $check_ary += array( + 'username' => array( + array('string', false, $config['min_name_chars'], $config['max_name_chars']), + array('username', $user_row['username']) + ), + ); + } + + // Check email if altered + if ($data['email'] != $user_row['user_email']) + { + $check_ary += array( + 'email' => array( + array('string', false, 6, 60), + array('email', $user_row['user_email']) + ), + 'email_confirm' => array('string', true, 6, 60) + ); + } + + $error = validate_data($data, $check_ary); + + if ($data['new_password'] && $data['password_confirm'] != $data['new_password']) + { + $error[] = 'NEW_PASSWORD_ERROR'; + } + + if ($data['email'] != $user_row['user_email'] && $data['email_confirm'] != $data['email']) + { + $error[] = 'NEW_EMAIL_ERROR'; + } + + if (!check_form_key($form_name)) + { + $error[] = 'FORM_INVALID'; + } + + // Which updates do we need to do? + $update_username = ($user_row['username'] != $data['username']) ? $data['username'] : false; + $update_password = ($data['new_password'] && !phpbb_check_hash($user_row['user_password'], $data['new_password'])) ? true : false; + $update_email = ($data['email'] != $user_row['user_email']) ? $data['email'] : false; + + if (!sizeof($error)) + { + $sql_ary = array(); + + if ($user_row['user_type'] != USER_FOUNDER || $user->data['user_type'] == USER_FOUNDER) + { + // Only allow founders updating the founder status... + if ($user->data['user_type'] == USER_FOUNDER) + { + // Setting a normal member to be a founder + if ($data['user_founder'] && $user_row['user_type'] != USER_FOUNDER) + { + // Make sure the user is not setting an Inactive or ignored user to be a founder + if ($user_row['user_type'] == USER_IGNORE) + { + trigger_error($user->lang['CANNOT_SET_FOUNDER_IGNORED'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if ($user_row['user_type'] == USER_INACTIVE) + { + trigger_error($user->lang['CANNOT_SET_FOUNDER_INACTIVE'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + $sql_ary['user_type'] = USER_FOUNDER; + } + else if (!$data['user_founder'] && $user_row['user_type'] == USER_FOUNDER) + { + // Check if at least one founder is present + $sql = 'SELECT user_id + FROM ' . USERS_TABLE . ' + WHERE user_type = ' . USER_FOUNDER . ' + AND user_id <> ' . $user_id; + $result = $db->sql_query_limit($sql, 1); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + $sql_ary['user_type'] = USER_NORMAL; + } + else + { + trigger_error($user->lang['AT_LEAST_ONE_FOUNDER'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + } + } + } + + if ($update_username !== false) + { + $sql_ary['username'] = $update_username; + $sql_ary['username_clean'] = utf8_clean_string($update_username); + + add_log('user', $user_id, 'LOG_USER_UPDATE_NAME', $user_row['username'], $update_username); + } + + if ($update_email !== false) + { + $sql_ary += array( + 'user_email' => $update_email, + 'user_email_hash' => phpbb_email_hash($update_email), + ); + + add_log('user', $user_id, 'LOG_USER_UPDATE_EMAIL', $user_row['username'], $user_row['user_email'], $update_email); + } + + if ($update_password) + { + $sql_ary += array( + 'user_password' => phpbb_hash($data['new_password']), + 'user_passchg' => time(), + 'user_pass_convert' => 0, + ); + + $user->reset_login_keys($user_id); + add_log('user', $user_id, 'LOG_USER_NEW_PASSWORD', $user_row['username']); + } + + if (sizeof($sql_ary)) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . $user_id; + $db->sql_query($sql); + } + + if ($update_username) + { + user_update_name($user_row['username'], $update_username); + } + + // Let the users permissions being updated + $auth->acl_clear_prefetch($user_id); + + add_log('admin', 'LOG_USER_USER_UPDATE', $data['username']); + + trigger_error($user->lang['USER_OVERVIEW_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + } + + if ($user_id == $user->data['user_id']) + { + $quick_tool_ary = array('delsig' => 'DEL_SIG', 'delavatar' => 'DEL_AVATAR', 'moveposts' => 'MOVE_POSTS', 'delposts' => 'DEL_POSTS', 'delattach' => 'DEL_ATTACH', 'deloutbox' => 'DEL_OUTBOX'); + if ($user_row['user_new']) + { + $quick_tool_ary['leave_nr'] = 'LEAVE_NR'; + } + } + else + { + $quick_tool_ary = array(); + + if ($user_row['user_type'] != USER_FOUNDER) + { + $quick_tool_ary += array('banuser' => 'BAN_USER', 'banemail' => 'BAN_EMAIL', 'banip' => 'BAN_IP'); + } + + if ($user_row['user_type'] != USER_FOUNDER && $user_row['user_type'] != USER_IGNORE) + { + $quick_tool_ary += array('active' => (($user_row['user_type'] == USER_INACTIVE) ? 'ACTIVATE' : 'DEACTIVATE')); + } + + $quick_tool_ary += array('delsig' => 'DEL_SIG', 'delavatar' => 'DEL_AVATAR', 'moveposts' => 'MOVE_POSTS', 'delposts' => 'DEL_POSTS', 'delattach' => 'DEL_ATTACH', 'deloutbox' => 'DEL_OUTBOX'); + + if ($config['email_enable'] && ($user_row['user_type'] == USER_NORMAL || $user_row['user_type'] == USER_INACTIVE)) + { + $quick_tool_ary['reactivate'] = 'FORCE'; + } + + if ($user_row['user_new']) + { + $quick_tool_ary['leave_nr'] = 'LEAVE_NR'; + } + } + + $s_action_options = '<option class="sep" value="">' . $user->lang['SELECT_OPTION'] . '</option>'; + foreach ($quick_tool_ary as $value => $lang) + { + $s_action_options .= '<option value="' . $value . '">' . $user->lang['USER_ADMIN_' . $lang] . '</option>'; + } + + if ($config['load_onlinetrack']) + { + $sql = 'SELECT MAX(session_time) AS session_time, MIN(session_viewonline) AS session_viewonline + FROM ' . SESSIONS_TABLE . " + WHERE session_user_id = $user_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $user_row['session_time'] = (isset($row['session_time'])) ? $row['session_time'] : 0; + $user_row['session_viewonline'] = (isset($row['session_viewonline'])) ? $row['session_viewonline'] : 0; + unset($row); + } + + $last_visit = (!empty($user_row['session_time'])) ? $user_row['session_time'] : $user_row['user_lastvisit']; + + $inactive_reason = ''; + if ($user_row['user_type'] == USER_INACTIVE) + { + $inactive_reason = $user->lang['INACTIVE_REASON_UNKNOWN']; + + switch ($user_row['user_inactive_reason']) + { + case INACTIVE_REGISTER: + $inactive_reason = $user->lang['INACTIVE_REASON_REGISTER']; + break; + + case INACTIVE_PROFILE: + $inactive_reason = $user->lang['INACTIVE_REASON_PROFILE']; + break; + + case INACTIVE_MANUAL: + $inactive_reason = $user->lang['INACTIVE_REASON_MANUAL']; + break; + + case INACTIVE_REMIND: + $inactive_reason = $user->lang['INACTIVE_REASON_REMIND']; + break; + } + } + + // Posts in Queue + $sql = 'SELECT COUNT(post_id) as posts_in_queue + FROM ' . POSTS_TABLE . ' + WHERE poster_id = ' . $user_id . ' + AND post_approved = 0'; + $result = $db->sql_query($sql); + $user_row['posts_in_queue'] = (int) $db->sql_fetchfield('posts_in_queue'); + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'L_NAME_CHARS_EXPLAIN' => sprintf($user->lang[$config['allow_name_chars'] . '_EXPLAIN'], $config['min_name_chars'], $config['max_name_chars']), + 'L_CHANGE_PASSWORD_EXPLAIN' => sprintf($user->lang[$config['pass_complex'] . '_EXPLAIN'], $config['min_pass_chars'], $config['max_pass_chars']), + 'L_POSTS_IN_QUEUE' => $user->lang('NUM_POSTS_IN_QUEUE', $user_row['posts_in_queue']), + 'S_FOUNDER' => ($user->data['user_type'] == USER_FOUNDER) ? true : false, + + 'S_OVERVIEW' => true, + 'S_USER_IP' => ($user_row['user_ip']) ? true : false, + 'S_USER_FOUNDER' => ($user_row['user_type'] == USER_FOUNDER) ? true : false, + 'S_ACTION_OPTIONS' => $s_action_options, + 'S_OWN_ACCOUNT' => ($user_id == $user->data['user_id']) ? true : false, + 'S_USER_INACTIVE' => ($user_row['user_type'] == USER_INACTIVE) ? true : false, + + 'U_SHOW_IP' => $this->u_action . "&u=$user_id&ip=" . (($ip == 'ip') ? 'hostname' : 'ip'), + 'U_WHOIS' => $this->u_action . "&action=whois&user_ip={$user_row['user_ip']}", + 'U_MCP_QUEUE' => ($auth->acl_getf_global('m_approve')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue', true, $user->session_id) : '', + + 'U_SWITCH_PERMISSIONS' => ($auth->acl_get('a_switchperm') && $user->data['user_id'] != $user_row['user_id']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", "mode=switch_perm&u={$user_row['user_id']}&hash=" . generate_link_hash('switchperm')) : '', + + 'POSTS_IN_QUEUE' => $user_row['posts_in_queue'], + 'USER' => $user_row['username'], + 'USER_REGISTERED' => $user->format_date($user_row['user_regdate']), + 'REGISTERED_IP' => ($ip == 'hostname') ? gethostbyaddr($user_row['user_ip']) : $user_row['user_ip'], + 'USER_LASTACTIVE' => ($last_visit) ? $user->format_date($last_visit) : ' - ', + 'USER_EMAIL' => $user_row['user_email'], + 'USER_WARNINGS' => $user_row['user_warnings'], + 'USER_POSTS' => $user_row['user_posts'], + 'USER_INACTIVE_REASON' => $inactive_reason, + )); + + break; + + case 'feedback': + + $user->add_lang('mcp'); + + // Set up general vars + $start = request_var('start', 0); + $deletemark = (isset($_POST['delmarked'])) ? true : false; + $deleteall = (isset($_POST['delall'])) ? true : false; + $marked = request_var('mark', array(0)); + $message = utf8_normalize_nfc(request_var('message', '', true)); + + // Sort keys + $sort_days = request_var('st', 0); + $sort_key = request_var('sk', 't'); + $sort_dir = request_var('sd', 'd'); + + // Delete entries if requested and able + if (($deletemark || $deleteall) && $auth->acl_get('a_clearlogs')) + { + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + $where_sql = ''; + if ($deletemark && $marked) + { + $sql_in = array(); + foreach ($marked as $mark) + { + $sql_in[] = $mark; + } + $where_sql = ' AND ' . $db->sql_in_set('log_id', $sql_in); + unset($sql_in); + } + + if ($where_sql || $deleteall) + { + $sql = 'DELETE FROM ' . LOG_TABLE . ' + WHERE log_type = ' . LOG_USERS . " + AND reportee_id = $user_id + $where_sql"; + $db->sql_query($sql); + + add_log('admin', 'LOG_CLEAR_USER', $user_row['username']); + } + } + + if ($submit && $message) + { + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + add_log('admin', 'LOG_USER_FEEDBACK', $user_row['username']); + add_log('mod', 0, 0, 'LOG_USER_FEEDBACK', $user_row['username']); + add_log('user', $user_id, 'LOG_USER_GENERAL', $message); + + trigger_error($user->lang['USER_FEEDBACK_ADDED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + + // Sorting + $limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + $sort_by_text = array('u' => $user->lang['SORT_USERNAME'], 't' => $user->lang['SORT_DATE'], 'i' => $user->lang['SORT_IP'], 'o' => $user->lang['SORT_ACTION']); + $sort_by_sql = array('u' => 'u.username_clean', 't' => 'l.log_time', 'i' => 'l.log_ip', 'o' => 'l.log_operation'); + + $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = ''; + 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); + + // Define where and sort sql for use in displaying logs + $sql_where = ($sort_days) ? (time() - ($sort_days * 86400)) : 0; + $sql_sort = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC'); + + // Grab log data + $log_data = array(); + $log_count = 0; + view_log('user', $log_data, $log_count, $config['topics_per_page'], $start, 0, 0, $user_id, $sql_where, $sql_sort); + + $template->assign_vars(array( + 'S_FEEDBACK' => true, + 'S_ON_PAGE' => on_page($log_count, $config['topics_per_page'], $start), + 'PAGINATION' => generate_pagination($this->u_action . "&u=$user_id&$u_sort_param", $log_count, $config['topics_per_page'], $start, true), + + 'S_LIMIT_DAYS' => $s_limit_days, + 'S_SORT_KEY' => $s_sort_key, + 'S_SORT_DIR' => $s_sort_dir, + 'S_CLEARLOGS' => $auth->acl_get('a_clearlogs')) + ); + + foreach ($log_data as $row) + { + $template->assign_block_vars('log', array( + 'USERNAME' => $row['username_full'], + 'IP' => $row['ip'], + 'DATE' => $user->format_date($row['time']), + 'ACTION' => nl2br($row['action']), + 'ID' => $row['id']) + ); + } + + break; + + case 'warnings': + $user->add_lang('mcp'); + + // Set up general vars + $start = request_var('start', 0); + $deletemark = (isset($_POST['delmarked'])) ? true : false; + $deleteall = (isset($_POST['delall'])) ? true : false; + $confirm = (isset($_POST['confirm'])) ? true : false; + $marked = request_var('mark', array(0)); + $message = utf8_normalize_nfc(request_var('message', '', true)); + + // Sort keys + $sort_days = request_var('st', 0); + $sort_key = request_var('sk', 't'); + $sort_dir = request_var('sd', 'd'); + + // Delete entries if requested and able + if ($deletemark || $deleteall || $confirm) + { + if (confirm_box(true)) + { + $where_sql = ''; + $deletemark = request_var('delmarked', 0); + $deleteall = request_var('delall', 0); + if ($deletemark && $marked) + { + $where_sql = ' AND ' . $db->sql_in_set('warning_id', array_values($marked)); + } + + if ($where_sql || $deleteall) + { + $sql = 'DELETE FROM ' . WARNINGS_TABLE . " + WHERE user_id = $user_id + $where_sql"; + $db->sql_query($sql); + + if ($deleteall) + { + $log_warnings = $deleted_warnings = 0; + } + else + { + $num_warnings = (int) $db->sql_affectedrows(); + $deleted_warnings = ' user_warnings - ' . $num_warnings; + $log_warnings = ($num_warnings > 2) ? 2 : $num_warnings; + } + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_warnings = $deleted_warnings + WHERE user_id = $user_id"; + $db->sql_query($sql); + + switch ($log_warnings) + { + case 2: + add_log('admin', 'LOG_WARNINGS_DELETED', $user_row['username'], $num_warnings); + break; + case 1: + add_log('admin', 'LOG_WARNING_DELETED', $user_row['username']); + break; + default: + add_log('admin', 'LOG_WARNINGS_DELETED_ALL', $user_row['username']); + break; + } + } + } + else + { + $s_hidden_fields = array( + 'i' => $id, + 'mode' => $mode, + 'u' => $user_id, + 'mark' => $marked, + ); + if (isset($_POST['delmarked'])) + { + $s_hidden_fields['delmarked'] = 1; + } + if (isset($_POST['delall'])) + { + $s_hidden_fields['delall'] = 1; + } + if (isset($_POST['delall']) || (isset($_POST['delmarked']) && sizeof($marked))) + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($s_hidden_fields)); + } + } + } + + $sql = 'SELECT w.warning_id, w.warning_time, w.post_id, l.log_operation, l.log_data, l.user_id AS mod_user_id, m.username AS mod_username, m.user_colour AS mod_user_colour + FROM ' . WARNINGS_TABLE . ' w + LEFT JOIN ' . LOG_TABLE . ' l + ON (w.log_id = l.log_id) + LEFT JOIN ' . USERS_TABLE . ' m + ON (l.user_id = m.user_id) + WHERE w.user_id = ' . $user_id . ' + ORDER BY w.warning_time DESC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if (!$row['log_operation']) + { + // We do not have a log-entry anymore, so there is no data available + $row['action'] = $user->lang['USER_WARNING_LOG_DELETED']; + } + else + { + $row['action'] = (isset($user->lang[$row['log_operation']])) ? $user->lang[$row['log_operation']] : '{' . ucfirst(str_replace('_', ' ', $row['log_operation'])) . '}'; + if (!empty($row['log_data'])) + { + $log_data_ary = @unserialize($row['log_data']); + $log_data_ary = ($log_data_ary === false) ? array() : $log_data_ary; + + if (isset($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($row['action'], '%') - sizeof($log_data_ary)) > 0) + { + $log_data_ary = array_merge($log_data_ary, array_fill(0, substr_count($row['action'], '%') - sizeof($log_data_ary), '')); + } + $row['action'] = vsprintf($row['action'], $log_data_ary); + $row['action'] = bbcode_nl2br(censor_text($row['action'])); + } + else if (!empty($log_data_ary)) + { + $row['action'] .= '<br />' . implode('', $log_data_ary); + } + } + } + + + $template->assign_block_vars('warn', array( + 'ID' => $row['warning_id'], + 'USERNAME' => ($row['log_operation']) ? get_username_string('full', $row['mod_user_id'], $row['mod_username'], $row['mod_user_colour']) : '-', + 'ACTION' => make_clickable($row['action']), + 'DATE' => $user->format_date($row['warning_time']), + )); + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'S_WARNINGS' => true, + )); + + break; + + case 'profile': + + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + include($phpbb_root_path . 'includes/functions_profile_fields.' . $phpEx); + + $cp = new custom_profile(); + + $cp_data = $cp_error = array(); + + $sql = 'SELECT lang_id + FROM ' . LANG_TABLE . " + WHERE lang_iso = '" . $db->sql_escape($user->data['user_lang']) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $user_row['iso_lang_id'] = $row['lang_id']; + + $data = array( + 'icq' => request_var('icq', $user_row['user_icq']), + 'aim' => request_var('aim', $user_row['user_aim']), + 'msn' => request_var('msn', $user_row['user_msnm']), + 'yim' => request_var('yim', $user_row['user_yim']), + 'jabber' => utf8_normalize_nfc(request_var('jabber', $user_row['user_jabber'], true)), + 'website' => request_var('website', $user_row['user_website']), + 'location' => utf8_normalize_nfc(request_var('location', $user_row['user_from'], true)), + 'occupation' => utf8_normalize_nfc(request_var('occupation', $user_row['user_occ'], true)), + 'interests' => utf8_normalize_nfc(request_var('interests', $user_row['user_interests'], true)), + 'bday_day' => 0, + 'bday_month' => 0, + 'bday_year' => 0, + ); + + if ($user_row['user_birthday']) + { + list($data['bday_day'], $data['bday_month'], $data['bday_year']) = explode('-', $user_row['user_birthday']); + } + + $data['bday_day'] = request_var('bday_day', $data['bday_day']); + $data['bday_month'] = request_var('bday_month', $data['bday_month']); + $data['bday_year'] = request_var('bday_year', $data['bday_year']); + $data['user_birthday'] = sprintf('%2d-%2d-%4d', $data['bday_day'], $data['bday_month'], $data['bday_year']); + + + if ($submit) + { + $error = validate_data($data, array( + 'icq' => array( + array('string', true, 3, 15), + array('match', true, '#^[0-9]+$#i')), + 'aim' => array('string', true, 3, 255), + 'msn' => array('string', true, 5, 255), + 'jabber' => array( + array('string', true, 5, 255), + array('jabber')), + 'yim' => array('string', true, 5, 255), + 'website' => array( + array('string', true, 12, 255), + array('match', true, '#^http[s]?://(.*?\.)*?[a-z0-9\-]+\.[a-z]{2,4}#i')), + 'location' => array('string', true, 2, 100), + 'occupation' => array('string', true, 2, 500), + 'interests' => array('string', true, 2, 500), + 'bday_day' => array('num', true, 1, 31), + 'bday_month' => array('num', true, 1, 12), + 'bday_year' => array('num', true, 1901, gmdate('Y', time())), + 'user_birthday' => array('date', true), + )); + + // validate custom profile fields + $cp->submit_cp_field('profile', $user_row['iso_lang_id'], $cp_data, $cp_error); + + if (sizeof($cp_error)) + { + $error = array_merge($error, $cp_error); + } + if (!check_form_key($form_name)) + { + $error[] = 'FORM_INVALID'; + } + + if (!sizeof($error)) + { + $sql_ary = array( + 'user_icq' => $data['icq'], + 'user_aim' => $data['aim'], + 'user_msnm' => $data['msn'], + 'user_yim' => $data['yim'], + 'user_jabber' => $data['jabber'], + 'user_website' => $data['website'], + 'user_from' => $data['location'], + 'user_occ' => $data['occupation'], + 'user_interests'=> $data['interests'], + 'user_birthday' => $data['user_birthday'], + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE user_id = $user_id"; + $db->sql_query($sql); + + // Update Custom Fields + $cp->update_profile_field_data($user_id, $cp_data); + + trigger_error($user->lang['USER_PROFILE_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + } + + $s_birthday_day_options = '<option value="0"' . ((!$data['bday_day']) ? ' selected="selected"' : '') . '>--</option>'; + for ($i = 1; $i < 32; $i++) + { + $selected = ($i == $data['bday_day']) ? ' selected="selected"' : ''; + $s_birthday_day_options .= "<option value=\"$i\"$selected>$i</option>"; + } + + $s_birthday_month_options = '<option value="0"' . ((!$data['bday_month']) ? ' selected="selected"' : '') . '>--</option>'; + for ($i = 1; $i < 13; $i++) + { + $selected = ($i == $data['bday_month']) ? ' selected="selected"' : ''; + $s_birthday_month_options .= "<option value=\"$i\"$selected>$i</option>"; + } + $s_birthday_year_options = ''; + + $now = getdate(); + $s_birthday_year_options = '<option value="0"' . ((!$data['bday_year']) ? ' selected="selected"' : '') . '>--</option>'; + for ($i = $now['year'] - 100; $i < $now['year']; $i++) + { + $selected = ($i == $data['bday_year']) ? ' selected="selected"' : ''; + $s_birthday_year_options .= "<option value=\"$i\"$selected>$i</option>"; + } + unset($now); + + $template->assign_vars(array( + 'ICQ' => $data['icq'], + 'YIM' => $data['yim'], + 'AIM' => $data['aim'], + 'MSN' => $data['msn'], + 'JABBER' => $data['jabber'], + 'WEBSITE' => $data['website'], + 'LOCATION' => $data['location'], + 'OCCUPATION' => $data['occupation'], + 'INTERESTS' => $data['interests'], + + 'S_BIRTHDAY_DAY_OPTIONS' => $s_birthday_day_options, + 'S_BIRTHDAY_MONTH_OPTIONS' => $s_birthday_month_options, + 'S_BIRTHDAY_YEAR_OPTIONS' => $s_birthday_year_options, + + 'S_PROFILE' => true) + ); + + // Get additional profile fields and assign them to the template block var 'profile_fields' + $user->get_profile_fields($user_id); + + $cp->generate_profile_fields('profile', $user_row['iso_lang_id']); + + break; + + case 'prefs': + + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + + $data = array( + 'dateformat' => utf8_normalize_nfc(request_var('dateformat', $user_row['user_dateformat'], true)), + 'lang' => basename(request_var('lang', $user_row['user_lang'])), + 'tz' => request_var('tz', (float) $user_row['user_timezone']), + 'style' => request_var('style', $user_row['user_style']), + 'dst' => request_var('dst', $user_row['user_dst']), + 'viewemail' => request_var('viewemail', $user_row['user_allow_viewemail']), + 'massemail' => request_var('massemail', $user_row['user_allow_massemail']), + 'hideonline' => request_var('hideonline', !$user_row['user_allow_viewonline']), + 'notifymethod' => request_var('notifymethod', $user_row['user_notify_type']), + 'notifypm' => request_var('notifypm', $user_row['user_notify_pm']), + 'popuppm' => request_var('popuppm', $this->optionget($user_row, 'popuppm')), + 'allowpm' => request_var('allowpm', $user_row['user_allow_pm']), + + 'topic_sk' => request_var('topic_sk', ($user_row['user_topic_sortby_type']) ? $user_row['user_topic_sortby_type'] : 't'), + 'topic_sd' => request_var('topic_sd', ($user_row['user_topic_sortby_dir']) ? $user_row['user_topic_sortby_dir'] : 'd'), + 'topic_st' => request_var('topic_st', ($user_row['user_topic_show_days']) ? $user_row['user_topic_show_days'] : 0), + + 'post_sk' => request_var('post_sk', ($user_row['user_post_sortby_type']) ? $user_row['user_post_sortby_type'] : 't'), + 'post_sd' => request_var('post_sd', ($user_row['user_post_sortby_dir']) ? $user_row['user_post_sortby_dir'] : 'a'), + 'post_st' => request_var('post_st', ($user_row['user_post_show_days']) ? $user_row['user_post_show_days'] : 0), + + 'view_images' => request_var('view_images', $this->optionget($user_row, 'viewimg')), + 'view_flash' => request_var('view_flash', $this->optionget($user_row, 'viewflash')), + 'view_smilies' => request_var('view_smilies', $this->optionget($user_row, 'viewsmilies')), + 'view_sigs' => request_var('view_sigs', $this->optionget($user_row, 'viewsigs')), + 'view_avatars' => request_var('view_avatars', $this->optionget($user_row, 'viewavatars')), + 'view_wordcensor' => request_var('view_wordcensor', $this->optionget($user_row, 'viewcensors')), + + 'bbcode' => request_var('bbcode', $this->optionget($user_row, 'bbcode')), + 'smilies' => request_var('smilies', $this->optionget($user_row, 'smilies')), + 'sig' => request_var('sig', $this->optionget($user_row, 'attachsig')), + 'notify' => request_var('notify', $user_row['user_notify']), + ); + + if ($submit) + { + $error = validate_data($data, array( + 'dateformat' => array('string', false, 1, 30), + 'lang' => array('match', false, '#^[a-z_\-]{2,}$#i'), + 'tz' => array('num', false, -14, 14), + + 'topic_sk' => array('string', false, 1, 1), + 'topic_sd' => array('string', false, 1, 1), + 'post_sk' => array('string', false, 1, 1), + 'post_sd' => array('string', false, 1, 1), + )); + + if (!check_form_key($form_name)) + { + $error[] = 'FORM_INVALID'; + } + + if (!sizeof($error)) + { + $this->optionset($user_row, 'popuppm', $data['popuppm']); + $this->optionset($user_row, 'viewimg', $data['view_images']); + $this->optionset($user_row, 'viewflash', $data['view_flash']); + $this->optionset($user_row, 'viewsmilies', $data['view_smilies']); + $this->optionset($user_row, 'viewsigs', $data['view_sigs']); + $this->optionset($user_row, 'viewavatars', $data['view_avatars']); + $this->optionset($user_row, 'viewcensors', $data['view_wordcensor']); + $this->optionset($user_row, 'bbcode', $data['bbcode']); + $this->optionset($user_row, 'smilies', $data['smilies']); + $this->optionset($user_row, 'attachsig', $data['sig']); + + $sql_ary = array( + 'user_options' => $user_row['user_options'], + + 'user_allow_pm' => $data['allowpm'], + 'user_allow_viewemail' => $data['viewemail'], + 'user_allow_massemail' => $data['massemail'], + 'user_allow_viewonline' => !$data['hideonline'], + 'user_notify_type' => $data['notifymethod'], + 'user_notify_pm' => $data['notifypm'], + + 'user_dst' => $data['dst'], + 'user_dateformat' => $data['dateformat'], + 'user_lang' => $data['lang'], + 'user_timezone' => $data['tz'], + 'user_style' => $data['style'], + + 'user_topic_sortby_type' => $data['topic_sk'], + 'user_post_sortby_type' => $data['post_sk'], + 'user_topic_sortby_dir' => $data['topic_sd'], + 'user_post_sortby_dir' => $data['post_sd'], + + 'user_topic_show_days' => $data['topic_st'], + 'user_post_show_days' => $data['post_st'], + + 'user_notify' => $data['notify'], + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE user_id = $user_id"; + $db->sql_query($sql); + + trigger_error($user->lang['USER_PREFS_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + } + + $dateformat_options = ''; + foreach ($user->lang['dateformats'] as $format => $null) + { + $dateformat_options .= '<option value="' . $format . '"' . (($format == $data['dateformat']) ? ' selected="selected"' : '') . '>'; + $dateformat_options .= $user->format_date(time(), $format, false) . ((strpos($format, '|') !== false) ? $user->lang['VARIANT_DATE_SEPARATOR'] . $user->format_date(time(), $format, true) : ''); + $dateformat_options .= '</option>'; + } + + $s_custom = false; + + $dateformat_options .= '<option value="custom"'; + if (!isset($user->lang['dateformats'][$data['dateformat']])) + { + $dateformat_options .= ' selected="selected"'; + $s_custom = true; + } + $dateformat_options .= '>' . $user->lang['CUSTOM_DATEFORMAT'] . '</option>'; + + $sort_dir_text = array('a' => $user->lang['ASCENDING'], 'd' => $user->lang['DESCENDING']); + + // Topic ordering options + $limit_topic_days = array(0 => $user->lang['ALL_TOPICS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + $sort_by_topic_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 'r' => $user->lang['REPLIES'], 's' => $user->lang['SUBJECT'], 'v' => $user->lang['VIEWS']); + + // Post ordering options + $limit_post_days = array(0 => $user->lang['ALL_POSTS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + $sort_by_post_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 's' => $user->lang['SUBJECT']); + + $_options = array('topic', 'post'); + foreach ($_options as $sort_option) + { + ${'s_limit_' . $sort_option . '_days'} = '<select name="' . $sort_option . '_st">'; + foreach (${'limit_' . $sort_option . '_days'} as $day => $text) + { + $selected = ($data[$sort_option . '_st'] == $day) ? ' selected="selected"' : ''; + ${'s_limit_' . $sort_option . '_days'} .= '<option value="' . $day . '"' . $selected . '>' . $text . '</option>'; + } + ${'s_limit_' . $sort_option . '_days'} .= '</select>'; + + ${'s_sort_' . $sort_option . '_key'} = '<select name="' . $sort_option . '_sk">'; + foreach (${'sort_by_' . $sort_option . '_text'} as $key => $text) + { + $selected = ($data[$sort_option . '_sk'] == $key) ? ' selected="selected"' : ''; + ${'s_sort_' . $sort_option . '_key'} .= '<option value="' . $key . '"' . $selected . '>' . $text . '</option>'; + } + ${'s_sort_' . $sort_option . '_key'} .= '</select>'; + + ${'s_sort_' . $sort_option . '_dir'} = '<select name="' . $sort_option . '_sd">'; + foreach ($sort_dir_text as $key => $value) + { + $selected = ($data[$sort_option . '_sd'] == $key) ? ' selected="selected"' : ''; + ${'s_sort_' . $sort_option . '_dir'} .= '<option value="' . $key . '"' . $selected . '>' . $value . '</option>'; + } + ${'s_sort_' . $sort_option . '_dir'} .= '</select>'; + } + + $template->assign_vars(array( + 'S_PREFS' => true, + 'S_JABBER_DISABLED' => ($config['jab_enable'] && $user_row['user_jabber'] && @extension_loaded('xml')) ? false : true, + + 'VIEW_EMAIL' => $data['viewemail'], + 'MASS_EMAIL' => $data['massemail'], + 'ALLOW_PM' => $data['allowpm'], + 'HIDE_ONLINE' => $data['hideonline'], + 'NOTIFY_EMAIL' => ($data['notifymethod'] == NOTIFY_EMAIL) ? true : false, + 'NOTIFY_IM' => ($data['notifymethod'] == NOTIFY_IM) ? true : false, + 'NOTIFY_BOTH' => ($data['notifymethod'] == NOTIFY_BOTH) ? true : false, + 'NOTIFY_PM' => $data['notifypm'], + 'POPUP_PM' => $data['popuppm'], + 'DST' => $data['dst'], + 'BBCODE' => $data['bbcode'], + 'SMILIES' => $data['smilies'], + 'ATTACH_SIG' => $data['sig'], + 'NOTIFY' => $data['notify'], + 'VIEW_IMAGES' => $data['view_images'], + 'VIEW_FLASH' => $data['view_flash'], + 'VIEW_SMILIES' => $data['view_smilies'], + 'VIEW_SIGS' => $data['view_sigs'], + 'VIEW_AVATARS' => $data['view_avatars'], + 'VIEW_WORDCENSOR' => $data['view_wordcensor'], + + 'S_TOPIC_SORT_DAYS' => $s_limit_topic_days, + 'S_TOPIC_SORT_KEY' => $s_sort_topic_key, + 'S_TOPIC_SORT_DIR' => $s_sort_topic_dir, + 'S_POST_SORT_DAYS' => $s_limit_post_days, + 'S_POST_SORT_KEY' => $s_sort_post_key, + 'S_POST_SORT_DIR' => $s_sort_post_dir, + + 'DATE_FORMAT' => $data['dateformat'], + 'S_DATEFORMAT_OPTIONS' => $dateformat_options, + 'S_CUSTOM_DATEFORMAT' => $s_custom, + 'DEFAULT_DATEFORMAT' => $config['default_dateformat'], + 'A_DEFAULT_DATEFORMAT' => addslashes($config['default_dateformat']), + + 'S_LANG_OPTIONS' => language_select($data['lang']), + 'S_STYLE_OPTIONS' => style_select($data['style']), + 'S_TZ_OPTIONS' => tz_select($data['tz'], true), + ) + ); + + break; + + case 'avatar': + + include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + + $can_upload = (file_exists($phpbb_root_path . $config['avatar_path']) && @is_writable($phpbb_root_path . $config['avatar_path']) && $file_uploads) ? true : false; + + if ($submit) + { + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if (avatar_process_user($error, $user_row)) + { + trigger_error($user->lang['USER_AVATAR_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_row['user_id'])); + } + + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + } + + if (!$config['allow_avatar'] && $user_row['user_avatar_type']) + { + $error[] = $user->lang['USER_AVATAR_NOT_ALLOWED']; + } + else if ((($user_row['user_avatar_type'] == AVATAR_UPLOAD) && !$config['allow_avatar_upload']) || + (($user_row['user_avatar_type'] == AVATAR_REMOTE) && !$config['allow_avatar_remote']) || + (($user_row['user_avatar_type'] == AVATAR_GALLERY) && !$config['allow_avatar_local'])) + { + $error[] = $user->lang['USER_AVATAR_TYPE_NOT_ALLOWED']; + } + + // Generate users avatar + $avatar_img = ($user_row['user_avatar']) ? get_user_avatar($user_row['user_avatar'], $user_row['user_avatar_type'], $user_row['user_avatar_width'], $user_row['user_avatar_height'], 'USER_AVATAR', true) : '<img src="' . $phpbb_admin_path . 'images/no_avatar.gif" alt="" />'; + + $display_gallery = (isset($_POST['display_gallery'])) ? true : false; + $avatar_select = basename(request_var('avatar_select', '')); + $category = basename(request_var('category', '')); + + if ($config['allow_avatar_local'] && $display_gallery) + { + avatar_gallery($category, $avatar_select, 4); + } + + $template->assign_vars(array( + 'S_AVATAR' => true, + 'S_CAN_UPLOAD' => $can_upload, + 'S_UPLOAD_FILE' => ($config['allow_avatar'] && $can_upload && $config['allow_avatar_upload']) ? true : false, + 'S_REMOTE_UPLOAD' => ($config['allow_avatar'] && $can_upload && $config['allow_avatar_remote_upload']) ? true : false, + 'S_ALLOW_REMOTE' => ($config['allow_avatar'] && $config['allow_avatar_remote']) ? true : false, + 'S_DISPLAY_GALLERY' => ($config['allow_avatar'] && $config['allow_avatar_local'] && !$display_gallery) ? true : false, + 'S_IN_GALLERY' => ($config['allow_avatar'] && $config['allow_avatar_local'] && $display_gallery) ? true : false, + + 'AVATAR_IMAGE' => $avatar_img, + 'AVATAR_MAX_FILESIZE' => $config['avatar_filesize'], + 'USER_AVATAR_WIDTH' => $user_row['user_avatar_width'], + 'USER_AVATAR_HEIGHT' => $user_row['user_avatar_height'], + + 'L_AVATAR_EXPLAIN' => sprintf($user->lang['AVATAR_EXPLAIN'], $config['avatar_max_width'], $config['avatar_max_height'], round($config['avatar_filesize'] / 1024))) + ); + + break; + + case 'rank': + + if ($submit) + { + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + $rank_id = request_var('user_rank', 0); + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_rank = $rank_id + WHERE user_id = $user_id"; + $db->sql_query($sql); + + trigger_error($user->lang['USER_RANK_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + + $sql = 'SELECT * + FROM ' . RANKS_TABLE . ' + WHERE rank_special = 1 + ORDER BY rank_title'; + $result = $db->sql_query($sql); + + $s_rank_options = '<option value="0"' . ((!$user_row['user_rank']) ? ' selected="selected"' : '') . '>' . $user->lang['NO_SPECIAL_RANK'] . '</option>'; + + while ($row = $db->sql_fetchrow($result)) + { + $selected = ($user_row['user_rank'] && $row['rank_id'] == $user_row['user_rank']) ? ' selected="selected"' : ''; + $s_rank_options .= '<option value="' . $row['rank_id'] . '"' . $selected . '>' . $row['rank_title'] . '</option>'; + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'S_RANK' => true, + 'S_RANK_OPTIONS' => $s_rank_options) + ); + + break; + + case 'sig': + + include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); + include_once($phpbb_root_path . 'includes/functions_display.' . $phpEx); + + $enable_bbcode = ($config['allow_sig_bbcode']) ? (bool) $this->optionget($user_row, 'sig_bbcode') : false; + $enable_smilies = ($config['allow_sig_smilies']) ? (bool) $this->optionget($user_row, 'sig_smilies') : false; + $enable_urls = ($config['allow_sig_links']) ? (bool) $this->optionget($user_row, 'sig_links') : false; + $signature = utf8_normalize_nfc(request_var('signature', (string) $user_row['user_sig'], true)); + + $preview = (isset($_POST['preview'])) ? true : false; + + if ($submit || $preview) + { + include_once($phpbb_root_path . 'includes/message_parser.' . $phpEx); + + $enable_bbcode = ($config['allow_sig_bbcode']) ? ((request_var('disable_bbcode', false)) ? false : true) : false; + $enable_smilies = ($config['allow_sig_smilies']) ? ((request_var('disable_smilies', false)) ? false : true) : false; + $enable_urls = ($config['allow_sig_links']) ? ((request_var('disable_magic_url', false)) ? false : true) : false; + + $message_parser = new parse_message($signature); + + // Allowing Quote BBCode + $message_parser->parse($enable_bbcode, $enable_urls, $enable_smilies, $config['allow_sig_img'], $config['allow_sig_flash'], true, $config['allow_sig_links'], true, 'sig'); + + if (sizeof($message_parser->warn_msg)) + { + $error[] = implode('<br />', $message_parser->warn_msg); + } + + if (!check_form_key($form_name)) + { + $error = 'FORM_INVALID'; + } + + if (!sizeof($error) && $submit) + { + $this->optionset($user_row, 'sig_bbcode', $enable_bbcode); + $this->optionset($user_row, 'sig_smilies', $enable_smilies); + $this->optionset($user_row, 'sig_links', $enable_urls); + + $sql_ary = array( + 'user_sig' => (string) $message_parser->message, + 'user_options' => $user_row['user_options'], + 'user_sig_bbcode_uid' => (string) $message_parser->bbcode_uid, + 'user_sig_bbcode_bitfield' => (string) $message_parser->bbcode_bitfield + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . $user_id; + $db->sql_query($sql); + + trigger_error($user->lang['USER_SIG_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + } + + $signature_preview = ''; + + if ($preview) + { + // Now parse it for displaying + $signature_preview = $message_parser->format_display($enable_bbcode, $enable_urls, $enable_smilies, false); + unset($message_parser); + } + + decode_message($signature, $user_row['user_sig_bbcode_uid']); + + $template->assign_vars(array( + 'S_SIGNATURE' => true, + + 'SIGNATURE' => $signature, + 'SIGNATURE_PREVIEW' => $signature_preview, + + 'S_BBCODE_CHECKED' => (!$enable_bbcode) ? ' checked="checked"' : '', + 'S_SMILIES_CHECKED' => (!$enable_smilies) ? ' checked="checked"' : '', + 'S_MAGIC_URL_CHECKED' => (!$enable_urls) ? ' checked="checked"' : '', + + 'BBCODE_STATUS' => ($config['allow_sig_bbcode']) ? sprintf($user->lang['BBCODE_IS_ON'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>') : sprintf($user->lang['BBCODE_IS_OFF'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>'), + 'SMILIES_STATUS' => ($config['allow_sig_smilies']) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'], + 'IMG_STATUS' => ($config['allow_sig_img']) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'], + 'FLASH_STATUS' => ($config['allow_sig_flash']) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], + 'URL_STATUS' => ($config['allow_sig_links']) ? $user->lang['URL_IS_ON'] : $user->lang['URL_IS_OFF'], + + 'L_SIGNATURE_EXPLAIN' => sprintf($user->lang['SIGNATURE_EXPLAIN'], $config['max_sig_chars']), + + 'S_BBCODE_ALLOWED' => $config['allow_sig_bbcode'], + 'S_SMILIES_ALLOWED' => $config['allow_sig_smilies'], + 'S_BBCODE_IMG' => ($config['allow_sig_img']) ? true : false, + 'S_BBCODE_FLASH' => ($config['allow_sig_flash']) ? true : false, + 'S_LINKS_ALLOWED' => ($config['allow_sig_links']) ? true : false) + ); + + // Assigning custom bbcodes + display_custom_bbcodes(); + + break; + + case 'attach': + + $start = request_var('start', 0); + $deletemark = (isset($_POST['delmarked'])) ? true : false; + $marked = request_var('mark', array(0)); + + // Sort keys + $sort_key = request_var('sk', 'a'); + $sort_dir = request_var('sd', 'd'); + + if ($deletemark && sizeof($marked)) + { + $sql = 'SELECT attach_id + FROM ' . ATTACHMENTS_TABLE . ' + WHERE poster_id = ' . $user_id . ' + AND is_orphan = 0 + AND ' . $db->sql_in_set('attach_id', $marked); + $result = $db->sql_query($sql); + + $marked = array(); + while ($row = $db->sql_fetchrow($result)) + { + $marked[] = $row['attach_id']; + } + $db->sql_freeresult($result); + } + + if ($deletemark && sizeof($marked)) + { + if (confirm_box(true)) + { + $sql = 'SELECT real_filename + FROM ' . ATTACHMENTS_TABLE . ' + WHERE ' . $db->sql_in_set('attach_id', $marked); + $result = $db->sql_query($sql); + + $log_attachments = array(); + while ($row = $db->sql_fetchrow($result)) + { + $log_attachments[] = $row['real_filename']; + } + $db->sql_freeresult($result); + + delete_attachments('attach', $marked); + + $message = (sizeof($log_attachments) == 1) ? $user->lang['ATTACHMENT_DELETED'] : $user->lang['ATTACHMENTS_DELETED']; + + add_log('admin', 'LOG_ATTACHMENTS_DELETED', implode(', ', $log_attachments)); + trigger_error($message . adm_back_link($this->u_action . '&u=' . $user_id)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'u' => $user_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'delmarked' => true, + 'mark' => $marked)) + ); + } + } + + $sk_text = array('a' => $user->lang['SORT_FILENAME'], 'c' => $user->lang['SORT_EXTENSION'], 'd' => $user->lang['SORT_SIZE'], 'e' => $user->lang['SORT_DOWNLOADS'], 'f' => $user->lang['SORT_POST_TIME'], 'g' => $user->lang['SORT_TOPIC_TITLE']); + $sk_sql = array('a' => 'a.real_filename', 'c' => 'a.extension', 'd' => 'a.filesize', 'e' => 'a.download_count', 'f' => 'a.filetime', 'g' => 't.topic_title'); + + $sd_text = array('a' => $user->lang['ASCENDING'], 'd' => $user->lang['DESCENDING']); + + $s_sort_key = ''; + foreach ($sk_text as $key => $value) + { + $selected = ($sort_key == $key) ? ' selected="selected"' : ''; + $s_sort_key .= '<option value="' . $key . '"' . $selected . '>' . $value . '</option>'; + } + + $s_sort_dir = ''; + foreach ($sd_text as $key => $value) + { + $selected = ($sort_dir == $key) ? ' selected="selected"' : ''; + $s_sort_dir .= '<option value="' . $key . '"' . $selected . '>' . $value . '</option>'; + } + + if (!isset($sk_sql[$sort_key])) + { + $sort_key = 'a'; + } + + $order_by = $sk_sql[$sort_key] . ' ' . (($sort_dir == 'a') ? 'ASC' : 'DESC'); + + $sql = 'SELECT COUNT(attach_id) as num_attachments + FROM ' . ATTACHMENTS_TABLE . " + WHERE poster_id = $user_id + AND is_orphan = 0"; + $result = $db->sql_query_limit($sql, 1); + $num_attachments = (int) $db->sql_fetchfield('num_attachments'); + $db->sql_freeresult($result); + + $sql = 'SELECT a.*, t.topic_title, p.message_subject as message_title + FROM ' . ATTACHMENTS_TABLE . ' a + LEFT JOIN ' . TOPICS_TABLE . ' t ON (a.topic_id = t.topic_id + AND a.in_message = 0) + LEFT JOIN ' . PRIVMSGS_TABLE . ' p ON (a.post_msg_id = p.msg_id + AND a.in_message = 1) + WHERE a.poster_id = ' . $user_id . " + AND a.is_orphan = 0 + ORDER BY $order_by"; + $result = $db->sql_query_limit($sql, $config['posts_per_page'], $start); + + while ($row = $db->sql_fetchrow($result)) + { + if ($row['in_message']) + { + $view_topic = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=pm&p={$row['post_msg_id']}"); + } + else + { + $view_topic = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "t={$row['topic_id']}&p={$row['post_msg_id']}") . '#p' . $row['post_msg_id']; + } + + $template->assign_block_vars('attach', array( + 'REAL_FILENAME' => $row['real_filename'], + 'COMMENT' => nl2br($row['attach_comment']), + 'EXTENSION' => $row['extension'], + 'SIZE' => get_formatted_filesize($row['filesize']), + 'DOWNLOAD_COUNT' => $row['download_count'], + 'POST_TIME' => $user->format_date($row['filetime']), + 'TOPIC_TITLE' => ($row['in_message']) ? $row['message_title'] : $row['topic_title'], + + 'ATTACH_ID' => $row['attach_id'], + 'POST_ID' => $row['post_msg_id'], + 'TOPIC_ID' => $row['topic_id'], + + 'S_IN_MESSAGE' => $row['in_message'], + + 'U_DOWNLOAD' => append_sid("{$phpbb_root_path}download/file.$phpEx", 'mode=view&id=' . $row['attach_id']), + 'U_VIEW_TOPIC' => $view_topic) + ); + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'S_ATTACHMENTS' => true, + 'S_ON_PAGE' => on_page($num_attachments, $config['topics_per_page'], $start), + 'S_SORT_KEY' => $s_sort_key, + 'S_SORT_DIR' => $s_sort_dir, + + 'PAGINATION' => generate_pagination($this->u_action . "&u=$user_id&sk=$sort_key&sd=$sort_dir", $num_attachments, $config['topics_per_page'], $start, true)) + ); + + break; + + case 'groups': + + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + + $user->add_lang(array('groups', 'acp/groups')); + $group_id = request_var('g', 0); + + if ($group_id) + { + // Check the founder only entry for this group to make sure everything is well + $sql = 'SELECT group_founder_manage + FROM ' . GROUPS_TABLE . ' + WHERE group_id = ' . $group_id; + $result = $db->sql_query($sql); + $founder_manage = (int) $db->sql_fetchfield('group_founder_manage'); + $db->sql_freeresult($result); + + if ($user->data['user_type'] != USER_FOUNDER && $founder_manage) + { + trigger_error($user->lang['NOT_ALLOWED_MANAGE_GROUP'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + } + else + { + $founder_manage = 0; + } + + switch ($action) + { + case 'demote': + case 'promote': + case 'default': + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + group_user_attributes($action, $group_id, $user_id); + + if ($action == 'default') + { + $user_row['group_id'] = $group_id; + } + break; + + case 'delete': + + if (confirm_box(true)) + { + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if ($error = group_user_del($group_id, $user_id)) + { + trigger_error($user->lang[$error] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + $error = array(); + + // The delete action was successful - therefore update the user row... + $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 = ' . $user_id . ' + ORDER BY s.session_time DESC'; + $result = $db->sql_query($sql); + $user_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'u' => $user_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'g' => $group_id)) + ); + } + + break; + + case 'approve': + + if (confirm_box(true)) + { + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + group_user_attributes($action, $group_id, $user_id); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'u' => $user_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'g' => $group_id)) + ); + } + + break; + } + + // Add user to group? + if ($submit) + { + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + // Add user/s to group + if ($error = group_user_add($group_id, $user_id)) + { + trigger_error($user->lang[$error] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + $error = array(); + } + + + $sql = 'SELECT ug.*, g.* + FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . " ug + WHERE ug.user_id = $user_id + AND g.group_id = ug.group_id + ORDER BY g.group_type DESC, ug.user_pending ASC, g.group_name"; + $result = $db->sql_query($sql); + + $i = 0; + $group_data = $id_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $type = ($row['group_type'] == GROUP_SPECIAL) ? 'special' : (($row['user_pending']) ? 'pending' : 'normal'); + + $group_data[$type][$i]['group_id'] = $row['group_id']; + $group_data[$type][$i]['group_name'] = $row['group_name']; + $group_data[$type][$i]['group_leader'] = ($row['group_leader']) ? 1 : 0; + + $id_ary[] = $row['group_id']; + + $i++; + } + $db->sql_freeresult($result); + + // Select box for other groups + $sql = 'SELECT group_id, group_name, group_type, group_founder_manage + FROM ' . GROUPS_TABLE . ' + ' . ((sizeof($id_ary)) ? 'WHERE ' . $db->sql_in_set('group_id', $id_ary, true) : '') . ' + ORDER BY group_type DESC, group_name ASC'; + $result = $db->sql_query($sql); + + $s_group_options = ''; + while ($row = $db->sql_fetchrow($result)) + { + if (!$config['coppa_enable'] && $row['group_name'] == 'REGISTERED_COPPA') + { + continue; + } + + // Do not display those groups not allowed to be managed + if ($user->data['user_type'] != USER_FOUNDER && $row['group_founder_manage']) + { + continue; + } + + $s_group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '">' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>'; + } + $db->sql_freeresult($result); + + $current_type = ''; + foreach ($group_data as $group_type => $data_ary) + { + if ($current_type != $group_type) + { + $template->assign_block_vars('group', array( + 'S_NEW_GROUP_TYPE' => true, + 'GROUP_TYPE' => $user->lang['USER_GROUP_' . strtoupper($group_type)]) + ); + } + + foreach ($data_ary as $data) + { + $template->assign_block_vars('group', array( + 'U_EDIT_GROUP' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=groups&mode=manage&action=edit&u=$user_id&g={$data['group_id']}&back_link=acp_users_groups"), + 'U_DEFAULT' => $this->u_action . "&action=default&u=$user_id&g=" . $data['group_id'], + 'U_DEMOTE_PROMOTE' => $this->u_action . '&action=' . (($data['group_leader']) ? 'demote' : 'promote') . "&u=$user_id&g=" . $data['group_id'], + 'U_DELETE' => $this->u_action . "&action=delete&u=$user_id&g=" . $data['group_id'], + 'U_APPROVE' => ($group_type == 'pending') ? $this->u_action . "&action=approve&u=$user_id&g=" . $data['group_id'] : '', + + 'GROUP_NAME' => ($group_type == 'special') ? $user->lang['G_' . $data['group_name']] : $data['group_name'], + 'L_DEMOTE_PROMOTE' => ($data['group_leader']) ? $user->lang['GROUP_DEMOTE'] : $user->lang['GROUP_PROMOTE'], + + 'S_IS_MEMBER' => ($group_type != 'pending') ? true : false, + 'S_NO_DEFAULT' => ($user_row['group_id'] != $data['group_id']) ? true : false, + 'S_SPECIAL_GROUP' => ($group_type == 'special') ? true : false, + ) + ); + } + } + + $template->assign_vars(array( + 'S_GROUPS' => true, + 'S_GROUP_OPTIONS' => $s_group_options) + ); + + break; + + case 'perm': + + include_once($phpbb_root_path . 'includes/acp/auth.' . $phpEx); + + $auth_admin = new auth_admin(); + + $user->add_lang('acp/permissions'); + add_permission_language(); + + $forum_id = request_var('f', 0); + + // Global Permissions + if (!$forum_id) + { + // Select auth options + $sql = 'SELECT auth_option, is_local, is_global + FROM ' . ACL_OPTIONS_TABLE . ' + WHERE auth_option ' . $db->sql_like_expression($db->any_char . '_') . ' + AND is_global = 1 + ORDER BY auth_option'; + $result = $db->sql_query($sql); + + $hold_ary = array(); + + while ($row = $db->sql_fetchrow($result)) + { + $hold_ary = $auth_admin->get_mask('view', $user_id, false, false, $row['auth_option'], 'global', ACL_NEVER); + $auth_admin->display_mask('view', $row['auth_option'], $hold_ary, 'user', false, false); + } + $db->sql_freeresult($result); + + unset($hold_ary); + } + else + { + $sql = 'SELECT auth_option, is_local, is_global + FROM ' . ACL_OPTIONS_TABLE . " + WHERE auth_option " . $db->sql_like_expression($db->any_char . '_') . " + AND is_local = 1 + ORDER BY is_global DESC, auth_option"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $hold_ary = $auth_admin->get_mask('view', $user_id, false, $forum_id, $row['auth_option'], 'local', ACL_NEVER); + $auth_admin->display_mask('view', $row['auth_option'], $hold_ary, 'user', true, false); + } + $db->sql_freeresult($result); + } + + $s_forum_options = '<option value="0"' . ((!$forum_id) ? ' selected="selected"' : '') . '>' . $user->lang['VIEW_GLOBAL_PERMS'] . '</option>'; + $s_forum_options .= make_forum_select($forum_id, false, true, false, false, false); + + $template->assign_vars(array( + 'S_PERMISSIONS' => true, + + 'S_GLOBAL' => (!$forum_id) ? true : false, + 'S_FORUM_OPTIONS' => $s_forum_options, + + 'U_ACTION' => $this->u_action . '&u=' . $user_id, + 'U_USER_PERMISSIONS' => append_sid("{$phpbb_admin_path}index.$phpEx" ,'i=permissions&mode=setting_user_global&user_id[]=' . $user_id), + 'U_USER_FORUM_PERMISSIONS' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=permissions&mode=setting_user_local&user_id[]=' . $user_id)) + ); + + break; + + } + + // Assign general variables + $template->assign_vars(array( + 'S_ERROR' => (sizeof($error)) ? true : false, + 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '') + ); + } + + /** + * Optionset replacement for this module based on $user->optionset + */ + function optionset(&$user_row, $key, $value, $data = false) + { + global $user; + + $var = ($data) ? $data : $user_row['user_options']; + + if ($value && !($var & 1 << $user->keyoptions[$key])) + { + $var += 1 << $user->keyoptions[$key]; + } + else if (!$value && ($var & 1 << $user->keyoptions[$key])) + { + $var -= 1 << $user->keyoptions[$key]; + } + else + { + return ($data) ? $var : false; + } + + if (!$data) + { + $user_row['user_options'] = $var; + return true; + } + else + { + return $var; + } + } + + /** + * Optionget replacement for this module based on $user->optionget + */ + function optionget(&$user_row, $key, $data = false) + { + global $user; + + $var = ($data) ? $data : $user_row['user_options']; + return ($var & 1 << $user->keyoptions[$key]) ? true : false; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_words.php b/phpBB/includes/acp/acp_words.php new file mode 100644 index 0000000000..1cb9545967 --- /dev/null +++ b/phpBB/includes/acp/acp_words.php @@ -0,0 +1,187 @@ +<?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; +} + +/** +* @todo [words] check regular expressions for special char replacements (stored specialchared in db) +* @package acp +*/ +class acp_words +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + $user->add_lang('acp/posting'); + + // Set up general vars + $action = request_var('action', ''); + $action = (isset($_POST['add'])) ? 'add' : ((isset($_POST['save'])) ? 'save' : $action); + + $s_hidden_fields = ''; + $word_info = array(); + + $this->tpl_name = 'acp_words'; + $this->page_title = 'ACP_WORDS'; + + $form_name = 'acp_words'; + add_form_key($form_name); + + switch ($action) + { + case 'edit': + + $word_id = request_var('id', 0); + + if (!$word_id) + { + trigger_error($user->lang['NO_WORD'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT * + FROM ' . WORDS_TABLE . " + WHERE word_id = $word_id"; + $result = $db->sql_query($sql); + $word_info = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $s_hidden_fields .= '<input type="hidden" name="id" value="' . $word_id . '" />'; + + case 'add': + + $template->assign_vars(array( + 'S_EDIT_WORD' => true, + 'U_ACTION' => $this->u_action, + 'U_BACK' => $this->u_action, + 'WORD' => (isset($word_info['word'])) ? $word_info['word'] : '', + 'REPLACEMENT' => (isset($word_info['replacement'])) ? $word_info['replacement'] : '', + 'S_HIDDEN_FIELDS' => $s_hidden_fields) + ); + + return; + + break; + + case 'save': + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); + } + + $word_id = request_var('id', 0); + $word = utf8_normalize_nfc(request_var('word', '', true)); + $replacement = utf8_normalize_nfc(request_var('replacement', '', true)); + + if ($word === '' || $replacement === '') + { + trigger_error($user->lang['ENTER_WORD'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql_ary = array( + 'word' => $word, + 'replacement' => $replacement + ); + + if ($word_id) + { + $db->sql_query('UPDATE ' . WORDS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' WHERE word_id = ' . $word_id); + } + else + { + $db->sql_query('INSERT INTO ' . WORDS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + } + + $cache->destroy('_word_censors'); + + $log_action = ($word_id) ? 'LOG_WORD_EDIT' : 'LOG_WORD_ADD'; + add_log('admin', $log_action, $word); + + $message = ($word_id) ? $user->lang['WORD_UPDATED'] : $user->lang['WORD_ADDED']; + trigger_error($message . adm_back_link($this->u_action)); + + break; + + case 'delete': + + $word_id = request_var('id', 0); + + if (!$word_id) + { + trigger_error($user->lang['NO_WORD'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (confirm_box(true)) + { + $sql = 'SELECT word + FROM ' . WORDS_TABLE . " + WHERE word_id = $word_id"; + $result = $db->sql_query($sql); + $deleted_word = $db->sql_fetchfield('word'); + $db->sql_freeresult($result); + + $sql = 'DELETE FROM ' . WORDS_TABLE . " + WHERE word_id = $word_id"; + $db->sql_query($sql); + + $cache->destroy('_word_censors'); + + add_log('admin', 'LOG_WORD_DELETE', $deleted_word); + + trigger_error($user->lang['WORD_REMOVED'] . adm_back_link($this->u_action)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'id' => $word_id, + 'action' => 'delete', + ))); + } + + break; + } + + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action, + 'S_HIDDEN_FIELDS' => $s_hidden_fields) + ); + + $sql = 'SELECT * + FROM ' . WORDS_TABLE . ' + ORDER BY word'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $template->assign_block_vars('words', array( + 'WORD' => $row['word'], + 'REPLACEMENT' => $row['replacement'], + 'U_EDIT' => $this->u_action . '&action=edit&id=' . $row['word_id'], + 'U_DELETE' => $this->u_action . '&action=delete&id=' . $row['word_id']) + ); + } + $db->sql_freeresult($result); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/auth.php b/phpBB/includes/acp/auth.php new file mode 100644 index 0000000000..10d7973da6 --- /dev/null +++ b/phpBB/includes/acp/auth.php @@ -0,0 +1,1285 @@ +<?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; +} + +/** +* ACP Permission/Auth class +* @package phpBB3 +*/ +class auth_admin extends auth +{ + /** + * Init auth settings + */ + function auth_admin() + { + global $db, $cache; + + if (($this->acl_options = $cache->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 = $db->sql_query($sql); + + $global = $local = 0; + $this->acl_options = array(); + while ($row = $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']; + } + $db->sql_freeresult($result); + + $cache->put('_acl_options', $this->acl_options); + } + } + + /** + * Get permission mask + * This function only supports getting permissions of one type (for example a_) + * + * @param set|view $mode defines the permissions we get, view gets effective permissions (checking user AND group permissions), set only gets the user or group permission set alone + * @param mixed $user_id user ids to search for (a user_id or a group_id has to be specified at least) + * @param mixed $group_id group ids to search for, return group related settings (a user_id or a group_id has to be specified at least) + * @param mixed $forum_id forum_ids to search for. Defining a forum id also means getting local settings + * @param string $auth_option the auth_option defines the permission setting to look for (a_ for example) + * @param local|global $scope the scope defines the permission scope. If local, a forum_id is additionally required + * @param ACL_NEVER|ACL_NO|ACL_YES $acl_fill defines the mode those permissions not set are getting filled with + */ + function get_mask($mode, $user_id = false, $group_id = false, $forum_id = false, $auth_option = false, $scope = false, $acl_fill = ACL_NEVER) + { + global $db, $user; + + $hold_ary = array(); + $view_user_mask = ($mode == 'view' && $group_id === false) ? true : false; + + if ($auth_option === false || $scope === false) + { + return array(); + } + + $acl_user_function = ($mode == 'set') ? 'acl_user_raw_data' : 'acl_raw_data'; + + if (!$view_user_mask) + { + if ($forum_id !== false) + { + $hold_ary = ($group_id !== false) ? $this->acl_group_raw_data($group_id, $auth_option . '%', $forum_id) : $this->$acl_user_function($user_id, $auth_option . '%', $forum_id); + } + else + { + $hold_ary = ($group_id !== false) ? $this->acl_group_raw_data($group_id, $auth_option . '%', ($scope == 'global') ? 0 : false) : $this->$acl_user_function($user_id, $auth_option . '%', ($scope == 'global') ? 0 : false); + } + } + + // Make sure hold_ary is filled with every setting (prevents missing forums/users/groups) + $ug_id = ($group_id !== false) ? ((!is_array($group_id)) ? array($group_id) : $group_id) : ((!is_array($user_id)) ? array($user_id) : $user_id); + $forum_ids = ($forum_id !== false) ? ((!is_array($forum_id)) ? array($forum_id) : $forum_id) : (($scope == 'global') ? array(0) : array()); + + // Only those options we need + $compare_options = array_diff(preg_replace('/^((?!' . $auth_option . ').+)|(' . $auth_option . ')$/', '', array_keys($this->acl_options[$scope])), array('')); + + // If forum_ids is false and the scope is local we actually want to have all forums within the array + if ($scope == 'local' && !sizeof($forum_ids)) + { + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE; + $result = $db->sql_query($sql, 120); + + while ($row = $db->sql_fetchrow($result)) + { + $forum_ids[] = (int) $row['forum_id']; + } + $db->sql_freeresult($result); + } + + if ($view_user_mask) + { + $auth2 = null; + + $sql = 'SELECT user_id, user_permissions, user_type + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', $ug_id); + $result = $db->sql_query($sql); + + while ($userdata = $db->sql_fetchrow($result)) + { + if ($user->data['user_id'] != $userdata['user_id']) + { + $auth2 = new auth(); + $auth2->acl($userdata); + } + else + { + global $auth; + $auth2 = &$auth; + } + + + $hold_ary[$userdata['user_id']] = array(); + foreach ($forum_ids as $f_id) + { + $hold_ary[$userdata['user_id']][$f_id] = array(); + foreach ($compare_options as $option) + { + $hold_ary[$userdata['user_id']][$f_id][$option] = $auth2->acl_get($option, $f_id); + } + } + } + $db->sql_freeresult($result); + + unset($userdata); + unset($auth2); + } + + foreach ($ug_id as $_id) + { + if (!isset($hold_ary[$_id])) + { + $hold_ary[$_id] = array(); + } + + foreach ($forum_ids as $f_id) + { + if (!isset($hold_ary[$_id][$f_id])) + { + $hold_ary[$_id][$f_id] = array(); + } + } + } + + // Now, we need to fill the gaps with $acl_fill. ;) + + // Now switch back to keys + if (sizeof($compare_options)) + { + $compare_options = array_combine($compare_options, array_fill(1, sizeof($compare_options), $acl_fill)); + } + + // Defining the user-function here to save some memory + $return_acl_fill = create_function('$value', 'return ' . $acl_fill . ';'); + + // Actually fill the gaps + if (sizeof($hold_ary)) + { + foreach ($hold_ary as $ug_id => $row) + { + foreach ($row as $id => $options) + { + // Do not include the global auth_option + unset($options[$auth_option]); + + // Not a "fine" solution, but at all it's a 1-dimensional + // array_diff_key function filling the resulting array values with zeros + // The differences get merged into $hold_ary (all permissions having $acl_fill set) + $hold_ary[$ug_id][$id] = array_merge($options, + + array_map($return_acl_fill, + array_flip( + array_diff( + array_keys($compare_options), array_keys($options) + ) + ) + ) + ); + } + } + } + else + { + $hold_ary[($group_id !== false) ? $group_id : $user_id][(int) $forum_id] = $compare_options; + } + + return $hold_ary; + } + + /** + * Get permission mask for roles + * This function only supports getting masks for one role + */ + function get_role_mask($role_id) + { + global $db; + + $hold_ary = array(); + + // Get users having this role set... + $sql = 'SELECT user_id, forum_id + FROM ' . ACL_USERS_TABLE . ' + WHERE auth_role_id = ' . $role_id . ' + ORDER BY forum_id'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $hold_ary[$row['forum_id']]['users'][] = $row['user_id']; + } + $db->sql_freeresult($result); + + // Now grab groups... + $sql = 'SELECT group_id, forum_id + FROM ' . ACL_GROUPS_TABLE . ' + WHERE auth_role_id = ' . $role_id . ' + ORDER BY forum_id'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $hold_ary[$row['forum_id']]['groups'][] = $row['group_id']; + } + $db->sql_freeresult($result); + + return $hold_ary; + } + + /** + * Display permission mask (assign to template) + */ + function display_mask($mode, $permission_type, &$hold_ary, $user_mode = 'user', $local = false, $group_display = true) + { + global $template, $user, $db, $phpbb_root_path, $phpEx; + + // Define names for template loops, might be able to be set + $tpl_pmask = 'p_mask'; + $tpl_fmask = 'f_mask'; + $tpl_category = 'category'; + $tpl_mask = 'mask'; + + $l_acl_type = (isset($user->lang['ACL_TYPE_' . (($local) ? 'LOCAL' : 'GLOBAL') . '_' . strtoupper($permission_type)])) ? $user->lang['ACL_TYPE_' . (($local) ? 'LOCAL' : 'GLOBAL') . '_' . strtoupper($permission_type)] : 'ACL_TYPE_' . (($local) ? 'LOCAL' : 'GLOBAL') . '_' . strtoupper($permission_type); + + // Allow trace for viewing permissions and in user mode + $show_trace = ($mode == 'view' && $user_mode == 'user') ? true : false; + + // Get names + if ($user_mode == 'user') + { + $sql = 'SELECT user_id as ug_id, username as ug_name + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', array_keys($hold_ary)) . ' + ORDER BY username_clean ASC'; + } + else + { + $sql = 'SELECT group_id as ug_id, group_name as ug_name, group_type + FROM ' . GROUPS_TABLE . ' + WHERE ' . $db->sql_in_set('group_id', array_keys($hold_ary)) . ' + ORDER BY group_type DESC, group_name ASC'; + } + $result = $db->sql_query($sql); + + $ug_names_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $ug_names_ary[$row['ug_id']] = ($user_mode == 'user') ? $row['ug_name'] : (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['ug_name']] : $row['ug_name']); + } + $db->sql_freeresult($result); + + // Get used forums + $forum_ids = array(); + foreach ($hold_ary as $ug_id => $row) + { + $forum_ids = array_merge($forum_ids, array_keys($row)); + } + $forum_ids = array_unique($forum_ids); + + $forum_names_ary = array(); + if ($local) + { + $forum_names_ary = make_forum_select(false, false, true, false, false, false, true); + + // Remove the disabled ones, since we do not create an option field here... + foreach ($forum_names_ary as $key => $value) + { + if (!$value['disabled']) + { + continue; + } + unset($forum_names_ary[$key]); + } + } + else + { + $forum_names_ary[0] = $l_acl_type; + } + + // Get available roles + $sql = 'SELECT * + FROM ' . ACL_ROLES_TABLE . " + WHERE role_type = '" . $db->sql_escape($permission_type) . "' + ORDER BY role_order ASC"; + $result = $db->sql_query($sql); + + $roles = array(); + while ($row = $db->sql_fetchrow($result)) + { + $roles[$row['role_id']] = $row; + } + $db->sql_freeresult($result); + + $cur_roles = $this->acl_role_data($user_mode, $permission_type, array_keys($hold_ary)); + + // Build js roles array (role data assignments) + $s_role_js_array = ''; + + if (sizeof($roles)) + { + $s_role_js_array = array(); + + // Make sure every role (even if empty) has its array defined + foreach ($roles as $_role_id => $null) + { + $s_role_js_array[$_role_id] = "\n" . 'role_options[' . $_role_id . '] = new Array();' . "\n"; + } + + $sql = 'SELECT r.role_id, o.auth_option, r.auth_setting + FROM ' . ACL_ROLES_DATA_TABLE . ' r, ' . ACL_OPTIONS_TABLE . ' o + WHERE o.auth_option_id = r.auth_option_id + AND ' . $db->sql_in_set('r.role_id', array_keys($roles)); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $flag = substr($row['auth_option'], 0, strpos($row['auth_option'], '_') + 1); + if ($flag == $row['auth_option']) + { + continue; + } + + $s_role_js_array[$row['role_id']] .= 'role_options[' . $row['role_id'] . '][\'' . addslashes($row['auth_option']) . '\'] = ' . $row['auth_setting'] . '; '; + } + $db->sql_freeresult($result); + + $s_role_js_array = implode('', $s_role_js_array); + } + + $template->assign_var('S_ROLE_JS_ARRAY', $s_role_js_array); + unset($s_role_js_array); + + // Now obtain memberships + $user_groups_default = $user_groups_custom = array(); + if ($user_mode == 'user' && $group_display) + { + $sql = 'SELECT group_id, group_name, group_type + FROM ' . GROUPS_TABLE . ' + ORDER BY group_type DESC, group_name ASC'; + $result = $db->sql_query($sql); + + $groups = array(); + while ($row = $db->sql_fetchrow($result)) + { + $groups[$row['group_id']] = $row; + } + $db->sql_freeresult($result); + + $memberships = group_memberships(false, array_keys($hold_ary), false); + + // User is not a member of any group? Bad admin, bad bad admin... + if ($memberships) + { + foreach ($memberships as $row) + { + if ($groups[$row['group_id']]['group_type'] == GROUP_SPECIAL) + { + $user_groups_default[$row['user_id']][] = $user->lang['G_' . $groups[$row['group_id']]['group_name']]; + } + else + { + $user_groups_custom[$row['user_id']][] = $groups[$row['group_id']]['group_name']; + } + } + } + unset($memberships, $groups); + } + + // If we only have one forum id to display or being in local mode and more than one user/group to display, + // we switch the complete interface to group by user/usergroup instead of grouping by forum + // To achieve this, we need to switch the array a bit + if (sizeof($forum_ids) == 1 || ($local && sizeof($ug_names_ary) > 1)) + { + $hold_ary_temp = $hold_ary; + $hold_ary = array(); + foreach ($hold_ary_temp as $ug_id => $row) + { + foreach ($forum_names_ary as $forum_id => $forum_row) + { + if (isset($row[$forum_id])) + { + $hold_ary[$forum_id][$ug_id] = $row[$forum_id]; + } + } + } + unset($hold_ary_temp); + + foreach ($hold_ary as $forum_id => $forum_array) + { + $content_array = $categories = array(); + $this->build_permission_array($hold_ary[$forum_id], $content_array, $categories, array_keys($ug_names_ary)); + + $template->assign_block_vars($tpl_pmask, array( + 'NAME' => ($forum_id == 0) ? $forum_names_ary[0] : $forum_names_ary[$forum_id]['forum_name'], + 'PADDING' => ($forum_id == 0) ? '' : $forum_names_ary[$forum_id]['padding'], + + 'CATEGORIES' => implode('</th><th>', $categories), + + 'L_ACL_TYPE' => $l_acl_type, + + 'S_LOCAL' => ($local) ? true : false, + 'S_GLOBAL' => (!$local) ? true : false, + 'S_NUM_CATS' => sizeof($categories), + 'S_VIEW' => ($mode == 'view') ? true : false, + 'S_NUM_OBJECTS' => sizeof($content_array), + 'S_USER_MODE' => ($user_mode == 'user') ? true : false, + 'S_GROUP_MODE' => ($user_mode == 'group') ? true : false) + ); + + @reset($content_array); + while (list($ug_id, $ug_array) = each($content_array)) + { + // Build role dropdown options + $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0; + + $s_role_options = ''; + + @reset($roles); + while (list($role_id, $role_row) = each($roles)) + { + $role_description = (!empty($user->lang[$role_row['role_description']])) ? $user->lang[$role_row['role_description']] : nl2br($role_row['role_description']); + $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name']; + + $title = ($role_description) ? ' title="' . $role_description . '"' : ''; + $s_role_options .= '<option value="' . $role_id . '"' . (($role_id == $current_role_id) ? ' selected="selected"' : '') . $title . '>' . $role_name . '</option>'; + } + + if ($s_role_options) + { + $s_role_options = '<option value="0"' . ((!$current_role_id) ? ' selected="selected"' : '') . ' title="' . htmlspecialchars($user->lang['NO_ROLE_ASSIGNED_EXPLAIN']) . '">' . $user->lang['NO_ROLE_ASSIGNED'] . '</option>' . $s_role_options; + } + + if (!$current_role_id && $mode != 'view') + { + $s_custom_permissions = false; + + foreach ($ug_array as $key => $value) + { + if ($value['S_NEVER'] || $value['S_YES']) + { + $s_custom_permissions = true; + break; + } + } + } + else + { + $s_custom_permissions = false; + } + + $template->assign_block_vars($tpl_pmask . '.' . $tpl_fmask, array( + 'NAME' => $ug_names_ary[$ug_id], + 'S_ROLE_OPTIONS' => $s_role_options, + 'UG_ID' => $ug_id, + 'S_CUSTOM' => $s_custom_permissions, + 'FORUM_ID' => $forum_id) + ); + + $this->assign_cat_array($ug_array, $tpl_pmask . '.' . $tpl_fmask . '.' . $tpl_category, $tpl_mask, $ug_id, $forum_id, $show_trace, ($mode == 'view')); + + unset($content_array[$ug_id]); + } + + unset($hold_ary[$forum_id]); + } + } + else + { + foreach ($ug_names_ary as $ug_id => $ug_name) + { + if (!isset($hold_ary[$ug_id])) + { + continue; + } + + $content_array = $categories = array(); + $this->build_permission_array($hold_ary[$ug_id], $content_array, $categories, array_keys($forum_names_ary)); + + $template->assign_block_vars($tpl_pmask, array( + 'NAME' => $ug_name, + 'CATEGORIES' => implode('</th><th>', $categories), + + 'USER_GROUPS_DEFAULT' => ($user_mode == 'user' && isset($user_groups_default[$ug_id]) && sizeof($user_groups_default[$ug_id])) ? implode(', ', $user_groups_default[$ug_id]) : '', + 'USER_GROUPS_CUSTOM' => ($user_mode == 'user' && isset($user_groups_custom[$ug_id]) && sizeof($user_groups_custom[$ug_id])) ? implode(', ', $user_groups_custom[$ug_id]) : '', + 'L_ACL_TYPE' => $l_acl_type, + + 'S_LOCAL' => ($local) ? true : false, + 'S_GLOBAL' => (!$local) ? true : false, + 'S_NUM_CATS' => sizeof($categories), + 'S_VIEW' => ($mode == 'view') ? true : false, + 'S_NUM_OBJECTS' => sizeof($content_array), + 'S_USER_MODE' => ($user_mode == 'user') ? true : false, + 'S_GROUP_MODE' => ($user_mode == 'group') ? true : false) + ); + + @reset($content_array); + while (list($forum_id, $forum_array) = each($content_array)) + { + // Build role dropdown options + $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0; + + $s_role_options = ''; + + @reset($roles); + while (list($role_id, $role_row) = each($roles)) + { + $role_description = (!empty($user->lang[$role_row['role_description']])) ? $user->lang[$role_row['role_description']] : nl2br($role_row['role_description']); + $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name']; + + $title = ($role_description) ? ' title="' . $role_description . '"' : ''; + $s_role_options .= '<option value="' . $role_id . '"' . (($role_id == $current_role_id) ? ' selected="selected"' : '') . $title . '>' . $role_name . '</option>'; + } + + if ($s_role_options) + { + $s_role_options = '<option value="0"' . ((!$current_role_id) ? ' selected="selected"' : '') . ' title="' . htmlspecialchars($user->lang['NO_ROLE_ASSIGNED_EXPLAIN']) . '">' . $user->lang['NO_ROLE_ASSIGNED'] . '</option>' . $s_role_options; + } + + if (!$current_role_id && $mode != 'view') + { + $s_custom_permissions = false; + + foreach ($forum_array as $key => $value) + { + if ($value['S_NEVER'] || $value['S_YES']) + { + $s_custom_permissions = true; + break; + } + } + } + else + { + $s_custom_permissions = false; + } + + $template->assign_block_vars($tpl_pmask . '.' . $tpl_fmask, array( + 'NAME' => ($forum_id == 0) ? $forum_names_ary[0] : $forum_names_ary[$forum_id]['forum_name'], + 'PADDING' => ($forum_id == 0) ? '' : $forum_names_ary[$forum_id]['padding'], + 'S_ROLE_OPTIONS' => $s_role_options, + 'S_CUSTOM' => $s_custom_permissions, + 'UG_ID' => $ug_id, + 'FORUM_ID' => $forum_id) + ); + + $this->assign_cat_array($forum_array, $tpl_pmask . '.' . $tpl_fmask . '.' . $tpl_category, $tpl_mask, $ug_id, $forum_id, $show_trace, ($mode == 'view')); + } + + unset($hold_ary[$ug_id], $ug_names_ary[$ug_id]); + } + } + } + + /** + * Display permission mask for roles + */ + function display_role_mask(&$hold_ary) + { + global $db, $template, $user, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + if (!sizeof($hold_ary)) + { + return; + } + + // Get forum names + $sql = 'SELECT forum_id, forum_name + FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', array_keys($hold_ary)) . ' + ORDER BY left_id'; + $result = $db->sql_query($sql); + + // If the role is used globally, then reflect that + $forum_names = (isset($hold_ary[0])) ? array(0 => '') : array(); + while ($row = $db->sql_fetchrow($result)) + { + $forum_names[$row['forum_id']] = $row['forum_name']; + } + $db->sql_freeresult($result); + + foreach ($forum_names as $forum_id => $forum_name) + { + $auth_ary = $hold_ary[$forum_id]; + + $template->assign_block_vars('role_mask', array( + 'NAME' => ($forum_id == 0) ? $user->lang['GLOBAL_MASK'] : $forum_name, + 'FORUM_ID' => $forum_id) + ); + + if (isset($auth_ary['users']) && sizeof($auth_ary['users'])) + { + $sql = 'SELECT user_id, username + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', $auth_ary['users']) . ' + ORDER BY username_clean ASC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $template->assign_block_vars('role_mask.users', array( + 'USER_ID' => $row['user_id'], + 'USERNAME' => $row['username'], + 'U_PROFILE' => append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=viewprofile&u={$row['user_id']}")) + ); + } + $db->sql_freeresult($result); + } + + if (isset($auth_ary['groups']) && sizeof($auth_ary['groups'])) + { + $sql = 'SELECT group_id, group_name, group_type + FROM ' . GROUPS_TABLE . ' + WHERE ' . $db->sql_in_set('group_id', $auth_ary['groups']) . ' + ORDER BY group_type ASC, group_name'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $template->assign_block_vars('role_mask.groups', array( + 'GROUP_ID' => $row['group_id'], + 'GROUP_NAME' => ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'], + 'U_PROFILE' => append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=group&g={$row['group_id']}")) + ); + } + $db->sql_freeresult($result); + } + } + } + + /** + * NOTE: this function is not in use atm + * Add a new option to the list ... $options is a hash of form -> + * $options = array( + * 'local' => array('option1', 'option2', ...), + * 'global' => array('optionA', 'optionB', ...) + * ); + */ + function acl_add_option($options) + { + global $db, $cache; + + if (!is_array($options)) + { + return false; + } + + $cur_options = array(); + + // Determine current options + $sql = 'SELECT auth_option, is_global, is_local + FROM ' . ACL_OPTIONS_TABLE . ' + ORDER BY auth_option_id'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $cur_options[$row['auth_option']] = ($row['is_global'] && $row['is_local']) ? 'both' : (($row['is_global']) ? 'global' : 'local'); + } + $db->sql_freeresult($result); + + // Here we need to insert new options ... this requires discovering whether + // an options is global, local or both and whether we need to add an permission + // set flag (x_) + $new_options = array('local' => array(), 'global' => array()); + + foreach ($options as $type => $option_ary) + { + $option_ary = array_unique($option_ary); + + foreach ($option_ary as $option_value) + { + $new_options[$type][] = $option_value; + + $flag = substr($option_value, 0, strpos($option_value, '_') + 1); + + if (!in_array($flag, $new_options[$type])) + { + $new_options[$type][] = $flag; + } + } + } + unset($options); + + $options = array(); + $options['local'] = array_diff($new_options['local'], $new_options['global']); + $options['global'] = array_diff($new_options['global'], $new_options['local']); + $options['both'] = array_intersect($new_options['local'], $new_options['global']); + + // Now check which options to add/update + $add_options = $update_options = array(); + + // First local ones... + foreach ($options as $type => $option_ary) + { + foreach ($option_ary as $option) + { + if (!isset($cur_options[$option])) + { + $add_options[] = array( + 'auth_option' => (string) $option, + 'is_global' => ($type == 'global' || $type == 'both') ? 1 : 0, + 'is_local' => ($type == 'local' || $type == 'both') ? 1 : 0 + ); + + continue; + } + + // Else, update existing entry if it is changed... + if ($type === $cur_options[$option]) + { + continue; + } + + // New type is always both: + // If is now both, we set both. + // If it was global the new one is local and we need to set it to both + // If it was local the new one is global and we need to set it to both + $update_options[] = $option; + } + } + + if (!empty($add_options)) + { + $db->sql_multi_insert(ACL_OPTIONS_TABLE, $add_options); + } + + if (!empty($update_options)) + { + $sql = 'UPDATE ' . ACL_OPTIONS_TABLE . ' + SET is_global = 1, is_local = 1 + WHERE ' . $db->sql_in_set('auth_option', $update_options); + $db->sql_query($sql); + } + + $cache->destroy('_acl_options'); + $this->acl_clear_prefetch(); + + // Because we just changed the options and also purged the options cache, we instantly update/regenerate it for later calls to succeed. + $this->acl_options = array(); + $this->auth_admin(); + + return true; + } + + /** + * Set a user or group ACL record + */ + function acl_set($ug_type, $forum_id, $ug_id, $auth, $role_id = 0, $clear_prefetch = true) + { + global $db; + + // One or more forums + if (!is_array($forum_id)) + { + $forum_id = array($forum_id); + } + + // One or more users + if (!is_array($ug_id)) + { + $ug_id = array($ug_id); + } + + $ug_id_sql = $db->sql_in_set($ug_type . '_id', array_map('intval', $ug_id)); + $forum_sql = $db->sql_in_set('forum_id', array_map('intval', $forum_id)); + + // Instead of updating, inserting, removing we just remove all current settings and re-set everything... + $table = ($ug_type == 'user') ? ACL_USERS_TABLE : ACL_GROUPS_TABLE; + $id_field = $ug_type . '_id'; + + // Get any flags as required + reset($auth); + $flag = key($auth); + $flag = substr($flag, 0, strpos($flag, '_') + 1); + + // This ID (the any-flag) is set if one or more permissions are true... + $any_option_id = (int) $this->acl_options['id'][$flag]; + + // Remove any-flag from auth ary + if (isset($auth[$flag])) + { + unset($auth[$flag]); + } + + // Remove current auth options... + $auth_option_ids = array((int)$any_option_id); + foreach ($auth as $auth_option => $auth_setting) + { + $auth_option_ids[] = (int) $this->acl_options['id'][$auth_option]; + } + + $sql = "DELETE FROM $table + WHERE $forum_sql + AND $ug_id_sql + AND " . $db->sql_in_set('auth_option_id', $auth_option_ids); + $db->sql_query($sql); + + // Remove those having a role assigned... the correct type of course... + $sql = 'SELECT role_id + FROM ' . ACL_ROLES_TABLE . " + WHERE role_type = '" . $db->sql_escape($flag) . "'"; + $result = $db->sql_query($sql); + + $role_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $role_ids[] = $row['role_id']; + } + $db->sql_freeresult($result); + + if (sizeof($role_ids)) + { + $sql = "DELETE FROM $table + WHERE $forum_sql + AND $ug_id_sql + AND auth_option_id = 0 + AND " . $db->sql_in_set('auth_role_id', $role_ids); + $db->sql_query($sql); + } + + // Ok, include the any-flag if one or more auth options are set to yes... + foreach ($auth as $auth_option => $setting) + { + if ($setting == ACL_YES && (!isset($auth[$flag]) || $auth[$flag] == ACL_NEVER)) + { + $auth[$flag] = ACL_YES; + } + } + + $sql_ary = array(); + foreach ($forum_id as $forum) + { + $forum = (int) $forum; + + if ($role_id) + { + foreach ($ug_id as $id) + { + $sql_ary[] = array( + $id_field => (int) $id, + 'forum_id' => (int) $forum, + 'auth_option_id' => 0, + 'auth_setting' => 0, + 'auth_role_id' => (int) $role_id, + ); + } + } + else + { + foreach ($auth as $auth_option => $setting) + { + $auth_option_id = (int) $this->acl_options['id'][$auth_option]; + + if ($setting != ACL_NO) + { + foreach ($ug_id as $id) + { + $sql_ary[] = array( + $id_field => (int) $id, + 'forum_id' => (int) $forum, + 'auth_option_id' => (int) $auth_option_id, + 'auth_setting' => (int) $setting + ); + } + } + } + } + } + + $db->sql_multi_insert($table, $sql_ary); + + if ($clear_prefetch) + { + $this->acl_clear_prefetch(); + } + } + + /** + * Set a role-specific ACL record + */ + function acl_set_role($role_id, $auth) + { + global $db; + + // Get any-flag as required + reset($auth); + $flag = key($auth); + $flag = substr($flag, 0, strpos($flag, '_') + 1); + + // Remove any-flag from auth ary + if (isset($auth[$flag])) + { + unset($auth[$flag]); + } + + // Re-set any flag... + foreach ($auth as $auth_option => $setting) + { + if ($setting == ACL_YES && (!isset($auth[$flag]) || $auth[$flag] == ACL_NEVER)) + { + $auth[$flag] = ACL_YES; + } + } + + $sql_ary = array(); + foreach ($auth as $auth_option => $setting) + { + $auth_option_id = (int) $this->acl_options['id'][$auth_option]; + + if ($setting != ACL_NO) + { + $sql_ary[] = array( + 'role_id' => (int) $role_id, + 'auth_option_id' => (int) $auth_option_id, + 'auth_setting' => (int) $setting + ); + } + } + + // If no data is there, we set the any-flag to ACL_NEVER... + if (!sizeof($sql_ary)) + { + $sql_ary[] = array( + 'role_id' => (int) $role_id, + 'auth_option_id' => (int) $this->acl_options['id'][$flag], + 'auth_setting' => ACL_NEVER + ); + } + + // Remove current auth options... + $sql = 'DELETE FROM ' . ACL_ROLES_DATA_TABLE . ' + WHERE role_id = ' . $role_id; + $db->sql_query($sql); + + // Now insert the new values + $db->sql_multi_insert(ACL_ROLES_DATA_TABLE, $sql_ary); + + $this->acl_clear_prefetch(); + } + + /** + * Remove local permission + */ + function acl_delete($mode, $ug_id = false, $forum_id = false, $permission_type = false) + { + global $db; + + if ($ug_id === false && $forum_id === false) + { + return; + } + + $option_id_ary = array(); + $table = ($mode == 'user') ? ACL_USERS_TABLE : ACL_GROUPS_TABLE; + $id_field = $mode . '_id'; + + $where_sql = array(); + + if ($forum_id !== false) + { + $where_sql[] = (!is_array($forum_id)) ? 'forum_id = ' . (int) $forum_id : $db->sql_in_set('forum_id', array_map('intval', $forum_id)); + } + + if ($ug_id !== false) + { + $where_sql[] = (!is_array($ug_id)) ? $id_field . ' = ' . (int) $ug_id : $db->sql_in_set($id_field, array_map('intval', $ug_id)); + } + + // There seem to be auth options involved, therefore we need to go through the list and make sure we capture roles correctly + if ($permission_type !== false) + { + // Get permission type + $sql = 'SELECT auth_option, auth_option_id + FROM ' . ACL_OPTIONS_TABLE . " + WHERE auth_option " . $db->sql_like_expression($permission_type . $db->any_char); + $result = $db->sql_query($sql); + + $auth_id_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $option_id_ary[] = $row['auth_option_id']; + $auth_id_ary[$row['auth_option']] = ACL_NO; + } + $db->sql_freeresult($result); + + // First of all, lets grab the items having roles with the specified auth options assigned + $sql = "SELECT auth_role_id, $id_field, forum_id + FROM $table, " . ACL_ROLES_TABLE . " r + WHERE auth_role_id <> 0 + AND auth_role_id = r.role_id + AND r.role_type = '{$permission_type}' + AND " . implode(' AND ', $where_sql) . ' + ORDER BY auth_role_id'; + $result = $db->sql_query($sql); + + $cur_role_auth = array(); + while ($row = $db->sql_fetchrow($result)) + { + $cur_role_auth[$row['auth_role_id']][$row['forum_id']][] = $row[$id_field]; + } + $db->sql_freeresult($result); + + // Get role data for resetting data + if (sizeof($cur_role_auth)) + { + $sql = 'SELECT ao.auth_option, rd.role_id, rd.auth_setting + FROM ' . ACL_OPTIONS_TABLE . ' ao, ' . ACL_ROLES_DATA_TABLE . ' rd + WHERE ao.auth_option_id = rd.auth_option_id + AND ' . $db->sql_in_set('rd.role_id', array_keys($cur_role_auth)); + $result = $db->sql_query($sql); + + $auth_settings = array(); + while ($row = $db->sql_fetchrow($result)) + { + // We need to fill all auth_options, else setting it will fail... + if (!isset($auth_settings[$row['role_id']])) + { + $auth_settings[$row['role_id']] = $auth_id_ary; + } + $auth_settings[$row['role_id']][$row['auth_option']] = $row['auth_setting']; + } + $db->sql_freeresult($result); + + // Set the options + foreach ($cur_role_auth as $role_id => $auth_row) + { + foreach ($auth_row as $f_id => $ug_row) + { + $this->acl_set($mode, $f_id, $ug_row, $auth_settings[$role_id], 0, false); + } + } + } + } + + // Now, normally remove permissions... + if ($permission_type !== false) + { + $where_sql[] = $db->sql_in_set('auth_option_id', array_map('intval', $option_id_ary)); + } + + $sql = "DELETE FROM $table + WHERE " . implode(' AND ', $where_sql); + $db->sql_query($sql); + + $this->acl_clear_prefetch(); + } + + /** + * Assign category to template + * used by display_mask() + */ + function assign_cat_array(&$category_array, $tpl_cat, $tpl_mask, $ug_id, $forum_id, $show_trace = false, $s_view) + { + global $template, $user, $phpbb_admin_path, $phpEx; + + @reset($category_array); + while (list($cat, $cat_array) = each($category_array)) + { + $template->assign_block_vars($tpl_cat, array( + 'S_YES' => ($cat_array['S_YES'] && !$cat_array['S_NEVER'] && !$cat_array['S_NO']) ? true : false, + 'S_NEVER' => ($cat_array['S_NEVER'] && !$cat_array['S_YES'] && !$cat_array['S_NO']) ? true : false, + 'S_NO' => ($cat_array['S_NO'] && !$cat_array['S_NEVER'] && !$cat_array['S_YES']) ? true : false, + + 'CAT_NAME' => $user->lang['permission_cat'][$cat]) + ); + + /* Sort permissions by name (more naturaly and user friendly than sorting by a primary key) + * Commented out due to it's memory consumption and time needed + * + $key_array = array_intersect(array_keys($user->lang), array_map(create_function('$a', 'return "acl_" . $a;'), array_keys($cat_array['permissions']))); + $values_array = $cat_array['permissions']; + + $cat_array['permissions'] = array(); + + foreach ($key_array as $key) + { + $key = str_replace('acl_', '', $key); + $cat_array['permissions'][$key] = $values_array[$key]; + } + unset($key_array, $values_array); +*/ + @reset($cat_array['permissions']); + while (list($permission, $allowed) = each($cat_array['permissions'])) + { + if ($s_view) + { + $template->assign_block_vars($tpl_cat . '.' . $tpl_mask, array( + 'S_YES' => ($allowed == ACL_YES) ? true : false, + 'S_NEVER' => ($allowed == ACL_NEVER) ? true : false, + + 'UG_ID' => $ug_id, + 'FORUM_ID' => $forum_id, + 'FIELD_NAME' => $permission, + 'S_FIELD_NAME' => 'setting[' . $ug_id . '][' . $forum_id . '][' . $permission . ']', + + 'U_TRACE' => ($show_trace) ? append_sid("{$phpbb_admin_path}index.$phpEx", "i=permissions&mode=trace&u=$ug_id&f=$forum_id&auth=$permission") : '', + 'UA_TRACE' => ($show_trace) ? append_sid("{$phpbb_admin_path}index.$phpEx", "i=permissions&mode=trace&u=$ug_id&f=$forum_id&auth=$permission", false) : '', + + 'PERMISSION' => $user->lang['acl_' . $permission]['lang']) + ); + } + else + { + $template->assign_block_vars($tpl_cat . '.' . $tpl_mask, array( + 'S_YES' => ($allowed == ACL_YES) ? true : false, + 'S_NEVER' => ($allowed == ACL_NEVER) ? true : false, + 'S_NO' => ($allowed == ACL_NO) ? true : false, + + 'UG_ID' => $ug_id, + 'FORUM_ID' => $forum_id, + 'FIELD_NAME' => $permission, + 'S_FIELD_NAME' => 'setting[' . $ug_id . '][' . $forum_id . '][' . $permission . ']', + + 'U_TRACE' => ($show_trace) ? append_sid("{$phpbb_admin_path}index.$phpEx", "i=permissions&mode=trace&u=$ug_id&f=$forum_id&auth=$permission") : '', + 'UA_TRACE' => ($show_trace) ? append_sid("{$phpbb_admin_path}index.$phpEx", "i=permissions&mode=trace&u=$ug_id&f=$forum_id&auth=$permission", false) : '', + + 'PERMISSION' => $user->lang['acl_' . $permission]['lang']) + ); + } + } + } + } + + /** + * Building content array from permission rows with explicit key ordering + * used by display_mask() + */ + function build_permission_array(&$permission_row, &$content_array, &$categories, $key_sort_array) + { + global $user; + + foreach ($key_sort_array as $forum_id) + { + if (!isset($permission_row[$forum_id])) + { + continue; + } + + $permissions = $permission_row[$forum_id]; + ksort($permissions); + + @reset($permissions); + while (list($permission, $auth_setting) = each($permissions)) + { + if (!isset($user->lang['acl_' . $permission])) + { + $user->lang['acl_' . $permission] = array( + 'cat' => 'misc', + 'lang' => '{ acl_' . $permission . ' }' + ); + } + + $cat = $user->lang['acl_' . $permission]['cat']; + + // Build our categories array + if (!isset($categories[$cat])) + { + $categories[$cat] = $user->lang['permission_cat'][$cat]; + } + + // Build our content array + if (!isset($content_array[$forum_id])) + { + $content_array[$forum_id] = array(); + } + + if (!isset($content_array[$forum_id][$cat])) + { + $content_array[$forum_id][$cat] = array( + 'S_YES' => false, + 'S_NEVER' => false, + 'S_NO' => false, + 'permissions' => array(), + ); + } + + $content_array[$forum_id][$cat]['S_YES'] |= ($auth_setting == ACL_YES) ? true : false; + $content_array[$forum_id][$cat]['S_NEVER'] |= ($auth_setting == ACL_NEVER) ? true : false; + $content_array[$forum_id][$cat]['S_NO'] |= ($auth_setting == ACL_NO) ? true : false; + + $content_array[$forum_id][$cat]['permissions'][$permission] = $auth_setting; + } + } + } + + /** + * Use permissions from another user. This transferes a permission set from one user to another. + * The other user is always able to revert back to his permission set. + * This function does not check for lower/higher permissions, it is possible for the user to gain + * "more" permissions by this. + * Admin permissions will not be copied. + */ + function ghost_permissions($from_user_id, $to_user_id) + { + global $db; + + if ($to_user_id == ANONYMOUS) + { + return false; + } + + $hold_ary = $this->acl_raw_data_single_user($from_user_id); + + // Key 0 in $hold_ary are global options, all others are forum_ids + + // We disallow copying admin permissions + foreach ($this->acl_options['global'] as $opt => $id) + { + if (strpos($opt, 'a_') === 0) + { + $hold_ary[0][$this->acl_options['id'][$opt]] = ACL_NEVER; + } + } + + // Force a_switchperm to be allowed + $hold_ary[0][$this->acl_options['id']['a_switchperm']] = ACL_YES; + + $user_permissions = $this->build_bitstring($hold_ary); + + if (!$user_permissions) + { + return false; + } + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_permissions = '" . $db->sql_escape($user_permissions) . "', + user_perm_from = $from_user_id + WHERE user_id = " . $to_user_id; + $db->sql_query($sql); + + return true; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_attachments.php b/phpBB/includes/acp/info/acp_attachments.php new file mode 100644 index 0000000000..b77785801f --- /dev/null +++ b/phpBB/includes/acp/info/acp_attachments.php @@ -0,0 +1,40 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_attachments_info +{ + function module() + { + return array( + 'filename' => 'acp_attachments', + 'title' => 'ACP_ATTACHMENTS', + 'version' => '1.0.0', + 'modes' => array( + 'attach' => array('title' => 'ACP_ATTACHMENT_SETTINGS', 'auth' => 'acl_a_attach', 'cat' => array('ACP_BOARD_CONFIGURATION', 'ACP_ATTACHMENTS')), + 'extensions' => array('title' => 'ACP_MANAGE_EXTENSIONS', 'auth' => 'acl_a_attach', 'cat' => array('ACP_ATTACHMENTS')), + 'ext_groups' => array('title' => 'ACP_EXTENSION_GROUPS', 'auth' => 'acl_a_attach', 'cat' => array('ACP_ATTACHMENTS')), + 'orphan' => array('title' => 'ACP_ORPHAN_ATTACHMENTS', 'auth' => 'acl_a_attach', 'cat' => array('ACP_ATTACHMENTS')) + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_ban.php b/phpBB/includes/acp/info/acp_ban.php new file mode 100644 index 0000000000..df51011ec6 --- /dev/null +++ b/phpBB/includes/acp/info/acp_ban.php @@ -0,0 +1,39 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_ban_info +{ + function module() + { + return array( + 'filename' => 'acp_ban', + 'title' => 'ACP_BAN', + 'version' => '1.0.0', + 'modes' => array( + 'email' => array('title' => 'ACP_BAN_EMAILS', 'auth' => 'acl_a_ban', 'cat' => array('ACP_USER_SECURITY')), + 'ip' => array('title' => 'ACP_BAN_IPS', 'auth' => 'acl_a_ban', 'cat' => array('ACP_USER_SECURITY')), + 'user' => array('title' => 'ACP_BAN_USERNAMES', 'auth' => 'acl_a_ban', 'cat' => array('ACP_USER_SECURITY')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_bbcodes.php b/phpBB/includes/acp/info/acp_bbcodes.php new file mode 100644 index 0000000000..c0206432d6 --- /dev/null +++ b/phpBB/includes/acp/info/acp_bbcodes.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_bbcodes_info +{ + function module() + { + return array( + 'filename' => 'acp_bbcodes', + 'title' => 'ACP_BBCODES', + 'version' => '1.0.0', + 'modes' => array( + 'bbcodes' => array('title' => 'ACP_BBCODES', 'auth' => 'acl_a_bbcode', 'cat' => array('ACP_MESSAGES')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_board.php b/phpBB/includes/acp/info/acp_board.php new file mode 100644 index 0000000000..58b650650c --- /dev/null +++ b/phpBB/includes/acp/info/acp_board.php @@ -0,0 +1,52 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_board_info +{ + function module() + { + return array( + 'filename' => 'acp_board', + 'title' => 'ACP_BOARD_MANAGEMENT', + 'version' => '1.0.0', + 'modes' => array( + 'settings' => array('title' => 'ACP_BOARD_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), + 'features' => array('title' => 'ACP_BOARD_FEATURES', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), + 'avatar' => array('title' => 'ACP_AVATAR_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), + 'message' => array('title' => 'ACP_MESSAGE_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION', 'ACP_MESSAGES')), + 'post' => array('title' => 'ACP_POST_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), + 'signature' => array('title' => 'ACP_SIGNATURE_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), + 'feed' => array('title' => 'ACP_FEED_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), + 'registration' => array('title' => 'ACP_REGISTER_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), + + 'auth' => array('title' => 'ACP_AUTH_SETTINGS', 'auth' => 'acl_a_server', 'cat' => array('ACP_CLIENT_COMMUNICATION')), + 'email' => array('title' => 'ACP_EMAIL_SETTINGS', 'auth' => 'acl_a_server', 'cat' => array('ACP_CLIENT_COMMUNICATION')), + + 'cookie' => array('title' => 'ACP_COOKIE_SETTINGS', 'auth' => 'acl_a_server', 'cat' => array('ACP_SERVER_CONFIGURATION')), + 'server' => array('title' => 'ACP_SERVER_SETTINGS', 'auth' => 'acl_a_server', 'cat' => array('ACP_SERVER_CONFIGURATION')), + 'security' => array('title' => 'ACP_SECURITY_SETTINGS', 'auth' => 'acl_a_server', 'cat' => array('ACP_SERVER_CONFIGURATION')), + 'load' => array('title' => 'ACP_LOAD_SETTINGS', 'auth' => 'acl_a_server', 'cat' => array('ACP_SERVER_CONFIGURATION')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_bots.php b/phpBB/includes/acp/info/acp_bots.php new file mode 100644 index 0000000000..45087f9225 --- /dev/null +++ b/phpBB/includes/acp/info/acp_bots.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_bots_info +{ + function module() + { + return array( + 'filename' => 'acp_bots', + 'title' => 'ACP_BOTS', + 'version' => '1.0.0', + 'modes' => array( + 'bots' => array('title' => 'ACP_BOTS', 'auth' => 'acl_a_bots', 'cat' => array('ACP_GENERAL_TASKS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_captcha.php b/phpBB/includes/acp/info/acp_captcha.php new file mode 100644 index 0000000000..b2541c252c --- /dev/null +++ b/phpBB/includes/acp/info/acp_captcha.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_captcha_info +{ + function module() + { + return array( + 'filename' => 'acp_captcha', + 'title' => 'ACP_CAPTCHA', + 'version' => '1.0.0', + 'modes' => array( + 'visual' => array('title' => 'ACP_VC_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), + 'img' => array('title' => 'ACP_VC_CAPTCHA_DISPLAY', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION'), 'display' => false) + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_database.php b/phpBB/includes/acp/info/acp_database.php new file mode 100644 index 0000000000..85c3c8b21c --- /dev/null +++ b/phpBB/includes/acp/info/acp_database.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_database_info +{ + function module() + { + return array( + 'filename' => 'acp_database', + 'title' => 'ACP_DATABASE', + 'version' => '1.0.0', + 'modes' => array( + 'backup' => array('title' => 'ACP_BACKUP', 'auth' => 'acl_a_backup', 'cat' => array('ACP_CAT_DATABASE')), + 'restore' => array('title' => 'ACP_RESTORE', 'auth' => 'acl_a_backup', 'cat' => array('ACP_CAT_DATABASE')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_disallow.php b/phpBB/includes/acp/info/acp_disallow.php new file mode 100644 index 0000000000..41315eb716 --- /dev/null +++ b/phpBB/includes/acp/info/acp_disallow.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_disallow_info +{ + function module() + { + return array( + 'filename' => 'acp_disallow', + 'title' => 'ACP_DISALLOW', + 'version' => '1.0.0', + 'modes' => array( + 'usernames' => array('title' => 'ACP_DISALLOW_USERNAMES', 'auth' => 'acl_a_names', 'cat' => array('ACP_USER_SECURITY')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_email.php b/phpBB/includes/acp/info/acp_email.php new file mode 100644 index 0000000000..4ad7bca58b --- /dev/null +++ b/phpBB/includes/acp/info/acp_email.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_email_info +{ + function module() + { + return array( + 'filename' => 'acp_email', + 'title' => 'ACP_MASS_EMAIL', + 'version' => '1.0.0', + 'modes' => array( + 'email' => array('title' => 'ACP_MASS_EMAIL', 'auth' => 'acl_a_email && cfg_email_enable', 'cat' => array('ACP_GENERAL_TASKS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_forums.php b/phpBB/includes/acp/info/acp_forums.php new file mode 100644 index 0000000000..8d82eaf42d --- /dev/null +++ b/phpBB/includes/acp/info/acp_forums.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_forums_info +{ + function module() + { + return array( + 'filename' => 'acp_forums', + 'title' => 'ACP_FORUM_MANAGEMENT', + 'version' => '1.0.0', + 'modes' => array( + 'manage' => array('title' => 'ACP_MANAGE_FORUMS', 'auth' => 'acl_a_forum', 'cat' => array('ACP_MANAGE_FORUMS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_groups.php b/phpBB/includes/acp/info/acp_groups.php new file mode 100644 index 0000000000..3910c24e6b --- /dev/null +++ b/phpBB/includes/acp/info/acp_groups.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_groups_info +{ + function module() + { + return array( + 'filename' => 'acp_groups', + 'title' => 'ACP_GROUPS_MANAGEMENT', + 'version' => '1.0.0', + 'modes' => array( + 'manage' => array('title' => 'ACP_GROUPS_MANAGE', 'auth' => 'acl_a_group', 'cat' => array('ACP_GROUPS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_icons.php b/phpBB/includes/acp/info/acp_icons.php new file mode 100644 index 0000000000..16bf753940 --- /dev/null +++ b/phpBB/includes/acp/info/acp_icons.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_icons_info +{ + function module() + { + return array( + 'filename' => 'acp_icons', + 'title' => 'ACP_ICONS_SMILIES', + 'version' => '1.0.0', + 'modes' => array( + 'icons' => array('title' => 'ACP_ICONS', 'auth' => 'acl_a_icons', 'cat' => array('ACP_MESSAGES')), + 'smilies' => array('title' => 'ACP_SMILIES', 'auth' => 'acl_a_icons', 'cat' => array('ACP_MESSAGES')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_inactive.php b/phpBB/includes/acp/info/acp_inactive.php new file mode 100644 index 0000000000..e17fbda9dd --- /dev/null +++ b/phpBB/includes/acp/info/acp_inactive.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2006 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_inactive_info +{ + function module() + { + return array( + 'filename' => 'acp_inactive', + 'title' => 'ACP_INACTIVE_USERS', + 'version' => '1.0.0', + 'modes' => array( + 'list' => array('title' => 'ACP_INACTIVE_USERS', 'auth' => 'acl_a_user', 'cat' => array('ACP_CAT_USERS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_jabber.php b/phpBB/includes/acp/info/acp_jabber.php new file mode 100644 index 0000000000..7bcf7744e1 --- /dev/null +++ b/phpBB/includes/acp/info/acp_jabber.php @@ -0,0 +1,36 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_jabber_info +{ + function module() + { + return array( + 'filename' => 'acp_jabber', + 'title' => 'ACP_JABBER_SETTINGS', + 'version' => '1.0.0', + 'modes' => array( + 'settings' => array('title' => 'ACP_JABBER_SETTINGS', 'auth' => 'acl_a_jabber', 'cat' => array('ACP_CLIENT_COMMUNICATION')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_language.php b/phpBB/includes/acp/info/acp_language.php new file mode 100644 index 0000000000..f7606631fe --- /dev/null +++ b/phpBB/includes/acp/info/acp_language.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_language_info +{ + function module() + { + return array( + 'filename' => 'acp_language', + 'title' => 'ACP_LANGUAGE', + 'version' => '1.0.0', + 'modes' => array( + 'lang_packs' => array('title' => 'ACP_LANGUAGE_PACKS', 'auth' => 'acl_a_language', 'cat' => array('ACP_GENERAL_TASKS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_logs.php b/phpBB/includes/acp/info/acp_logs.php new file mode 100644 index 0000000000..f119e10b83 --- /dev/null +++ b/phpBB/includes/acp/info/acp_logs.php @@ -0,0 +1,40 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_logs_info +{ + function module() + { + return array( + 'filename' => 'acp_logs', + 'title' => 'ACP_LOGGING', + 'version' => '1.0.0', + 'modes' => array( + 'admin' => array('title' => 'ACP_ADMIN_LOGS', 'auth' => 'acl_a_viewlogs', 'cat' => array('ACP_FORUM_LOGS')), + 'mod' => array('title' => 'ACP_MOD_LOGS', 'auth' => 'acl_a_viewlogs', 'cat' => array('ACP_FORUM_LOGS')), + 'users' => array('title' => 'ACP_USERS_LOGS', 'auth' => 'acl_a_viewlogs', 'cat' => array('ACP_FORUM_LOGS')), + 'critical' => array('title' => 'ACP_CRITICAL_LOGS', 'auth' => 'acl_a_viewlogs', 'cat' => array('ACP_FORUM_LOGS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_main.php b/phpBB/includes/acp/info/acp_main.php new file mode 100644 index 0000000000..5574cc40d1 --- /dev/null +++ b/phpBB/includes/acp/info/acp_main.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_main_info +{ + function module() + { + return array( + 'filename' => 'acp_main', + 'title' => 'ACP_INDEX', + 'version' => '1.0.0', + 'modes' => array( + 'main' => array('title' => 'ACP_INDEX', 'auth' => '', 'cat' => array('ACP_CAT_GENERAL')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_modules.php b/phpBB/includes/acp/info/acp_modules.php new file mode 100644 index 0000000000..886f17d628 --- /dev/null +++ b/phpBB/includes/acp/info/acp_modules.php @@ -0,0 +1,39 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_modules_info +{ + function module() + { + return array( + 'filename' => 'acp_modules', + 'title' => 'ACP_MODULE_MANAGEMENT', + 'version' => '1.0.0', + 'modes' => array( + 'acp' => array('title' => 'ACP', 'auth' => 'acl_a_modules', 'cat' => array('ACP_MODULE_MANAGEMENT')), + 'ucp' => array('title' => 'UCP', 'auth' => 'acl_a_modules', 'cat' => array('ACP_MODULE_MANAGEMENT')), + 'mcp' => array('title' => 'MCP', 'auth' => 'acl_a_modules', 'cat' => array('ACP_MODULE_MANAGEMENT')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_permission_roles.php b/phpBB/includes/acp/info/acp_permission_roles.php new file mode 100644 index 0000000000..3ab2fecd53 --- /dev/null +++ b/phpBB/includes/acp/info/acp_permission_roles.php @@ -0,0 +1,40 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_permission_roles_info +{ + function module() + { + return array( + 'filename' => 'acp_permission_roles', + 'title' => 'ACP_PERMISSION_ROLES', + 'version' => '1.0.0', + 'modes' => array( + 'admin_roles' => array('title' => 'ACP_ADMIN_ROLES', 'auth' => 'acl_a_roles && acl_a_aauth', 'cat' => array('ACP_PERMISSION_ROLES')), + 'user_roles' => array('title' => 'ACP_USER_ROLES', 'auth' => 'acl_a_roles && acl_a_uauth', 'cat' => array('ACP_PERMISSION_ROLES')), + 'mod_roles' => array('title' => 'ACP_MOD_ROLES', 'auth' => 'acl_a_roles && acl_a_mauth', 'cat' => array('ACP_PERMISSION_ROLES')), + 'forum_roles' => array('title' => 'ACP_FORUM_ROLES', 'auth' => 'acl_a_roles && acl_a_fauth', 'cat' => array('ACP_PERMISSION_ROLES')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_permissions.php b/phpBB/includes/acp/info/acp_permissions.php new file mode 100644 index 0000000000..6f341742f3 --- /dev/null +++ b/phpBB/includes/acp/info/acp_permissions.php @@ -0,0 +1,54 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_permissions_info +{ + function module() + { + return array( + 'filename' => 'acp_permissions', + 'title' => 'ACP_PERMISSIONS', + 'version' => '1.0.0', + 'modes' => array( + 'intro' => array('title' => 'ACP_PERMISSIONS', 'auth' => 'acl_a_authusers || acl_a_authgroups || acl_a_viewauth', 'cat' => array('ACP_CAT_PERMISSIONS')), + 'trace' => array('title' => 'ACP_PERMISSION_TRACE', 'auth' => 'acl_a_viewauth', 'display' => false, 'cat' => array('ACP_PERMISSION_MASKS')), + + 'setting_forum_local' => array('title' => 'ACP_FORUM_PERMISSIONS', 'auth' => 'acl_a_fauth && (acl_a_authusers || acl_a_authgroups)', 'cat' => array('ACP_FORUM_BASED_PERMISSIONS')), + 'setting_forum_copy' => array('title' => 'ACP_FORUM_PERMISSIONS_COPY', 'auth' => 'acl_a_fauth && acl_a_authusers && acl_a_authgroups && acl_a_mauth', 'cat' => array('ACP_FORUM_BASED_PERMISSIONS')), + 'setting_mod_local' => array('title' => 'ACP_FORUM_MODERATORS', 'auth' => 'acl_a_mauth && (acl_a_authusers || acl_a_authgroups)', 'cat' => array('ACP_FORUM_BASED_PERMISSIONS')), + 'setting_user_global' => array('title' => 'ACP_USERS_PERMISSIONS', 'auth' => 'acl_a_authusers && (acl_a_aauth || acl_a_mauth || acl_a_uauth)', 'cat' => array('ACP_GLOBAL_PERMISSIONS', 'ACP_CAT_USERS')), + 'setting_user_local' => array('title' => 'ACP_USERS_FORUM_PERMISSIONS', 'auth' => 'acl_a_authusers && (acl_a_mauth || acl_a_fauth)', 'cat' => array('ACP_FORUM_BASED_PERMISSIONS', 'ACP_CAT_USERS')), + 'setting_group_global' => array('title' => 'ACP_GROUPS_PERMISSIONS', 'auth' => 'acl_a_authgroups && (acl_a_aauth || acl_a_mauth || acl_a_uauth)', 'cat' => array('ACP_GLOBAL_PERMISSIONS', 'ACP_GROUPS')), + 'setting_group_local' => array('title' => 'ACP_GROUPS_FORUM_PERMISSIONS', 'auth' => 'acl_a_authgroups && (acl_a_mauth || acl_a_fauth)', 'cat' => array('ACP_FORUM_BASED_PERMISSIONS', 'ACP_GROUPS')), + 'setting_admin_global' => array('title' => 'ACP_ADMINISTRATORS', 'auth' => 'acl_a_aauth && (acl_a_authusers || acl_a_authgroups)', 'cat' => array('ACP_GLOBAL_PERMISSIONS')), + 'setting_mod_global' => array('title' => 'ACP_GLOBAL_MODERATORS', 'auth' => 'acl_a_mauth && (acl_a_authusers || acl_a_authgroups)', 'cat' => array('ACP_GLOBAL_PERMISSIONS')), + + 'view_admin_global' => array('title' => 'ACP_VIEW_ADMIN_PERMISSIONS', 'auth' => 'acl_a_viewauth', 'cat' => array('ACP_PERMISSION_MASKS')), + 'view_user_global' => array('title' => 'ACP_VIEW_USER_PERMISSIONS', 'auth' => 'acl_a_viewauth', 'cat' => array('ACP_PERMISSION_MASKS')), + 'view_mod_global' => array('title' => 'ACP_VIEW_GLOBAL_MOD_PERMISSIONS', 'auth' => 'acl_a_viewauth', 'cat' => array('ACP_PERMISSION_MASKS')), + 'view_mod_local' => array('title' => 'ACP_VIEW_FORUM_MOD_PERMISSIONS', 'auth' => 'acl_a_viewauth', 'cat' => array('ACP_PERMISSION_MASKS')), + 'view_forum_local' => array('title' => 'ACP_VIEW_FORUM_PERMISSIONS', 'auth' => 'acl_a_viewauth', 'cat' => array('ACP_PERMISSION_MASKS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_php_info.php b/phpBB/includes/acp/info/acp_php_info.php new file mode 100644 index 0000000000..7d716b0f83 --- /dev/null +++ b/phpBB/includes/acp/info/acp_php_info.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_php_info_info +{ + function module() + { + return array( + 'filename' => 'acp_php_info', + 'title' => 'ACP_PHP_INFO', + 'version' => '1.0.0', + 'modes' => array( + 'info' => array('title' => 'ACP_PHP_INFO', 'auth' => 'acl_a_phpinfo', 'cat' => array('ACP_GENERAL_TASKS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_profile.php b/phpBB/includes/acp/info/acp_profile.php new file mode 100644 index 0000000000..8590226038 --- /dev/null +++ b/phpBB/includes/acp/info/acp_profile.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_profile_info +{ + function module() + { + return array( + 'filename' => 'acp_profile', + 'title' => 'ACP_CUSTOM_PROFILE_FIELDS', + 'version' => '1.0.0', + 'modes' => array( + 'profile' => array('title' => 'ACP_CUSTOM_PROFILE_FIELDS', 'auth' => 'acl_a_profile', 'cat' => array('ACP_CAT_USERS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_prune.php b/phpBB/includes/acp/info/acp_prune.php new file mode 100644 index 0000000000..46565c4f16 --- /dev/null +++ b/phpBB/includes/acp/info/acp_prune.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_prune_info +{ + function module() + { + return array( + 'filename' => 'acp_prune', + 'title' => 'ACP_PRUNING', + 'version' => '1.0.0', + 'modes' => array( + 'forums' => array('title' => 'ACP_PRUNE_FORUMS', 'auth' => 'acl_a_prune', 'cat' => array('ACP_MANAGE_FORUMS')), + 'users' => array('title' => 'ACP_PRUNE_USERS', 'auth' => 'acl_a_userdel', 'cat' => array('ACP_USER_SECURITY')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_ranks.php b/phpBB/includes/acp/info/acp_ranks.php new file mode 100644 index 0000000000..06b9c6d284 --- /dev/null +++ b/phpBB/includes/acp/info/acp_ranks.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_ranks_info +{ + function module() + { + return array( + 'filename' => 'acp_ranks', + 'title' => 'ACP_RANKS', + 'version' => '1.0.0', + 'modes' => array( + 'ranks' => array('title' => 'ACP_MANAGE_RANKS', 'auth' => 'acl_a_ranks', 'cat' => array('ACP_CAT_USERS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_reasons.php b/phpBB/includes/acp/info/acp_reasons.php new file mode 100644 index 0000000000..65d805ee18 --- /dev/null +++ b/phpBB/includes/acp/info/acp_reasons.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_reasons_info +{ + function module() + { + return array( + 'filename' => 'acp_reasons', + 'title' => 'ACP_REASONS', + 'version' => '1.0.0', + 'modes' => array( + 'main' => array('title' => 'ACP_MANAGE_REASONS', 'auth' => 'acl_a_reasons', 'cat' => array('ACP_GENERAL_TASKS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_search.php b/phpBB/includes/acp/info/acp_search.php new file mode 100644 index 0000000000..4afd6c6994 --- /dev/null +++ b/phpBB/includes/acp/info/acp_search.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_search_info +{ + function module() + { + return array( + 'filename' => 'acp_search', + 'title' => 'ACP_SEARCH', + 'version' => '1.0.0', + 'modes' => array( + 'settings' => array('title' => 'ACP_SEARCH_SETTINGS', 'auth' => 'acl_a_search', 'cat' => array('ACP_SERVER_CONFIGURATION')), + 'index' => array('title' => 'ACP_SEARCH_INDEX', 'auth' => 'acl_a_search', 'cat' => array('ACP_CAT_DATABASE')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_send_statistics.php b/phpBB/includes/acp/info/acp_send_statistics.php new file mode 100644 index 0000000000..de5dcdb8ad --- /dev/null +++ b/phpBB/includes/acp/info/acp_send_statistics.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_send_statistics_info +{ + function module() + { + return array( + 'filename' => 'acp_send_statistics', + 'title' => 'ACP_SEND_STATISTICS', + 'version' => '1.0.0', + 'modes' => array( + 'send_statistics' => array('title' => 'ACP_SEND_STATISTICS', 'auth' => 'acl_a_server', 'cat' => array('ACP_SERVER_CONFIGURATION')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_styles.php b/phpBB/includes/acp/info/acp_styles.php new file mode 100644 index 0000000000..db67167e39 --- /dev/null +++ b/phpBB/includes/acp/info/acp_styles.php @@ -0,0 +1,40 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_styles_info +{ + function module() + { + return array( + 'filename' => 'acp_styles', + 'title' => 'ACP_CAT_STYLES', + 'version' => '1.0.0', + 'modes' => array( + 'style' => array('title' => 'ACP_STYLES', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_MANAGEMENT')), + 'template' => array('title' => 'ACP_TEMPLATES', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_COMPONENTS')), + 'theme' => array('title' => 'ACP_THEMES', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_COMPONENTS')), + 'imageset' => array('title' => 'ACP_IMAGESETS', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_COMPONENTS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_update.php b/phpBB/includes/acp/info/acp_update.php new file mode 100644 index 0000000000..886cdc94d5 --- /dev/null +++ b/phpBB/includes/acp/info/acp_update.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_update_info +{ + function module() + { + return array( + 'filename' => 'acp_update', + 'title' => 'ACP_UPDATE', + 'version' => '1.0.0', + 'modes' => array( + 'version_check' => array('title' => 'ACP_VERSION_CHECK', 'auth' => 'acl_a_board', 'cat' => array('ACP_AUTOMATION')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_users.php b/phpBB/includes/acp/info/acp_users.php new file mode 100644 index 0000000000..10081ac870 --- /dev/null +++ b/phpBB/includes/acp/info/acp_users.php @@ -0,0 +1,47 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_users_info +{ + function module() + { + return array( + 'filename' => 'acp_users', + 'title' => 'ACP_USER_MANAGEMENT', + 'version' => '1.0.0', + 'modes' => array( + 'overview' => array('title' => 'ACP_MANAGE_USERS', 'auth' => 'acl_a_user', 'cat' => array('ACP_CAT_USERS')), + 'feedback' => array('title' => 'ACP_USER_FEEDBACK', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')), + 'warnings' => array('title' => 'ACP_USER_WARNINGS', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')), + 'profile' => array('title' => 'ACP_USER_PROFILE', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')), + 'prefs' => array('title' => 'ACP_USER_PREFS', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')), + 'avatar' => array('title' => 'ACP_USER_AVATAR', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')), + 'rank' => array('title' => 'ACP_USER_RANK', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')), + 'sig' => array('title' => 'ACP_USER_SIG', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')), + 'groups' => array('title' => 'ACP_USER_GROUPS', 'auth' => 'acl_a_user && acl_a_group', 'display' => false, 'cat' => array('ACP_CAT_USERS')), + 'perm' => array('title' => 'ACP_USER_PERM', 'auth' => 'acl_a_user && acl_a_viewauth', 'display' => false, 'cat' => array('ACP_CAT_USERS')), + 'attach' => array('title' => 'ACP_USER_ATTACH', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/info/acp_words.php b/phpBB/includes/acp/info/acp_words.php new file mode 100644 index 0000000000..a2417f8a7f --- /dev/null +++ b/phpBB/includes/acp/info/acp_words.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_words_info +{ + function module() + { + return array( + 'filename' => 'acp_words', + 'title' => 'ACP_WORDS', + 'version' => '1.0.0', + 'modes' => array( + 'words' => array('title' => 'ACP_WORDS', 'auth' => 'acl_a_words', 'cat' => array('ACP_MESSAGES')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/auth.php b/phpBB/includes/auth.php new file mode 100644 index 0000000000..02819f9e78 --- /dev/null +++ b/phpBB/includes/auth.php @@ -0,0 +1,1046 @@ +<?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/Auth class +* @package phpBB3 +*/ +class auth +{ + var $acl = array(); + var $cache = array(); + var $acl_options = array(); + var $acl_forum_ids = false; + + /** + * Init permissions + */ + function acl(&$userdata) + { + global $db, $cache; + + $this->acl = $this->cache = $this->acl_options = array(); + $this->acl_forum_ids = false; + + if (($this->acl_options = $cache->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 = $db->sql_query($sql); + + $global = $local = 0; + $this->acl_options = array(); + while ($row = $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']; + } + $db->sql_freeresult($result); + + $cache->put('_acl_options', $this->acl_options); + } + + if (!trim($userdata['user_permissions'])) + { + $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 + */ + 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. + */ + 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) ? !$this->cache[$f][$opt] : $this->cache[$f][$opt]; + } + + /** + * Get forums with the specified permission setting + * if the option is prefixed with !, then the result becomes nagated + * + * @param bool $clean set to true if only values needs to be returned which are set/unset + */ + 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) + { + global $db; + + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE; + + if (sizeof($this->acl)) + { + $sql .= ' WHERE ' . $db->sql_in_set('forum_id', array_keys($this->acl), true); + } + $result = $db->sql_query($sql); + + $this->acl_forum_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $this->acl_forum_ids[] = $row['forum_id']; + } + $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) ? !$allowed : $allowed; + } + else + { + if (($negate && !$allowed) || (!$negate && $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... + */ + 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) + */ + 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 + */ + 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_data_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 + */ + function acl_cache(&$userdata) + { + global $db; + + // Empty user_permissions + $userdata['user_permissions'] = ''; + + $hold_ary = $this->acl_raw_data_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'] == USER_FOUNDER) + { + foreach ($this->acl_options['global'] as $opt => $id) + { + if (strpos($opt, 'a_') === 0) + { + $hold_ary[0][$this->acl_options['id'][$opt]] = ACL_YES; + } + } + } + + $hold_str = $this->build_bitstring($hold_ary); + + if ($hold_str) + { + $userdata['user_permissions'] = $hold_str; + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_permissions = '" . $db->sql_escape($userdata['user_permissions']) . "', + user_perm_from = 0 + WHERE user_id = " . $userdata['user_id']; + $db->sql_query($sql); + } + + return; + } + + /** + * Build bitstring from permission set + */ + 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]] == ACL_YES && (!isset($bitstring[$this->acl_options[$ary_key][$option_key]]) || $bitstring[$this->acl_options[$ary_key][$option_key]] == ACL_NEVER)) + { + $bitstring[$this->acl_options[$ary_key][$option_key]] = ACL_YES; + } + } + else + { + $bitstring[$id] = 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 + */ + function acl_clear_prefetch($user_id = false) + { + global $db, $cache; + + // Rebuild options cache + $cache->destroy('_role_cache'); + + $sql = 'SELECT * + FROM ' . ACL_ROLES_DATA_TABLE . ' + ORDER BY role_id ASC'; + $result = $db->sql_query($sql); + + $this->role_cache = array(); + while ($row = $db->sql_fetchrow($result)) + { + $this->role_cache[$row['role_id']][$row['auth_option_id']] = (int) $row['auth_setting']; + } + $db->sql_freeresult($result); + + foreach ($this->role_cache as $role_id => $role_options) + { + $this->role_cache[$role_id] = serialize($role_options); + } + + $cache->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 ' . $db->sql_in_set('user_id', $user_id); + } + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_permissions = '', + user_perm_from = 0 + $where_sql"; + $db->sql_query($sql); + + return; + } + + /** + * Get assigned roles + */ + function acl_role_data($user_type, $role_type, $ug_id = false, $forum_id = false) + { + global $db; + + $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 ' . $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 ' . $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 = '" . $db->sql_escape($role_type) . "' + $sql_ug + $sql_forum + ORDER BY r.role_order ASC"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $roles[$row[$sql_id]][$row['forum_id']] = $row['auth_role_id']; + } + $db->sql_freeresult($result); + + return $roles; + } + + /** + * Get raw acl data based on user/option/forum + */ + function acl_raw_data($user_id = false, $opts = false, $forum_id = false) + { + global $db; + + $sql_user = ($user_id !== false) ? ((!is_array($user_id)) ? 'user_id = ' . (int) $user_id : $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 ' . $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 = $db->sql_query($sql); + + while ($row = $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']; + } + $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, ' . GROUPS_TABLE . ' g' . $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 g.group_id = ug.group_id + AND ug.user_pending = 0 + AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1) + ' . (($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, ' . GROUPS_TABLE . ' g, ' . 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 g.group_id = ug.group_id + AND ug.user_pending = 0 + AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1) + ' . (($sql_user) ? 'AND ug.' . $sql_user : '') . " + $sql_forum + $sql_opts"; + + foreach ($sql_ary as $sql) + { + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $option = ($sql_opts_select) ? $row['auth_option'] : $this->acl_options['option'][$row['auth_option_id']]; + + 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] != ACL_NEVER)) + { + $hold_ary[$row['user_id']][$row['forum_id']][$option] = $row['auth_setting']; + + // If we detect ACL_NEVER, we will unset the flag option (within building the bitstring it is correctly set again) + if ($row['auth_setting'] == 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] == ACL_YES) + { + unset($hold_ary[$row['user_id']][$row['forum_id']][$flag]); + +/* if (in_array(ACL_YES, $hold_ary[$row['user_id']][$row['forum_id']])) + { + $hold_ary[$row['user_id']][$row['forum_id']][$flag] = ACL_YES; + } +*/ + } + } + } + } + $db->sql_freeresult($result); + } + + return $hold_ary; + } + + /** + * Get raw user based permission settings + */ + function acl_user_raw_data($user_id = false, $opts = false, $forum_id = false) + { + global $db; + + $sql_user = ($user_id !== false) ? ((!is_array($user_id)) ? 'user_id = ' . (int) $user_id : $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 ' . $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 = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $hold_ary[$row['user_id']][$row['forum_id']][$row['auth_option']] = $row['auth_setting']; + } + $db->sql_freeresult($result); + } + + return $hold_ary; + } + + /** + * Get raw group based permission settings + */ + function acl_group_raw_data($group_id = false, $opts = false, $forum_id = false) + { + global $db; + + $sql_group = ($group_id !== false) ? ((!is_array($group_id)) ? 'group_id = ' . (int) $group_id : $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 ' . $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 = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $hold_ary[$row['group_id']][$row['forum_id']][$row['auth_option']] = $row['auth_setting']; + } + $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 acl_raw_data(), but without the user id as the first key within the array. + */ + function acl_raw_data_single_user($user_id) + { + global $db, $cache; + + // Check if the role-cache is there + if (($this->role_cache = $cache->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 = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $this->role_cache[$row['role_id']][$row['auth_option_id']] = (int) $row['auth_setting']; + } + $db->sql_freeresult($result); + + foreach ($this->role_cache as $role_id => $role_options) + { + $this->role_cache[$role_id] = serialize($role_options); + } + + $cache->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 = $db->sql_query($sql); + + while ($row = $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']; + } + } + $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, ' . GROUPS_TABLE . ' g + WHERE a.group_id = ug.group_id + AND g.group_id = ug.group_id + AND ug.user_pending = 0 + AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1) + AND ug.user_id = ' . $user_id; + $result = $db->sql_query($sql); + + while ($row = $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); + } + } + } + $db->sql_freeresult($result); + + return $hold_ary; + } + + /** + * Private function snippet for setting a specific piece of the hold_ary + */ + 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] != ACL_NEVER)) + { + $hold_ary[$option_id] = $setting; + + // If we detect ACL_NEVER, we will unset the flag option (within building the bitstring it is correctly set again) + if ($setting == 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] == 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(ACL_YES, $hold_ary)) + { + $hold_ary[$flag] = ACL_YES; + }*/ + } + } + } + } + + /** + * Authentication plug-ins is largely down to Sergey Kanareykin, our thanks to him. + */ + function login($username, $password, $autologin = false, $viewonline = 1, $admin = 0) + { + global $config, $db, $user, $phpbb_root_path, $phpEx; + + $method = trim(basename($config['auth_method'])); + include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx); + + $method = 'login_' . $method; + if (function_exists($method)) + { + $login = $method($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) + { + // we are going to use the user_add function so include functions_user.php if it wasn't defined yet + if (!function_exists('user_add')) + { + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + } + + 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 = '" . $db->sql_escape(utf8_clean_string($username)) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $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) + { + $old_session_id = $user->session_id; + + if ($admin) + { + global $SID, $_SID; + + $cookie_expire = time() - 31536000; + $user->set_cookie('u', '', $cookie_expire); + $user->set_cookie('sid', '', $cookie_expire); + unset($cookie_expire); + + $SID = '?sid='; + $user->session_id = $_SID = ''; + } + + $result = $user->session_create($login['user_row']['user_id'], $admin, $autologin, $viewonline); + + // Successful session creation + if ($result === true) + { + // If admin re-authentication we remove the old session entry because a new one has been created... + if ($admin) + { + // the login array is used because the user ids do not differ for re-authentication + $sql = 'DELETE FROM ' . SESSIONS_TABLE . " + WHERE session_id = '" . $db->sql_escape($old_session_id) . "' + AND session_user_id = {$login['user_row']['user_id']}"; + $db->sql_query($sql); + } + + 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; + } + + trigger_error('Authentication method not found', E_USER_ERROR); + } + + /** + * Fill auth_option statement for later querying based on the supplied options + */ + function build_auth_option_statement($key, $auth_options, &$sql_opts) + { + global $db; + + if (!is_array($auth_options)) + { + if (strpos($auth_options, '%') !== false) + { + $sql_opts = "AND $key " . $db->sql_like_expression(str_replace('%', $db->any_char, $auth_options)); + } + else + { + $sql_opts = "AND $key = '" . $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 ' . $db->sql_in_set($key, $auth_options); + } + else + { + $sql = array(); + + foreach ($auth_options as $option) + { + if (strpos($option, '%') !== false) + { + $sql[] = $key . ' ' . $db->sql_like_expression(str_replace('%', $db->any_char, $option)); + } + else + { + $sql[] = $key . " = '" . $db->sql_escape($option) . "'"; + } + } + + $sql_opts = 'AND (' . implode(' OR ', $sql) . ')'; + } + } + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/auth/auth_apache.php b/phpBB/includes/auth/auth_apache.php new file mode 100644 index 0000000000..391e7abb0e --- /dev/null +++ b/phpBB/includes/auth/auth_apache.php @@ -0,0 +1,249 @@ +<?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() +{ + global $user; + + if (!isset($_SERVER['PHP_AUTH_USER']) || $user->data['username'] !== $_SERVER['PHP_AUTH_USER']) + { + return $user->lang['APACHE_SETUP_BEFORE_USE']; + } + return false; +} + +/** +* Login function +*/ +function login_apache(&$username, &$password) +{ + global $db; + + // 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 = '" . $db->sql_escape($php_auth_user) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + // User inactive... + if ($row['user_type'] == USER_INACTIVE || $row['user_type'] == 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() +{ + global $db; + + 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 = '" . $db->sql_escape($php_auth_user) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + return ($row['user_type'] == USER_INACTIVE || $row['user_type'] == USER_IGNORE) ? array() : $row; + } + + if (!function_exists('user_add')) + { + global $phpbb_root_path, $phpEx; + + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + } + + // 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 = '" . $db->sql_escape(utf8_clean_string($php_auth_user)) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $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) +{ + global $db, $config, $user; + // first retrieve default group id + $sql = 'SELECT group_id + FROM ' . GROUPS_TABLE . " + WHERE group_name = '" . $db->sql_escape('REGISTERED') . "' + AND group_type = " . GROUP_SPECIAL; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $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' => USER_NORMAL, + 'user_ip' => $user->ip, + 'user_new' => ($config['new_member_post_limit']) ? 1 : 0, + ); +} + +/** +* 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) +{ + // Check if PHP_AUTH_USER is set and handle this case + 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_db.php b/phpBB/includes/auth/auth_db.php new file mode 100644 index 0000000000..71f8a7c082 --- /dev/null +++ b/phpBB/includes/auth/auth_db.php @@ -0,0 +1,198 @@ +<?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; +} + +/** +* Login function +*/ +function login_db(&$username, &$password) +{ + global $db, $config; + + // 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 = '" . $db->sql_escape(utf8_clean_string($username)) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $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 ($config['max_login_attempts'] && $row['user_login_attempts'] >= $config['max_login_attempts']) + { + // Visual Confirmation handling + + $captcha =& phpbb_captcha_factory::get_instance($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, + ); + } + + } + + // If the password convert flag is set we need to convert it + if ($row['user_pass_convert']) + { + // in phpBB2 passwords were used exactly as they were sent, with addslashes applied + $password_old_format = isset($_REQUEST['password']) ? (string) $_REQUEST['password'] : ''; + $password_old_format = (!STRIP) ? addslashes($password_old_format) : $password_old_format; + $password_new_format = ''; + + set_var($password_new_format, stripslashes($password_old_format), 'string'); + + if ($password == $password_new_format) + { + if (!function_exists('utf8_to_cp1252')) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/utf/data/recode_basic.' . $phpEx); + } + + // cp1252 is phpBB2's default encoding, characters outside ASCII range might work when converted into that encoding + // plain md5 support left in for conversions from other systems. + if ((strlen($row['user_password']) == 34 && (phpbb_check_hash(md5($password_old_format), $row['user_password']) || phpbb_check_hash(md5(utf8_to_cp1252($password_old_format)), $row['user_password']))) + || (strlen($row['user_password']) == 32 && (md5($password_old_format) == $row['user_password'] || md5(utf8_to_cp1252($password_old_format)) == $row['user_password']))) + { + $hash = phpbb_hash($password_new_format); + + // Update the password in the users table to the new format and remove user_pass_convert flag + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_password = \'' . $db->sql_escape($hash) . '\', + user_pass_convert = 0 + WHERE user_id = ' . $row['user_id']; + $db->sql_query($sql); + + $row['user_pass_convert'] = 0; + $row['user_password'] = $hash; + } + else + { + // Although we weren't able to convert this password we have to + // increase login attempt count to make sure this cannot be exploited + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_login_attempts = user_login_attempts + 1 + WHERE user_id = ' . $row['user_id']; + $db->sql_query($sql); + + return array( + 'status' => LOGIN_ERROR_PASSWORD_CONVERT, + 'error_msg' => 'LOGIN_ERROR_PASSWORD_CONVERT', + 'user_row' => $row, + ); + } + } + } + + // Check password ... + if (!$row['user_pass_convert'] && phpbb_check_hash($password, $row['user_password'])) + { + // Check for old password hash... + if (strlen($row['user_password']) == 32) + { + $hash = phpbb_hash($password); + + // Update the password in the users table to the new format + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_password = '" . $db->sql_escape($hash) . "', + user_pass_convert = 0 + WHERE user_id = {$row['user_id']}"; + $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']; + $db->sql_query($sql); + } + + // User inactive... + if ($row['user_type'] == USER_INACTIVE || $row['user_type'] == 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']; + $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/auth/auth_ldap.php b/phpBB/includes/auth/auth_ldap.php new file mode 100644 index 0000000000..a6092baba5 --- /dev/null +++ b/phpBB/includes/auth/auth_ldap.php @@ -0,0 +1,349 @@ +<?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() +{ + global $config, $user; + + if (!@extension_loaded('ldap')) + { + return $user->lang['LDAP_NO_LDAP_EXTENSION']; + } + + $config['ldap_port'] = (int) $config['ldap_port']; + if ($config['ldap_port']) + { + $ldap = @ldap_connect($config['ldap_server'], $config['ldap_port']); + } + else + { + $ldap = @ldap_connect($config['ldap_server']); + } + + if (!$ldap) + { + return $user->lang['LDAP_NO_SERVER_CONNECTION']; + } + + @ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3); + @ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0); + + if ($config['ldap_user'] || $config['ldap_password']) + { + if (!@ldap_bind($ldap, htmlspecialchars_decode($config['ldap_user']), htmlspecialchars_decode($config['ldap_password']))) + { + return $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, + htmlspecialchars_decode($config['ldap_base_dn']), + ldap_user_filter($user->data['username']), + (empty($config['ldap_email'])) ? + array(htmlspecialchars_decode($config['ldap_uid'])) : + array(htmlspecialchars_decode($config['ldap_uid']), htmlspecialchars_decode($config['ldap_email'])), + 0, + 1 + ); + + if ($search === false) + { + return $user->lang['LDAP_NO_SERVER_CONNECTION']; + } + + $result = @ldap_get_entries($ldap, $search); + + @ldap_close($ldap); + + + if (!is_array($result) || sizeof($result) < 2) + { + return sprintf($user->lang['LDAP_NO_IDENTITY'], $user->data['username']); + } + + if (!empty($config['ldap_email']) && !isset($result[0][htmlspecialchars_decode($config['ldap_email'])])) + { + return $user->lang['LDAP_NO_EMAIL']; + } + + return false; +} + +/** +* Login function +*/ +function login_ldap(&$username, &$password) +{ + global $db, $config, $user; + + // 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), + ); + } + + $config['ldap_port'] = (int) $config['ldap_port']; + if ($config['ldap_port']) + { + $ldap = @ldap_connect($config['ldap_server'], $config['ldap_port']); + } + else + { + $ldap = @ldap_connect($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 ($config['ldap_user'] || $config['ldap_password']) + { + if (!@ldap_bind($ldap, htmlspecialchars_decode($config['ldap_user']), htmlspecialchars_decode($config['ldap_password']))) + { + return $user->lang['LDAP_NO_SERVER_CONNECTION']; + } + } + + $search = @ldap_search( + $ldap, + htmlspecialchars_decode($config['ldap_base_dn']), + ldap_user_filter($username), + (empty($config['ldap_email'])) ? + array(htmlspecialchars_decode($config['ldap_uid'])) : + array(htmlspecialchars_decode($config['ldap_uid']), htmlspecialchars_decode($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 = '" . $db->sql_escape(utf8_clean_string($username)) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + unset($ldap_result); + + // User inactive... + if ($row['user_type'] == USER_INACTIVE || $row['user_type'] == 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 = '" . $db->sql_escape('REGISTERED') . "' + AND group_type = " . GROUP_SPECIAL; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $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($config['ldap_email'])) ? utf8_htmlspecialchars($ldap_result[0][htmlspecialchars_decode($config['ldap_email'])][0]) : '', + 'group_id' => (int) $row['group_id'], + 'user_type' => USER_NORMAL, + 'user_ip' => $user->ip, + 'user_new' => ($config['new_member_post_limit']) ? 1 : 0, + ); + + 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) +{ + global $config; + + $filter = '(' . $config['ldap_uid'] . '=' . ldap_escape(htmlspecialchars_decode($username)) . ')'; + if ($config['ldap_user_filter']) + { + $_filter = ($config['ldap_user_filter'][0] == '(' && substr($config['ldap_user_filter'], -1) == ')') ? $config['ldap_user_filter'] : "({$config['ldap_user_filter']})"; + $filter = "(&{$filter}{$_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) +{ + global $user; + + $tpl = ' + + <dl> + <dt><label for="ldap_server">' . $user->lang['LDAP_SERVER'] . ':</label><br /><span>' . $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">' . $user->lang['LDAP_PORT'] . ':</label><br /><span>' . $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">' . $user->lang['LDAP_DN'] . ':</label><br /><span>' . $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">' . $user->lang['LDAP_UID'] . ':</label><br /><span>' . $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">' . $user->lang['LDAP_USER_FILTER'] . ':</label><br /><span>' . $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">' . $user->lang['LDAP_EMAIL'] . ':</label><br /><span>' . $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">' . $user->lang['LDAP_USER'] . ':</label><br /><span>' . $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">' . $user->lang['LDAP_PASSWORD'] . ':</label><br /><span>' . $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/index.htm b/phpBB/includes/auth/index.htm new file mode 100644 index 0000000000..ee1f723a7d --- /dev/null +++ b/phpBB/includes/auth/index.htm @@ -0,0 +1,10 @@ +<html> +<head> +<title></title> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> +</head> + +<body bgcolor="#FFFFFF" text="#000000"> + +</body> +</html> diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php new file mode 100644 index 0000000000..f58852c00b --- /dev/null +++ b/phpBB/includes/bbcode.php @@ -0,0 +1,602 @@ +<?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 bbcode($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() + { + global $phpbb_root_path, $template, $user; + + if (empty($this->template_filename)) + { + $this->template_bitfield = new bitfield($user->theme['bbcode_bitfield']); + $this->template_filename = $phpbb_root_path . 'styles/' . $user->theme['template_path'] . '/template/bbcode.html'; + + if (!@file_exists($this->template_filename)) + { + if (isset($template->orig_tpl_inherits_id) && $template->orig_tpl_inherits_id) + { + $this->template_filename = $phpbb_root_path . 'styles/' . $user->theme['template_inherit_path'] . '/template/bbcode.html'; + if (!@file_exists($this->template_filename)) + { + trigger_error('The file ' . $this->template_filename . ' is missing.', E_USER_ERROR); + } + } + else + { + 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)) + { + global $db; + + $sql = 'SELECT * + FROM ' . BBCODES_TABLE . ' + WHERE ' . $db->sql_in_set('bbcode_id', $sql); + $result = $db->sql_query($sql, 3600); + + while ($row = $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; + } + $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 ($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]{3}|#[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 ($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', "(!empty(\$user->lang['\$1'])) ? \$user->lang['\$1'] : ucwords(strtolower(str_replace('_', ' ', '\$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)) + { + global $user; + + $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="' . $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) + { + global $user; + + 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', "(!empty(\$user->lang['\$1'])) ? \$user->lang['\$1'] : ucwords(strtolower(str_replace('_', ' ', '\$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/cache.php b/phpBB/includes/cache.php new file mode 100644 index 0000000000..1effada666 --- /dev/null +++ b/phpBB/includes/cache.php @@ -0,0 +1,444 @@ +<?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; +} + +/** +* Class for grabbing/handling cached entries, extends acm_file or acm_db depending on the setup +* @package acm +*/ +class cache extends acm +{ + /** + * Get config values + */ + function obtain_config() + { + global $db; + + if (($config = $this->get('config')) !== false) + { + $sql = 'SELECT config_name, config_value + FROM ' . CONFIG_TABLE . ' + WHERE is_dynamic = 1'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $config[$row['config_name']] = $row['config_value']; + } + $db->sql_freeresult($result); + } + else + { + $config = $cached_config = array(); + + $sql = 'SELECT config_name, config_value, is_dynamic + FROM ' . CONFIG_TABLE; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if (!$row['is_dynamic']) + { + $cached_config[$row['config_name']] = $row['config_value']; + } + + $config[$row['config_name']] = $row['config_value']; + } + $db->sql_freeresult($result); + + $this->put('config', $cached_config); + } + + return $config; + } + + /** + * Obtain list of naughty words and build preg style replacement arrays for use by the + * calling script + */ + function obtain_word_list() + { + global $db; + + if (($censors = $this->get('_word_censors')) === false) + { + $sql = 'SELECT word, replacement + FROM ' . WORDS_TABLE; + $result = $db->sql_query($sql); + + $censors = array(); + while ($row = $db->sql_fetchrow($result)) + { + if ((version_compare(PHP_VERSION, '5.1.0', '>=') || (version_compare(PHP_VERSION, '5.0.0-dev', '<=') && version_compare(PHP_VERSION, '4.4.0', '>='))) && @preg_match('/\p{L}/u', 'a') !== false) + { + $censors['match'][] = '#(?<![\p{Nd}\p{L}_])(' . str_replace('\*', '[\p{Nd}\p{L}_]*?', preg_quote($row['word'], '#')) . ')(?![\p{Nd}\p{L}_])#u'; + } + else + { + $censors['match'][] = '#(?<!\S)(' . str_replace('\*', '\S*?', preg_quote($row['word'], '#')) . ')(?!\S)#iu'; + } + + $censors['replace'][] = $row['replacement']; + } + $db->sql_freeresult($result); + + $this->put('_word_censors', $censors); + } + + return $censors; + } + + /** + * Obtain currently listed icons + */ + function obtain_icons() + { + if (($icons = $this->get('_icons')) === false) + { + global $db; + + // Topic icons + $sql = 'SELECT * + FROM ' . ICONS_TABLE . ' + ORDER BY icons_order'; + $result = $db->sql_query($sql); + + $icons = array(); + while ($row = $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']; + } + $db->sql_freeresult($result); + + $this->put('_icons', $icons); + } + + return $icons; + } + + /** + * Obtain ranks + */ + function obtain_ranks() + { + if (($ranks = $this->get('_ranks')) === false) + { + global $db; + + $sql = 'SELECT * + FROM ' . RANKS_TABLE . ' + ORDER BY rank_min DESC'; + $result = $db->sql_query($sql); + + $ranks = array(); + while ($row = $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'] + ); + } + } + $db->sql_freeresult($result); + + $this->put('_ranks', $ranks); + } + + return $ranks; + } + + /** + * Obtain allowed extensions + * + * @param mixed $forum_id If false then check for private messaging, if int then check for forum id. If true, then only return extension informations. + * + * @return array allowed extensions array. + */ + function obtain_attach_extensions($forum_id) + { + if (($extensions = $this->get('_extensions')) === false) + { + global $db; + + $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 = $db->sql_query($sql); + + while ($row = $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; + } + } + $db->sql_freeresult($result); + + $this->put('_extensions', $extensions); + } + + // Forum post + if ($forum_id === false) + { + // We are checking for private messages, therefore we only need to get the pm extensions... + $return = array('_allowed_' => array()); + + foreach ($extensions['_allowed_pm'] as $extension => $check) + { + $return['_allowed_'][$extension] = 0; + $return[$extension] = $extensions[$extension]; + } + + $extensions = $return; + } + else if ($forum_id === true) + { + return $extensions; + } + else + { + $forum_id = (int) $forum_id; + $return = 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) + { + $return['_allowed_'][$extension] = 0; + $return[$extension] = $extensions[$extension]; + } + } + + $extensions = $return; + } + + if (!isset($extensions['_allowed_'])) + { + $extensions['_allowed_'] = array(); + } + + return $extensions; + } + + /** + * Obtain active bots + */ + function obtain_bots() + { + if (($bots = $this->get('_bots')) === false) + { + global $db; + + switch ($db->sql_layer) + { + case 'mssql': + case 'mssql_odbc': + $sql = 'SELECT user_id, bot_agent, bot_ip + FROM ' . BOTS_TABLE . ' + WHERE bot_active = 1 + ORDER BY LEN(bot_agent) DESC'; + break; + + case 'firebird': + $sql = 'SELECT user_id, bot_agent, bot_ip + FROM ' . BOTS_TABLE . ' + WHERE bot_active = 1 + ORDER BY CHAR_LENGTH(bot_agent) DESC'; + break; + + // LENGTH supported by MySQL, IBM DB2 and Oracle for sure... + default: + $sql = 'SELECT user_id, bot_agent, bot_ip + FROM ' . BOTS_TABLE . ' + WHERE bot_active = 1 + ORDER BY LENGTH(bot_agent) DESC'; + break; + } + $result = $db->sql_query($sql); + + $bots = array(); + while ($row = $db->sql_fetchrow($result)) + { + $bots[] = $row; + } + $db->sql_freeresult($result); + + $this->put('_bots', $bots); + } + + return $bots; + } + + /** + * Obtain cfg file data + */ + function obtain_cfg_items($theme) + { + global $config, $phpbb_root_path; + + $parsed_items = array( + 'theme' => array(), + 'template' => array(), + 'imageset' => array() + ); + + foreach ($parsed_items as $key => $parsed_array) + { + $parsed_array = $this->get('_cfg_' . $key . '_' . $theme[$key . '_path']); + + if ($parsed_array === false) + { + $parsed_array = array(); + } + + $reparse = false; + $filename = $phpbb_root_path . 'styles/' . $theme[$key . '_path'] . '/' . $key . '/' . $key . '.cfg'; + + if (!file_exists($filename)) + { + continue; + } + + if (!isset($parsed_array['filetime']) || (($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); + + $this->put('_cfg_' . $key . '_' . $theme[$key . '_path'], $parsed_array); + } + $parsed_items[$key] = $parsed_array; + } + + return $parsed_items; + } + + /** + * Obtain disallowed usernames + */ + function obtain_disallowed_usernames() + { + if (($usernames = $this->get('_disallowed_usernames')) === false) + { + global $db; + + $sql = 'SELECT disallow_username + FROM ' . DISALLOW_TABLE; + $result = $db->sql_query($sql); + + $usernames = array(); + while ($row = $db->sql_fetchrow($result)) + { + $usernames[] = str_replace('%', '.*?', preg_quote(utf8_clean_string($row['disallow_username']), '#')); + } + $db->sql_freeresult($result); + + $this->put('_disallowed_usernames', $usernames); + } + + return $usernames; + } + + /** + * Obtain hooks... + */ + function obtain_hooks() + { + global $phpbb_root_path, $phpEx; + + if (($hook_files = $this->get('_hooks')) === false) + { + $hook_files = array(); + + // Now search for hooks... + $dh = @opendir($phpbb_root_path . 'includes/hooks/'); + + if ($dh) + { + while (($file = readdir($dh)) !== false) + { + if (strpos($file, 'hook_') === 0 && substr($file, -(strlen($phpEx) + 1)) === '.' . $phpEx) + { + $hook_files[] = substr($file, 0, -(strlen($phpEx) + 1)); + } + } + closedir($dh); + } + + $this->put('_hooks', $hook_files); + } + + return $hook_files; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/captcha/captcha_factory.php b/phpBB/includes/captcha/captcha_factory.php new file mode 100644 index 0000000000..73406a954f --- /dev/null +++ b/phpBB/includes/captcha/captcha_factory.php @@ -0,0 +1,100 @@ +<?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; +} + +/** +* A small class for 3.0.x (no autoloader in 3.0.x) +* +* @package VC +*/ +class phpbb_captcha_factory +{ + /** + * return an instance of class $name in file $name_plugin.php + */ + function &get_instance($name) + { + global $phpbb_root_path, $phpEx; + + $name = basename($name); + if (!class_exists($name)) + { + include($phpbb_root_path . "includes/captcha/plugins/{$name}_plugin." . $phpEx); + } + $instance =& call_user_func(array($name, 'get_instance')); + return $instance; + } + + /** + * Call the garbage collector + */ + function garbage_collect($name) + { + global $phpbb_root_path, $phpEx; + + $name = basename($name); + if (!class_exists($name)) + { + include($phpbb_root_path . "includes/captcha/plugins/{$name}_plugin." . $phpEx); + } + call_user_func(array($name, 'garbage_collect'), 0); + } + + /** + * return a list of all discovered CAPTCHA plugins + */ + function get_captcha_types() + { + global $phpbb_root_path, $phpEx; + + $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\.' . $phpEx . '$#', $file))) + { + $name = preg_replace('#^(.*?)_plugin\.' . $phpEx . '$#', '\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 new file mode 100644 index 0000000000..96e39af85b --- /dev/null +++ b/phpBB/includes/captcha/captcha_gd.php @@ -0,0 +1,2640 @@ +<?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 +{ + var $width = 360; + var $height = 96; + + + /** + * Create the image containing $code with a seed of $seed + */ + function execute($code, $seed) + { + global $config; + + mt_srand($seed); + + // Create image + $img = imagecreatetruecolor($this->width, $this->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 = $this->width - 15; + $code_len = strlen($code); + $captcha_bitmaps = $this->captcha_bitmaps(); + + for ($i = 0; $i < $code_len; ++$i) + { + $characters[$i] = new char_cube3d($captcha_bitmaps, $code[$i]); + + list($min, $max) = $characters[$i]->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 ($config['captcha_gd_x_grid']) + { + $grid = (int) $config['captcha_gd_x_grid']; + for ($y = 0; $y < $this->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($this->width - 5, $this->width), mt_rand($y - 3, $y), $current_colour); + } + } + + if ($config['captcha_gd_y_grid']) + { + $grid = (int) $config['captcha_gd_y_grid']; + for ($x = 0; $x < $this->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($this->height - 5, $this->height), $current_colour); + } + } + if ($config['captcha_gd_wave'] && ($config['captcha_gd_y_grid'] || $config['captcha_gd_y_grid'])) + { + $this->wave($img); + } + + + if ($config['captcha_gd_3d_noise']) + { + $xoffset = mt_rand(0,9); + $noise_bitmaps = $this->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], $this->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], $this->height - $dimm[3]); + + $characters[$i]->drawchar($sizes[$i], $xoffset, $yoffset, $img, $colour->get_resource('background'), $scheme); + $xoffset += $dimm[2]; + } + if ($config['captcha_gd_wave']) + { + $this->wave($img); + } + if ($config['captcha_gd_foreground_noise']) + { + $this->noise_line($img, 0, 0, $this->width, $this->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 + */ + function wave($img) + { + global $config; + + $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($this->width/5, $this->width/2); + $dampen_y = mt_rand($this->height/5, $this->height/2); + $direction_x = (mt_rand (0, 1)); + $direction_y = (mt_rand (0, 1)); + + for ($i = 0; $i < $this->width; $i++) + { + $dir = ($direction_x) ? $i : ($this->width - $i); + imagecopy($img, $img, $i-1, sin($socket+ $i/($period_x + $dir/$dampen_x)) * $amp_x, $i, 0, 1, $this->height); + } + $socket = mt_rand(0,100); + for ($i = 0; $i < $this->height; $i++) + { + $dir = ($direction_y) ? $i : ($this->height - $i); + imagecopy($img, $img ,sin($socket + $i/($period_y + ($dir)/$dampen_y)) * $amp_y, $i-1, 0, $i, $this->width, 1); + } + return $img; + } + + /** + * Noise line + */ + 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 + */ + function captcha_bitmaps() + { + global $config; + + $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']), $config['captcha_gd_fonts']) -1)], + 'B' => $chars['B'][mt_rand(0, min(count($chars['B']), $config['captcha_gd_fonts']) -1)], + 'C' => $chars['C'][mt_rand(0, min(count($chars['C']), $config['captcha_gd_fonts']) -1)], + 'D' => $chars['D'][mt_rand(0, min(count($chars['D']), $config['captcha_gd_fonts']) -1)], + 'E' => $chars['E'][mt_rand(0, min(count($chars['E']), $config['captcha_gd_fonts']) -1)], + 'F' => $chars['F'][mt_rand(0, min(count($chars['F']), $config['captcha_gd_fonts']) -1)], + 'G' => $chars['G'][mt_rand(0, min(count($chars['G']), $config['captcha_gd_fonts']) -1)], + 'H' => $chars['H'][mt_rand(0, min(count($chars['H']), $config['captcha_gd_fonts']) -1)], + 'I' => $chars['I'][mt_rand(0, min(count($chars['I']), $config['captcha_gd_fonts']) -1)], + 'J' => $chars['J'][mt_rand(0, min(count($chars['J']), $config['captcha_gd_fonts']) -1)], + 'K' => $chars['K'][mt_rand(0, min(count($chars['K']), $config['captcha_gd_fonts']) -1)], + 'L' => $chars['L'][mt_rand(0, min(count($chars['L']), $config['captcha_gd_fonts']) -1)], + 'M' => $chars['M'][mt_rand(0, min(count($chars['M']), $config['captcha_gd_fonts']) -1)], + 'N' => $chars['N'][mt_rand(0, min(count($chars['N']), $config['captcha_gd_fonts']) -1)], + 'O' => $chars['O'][mt_rand(0, min(count($chars['O']), $config['captcha_gd_fonts']) -1)], + 'P' => $chars['P'][mt_rand(0, min(count($chars['P']), $config['captcha_gd_fonts']) -1)], + 'Q' => $chars['Q'][mt_rand(0, min(count($chars['Q']), $config['captcha_gd_fonts']) -1)], + 'R' => $chars['R'][mt_rand(0, min(count($chars['R']), $config['captcha_gd_fonts']) -1)], + 'S' => $chars['S'][mt_rand(0, min(count($chars['S']), $config['captcha_gd_fonts']) -1)], + 'T' => $chars['T'][mt_rand(0, min(count($chars['T']), $config['captcha_gd_fonts']) -1)], + 'U' => $chars['U'][mt_rand(0, min(count($chars['U']), $config['captcha_gd_fonts']) -1)], + 'V' => $chars['V'][mt_rand(0, min(count($chars['V']), $config['captcha_gd_fonts']) -1)], + 'W' => $chars['W'][mt_rand(0, min(count($chars['W']), $config['captcha_gd_fonts']) -1)], + 'X' => $chars['X'][mt_rand(0, min(count($chars['X']), $config['captcha_gd_fonts']) -1)], + 'Y' => $chars['Y'][mt_rand(0, min(count($chars['Y']), $config['captcha_gd_fonts']) -1)], + 'Z' => $chars['Z'][mt_rand(0, min(count($chars['Z']), $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 +{ + var $bitmap; + var $bitmap_width; + var $bitmap_height; + + var $basis_matrix = array(array(1, 0, 0), array(0, 1, 0), array(0, 0, 1)); + var $abs_x = array(1, 0); + var $abs_y = array(0, 1); + var $x = 0; + var $y = 1; + var $z = 2; + var $letter = ''; + + /** + */ + function char_cube3d(&$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 + */ + 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 = $this->sum2($xvec, $yvec); + + $zvec = $this->scale($this->basis_matrix[$this->z], $scale); + $x_corner = $this->sum2($xvec, $zvec); + $y_corner = $this->sum2($yvec, $zvec); + + imagefilledpolygon($img, $this->gen_poly($xo, $yo, $origin, $xvec, $x_corner,$zvec), 4, $colour1); + imagefilledpolygon($img, $this->gen_poly($xo, $yo, $origin, $yvec, $y_corner,$zvec), 4, $colour2); + + $face = $this->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 + */ + function range() + { + return array(3, 4); + } + + /** + * Vector length + */ + function vectorlen($vector) + { + return sqrt(pow($vector[0], 2) + pow($vector[1], 2) + pow($vector[2], 2)); + } + + /** + * Normalize + */ + function normalize(&$vector, $length = 1) + { + $length = (( $length < 1) ? 1 : $length); + $length /= $this->vectorlen($vector); + $vector[0] *= $length; + $vector[1] *= $length; + $vector[2] *= $length; + } + + /** + */ + 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; + } + + /** + */ + function sum($vector1, $vector2) + { + return array($vector1[0] + $vector2[0], $vector1[1] + $vector2[1], $vector1[2] + $vector2[2]); + } + + /** + */ + function sum2($vector1, $vector2) + { + return array($vector1[0] + $vector2[0], $vector1[1] + $vector2[1]); + } + + /** + */ + 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); + } + + /** + */ + 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 + */ + 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] = $this->sum2($xn, $yn); + $p[1] = $this->sum2($xp, $yn); + $p[2] = $this->sum2($xp, $yp); + $p[3] = $this->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 +{ + var $img; + var $mode; + var $colours; + var $named_colours; + + /** + * Create the colour manager, link it to the image resource + */ + function colour_manager($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 + */ + 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 + */ + function name_colour($name, $resource) + { + $this->named_colours[$name] = $resource; + } + + /** + * names and allocates a colour resource + */ + 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 + */ + 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 + */ + 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; + } + } + + /** + */ + 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; + } + + /** + */ + 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 + */ + 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 + */ + 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 + */ + 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); + } + + /** + */ + function normalize_hue(&$hue) + { + $hue %= 360; + + if ($hue < 0) + { + $hue += 360; + } + } + + /** + * Alternate hue to hue + */ + 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 + */ + 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 new file mode 100644 index 0000000000..f706c98d43 --- /dev/null +++ b/phpBB/includes/captcha/captcha_gd_wave.php @@ -0,0 +1,845 @@ +<?php +/** +* +* @package VC +* @version $Id$ +* @copyright (c) 2006 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* Wave3D CAPTCHA +* +* @author Robert Hetzler +* @package VC +*/ +class captcha +{ + var $width = 360; + var $height = 96; + + function execute($code, $seed) + { + global $starttime; + + // seed the random generator + mt_srand($seed); + + // set height and width + $img_x = $this->width; + $img_y = $this->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 = $this->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 = $this->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 = $this->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 = $this->wave_height(0, $y, $subdivision_factor); + $offset = $prev_height - $this->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 = $this->wave_height($x, $y, $subdivision_factor) + $this->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] += $this->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); + } + + 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); + } + + function grid_height($x, $y, $factor = 1, $x_grid, $y_grid) + { + return ((!($x % ($x_grid * $factor)) || !($y % ($y_grid * $factor))) ? 3 : 0); + } + + 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 new file mode 100644 index 0000000000..f82896f628 --- /dev/null +++ b/phpBB/includes/captcha/captcha_non_gd.php @@ -0,0 +1,392 @@ +<?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 +{ + var $filtered_pngs; + var $width = 320; + var $height = 50; + + /** + * Define filtered pngs on init + */ + function captcha() + { + // If we can we will generate a single filtered png, we avoid nastiness via emulation of some Zlib stuff + $this->define_filtered_pngs(); + } + + /** + * Create the image containing $code with a seed of $seed + */ + function execute($code, $seed) + { + $img_height = $this->height - 10; + $img_width = 0; + + mt_srand($seed); + + $char_widths = $hold_chars = array(); + $code_len = strlen($code); + + for ($i = 0; $i < $code_len; $i++) + { + $char = $code[$i]; + + $width = mt_rand(0, 4); + $raw_width = $this->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($this->filtered_pngs[$char]['data']), $raw_width + 1); + } + } + + $offset_x = mt_rand(0, $this->width - $img_width); + $offset_y = mt_rand(0, $this->height - $img_height); + + $image = ''; + for ($i = 0; $i < $this->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 .= $this->randomise(substr($hold_chars[$code{$j}][$i - $offset_y - 1], 1), $char_widths[$j]); + } + + for ($j = $offset_x + $img_width; $j < $this->width; $j++) + { + $image .= chr(mt_rand(140, 255)); + } + } + else + { + for ($j = 0; $j < $this->width; $j++) + { + $image .= chr(mt_rand(140, 255)); + } + } + } + unset($hold_chars); + + $image = $this->create_png($image, $this->width, $this->height); + + // Output image + header('Content-Type: image/png'); + header('Cache-control: no-cache, no-store'); + echo $image; + exit; + } + + /** + * 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 + */ + function randomise($scanline, $width) + { + $new_line = ''; + + $end = strlen($scanline) - ceil($width/2); + for ($i = floor($width/2); $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 + */ + 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 + */ + 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 .= $this->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 .= $this->png_chunk($length, 'IDAT', $raw_image); + + // IEND + $image .= $this->png_chunk(0, 'IEND', ''); + + return $image; + } + + /** + * png image data + * Each 'data' element is base64_encoded uncompressed IDAT + */ + function define_filtered_pngs() + { + $this->filtered_pngs = 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/plugins/captcha_abstract.php b/phpBB/includes/captcha/plugins/captcha_abstract.php new file mode 100644 index 0000000000..db4b7649c7 --- /dev/null +++ b/phpBB/includes/captcha/plugins/captcha_abstract.php @@ -0,0 +1,375 @@ +<?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.x CAPTCHAs. +* +* @package VC +*/ +class phpbb_default_captcha +{ + var $confirm_id; + var $confirm_code; + var $code; + var $seed; + var $attempts = 0; + var $type; + var $solved = 0; + var $captcha_vars = false; + + function init($type) + { + global $config, $db, $user; + + // read input + $this->confirm_id = request_var('confirm_id', ''); + $this->confirm_code = request_var('confirm_code', ''); + $refresh = request_var('refresh_vc', false) && $config['confirm_refresh']; + + $this->type = (int) $type; + + if (!strlen($this->confirm_id) || !$this->load_code()) + { + // we have no confirm ID, better get ready to display something + $this->generate_code(); + } + else if ($refresh) + { + $this->regenerate_code(); + } + } + + function execute_demo() + { + global $user; + + $this->code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS)); + $this->seed = hexdec(substr(unique_id(), 4, 10)); + + // compute $seed % 0x7fffffff + $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff); + + $captcha = new captcha(); + define('IMAGE_OUTPUT', 1); + $captcha->execute($this->code, $this->seed); + } + + function execute() + { + if (empty($this->code)) + { + if (!$this->load_code()) + { + // invalid request, bail out + return false; + } + } + $captcha = new captcha(); + define('IMAGE_OUTPUT', 1); + $captcha->execute($this->code, $this->seed); + } + + function get_template() + { + global $config, $user, $template, $phpEx, $phpbb_root_path; + + if ($this->is_solved()) + { + return false; + } + else + { + $link = append_sid($phpbb_root_path . 'ucp.' . $phpEx, 'mode=confirm&confirm_id=' . $this->confirm_id . '&type=' . $this->type); + $explain = $user->lang(($this->type != CONFIRM_POST) ? 'CONFIRM_EXPLAIN' : 'POST_CONFIRM_EXPLAIN', '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'); + + $template->assign_vars(array( + 'CONFIRM_IMAGE_LINK' => $link, + 'CONFIRM_IMAGE' => '<img src="' . $link . '" />', + 'CONFIRM_IMG' => '<img src="' . $link . '" />', + 'CONFIRM_ID' => $this->confirm_id, + 'S_CONFIRM_CODE' => true, + 'S_TYPE' => $this->type, + 'S_CONFIRM_REFRESH' => ($config['enable_confirm'] && $config['confirm_refresh'] && $this->type == CONFIRM_REG) ? true : false, + 'L_CONFIRM_EXPLAIN' => $explain, + )); + + return 'captcha_default.html'; + } + } + + function get_demo_template($id) + { + global $config, $user, $template, $phpbb_admin_path, $phpEx; + + $variables = ''; + + if (is_array($this->captcha_vars)) + { + foreach ($this->captcha_vars as $captcha_var => $template_var) + { + $variables .= '&' . rawurlencode($captcha_var) . '=' . request_var($captcha_var, (int) $config[$captcha_var]); + } + } + + // acp_captcha has a delivery function; let's use it + $template->assign_vars(array( + 'CONFIRM_IMAGE' => append_sid($phpbb_admin_path . 'index.' . $phpEx, 'captcha_demo=1&mode=visual&i=' . $id . '&select_captcha=' . $this->get_class_name()) . $variables, + 'CONFIRM_ID' => $this->confirm_id, + )); + + return 'captcha_default_acp_demo.html'; + } + + function get_hidden_fields() + { + $hidden_fields = array(); + + // this is required for posting.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 garbage_collect($type) + { + global $db, $config; + + $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 = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + $sql_in = array(); + do + { + $sql_in[] = (string) $row['session_id']; + } + while ($row = $db->sql_fetchrow($result)); + + if (sizeof($sql_in)) + { + $sql = 'DELETE FROM ' . CONFIRM_TABLE . ' + WHERE ' . $db->sql_in_set('session_id', $sql_in); + $db->sql_query($sql); + } + } + $db->sql_freeresult($result); + } + + function uninstall() + { + $this->garbage_collect(0); + } + + function install() + { + return; + } + + function validate() + { + global $config, $db, $user; + + $error = ''; + if (!$this->confirm_id) + { + $error = $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 = $user->lang['CONFIRM_CODE_WRONG']; + } + } + + if (strlen($error)) + { + // okay, incorrect answer. Let's ask a new question. + $this->new_attempt(); + return $error; + } + else + { + return false; + } + } + + /** + * The old way to generate code, suitable for GD and non-GD. Resets the internal state. + */ + function generate_code() + { + global $db, $user; + + $this->code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS)); + $this->confirm_id = md5(unique_id($user->ip)); + $this->seed = hexdec(substr(unique_id(), 4, 10)); + $this->solved = 0; + // compute $seed % 0x7fffffff + $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff); + + $sql = 'INSERT INTO ' . CONFIRM_TABLE . ' ' . $db->sql_build_array('INSERT', array( + 'confirm_id' => (string) $this->confirm_id, + 'session_id' => (string) $user->session_id, + 'confirm_type' => (int) $this->type, + 'code' => (string) $this->code, + 'seed' => (int) $this->seed) + ); + $db->sql_query($sql); + } + + /** + * New Question, if desired. + */ + function regenerate_code() + { + global $db, $user; + + $this->code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS)); + $this->seed = hexdec(substr(unique_id(), 4, 10)); + $this->solved = 0; + // compute $seed % 0x7fffffff + $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff); + + $sql = 'UPDATE ' . CONFIRM_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array( + 'code' => (string) $this->code, + 'seed' => (int) $this->seed)) . ' + WHERE + confirm_id = \'' . $db->sql_escape($this->confirm_id) . '\' + AND session_id = \'' . $db->sql_escape($user->session_id) . '\''; + $db->sql_query($sql); + } + + /** + * New Question, if desired. + */ + function new_attempt() + { + global $db, $user; + + $this->code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS)); + $this->seed = hexdec(substr(unique_id(), 4, 10)); + $this->solved = 0; + // compute $seed % 0x7fffffff + $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff); + + $sql = 'UPDATE ' . CONFIRM_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array( + 'code' => (string) $this->code, + 'seed' => (int) $this->seed)) . ' + , attempts = attempts + 1 + WHERE + confirm_id = \'' . $db->sql_escape($this->confirm_id) . '\' + AND session_id = \'' . $db->sql_escape($user->session_id) . '\''; + $db->sql_query($sql); + } + + /** + * Look up everything we need for painting&checking. + */ + function load_code() + { + global $db, $user; + + $sql = 'SELECT code, seed, attempts + FROM ' . CONFIRM_TABLE . " + WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "' + AND session_id = '" . $db->sql_escape($user->session_id) . "' + AND confirm_type = " . $this->type; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + $this->code = $row['code']; + $this->seed = $row['seed']; + $this->attempts = $row['attempts']; + return true; + } + + return false; + } + + function check_code() + { + return (strcasecmp($this->code, $this->confirm_code) === 0); + } + + function delete_code() + { + global $db, $user; + + $sql = 'DELETE FROM ' . CONFIRM_TABLE . " + WHERE confirm_id = '" . $db->sql_escape($confirm_id) . "' + AND session_id = '" . $db->sql_escape($user->session_id) . "' + AND confirm_type = " . $this->type; + $db->sql_query($sql); + } + + function get_attempt_count() + { + return $this->attempts; + } + + function reset() + { + global $db, $user; + + $sql = 'DELETE FROM ' . CONFIRM_TABLE . " + WHERE session_id = '" . $db->sql_escape($user->session_id) . "' + AND confirm_type = " . (int) $this->type; + $db->sql_query($sql); + + // we leave the class usable by generating a new question + $this->generate_code(); + } + + function is_solved() + { + if (request_var('confirm_code', false) && $this->solved === 0) + { + $this->validate(); + } + return (bool) $this->solved; + } + + /** + * API function + */ + function has_config() + { + return false; + } + +} + +?>
\ 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 new file mode 100644 index 0000000000..6e899adc16 --- /dev/null +++ b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php @@ -0,0 +1,165 @@ +<?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 +*/ +if (!class_exists('phpbb_default_captcha')) +{ + include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx); +} + +/** +* @package VC +*/ +class phpbb_captcha_gd extends phpbb_default_captcha +{ + + var $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', + 'captcha_gd_wave' => 'CAPTCHA_GD_WAVE', + 'captcha_gd_3d_noise' => 'CAPTCHA_GD_3D_NOISE', + 'captcha_gd_fonts' => 'CAPTCHA_GD_FONTS', + ); + + function phpbb_captcha_gd() + { + global $phpbb_root_path, $phpEx; + + if (!class_exists('captcha')) + { + include($phpbb_root_path . 'includes/captcha/captcha_gd.' . $phpEx); + } + } + + function &get_instance() + { + $instance =& new phpbb_captcha_gd(); + return $instance; + } + + function is_available() + { + global $phpbb_root_path, $phpEx; + + if (@extension_loaded('gd')) + { + return true; + } + + if (!function_exists('can_load_dll')) + { + include($phpbb_root_path . 'includes/functions_install.' . $phpEx); + } + + return can_load_dll('gd'); + } + + /** + * API function + */ + function has_config() + { + return true; + } + + function get_name() + { + return 'CAPTCHA_GD'; + } + + function get_class_name() + { + return 'phpbb_captcha_gd'; + } + + function acp_page($id, &$module) + { + global $db, $user, $auth, $template; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + $user->add_lang('acp/board'); + + $config_vars = array( + 'enable_confirm' => 'REG_ENABLE', + 'enable_post_confirm' => 'POST_ENABLE', + 'confirm_refresh' => 'CONFIRM_REFRESH', + 'captcha_gd' => 'CAPTCHA_GD', + ); + + $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($this->captcha_vars); + foreach ($captcha_vars as $captcha_var) + { + $value = request_var($captcha_var, 0); + if ($value >= 0) + { + set_config($captcha_var, $value); + } + } + + add_log('admin', 'LOG_CONFIG_VISUAL'); + trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($module->u_action)); + } + else if ($submit) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($module->u_action)); + } + else + { + foreach ($this->captcha_vars as $captcha_var => $template_var) + { + $var = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, 0) : $config[$captcha_var]; + $template->assign_var($template_var, $var); + } + + $template->assign_vars(array( + 'CAPTCHA_PREVIEW' => $this->get_demo_template($id), + 'CAPTCHA_NAME' => $this->get_class_name(), + 'U_ACTION' => $module->u_action, + )); + } + } + + function execute_demo() + { + global $config; + + $config_old = $config; + foreach ($this->captcha_vars as $captcha_var => $template_var) + { + $config[$captcha_var] = request_var($captcha_var, (int) $config[$captcha_var]); + } + parent::execute_demo(); + $config = $config_old; + } + +} + +?>
\ 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 new file mode 100644 index 0000000000..2f55d15efd --- /dev/null +++ b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php @@ -0,0 +1,83 @@ +<?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 +*/ +if (!class_exists('phpbb_default_captcha')) +{ + include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx); +} + +/** +* @package VC +*/ +class phpbb_captcha_gd_wave extends phpbb_default_captcha +{ + + function phpbb_captcha_gd_wave() + { + global $phpbb_root_path, $phpEx; + + if (!class_exists('captcha')) + { + include_once($phpbb_root_path . 'includes/captcha/captcha_gd_wave.' . $phpEx); + } + } + + function get_instance() + { + return new phpbb_captcha_gd_wave(); + } + + function is_available() + { + global $phpbb_root_path, $phpEx; + + if (@extension_loaded('gd')) + { + return true; + } + + if (!function_exists('can_load_dll')) + { + include($phpbb_root_path . 'includes/functions_install.' . $phpEx); + } + + return can_load_dll('gd'); + } + + function get_name() + { + return 'CAPTCHA_GD_3D'; + } + + function get_class_name() + { + return 'phpbb_captcha_gd_wave'; + } + + function acp_page($id, &$module) + { + global $config, $db, $template, $user; + + trigger_error($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 new file mode 100644 index 0000000000..ac30ed4297 --- /dev/null +++ b/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php @@ -0,0 +1,72 @@ +<?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 +*/ +if (!class_exists('phpbb_default_captcha')) +{ + include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx); +} + +/** +* @package VC +*/ +class phpbb_captcha_nogd extends phpbb_default_captcha +{ + + function phpbb_captcha_nogd() + { + global $phpbb_root_path, $phpEx; + + if (!class_exists('captcha')) + { + include_once($phpbb_root_path . 'includes/captcha/captcha_non_gd.' . $phpEx); + } + } + + function &get_instance() + { + $instance =& new phpbb_captcha_nogd(); + return $instance; + } + + function is_available() + { + return true; + } + + function get_name() + { + return 'CAPTCHA_NO_GD'; + } + + function get_class_name() + { + return 'phpbb_captcha_nogd'; + } + + function acp_page($id, &$module) + { + global $user; + + trigger_error($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_qa_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php new file mode 100644 index 0000000000..c17cfa7bbe --- /dev/null +++ b/phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php @@ -0,0 +1,945 @@ +<?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; +} + +global $table_prefix; + +define('CAPTCHA_QUESTIONS_TABLE', $table_prefix . 'captcha_questions'); +define('CAPTCHA_ANSWERS_TABLE', $table_prefix . 'captcha_answers'); +define('CAPTCHA_QA_CONFIRM_TABLE', $table_prefix . 'qa_confirm'); + +/** +* And now to something completely different. Let's make a captcha without extending the abstract class. +* QA CAPTCHA sample implementation +* +* @package VC +*/ +class phpbb_captcha_qa +{ + var $confirm_id; + var $answer; + var $question_ids; + var $question_text; + var $question_lang; + var $question_strict; + var $attempts = 0; + var $type; + // dirty trick: 0 is false, but can still encode that the captcha is not yet validated + var $solved = 0; + + /** + * @param int $type as per the CAPTCHA API docs, the type + */ + function init($type) + { + global $config, $db, $user; + + // load our language file + $user->add_lang('captcha_qa'); + + // read input + $this->confirm_id = request_var('qa_confirm_id', ''); + $this->answer = request_var('qa_answer', '', true); + + $this->type = (int) $type; + $this->question_lang = $user->lang_name; + + // we need all defined questions - shouldn't be too many, so we can just grab them + // try the user's lang first + $sql = 'SELECT question_id + FROM ' . CAPTCHA_QUESTIONS_TABLE . " + WHERE lang_iso = '" . $db->sql_escape($user->lang_name) . "'"; + $result = $db->sql_query($sql, 3600); + + while ($row = $db->sql_fetchrow($result)) + { + $this->question_ids[$row['question_id']] = $row['question_id']; + } + $db->sql_freeresult($result); + + // fallback to the board default lang + if (!sizeof($this->question_ids)) + { + $this->question_lang = $config['default_lang']; + + $sql = 'SELECT question_id + FROM ' . CAPTCHA_QUESTIONS_TABLE . " + WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'"; + $result = $db->sql_query($sql, 7200); + + while ($row = $db->sql_fetchrow($result)) + { + $this->question_ids[$row['question_id']] = $row['question_id']; + } + $db->sql_freeresult($result); + } + + // okay, if there is a confirm_id, we try to load that confirm's state + if (!strlen($this->confirm_id) || !$this->load_answer()) + { + // we have no valid confirm ID, better get ready to ask something + $this->select_question(); + } + } + + /** + * API function + */ + function &get_instance() + { + $instance =& new phpbb_captcha_qa(); + + return $instance; + } + + /** + * See if the captcha has created its tables. + */ + function is_installed() + { + global $db, $phpbb_root_path, $phpEx; + + if (!class_exists('phpbb_db_tools')) + { + include("$phpbb_root_path/includes/db/db_tools.$phpEx"); + } + $db_tool = new phpbb_db_tools($db); + + return $db_tool->sql_table_exists(CAPTCHA_QUESTIONS_TABLE); + } + + /** + * API function - for the captcha to be available, it must have installed itself and there has to be at least one question in the board's default lang + */ + function is_available() + { + global $config, $db, $phpbb_root_path, $phpEx, $user; + + // load language file for pretty display in the ACP dropdown + $user->add_lang('captcha_qa'); + + if (!phpbb_captcha_qa::is_installed()) + { + return false; + } + + $sql = 'SELECT COUNT(question_id) as count + FROM ' . CAPTCHA_QUESTIONS_TABLE . " + WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + return ((bool) $row['count']); + } + + /** + * API function + */ + function has_config() + { + return true; + } + + /** + * API function + */ + function get_name() + { + return 'CAPTCHA_QA'; + } + + /** + * API function + */ + function get_class_name() + { + return 'phpbb_captcha_qa'; + } + + /** + * API function - not needed as we don't display an image + */ + function execute_demo() + { + } + + /** + * API function - not needed as we don't display an image + */ + function execute() + { + } + + /** + * API function - send the question to the template + */ + function get_template() + { + global $template; + + if ($this->is_solved()) + { + return false; + } + else + { + $template->assign_vars(array( + 'QA_CONFIRM_QUESTION' => $this->question_text, + 'QA_CONFIRM_ID' => $this->confirm_id, + 'S_CONFIRM_CODE' => true, + 'S_TYPE' => $this->type, + )); + + return 'captcha_qa.html'; + } + } + + /** + * API function - we just display a mockup so that the captcha doesn't need to be installed + */ + function get_demo_template() + { + return 'captcha_qa_acp_demo.html'; + } + + /** + * API function + */ + function get_hidden_fields() + { + $hidden_fields = array(); + + // this is required - otherwise we would forget about the captcha being already solved + if ($this->solved) + { + $hidden_fields['qa_answer'] = $this->answer; + } + $hidden_fields['qa_confirm_id'] = $this->confirm_id; + + return $hidden_fields; + } + + /** + * API function + */ + function garbage_collect($type) + { + global $db, $config; + + $sql = 'SELECT DISTINCT c.session_id + FROM ' . CAPTCHA_QA_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 = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + $sql_in = array(); + + do + { + $sql_in[] = (string) $row['session_id']; + } + while ($row = $db->sql_fetchrow($result)); + + if (sizeof($sql_in)) + { + $sql = 'DELETE FROM ' . CAPTCHA_QA_CONFIRM_TABLE . ' + WHERE ' . $db->sql_in_set('session_id', $sql_in); + $db->sql_query($sql); + } + } + $db->sql_freeresult($result); + } + + /** + * API function - we don't drop the tables here, as that would cause the loss of all entered questions. + */ + function uninstall() + { + $this->garbage_collect(0); + } + + /** + * API function - set up shop + */ + function install() + { + global $db, $phpbb_root_path, $phpEx; + + if (!class_exists('phpbb_db_tools')) + { + include("$phpbb_root_path/includes/db/db_tools.$phpEx"); + } + $db_tool = new phpbb_db_tools($db); + + $tables = array(CAPTCHA_QUESTIONS_TABLE, CAPTCHA_ANSWERS_TABLE, CAPTCHA_QA_CONFIRM_TABLE); + + $schemas = array( + CAPTCHA_QUESTIONS_TABLE => array ( + 'COLUMNS' => array( + 'question_id' => array('UINT', Null, 'auto_increment'), + 'strict' => array('BOOL', 0), + 'lang_id' => array('UINT', 0), + 'lang_iso' => array('VCHAR:30', ''), + 'question_text' => array('TEXT_UNI', ''), + ), + 'PRIMARY_KEY' => 'question_id', + 'KEYS' => array( + 'lang_iso' => array('INDEX', 'lang_iso'), + ), + ), + CAPTCHA_ANSWERS_TABLE => array ( + 'COLUMNS' => array( + 'question_id' => array('UINT', 0), + 'answer_text' => array('STEXT_UNI', ''), + ), + 'KEYS' => array( + 'question_id' => array('INDEX', 'question_id'), + ), + ), + CAPTCHA_QA_CONFIRM_TABLE => array ( + 'COLUMNS' => array( + 'session_id' => array('CHAR:32', ''), + 'confirm_id' => array('CHAR:32', ''), + 'lang_iso' => array('VCHAR:30', ''), + 'question_id' => array('UINT', 0), + 'attempts' => array('UINT', 0), + 'confirm_type' => array('USINT', 0), + ), + 'KEYS' => array( + 'session_id' => array('INDEX', 'session_id'), + 'lookup' => array('INDEX', array('confirm_id', 'session_id', 'lang_iso')), + ), + 'PRIMARY_KEY' => 'confirm_id', + ), + ); + + foreach($schemas as $table => $schema) + { + if (!$db_tool->sql_table_exists($table)) + { + $db_tool->sql_create_table($table, $schema); + } + } + } + + /** + * API function - see what has to be done to validate + */ + function validate() + { + global $config, $db, $user; + + $error = ''; + + if (!sizeof($this->question_ids)) + { + return false; + } + + if (!$this->confirm_id) + { + $error = $user->lang['CONFIRM_QUESTION_WRONG']; + } + else + { + if ($this->check_answer()) + { + // $this->delete_code(); commented out to allow posting.php to repeat the question + $this->solved = true; + } + else + { + $error = $user->lang['CONFIRM_QUESTION_WRONG']; + } + } + + if (strlen($error)) + { + // okay, incorrect answer. Let's ask a new question. + $this->new_attempt(); + $this->solved = false; + + return $error; + } + else + { + return false; + } + } + + /** + * Select a question + */ + function select_question() + { + global $db, $user; + + + if (!sizeof($this->question_ids)) + { + return false; + } + $this->confirm_id = md5(unique_id($user->ip)); + $this->question = (int) array_rand($this->question_ids); + + $sql = 'INSERT INTO ' . CAPTCHA_QA_CONFIRM_TABLE . ' ' . $db->sql_build_array('INSERT', array( + 'confirm_id' => (string) $this->confirm_id, + 'session_id' => (string) $user->session_id, + 'lang_iso' => (string) $this->question_lang, + 'confirm_type' => (int) $this->type, + 'question_id' => (int) $this->question, + )); + $db->sql_query($sql); + + $this->load_answer(); + } + + /** + * New Question, if desired. + */ + function reselect_question() + { + global $db, $user; + + if (!sizeof($this->question_ids)) + { + return false; + } + + $this->question = (int) array_rand($this->question_ids); + $this->solved = 0; + + $sql = 'UPDATE ' . CAPTCHA_QA_CONFIRM_TABLE . ' + SET question_id = ' . (int) $this->question . " + WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "' + AND session_id = '" . $db->sql_escape($user->session_id) . "'"; + $db->sql_query($sql); + + $this->load_answer(); + } + + /** + * Wrong answer, so we increase the attempts and use a different question. + */ + function new_attempt() + { + global $db, $user; + + // yah, I would prefer a stronger rand, but this should work + $this->question = (int) array_rand($this->question_ids); + $this->solved = 0; + + $sql = 'UPDATE ' . CAPTCHA_QA_CONFIRM_TABLE . ' + SET question_id = ' . (int) $this->question . ", + attempts = attempts + 1 + WHERE confirm_id = '" . $db->sql_escape($this->confirm_id) . "' + AND session_id = '" . $db->sql_escape($user->session_id) . "'"; + $db->sql_query($sql); + + $this->load_answer(); + } + + /** + * Look up everything we need and populate the instance variables. + */ + function load_answer() + { + global $db, $user; + + if (!sizeof($this->question_ids)) + { + return false; + } + + $sql = 'SELECT con.question_id, attempts, question_text, strict + FROM ' . CAPTCHA_QA_CONFIRM_TABLE . ' con, ' . CAPTCHA_QUESTIONS_TABLE . " qes + WHERE con.question_id = qes.question_id + AND confirm_id = '" . $db->sql_escape($this->confirm_id) . "' + AND session_id = '" . $db->sql_escape($user->session_id) . "' + AND qes.lang_iso = '" . $db->sql_escape($this->question_lang) . "' + AND confirm_type = " . $this->type; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + $this->question = $row['question_id']; + + $this->attempts = $row['attempts']; + $this->question_strict = $row['strict']; + $this->question_text = $row['question_text']; + + return true; + } + + return false; + } + + /** + * The actual validation + */ + function check_answer() + { + global $db; + + $answer = ($this->question_strict) ? request_var('qa_answer', '', true) : utf8_clean_string(request_var('qa_answer', '', true)); + + $sql = 'SELECT answer_text + FROM ' . CAPTCHA_ANSWERS_TABLE . ' + WHERE question_id = ' . (int) $this->question; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $solution = ($this->question_strict) ? $row['answer_text'] : utf8_clean_string($row['answer_text']); + + if ($solution === $answer) + { + $this->solved = true; + + break; + } + } + $db->sql_freeresult($result); + + return $this->solved; + } + + /** + * API function - clean the entry + */ + function delete_code() + { + global $db, $user; + + $sql = 'DELETE FROM ' . CAPTCHA_QA_CONFIRM_TABLE . " + WHERE confirm_id = '" . $db->sql_escape($confirm_id) . "' + AND session_id = '" . $db->sql_escape($user->session_id) . "' + AND confirm_type = " . $this->type; + $db->sql_query($sql); + } + + /** + * API function + */ + function get_attempt_count() + { + return $this->attempts; + } + + /** + * API function + */ + function reset() + { + global $db, $user; + + $sql = 'DELETE FROM ' . CAPTCHA_QA_CONFIRM_TABLE . " + WHERE session_id = '" . $db->sql_escape($user->session_id) . "' + AND confirm_type = " . (int) $this->type; + $db->sql_query($sql); + + // we leave the class usable by generating a new question + $this->select_question(); + } + + /** + * API function + */ + function is_solved() + { + if (request_var('qa_answer', false) && $this->solved === 0) + { + $this->validate(); + } + + return (bool) $this->solved; + } + + /** + * API function - The ACP backend, this marks the end of the easy methods + */ + function acp_page($id, &$module) + { + global $db, $user, $auth, $template; + global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + + $user->add_lang('acp/board'); + $user->add_lang('captcha_qa'); + + if (!$this->is_installed()) + { + $this->install(); + } + + $module->tpl_name = 'captcha_qa_acp'; + $module->page_title = 'ACP_VC_SETTINGS'; + $form_key = 'acp_captcha'; + add_form_key($form_key); + + $submit = request_var('submit', false); + $question_id = request_var('question_id', 0); + $action = request_var('action', ''); + + // we have two pages, so users might want to navigate from one to the other + $list_url = $module->u_action . "&configure=1&select_captcha=" . $this->get_class_name(); + + $template->assign_vars(array( + 'U_ACTION' => $module->u_action, + 'QUESTION_ID' => $question_id , + 'CLASS' => $this->get_class_name(), + )); + + // show the list? + if (!$question_id && $action != 'add') + { + $this->acp_question_list($module); + } + else if ($question_id && $action == 'delete') + { + if (confirm_box(true)) + { + $this->acp_delete_question($question_id); + + trigger_error($user->lang['QUESTION_DELETED'] . adm_back_link($list_url)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'question_id' => $question_id, + 'action' => $action, + 'configure' => 1, + 'select_captcha' => $this->get_class_name(), + )) + ); + } + } + else + { + // okay, show the editor + $error = false; + $input_question = request_var('question_text', '', true); + $input_answers = request_var('answers', '', true); + $input_lang = request_var('lang_iso', '', true); + $input_strict = request_var('strict', false); + $langs = $this->get_languages(); + + foreach ($langs as $lang => $entry) + { + $template->assign_block_vars('langs', array( + 'ISO' => $lang, + 'NAME' => $entry['name'], + )); + } + + $template->assign_vars(array( + 'U_LIST' => $list_url, + )); + + if ($question_id) + { + if ($question = $this->acp_get_question_data($question_id)) + { + $answers = (isset($input_answers[$lang])) ? $input_answers[$lang] : implode("\n", $question['answers']); + + $template->assign_vars(array( + 'QUESTION_TEXT' => ($input_question) ? $input_question : $question['question_text'], + 'LANG_ISO' => ($input_lang) ? $input_lang : $question['lang_iso'], + 'STRICT' => (isset($_REQUEST['strict'])) ? $input_strict : $question['strict'], + 'ANSWERS' => $answers, + )); + } + else + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($list_url)); + } + } + else + { + $template->assign_vars(array( + 'QUESTION_TEXT' => $input_question, + 'LANG_ISO' => $input_lang, + 'STRICT' => $input_strict, + 'ANSWERS' => $input_answers, + )); + } + + if ($submit && check_form_key($form_key)) + { + $data = $this->acp_get_question_input(); + + if (!$this->validate_input($data)) + { + $template->assign_vars(array( + 'S_ERROR' => true, + )); + } + else + { + if ($question_id) + { + $this->acp_update_question($data, $question_id); + } + else + { + $this->acp_add_question($data); + } + + add_log('admin', 'LOG_CONFIG_VISUAL'); + trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($list_url)); + } + } + else if ($submit) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($list_url)); + } + } + } + + /** + * This handles the list overview + */ + function acp_question_list(&$module) + { + global $db, $template; + + $sql = 'SELECT * + FROM ' . CAPTCHA_QUESTIONS_TABLE; + $result = $db->sql_query($sql); + + $template->assign_vars(array( + 'S_LIST' => true, + )); + + while ($row = $db->sql_fetchrow($result)) + { + $url = $module->u_action . "&question_id={$row['question_id']}&configure=1&select_captcha=" . $this->get_class_name() . '&'; + + $template->assign_block_vars('questions', array( + 'QUESTION_TEXT' => $row['question_text'], + 'QUESTION_ID' => $row['question_id'], + 'QUESTION_LANG' => $row['lang_iso'], + 'U_DELETE' => "{$url}action=delete", + 'U_EDIT' => "{$url}action=edit", + )); + } + $db->sql_freeresult($result); + } + + /** + * Grab a question and bring it into a format the editor understands + */ + function acp_get_question_data($question_id) + { + global $db; + + if ($question_id) + { + $sql = 'SELECT * + FROM ' . CAPTCHA_QUESTIONS_TABLE . ' + WHERE question_id = ' . $question_id; + $result = $db->sql_query($sql); + $question = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$question) + { + return false; + } + + $question['answers'] = array(); + + $sql = 'SELECT * + FROM ' . CAPTCHA_ANSWERS_TABLE . ' + WHERE question_id = ' . $question_id; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $question['answers'][] = $row['answer_text']; + } + $db->sql_freeresult($result); + + return $question; + } + } + + /** + * Grab a question from input and bring it into a format the editor understands + */ + function acp_get_question_input() + { + $question = array( + 'question_text' => request_var('question_text', '', true), + 'strict' => request_var('strict', false), + 'lang_iso' => request_var('lang_iso', ''), + 'answers' => explode("\n", request_var('answers', '', true)), + ); + + return $question; + } + + /** + * Update a question. + * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data + */ + function acp_update_question($data, $question_id) + { + global $db, $cache; + + // easier to delete all answers than to figure out which to update + $sql = 'DELETE FROM ' . CAPTCHA_ANSWERS_TABLE . " WHERE question_id = $question_id"; + $db->sql_query($sql); + + $langs = $this->get_languages(); + $question_ary = $data; + $question_ary['lang_id'] = $langs[$question_ary['lang_iso']]['id']; + unset($question_ary['answers']); + + $sql = 'UPDATE ' . CAPTCHA_QUESTIONS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $question_ary) . " + WHERE question_id = $question_id"; + $db->sql_query($sql); + + $this->acp_insert_answers($data, $question_id); + + $cache->destroy('sql', CAPTCHA_QUESTIONS_TABLE); + } + + /** + * Insert a question. + * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data + */ + function acp_add_question($data) + { + global $db, $cache; + + $langs = $this->get_languages(); + $question_ary = $data; + + $question_ary['lang_id'] = $langs[$data['lang_iso']]['id']; + unset($question_ary['answers']); + + $sql = 'INSERT INTO ' . CAPTCHA_QUESTIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $question_ary); + $db->sql_query($sql); + + $question_id = $db->sql_nextid(); + + $this->acp_insert_answers($data, $question_id); + + $cache->destroy('sql', CAPTCHA_QUESTIONS_TABLE); + } + + /** + * Insert the answers. + * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data + */ + function acp_insert_answers($data, $question_id) + { + global $db, $cache; + + foreach ($data['answers'] as $answer) + { + $answer_ary = array( + 'question_id' => $question_id, + 'answer_text' => $answer, + ); + + $sql = 'INSERT INTO ' . CAPTCHA_ANSWERS_TABLE . ' ' . $db->sql_build_array('INSERT', $answer_ary); + $db->sql_query($sql); + } + + $cache->destroy('sql', CAPTCHA_ANSWERS_TABLE); + } + + /** + * Delete a question. + */ + function acp_delete_question($question_id) + { + global $db, $cache; + + $tables = array(CAPTCHA_QUESTIONS_TABLE, CAPTCHA_ANSWERS_TABLE); + + foreach ($tables as $table) + { + $sql = "DELETE FROM $table + WHERE question_id = $question_id"; + $db->sql_query($sql); + } + + $cache->destroy('sql', $tables); + } + + /** + * Check if the entered data can be inserted/used + * param mixed $data : an array as created from acp_get_question_input or acp_get_question_data + */ + function validate_input($question_data) + { + $langs = $this->get_languages(); + + if (!isset($question_data['lang_iso']) || + !isset($question_data['question_text']) || + !isset($question_data['strict']) || + !isset($question_data['answers'])) + { + return false; + } + + if (!isset($langs[$question_data['lang_iso']]) || + !$question_data['question_text'] || + !sizeof($question_data['answers'])) + { + return false; + } + + return true; + } + + /** + * List the installed language packs + */ + function get_languages() + { + global $db; + + $sql = 'SELECT * + FROM ' . LANG_TABLE; + $result = $db->sql_query($sql); + + $langs = array(); + while ($row = $db->sql_fetchrow($result)) + { + $langs[$row['lang_iso']] = array( + 'name' => $row['lang_local_name'], + 'id' => (int) $row['lang_id'], + ); + } + $db->sql_freeresult($result); + + return $langs; + } +} + +?>
\ 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 new file mode 100644 index 0000000000..d4543dddfc --- /dev/null +++ b/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php @@ -0,0 +1,336 @@ +<?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; +} + +if (!class_exists('phpbb_default_captcha')) +{ + // we need the classic captcha code for tracking solutions and attempts + include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx); +} + +/** +* @package VC +*/ +class phpbb_recaptcha extends phpbb_default_captcha +{ + var $recaptcha_server = 'http://api.recaptcha.net'; + var $recaptcha_verify_server = 'api-verify.recaptcha.net'; + var $challenge; + var $response; + + function init($type) + { + global $config, $db, $user; + + $user->add_lang('captcha_recaptcha'); + parent::init($type); + $this->challenge = request_var('recaptcha_challenge_field', ''); + $this->response = request_var('recaptcha_response_field', ''); + } + + function &get_instance() + { + $instance =& new phpbb_recaptcha(); + return $instance; + } + + function is_available() + { + global $config, $user; + $user->add_lang('captcha_recaptcha'); + return (isset($config['recaptcha_pubkey']) && !empty($config['recaptcha_pubkey'])); + } + + /** + * API function + */ + function has_config() + { + return true; + } + + function get_name() + { + return 'CAPTCHA_RECAPTCHA'; + } + + function get_class_name() + { + return 'phpbb_recaptcha'; + } + + function acp_page($id, &$module) + { + global $config, $db, $template, $user; + + $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); + } + } + + add_log('admin', 'LOG_CONFIG_VISUAL'); + trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($module->u_action)); + } + else if ($submit) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($module->u_action)); + } + else + { + foreach ($captcha_vars as $captcha_var => $template_var) + { + $var = (isset($_REQUEST[$captcha_var])) ? request_var($captcha_var, '') : ((isset($config[$captcha_var])) ? $config[$captcha_var] : ''); + $template->assign_var($template_var, $var); + } + + $template->assign_vars(array( + 'CAPTCHA_PREVIEW' => $this->get_demo_template($id), + 'CAPTCHA_NAME' => $this->get_class_name(), + 'U_ACTION' => $module->u_action, + )); + + } + } + + // not needed + function execute_demo() + { + } + + // not needed + function execute() + { + } + + function get_template() + { + global $config, $user, $template; + + if ($this->is_solved()) + { + return false; + } + else + { + $explain = $user->lang(($this->type != CONFIRM_POST) ? 'CONFIRM_EXPLAIN' : 'POST_CONFIRM_EXPLAIN', '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'); + + $template->assign_vars(array( + 'RECAPTCHA_SERVER' => $this->recaptcha_server, + 'RECAPTCHA_PUBKEY' => isset($config['recaptcha_pubkey']) ? $config['recaptcha_pubkey'] : '', + 'RECAPTCHA_ERRORGET' => '', + 'S_RECAPTCHA_AVAILABLE' => $this->is_available(), + 'S_CONFIRM_CODE' => true, + 'S_TYPE' => $this->type, + 'L_CONFIRM_EXPLAIN' => $explain, + )); + + return 'captcha_recaptcha.html'; + } + } + + function get_demo_template($id) + { + return $this->get_template(); + } + + function get_hidden_fields() + { + $hidden_fields = array(); + + // this is required for posting.php - otherwise we would forget about the captcha being already solved + if ($this->solved) + { + $hidden_fields['confirm_code'] = $this->code; + } + $hidden_fields['confirm_id'] = $this->confirm_id; + return $hidden_fields; + } + + function uninstall() + { + $this->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 + */ + 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 + */ + function recaptcha_check_answer($extra_params = array()) + { + global $config, $user; + + //discard spam submissions + if ($this->challenge == null || strlen($this->challenge) == 0 || $this->response == null || strlen($this->response) == 0) + { + return $user->lang['RECAPTCHA_INCORRECT']; + } + + $response = $this->_recaptcha_http_post($this->recaptcha_verify_server, '/verify', + array( + 'privatekey' => $config['recaptcha_privkey'], + 'remoteip' => $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 $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 + */ + 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/constants.php b/phpBB/includes/constants.php new file mode 100644 index 0000000000..3bb9467bbf --- /dev/null +++ b/phpBB/includes/constants.php @@ -0,0 +1,270 @@ +<?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.0.6-RC2'); + +// 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('USER_NORMAL', 0); +define('USER_INACTIVE', 1); +define('USER_IGNORE', 2); +define('USER_FOUNDER', 3); + +define('INACTIVE_REGISTER', 1); +define('INACTIVE_PROFILE', 2); +define('INACTIVE_MANUAL', 3); +define('INACTIVE_REMIND', 4); + +// ACL +define('ACL_NEVER', 0); +define('ACL_YES', 1); +define('ACL_NO', -1); + +// 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); +define('FORUM_FLAG_QUICK_REPLY', 64); + +// Forum Options... sequential order. Modifications should begin at number 10 (number 29 is maximum) +define('FORUM_OPTION_FEED_NEWS', 1); +define('FORUM_OPTION_FEED_EXCLUDE', 2); + +// 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); + +// Smiley hard limit +define('SMILEY_LIMIT', 1000); + +// 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); + +// phpbb_chmod() permissions +@define('CHMOD_ALL', 7); +@define('CHMOD_READ', 4); +@define('CHMOD_WRITE', 2); +@define('CHMOD_EXECUTE', 1); + +// Captcha code length +define('CAPTCHA_MIN_CHARS', 4); +define('CAPTCHA_MAX_CHARS', 7); + +// Additional constants +define('VOTE_CONVERTED', 127); + +// Table names +define('ACL_GROUPS_TABLE', $table_prefix . 'acl_groups'); +define('ACL_OPTIONS_TABLE', $table_prefix . 'acl_options'); +define('ACL_ROLES_DATA_TABLE', $table_prefix . 'acl_roles_data'); +define('ACL_ROLES_TABLE', $table_prefix . 'acl_roles'); +define('ACL_USERS_TABLE', $table_prefix . 'acl_users'); +define('ATTACHMENTS_TABLE', $table_prefix . 'attachments'); +define('BANLIST_TABLE', $table_prefix . 'banlist'); +define('BBCODES_TABLE', $table_prefix . 'bbcodes'); +define('BOOKMARKS_TABLE', $table_prefix . 'bookmarks'); +define('BOTS_TABLE', $table_prefix . 'bots'); +define('CONFIG_TABLE', $table_prefix . 'config'); +define('CONFIRM_TABLE', $table_prefix . 'confirm'); +define('DISALLOW_TABLE', $table_prefix . 'disallow'); +define('DRAFTS_TABLE', $table_prefix . 'drafts'); +define('EXTENSIONS_TABLE', $table_prefix . 'extensions'); +define('EXTENSION_GROUPS_TABLE', $table_prefix . 'extension_groups'); +define('FORUMS_TABLE', $table_prefix . 'forums'); +define('FORUMS_ACCESS_TABLE', $table_prefix . 'forums_access'); +define('FORUMS_TRACK_TABLE', $table_prefix . 'forums_track'); +define('FORUMS_WATCH_TABLE', $table_prefix . 'forums_watch'); +define('GROUPS_TABLE', $table_prefix . 'groups'); +define('ICONS_TABLE', $table_prefix . 'icons'); +define('LANG_TABLE', $table_prefix . 'lang'); +define('LOG_TABLE', $table_prefix . 'log'); +define('MODERATOR_CACHE_TABLE', $table_prefix . 'moderator_cache'); +define('MODULES_TABLE', $table_prefix . 'modules'); +define('POLL_OPTIONS_TABLE', $table_prefix . 'poll_options'); +define('POLL_VOTES_TABLE', $table_prefix . 'poll_votes'); +define('POSTS_TABLE', $table_prefix . 'posts'); +define('PRIVMSGS_TABLE', $table_prefix . 'privmsgs'); +define('PRIVMSGS_FOLDER_TABLE', $table_prefix . 'privmsgs_folder'); +define('PRIVMSGS_RULES_TABLE', $table_prefix . 'privmsgs_rules'); +define('PRIVMSGS_TO_TABLE', $table_prefix . 'privmsgs_to'); +define('PROFILE_FIELDS_TABLE', $table_prefix . 'profile_fields'); +define('PROFILE_FIELDS_DATA_TABLE', $table_prefix . 'profile_fields_data'); +define('PROFILE_FIELDS_LANG_TABLE', $table_prefix . 'profile_fields_lang'); +define('PROFILE_LANG_TABLE', $table_prefix . 'profile_lang'); +define('RANKS_TABLE', $table_prefix . 'ranks'); +define('REPORTS_TABLE', $table_prefix . 'reports'); +define('REPORTS_REASONS_TABLE', $table_prefix . 'reports_reasons'); +define('SEARCH_RESULTS_TABLE', $table_prefix . 'search_results'); +define('SEARCH_WORDLIST_TABLE', $table_prefix . 'search_wordlist'); +define('SEARCH_WORDMATCH_TABLE', $table_prefix . 'search_wordmatch'); +define('SESSIONS_TABLE', $table_prefix . 'sessions'); +define('SESSIONS_KEYS_TABLE', $table_prefix . 'sessions_keys'); +define('SITELIST_TABLE', $table_prefix . 'sitelist'); +define('SMILIES_TABLE', $table_prefix . 'smilies'); +define('STYLES_TABLE', $table_prefix . 'styles'); +define('STYLES_TEMPLATE_TABLE', $table_prefix . 'styles_template'); +define('STYLES_TEMPLATE_DATA_TABLE',$table_prefix . 'styles_template_data'); +define('STYLES_THEME_TABLE', $table_prefix . 'styles_theme'); +define('STYLES_IMAGESET_TABLE', $table_prefix . 'styles_imageset'); +define('STYLES_IMAGESET_DATA_TABLE',$table_prefix . 'styles_imageset_data'); +define('TOPICS_TABLE', $table_prefix . 'topics'); +define('TOPICS_POSTED_TABLE', $table_prefix . 'topics_posted'); +define('TOPICS_TRACK_TABLE', $table_prefix . 'topics_track'); +define('TOPICS_WATCH_TABLE', $table_prefix . 'topics_watch'); +define('USER_GROUP_TABLE', $table_prefix . 'user_group'); +define('USERS_TABLE', $table_prefix . 'users'); +define('WARNINGS_TABLE', $table_prefix . 'warnings'); +define('WORDS_TABLE', $table_prefix . 'words'); +define('ZEBRA_TABLE', $table_prefix . 'zebra'); + +// Additional tables + + +?>
\ No newline at end of file diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php new file mode 100644 index 0000000000..eabcfd818e --- /dev/null +++ b/phpBB/includes/db/db_tools.php @@ -0,0 +1,2032 @@ +<?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. +* Currently not supported is returning SQL for creating tables. +* +* @package dbal +* @note currently not used within phpBB3, but may be utilized later. +*/ +class phpbb_db_tools +{ + /** + * Current sql layer + */ + var $sql_layer = ''; + + /** + * @var object DB object + */ + var $db = NULL; + + /** + * The Column types for every database we support + * @var array + */ + var $dbms_type_map = array( + 'mysql_41' => 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)', + 'VCHAR_CI' => 'varchar(255)', + 'VARBINARY' => 'varbinary(255)', + ), + + 'mysql_40' => 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' => 'varbinary(255)', + 'VCHAR:' => 'varbinary(%d)', + 'CHAR:' => 'binary(%d)', + 'XSTEXT' => 'blob', + 'XSTEXT_UNI'=> 'blob', + 'STEXT' => 'blob', + 'STEXT_UNI' => 'blob', + 'TEXT' => 'blob', + 'TEXT_UNI' => 'blob', + 'MTEXT' => 'mediumblob', + 'MTEXT_UNI' => 'mediumblob', + 'TIMESTAMP' => 'int(11) UNSIGNED', + 'DECIMAL' => 'decimal(5,2)', + 'DECIMAL:' => 'decimal(%d,2)', + 'PDECIMAL' => 'decimal(6,3)', + 'PDECIMAL:' => 'decimal(%d,3)', + 'VCHAR_UNI' => 'blob', + 'VCHAR_UNI:'=> array('varbinary(%d)', 'limit' => array('mult', 3, 255, 'blob')), + 'VCHAR_CI' => 'blob', + 'VARBINARY' => 'varbinary(255)', + ), + + 'firebird' => 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', + 'VCHAR_CI' => 'VARCHAR(255) CHARACTER SET UTF8', + 'VARBINARY' => 'CHAR(255) CHARACTER SET NONE', + ), + + 'mssql' => 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)', + 'VCHAR_CI' => '[varchar] (255)', + 'VARBINARY' => '[varchar] (255)', + ), + + 'oracle' => 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(765)', + 'VCHAR_UNI:'=> array('varchar2(%d)', 'limit' => array('mult', 3, 765, 'clob')), + 'VCHAR_CI' => 'varchar2(255)', + 'VARBINARY' => 'raw(255)', + ), + + 'sqlite' => 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)', + 'VCHAR_CI' => 'varchar(255)', + 'VARBINARY' => 'blob', + ), + + 'postgres' => 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)', + 'VCHAR_CI' => 'varchar_ci', + 'VARBINARY' => 'bytea', + ), + ); + + /** + * A list of types being unsigned for better reference in some db's + * @var array + */ + var $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 + */ + var $supported_dbms = array('firebird', 'mssql', 'mysql_40', 'mysql_41', 'oracle', 'postgres', 'sqlite'); + + /** + * 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. + */ + var $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 + */ + function phpbb_db_tools(&$db, $return_statements = false) + { + $this->db = $db; + $this->return_statements = $return_statements; + + // Determine mapping database type + switch ($this->db->sql_layer) + { + case 'mysql': + $this->sql_layer = 'mysql_40'; + break; + + case 'mysql4': + if (version_compare($this->db->sql_server_info(true), '4.1.3', '>=')) + { + $this->sql_layer = 'mysql_41'; + } + else + { + $this->sql_layer = 'mysql_40'; + } + break; + + case 'mysqli': + $this->sql_layer = 'mysql_41'; + break; + + case 'mssql': + case 'mssql_odbc': + $this->sql_layer = 'mssql'; + break; + + default: + $this->sql_layer = $this->db->sql_layer; + break; + } + } + + /** + * Check if table exists + * + * + * @param string $table_name The table name to check for + * @return bool true if table exists, else false + */ + function sql_table_exists($table_name) + { + $this->db->sql_return_on_error(true); + $result = $this->db->sql_query_limit('SELECT * FROM ' . $table_name, 1); + $this->db->sql_return_on_error(false); + + if ($result) + { + $this->db->sql_freeresult($result); + return true; + } + + return false; + } + + /** + * Create SQL Table + * + * @param string $table_name The table name to create + * @param array $table_data Array containing table data. + * @return array Statements if $return_statements is true. + */ + function sql_create_table($table_name, $table_data) + { + // holds the DDL for a column + $columns = $statements = array(); + + if ($this->sql_table_exists($table_name)) + { + return $this->_sql_run_sql($statements); + } + + // 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->sql_layer) + { + 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->sql_layer) + { + case 'mysql_40': + case 'mysql_41': + case 'postgres': + 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->sql_layer) + { + case 'mysql_41': + // make sure the table is in UTF-8 mode + $table_sql .= "\n) CHARACTER SET `utf8` COLLATE `utf8_bin`;"; + $statements[] = $table_sql; + break; + + case 'mysql_40': + case 'sqlite': + $table_sql .= "\n);"; + $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 '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. + * Expected structure... + * Key being one of the following + * 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 + * + * The values are in this format: + * {TABLE NAME} => array( + * {COLUMN NAME} => array({COLUMN TYPE}, {DEFAULT VALUE}, {OPTIONAL VARIABLES}), + * {KEY/INDEX NAME} => array({COLUMN NAMES}), + * ) + * + * For more information have a look at /develop/create_schema_files.php (only available through SVN) + */ + function perform_schema_changes($schema_changes) + { + if (empty($schema_changes)) + { + return; + } + + $statements = array(); + $sqlite = false; + + // For SQLite we need to perform the schema changes in a much more different way + if ($this->db->sql_layer == 'sqlite' && $this->return_statements) + { + $sqlite_data = array(); + $sqlite = true; + } + + // 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 ($column_exists = $this->sql_column_exists($table, $column_name)) + { + $result = $this->sql_column_change($table, $column_name, $column_data, true); + } + else + { + $result = $this->sql_column_add($table, $column_name, $column_data, true); + } + + if ($sqlite) + { + if ($column_exists) + { + $sqlite_data[$table]['change_columns'][] = $result; + } + else + { + $sqlite_data[$table]['add_columns'][] = $result; + } + } + else 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 ($column_exists = $this->sql_column_exists($table, $column_name)) + { + $result = $this->sql_column_change($table, $column_name, $column_data, true); + } + else + { + $result = $this->sql_column_add($table, $column_name, $column_data, true); + } + + if ($sqlite) + { + if ($column_exists) + { + $sqlite_data[$table]['change_columns'][] = $result; + } + else + { + $sqlite_data[$table]['add_columns'][] = $result; + } + } + else 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, true); + + if ($sqlite) + { + $sqlite_data[$table]['drop_columns'][] = $result; + } + else 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, true); + + if ($sqlite) + { + $sqlite_data[$table]['primary_key'] = $result; + } + else 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 ($sqlite) + { + foreach ($sqlite_data as $table_name => $sql_schema_changes) + { + // Create temporary table with original data + $statements[] = 'begin'; + + $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) + { + continue; + } + + $row = $this->db->sql_fetchrow($result); + $this->db->sql_freeresult($result); + + // 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; + + // Get the columns... + preg_match('#\((.*)\)#s', $row['sql'], $matches); + + $plain_table_cols = trim($matches[1]); + $new_table_cols = preg_split('/,(?![\s\w]+\))/m', $plain_table_cols); + $column_list = array(); + + foreach ($new_table_cols as $declaration) + { + $entities = preg_split('#\s+#', trim($declaration)); + if ($entities[0] == 'PRIMARY') + { + continue; + } + $column_list[] = $entities[0]; + } + + // note down the primary key notation because sqlite only supports adding it to the end for the new table + $primary_key = false; + $_new_cols = array(); + + foreach ($new_table_cols as $key => $declaration) + { + $entities = preg_split('#\s+#', trim($declaration)); + if ($entities[0] == 'PRIMARY') + { + $primary_key = $declaration; + continue; + } + $_new_cols[] = $declaration; + } + + $new_table_cols = $_new_cols; + + // First of all... change columns + if (!empty($sql_schema_changes['change_columns'])) + { + foreach ($sql_schema_changes['change_columns'] as $column_sql) + { + foreach ($new_table_cols as $key => $declaration) + { + $entities = preg_split('#\s+#', trim($declaration)); + if (strpos($column_sql, $entities[0] . ' ') === 0) + { + $new_table_cols[$key] = $column_sql; + } + } + } + } + + if (!empty($sql_schema_changes['add_columns'])) + { + foreach ($sql_schema_changes['add_columns'] as $column_sql) + { + $new_table_cols[] = $column_sql; + } + } + + // Now drop them... + if (!empty($sql_schema_changes['drop_columns'])) + { + foreach ($sql_schema_changes['drop_columns'] as $column_name) + { + // Remove from column list... + $new_column_list = array(); + foreach ($column_list as $key => $value) + { + if ($value === $column_name) + { + continue; + } + + $new_column_list[] = $value; + } + + $column_list = $new_column_list; + + // Remove from table... + $_new_cols = array(); + foreach ($new_table_cols as $key => $declaration) + { + $entities = preg_split('#\s+#', trim($declaration)); + if (strpos($column_name . ' ', $entities[0] . ' ') === 0) + { + continue; + } + $_new_cols[] = $declaration; + } + $new_table_cols = $_new_cols; + } + } + + // Primary key... + if (!empty($sql_schema_changes['primary_key'])) + { + $new_table_cols[] = 'PRIMARY KEY (' . implode(', ', $sql_schema_changes['primary_key']) . ')'; + } + // Add a new one or the old primary key + else if ($primary_key !== false) + { + $new_table_cols[] = $primary_key; + } + + $columns = implode(',', $column_list); + + // create a new table and fill it up. destroy the temp one + $statements[] = 'CREATE TABLE ' . $table_name . ' (' . implode(',', $new_table_cols) . ');'; + $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;'; + $statements[] = 'DROP TABLE ' . $table_name . '_temp'; + + $statements[] = 'commit'; + } + } + + if ($this->return_statements) + { + return $statements; + } + } + + /** + * 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 + */ + function sql_column_exists($table, $column_name) + { + switch ($this->sql_layer) + { + case 'mysql_40': + case 'mysql_41': + + $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 LOWER(table_name) = '" . strtolower($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 = '" . strtoupper($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; + + // 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; + } + } + + /** + * Private method for performing sql statements (either execute them or return them) + * @access 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 + */ + 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->dbms_type_map[$this->sql_layer][$orig_column_type . ':'])) + { + $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'], $column_length); + } + else + { + if (isset($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'])) + { + switch ($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'][0]) + { + case 'div': + $column_length /= $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['rule'][1]; + $column_length = ceil($column_length); + $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'][0], $column_length); + break; + } + } + + if (isset($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'])) + { + switch ($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][0]) + { + case 'mult': + $column_length *= $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][1]; + if ($column_length > $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][2]) + { + $column_type = $this->dbms_type_map[$this->sql_layer][$orig_column_type . ':']['limit'][3]; + } + else + { + $column_type = sprintf($this->dbms_type_map[$this->sql_layer][$orig_column_type . ':'][0], $column_length); + } + break; + } + } + } + $orig_column_type .= ':'; + } + else + { + $orig_column_type = $column_data[0]; + $column_type = $this->dbms_type_map[$this->sql_layer][$column_data[0]]; + } + + // Adjust default value if db-dependant specified + if (is_array($column_data[1])) + { + $column_data[1] = (isset($column_data[1][$this->sql_layer])) ? $column_data[1][$this->sql_layer] : $column_data[1]['default']; + } + + $sql = ''; + + $return_array = array(); + + switch ($this->sql_layer) + { + case 'firebird': + $sql .= " {$column_type} "; + $return_array['column_type_sql_type'] = " {$column_type} "; + + if (!is_null($column_data[1])) + { + $sql .= 'DEFAULT ' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ' '; + $return_array['column_type_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) + { + $return_array['default'] = 'DEFAULT (' . $column_data[1] . ') '; + $sql_default .= $return_array['default']; + } + else + { + $return_array['default'] = 'DEFAULT (' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ') '; + $sql_default .= $return_array['default']; + } + } + + 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_40': + case 'mysql_41': + $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 ($this->sql_layer === 'mysql_41' && $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; + } + + $return_array['column_type_sql'] = $sql; + + return $return_array; + } + + /** + * Add new column + */ + function sql_column_add($table_name, $column_name, $column_data, $inline = false) + { + $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data); + $statements = array(); + + switch ($this->sql_layer) + { + case 'firebird': + $statements[] = 'ALTER TABLE ' . $table_name . ' ADD "' . strtoupper($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_40': + case 'mysql_41': + $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 'sqlite': + + if ($inline && $this->return_statements) + { + return $column_name . ' ' . $column_data['column_type_sql']; + } + + 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 + */ + function sql_column_remove($table_name, $column_name, $inline = false) + { + $statements = array(); + + switch ($this->sql_layer) + { + case 'firebird': + $statements[] = 'ALTER TABLE ' . $table_name . ' DROP "' . strtoupper($column_name) . '"'; + break; + + case 'mssql': + $statements[] = 'ALTER TABLE [' . $table_name . '] DROP COLUMN [' . $column_name . ']'; + break; + + case 'mysql_40': + case 'mysql_41': + $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 'sqlite': + + if ($inline && $this->return_statements) + { + return $column_name; + } + + 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 = 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 + */ + function sql_index_drop($table_name, $index_name) + { + $statements = array(); + + switch ($this->sql_layer) + { + case 'mssql': + $statements[] = 'DROP INDEX ' . $table_name . '.' . $index_name; + break; + + case 'mysql_40': + case 'mysql_41': + $statements[] = 'DROP INDEX ' . $index_name . ' ON ' . $table_name; + break; + + case 'firebird': + case 'oracle': + case 'postgres': + case 'sqlite': + $statements[] = 'DROP INDEX ' . $table_name . '_' . $index_name; + break; + } + + return $this->_sql_run_sql($statements); + } + + /** + * Drop Table + */ + function sql_table_drop($table_name) + { + $statements = array(); + + if (!$this->sql_table_exists($table_name)) + { + return $this->_sql_run_sql($statements); + } + + // the most basic operation, get rid of the table + $statements[] = 'DROP TABLE ' . $table_name; + + switch ($this->sql_layer) + { + 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 + */ + function sql_create_primary_key($table_name, $column, $inline = false) + { + $statements = array(); + + switch ($this->sql_layer) + { + case 'firebird': + case 'postgres': + case 'mysql_40': + case 'mysql_41': + $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': + + if ($inline && $this->return_statements) + { + return $column; + } + + $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 + */ + function sql_create_unique_index($table_name, $index_name, $column) + { + $statements = array(); + + switch ($this->sql_layer) + { + case 'firebird': + case 'postgres': + case 'oracle': + case 'sqlite': + $statements[] = 'CREATE UNIQUE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; + break; + + case 'mysql_40': + case 'mysql_41': + $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 + */ + function sql_create_index($table_name, $index_name, $column) + { + $statements = array(); + + switch ($this->sql_layer) + { + case 'firebird': + case 'postgres': + case 'oracle': + case 'sqlite': + $statements[] = 'CREATE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; + break; + + case 'mysql_40': + case 'mysql_41': + $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 + */ + function sql_list_index($table_name) + { + $index_array = array(); + + if ($this->sql_layer == '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->sql_layer) + { + 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_40': + case 'mysql_41': + $sql = 'SHOW KEYS + FROM ' . $table_name; + $col = 'Key_name'; + break; + + case 'oracle': + $sql = "SELECT index_name + FROM user_indexes + WHERE table_name = '" . strtoupper($table_name) . "' + AND generated = 'N' + AND uniqueness = 'NONUNIQUE'"; + $col = 'index_name'; + break; + + case 'sqlite': + $sql = "PRAGMA index_info('" . $table_name . "');"; + $col = 'name'; + break; + } + + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + if (($this->sql_layer == 'mysql_40' || $this->sql_layer == 'mysql_41') && !$row['Non_unique']) + { + continue; + } + + switch ($this->sql_layer) + { + case 'firebird': + case 'oracle': + case 'postgres': + case 'sqlite': + $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!) + */ + function sql_column_change($table_name, $column_name, $column_data, $inline = false) + { + $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data); + $statements = array(); + + switch ($this->sql_layer) + { + case 'firebird': + // Change type... + if (!empty($column_data['column_type_sql_default'])) + { + $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN "' . strtoupper($column_name) . '" TYPE ' . ' ' . $column_data['column_type_sql_type']; + $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN "' . strtoupper($column_name) . '" SET DEFAULT ' . ' ' . $column_data['column_type_sql_default']; + } + else + { + $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER COLUMN "' . strtoupper($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']; + + if (!empty($column_data['default'])) + { + // Using TRANSACT-SQL for this statement because we do not want to have colliding data if statements are executed at a later stage + $statements[] = "DECLARE @drop_default_name VARCHAR(100), @cmd VARCHAR(1000) + SET @drop_default_name = + (SELECT so.name FROM sysobjects so + JOIN sysconstraints sc ON so.id = sc.constid + WHERE object_name(so.parent_obj) = '{$table_name}' + AND so.xtype = 'D' + AND sc.colid = (SELECT colid FROM syscolumns + WHERE id = object_id('{$table_name}') + AND name = '{$column_name}')) + IF @drop_default_name <> '' + BEGIN + SET @cmd = 'ALTER TABLE [{$table_name}] DROP CONSTRAINT [' + @drop_default_name + ']' + EXEC(@cmd) + END + SET @cmd = 'ALTER TABLE [{$table_name}] ADD CONSTRAINT [DF_{$table_name}_{$column_name}_1] {$column_data['default']} FOR [{$column_name}]' + EXEC(@cmd)"; + } + break; + + case 'mysql_40': + case 'mysql_41': + $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 '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': + + if ($inline && $this->return_statements) + { + return $column_name . ' ' . $column_data['column_type_sql']; + } + + $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); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/db/dbal.php b/phpBB/includes/db/dbal.php new file mode 100644 index 0000000000..a962696bb8 --- /dev/null +++ b/phpBB/includes/db/dbal.php @@ -0,0 +1,887 @@ +<?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; +} + +/** +* Database Abstraction Layer +* @package dbal +*/ +class dbal +{ + var $db_connect_id; + var $query_result; + var $return_on_error = false; + var $transaction = false; + var $sql_time = 0; + var $num_queries = array(); + var $open_queries = array(); + + var $curtime = 0; + var $query_hold = ''; + var $html_hold = ''; + var $sql_report = ''; + + var $persistency = false; + var $user = ''; + var $server = ''; + var $dbname = ''; + + // Set to true if error triggered + var $sql_error_triggered = false; + + // Holding the last sql query on sql error + var $sql_error_sql = ''; + // Holding the error information - only populated if sql_error_triggered is set + var $sql_error_returned = array(); + + // Holding transaction count + var $transactions = 0; + + // Supports multi inserts? + var $multi_insert = false; + + /** + * Current sql layer + */ + var $sql_layer = ''; + + /** + * Wildcards for matching any (%) or exactly one (_) character within LIKE expressions + */ + var $any_char; + var $one_char; + + /** + * Exact version of the DBAL, directly queried + */ + var $sql_server_version = false; + + /** + * Constructor + */ + function dbal() + { + $this->num_queries = array( + 'cached' => 0, + 'normal' => 0, + 'total' => 0, + ); + + // Fill default sql layer based on the class being called. + // This can be changed by the specified layer itself later if needed. + $this->sql_layer = substr(get_class($this), 5); + + // 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) . '_'; + } + + /** + * return on error or display error message + */ + 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 + */ + function sql_num_queries($cached = false) + { + return ($cached) ? $this->num_queries['cached'] : $this->num_queries['normal']; + } + + /** + * Add to query count + */ + 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; + } + + /** + * DBAL garbage collection, close sql connection + */ + 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 $query_id) + { + $this->sql_freeresult($query_id); + } + + // Connection closed correctly. Set db_connect_id to false to prevent errors + if ($result = $this->_sql_close()) + { + $this->db_connect_id = false; + } + + return $result; + } + + /** + * Build LIMIT query + * Doing some validation here. + */ + 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); + } + + /** + * Fetch all rows + */ + 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 + * if rownum is false, the current row is used, else it is pointing to the row (zero-based) + */ + function sql_fetchfield($field, $rownum = false, $query_id = false) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if ($query_id !== false) + { + if ($rownum !== false) + { + $this->sql_rowseek($rownum, $query_id); + } + + if (!is_object($query_id) && isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_fetchfield($query_id, $field); + } + + $row = $this->sql_fetchrow($query_id); + return (isset($row[$field])) ? $row[$field] : false; + } + + return false; + } + + /** + * 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 $this->any_char and $this->one_char + * @return string LIKE expression including the keyword! + */ + function sql_like_expression($expression) + { + $expression = utf8_str_replace(array('_', '%'), array("\_", "\%"), $expression); + $expression = utf8_str_replace(array(chr(0) . "\_", chr(0) . "\%"), array('_', '%'), $expression); + + return $this->_sql_like_expression('LIKE \'' . $this->sql_escape($expression) . '\''); + } + + /** + * SQL Transaction + * @access private + */ + 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; + } + + /** + * Build sql statement from array for insert/update/select statements + * + * Idea for this from Ikonboard + * Possible query values: INSERT, INSERT_SELECT, UPDATE, SELECT + * + */ + function sql_build_array($query, $assoc_ary = false) + { + if (!is_array($assoc_ary)) + { + return false; + } + + $fields = $values = array(); + + if ($query == 'INSERT' || $query == '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 = ($query == 'INSERT') ? ' (' . implode(', ', $fields) . ') VALUES (' . implode(', ', $values) . ')' : ' (' . implode(', ', $fields) . ') SELECT ' . implode(', ', $values) . ' '; + } + else if ($query == 'MULTI_INSERT') + { + trigger_error('The MULTI_INSERT query value is no longer supported. Please use sql_multi_insert() instead.', E_USER_ERROR); + } + else if ($query == 'UPDATE' || $query == 'SELECT') + { + $values = array(); + foreach ($assoc_ary as $key => $var) + { + $values[] = "$key = " . $this->_sql_validate_value($var); + } + $query = implode(($query == 'UPDATE') ? ', ' : ' AND ', $values); + } + + return $query; + } + + /** + * Build IN or NOT IN sql comparison string, uses <> or = on single element + * arrays to improve comparison speed + * + * @access public + * @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. Default to false. + */ + 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 binary AND operator on DB column. + * Results in sql statement: "{$column_name} & (1 << {$bit}) {$compare}" + * + * @param string $column_name The column name to use + * @param int $bit The value to use for the AND operator, will be converted to (1 << $bit). Is used by options, using the number schema... 0, 1, 2...29 + * @param string $compare Any custom SQL code after the check (for example "= 0") + */ + function sql_bit_and($column_name, $bit, $compare = '') + { + if (method_exists($this, '_sql_bit_and')) + { + return $this->_sql_bit_and($column_name, $bit, $compare); + } + + return $column_name . ' & ' . (1 << $bit) . (($compare) ? ' ' . $compare : ''); + } + + /** + * 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 + */ + function sql_multi_insert($table, &$sql_ary) + { + if (!sizeof($sql_ary)) + { + return false; + } + + if ($this->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)) + { + return $this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('INSERT', $sql_ary)); + } + + $values = array(); + foreach ($_sql_ary as $key => $var) + { + $values[] = $this->_sql_validate_value($var); + } + $ary[] = '(' . implode(', ', $values) . ')'; + } + + return $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; + } + + $result = $this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('INSERT', $ary)); + + if (!$result) + { + return false; + } + } + } + + return true; + } + + /** + * Function for validating values + * @access 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; + } + } + + /** + * Build sql statement from array for select and select distinct statements + * + * Possible query values: SELECT, SELECT_DISTINCT + */ + function sql_build_query($query, $array) + { + $sql = ''; + switch ($query) + { + case 'SELECT': + case 'SELECT_DISTINCT'; + + $sql = str_replace('_', ' ', $query) . ' ' . $array['SELECT'] . ' FROM '; + + // Build table array. We also build an alias array for later checks. + $table_array = $aliases = array(); + $used_multi_alias = false; + + foreach ($array['FROM'] as $table_name => $alias) + { + if (is_array($alias)) + { + $used_multi_alias = true; + + foreach ($alias as $multi_alias) + { + $table_array[] = $table_name . ' ' . $multi_alias; + $aliases[] = $multi_alias; + } + } + else + { + $table_array[] = $table_name . ' ' . $alias; + $aliases[] = $alias; + } + } + + // We run the following code to determine if we need to re-order the table array. ;) + // The reason for this is that for multi-aliased tables (two equal tables) in the FROM statement the last table need to match the first comparison. + // DBMS who rely on this: Oracle, PostgreSQL and MSSQL. For all other DBMS it makes absolutely no difference in which order the table is. + if (!empty($array['LEFT_JOIN']) && sizeof($array['FROM']) > 1 && $used_multi_alias !== false) + { + // Take first LEFT JOIN + $join = current($array['LEFT_JOIN']); + + // Determine the table used there (even if there are more than one used, we only want to have one + preg_match('/(' . implode('|', $aliases) . ')\.[^\s]+/U', str_replace(array('(', ')', 'AND', 'OR', ' '), '', $join['ON']), $matches); + + // If there is a first join match, we need to make sure the table order is correct + if (!empty($matches[1])) + { + $first_join_match = trim($matches[1]); + $table_array = $last = array(); + + foreach ($array['FROM'] as $table_name => $alias) + { + if (is_array($alias)) + { + foreach ($alias as $multi_alias) + { + ($multi_alias === $first_join_match) ? $last[] = $table_name . ' ' . $multi_alias : $table_array[] = $table_name . ' ' . $multi_alias; + } + } + else + { + ($alias === $first_join_match) ? $last[] = $table_name . ' ' . $alias : $table_array[] = $table_name . ' ' . $alias; + } + } + + $table_array = array_merge($table_array, $last); + } + } + + $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 page + */ + function sql_error($sql = '') + { + global $auth, $user, $config; + + // 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) + { + $message = 'SQL ERROR [ ' . $this->sql_layer . ' ]<br /><br />' . $this->sql_error_returned['message'] . ' [' . $this->sql_error_returned['code'] . ']'; + + // Show complete SQL error and path to administrators only + // Additionally show complete error on installation or if extended debug mode is enabled + // The DEBUG_EXTRA constant is for development only! + if ((isset($auth) && $auth->acl_get('a_')) || defined('IN_INSTALL') || defined('DEBUG_EXTRA')) + { + // Print out a nice backtrace... + $backtrace = get_backtrace(); + + $message .= ($sql) ? '<br /><br />SQL<br /><br />' . htmlspecialchars($sql) : ''; + $message .= ($backtrace) ? '<br /><br />BACKTRACE<br />' . $backtrace : ''; + $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 (!isset($user->lang['SQL_ERROR_OCCURRED'])) + { + $message .= '<br /><br />An sql error occurred while fetching this page. Please contact an administrator if this problem persists.'; + } + else + { + if (!empty($config['board_contact'])) + { + $message .= '<br /><br />' . sprintf($user->lang['SQL_ERROR_OCCURRED'], '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'); + } + else + { + $message .= '<br /><br />' . sprintf($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; + } + + /** + * Explain queries + */ + function sql_report($mode, $query = '') + { + global $cache, $starttime, $phpbb_root_path, $user; + + if (empty($_REQUEST['explain'])) + { + return false; + } + + if (!$query && $this->query_hold != '') + { + $query = $this->query_hold; + } + + switch ($mode) + { + case 'display': + if (!empty($cache)) + { + $cache->unload(); + } + $this->sql_close(); + + $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="' . 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; + } +} + +/** +* This variable holds the class name to use later +*/ +$sql_db = (!empty($dbms)) ? 'dbal_' . basename($dbms) : 'dbal'; + +?>
\ No newline at end of file diff --git a/phpBB/includes/db/firebird.php b/phpBB/includes/db/firebird.php new file mode 100644 index 0000000000..fb1ef44c55 --- /dev/null +++ b/phpBB/includes/db/firebird.php @@ -0,0 +1,512 @@ +<?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.' . $phpEx); + +/** +* Firebird/Interbase Database Abstraction Layer +* Minimum Requirement is Firebird 2.1 +* @package dbal +*/ +class dbal_firebird extends dbal +{ + var $last_query_text = ''; + var $service_handle = false; + var $affected_rows = 0; + + /** + * Connect to server + */ + function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) + { + $this->persistency = $persistency; + $this->user = $sqluser; + $this->server = $sqlserver . (($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, $sqlpassword, false, false, 3) : @ibase_connect($use_database, $this->user, $sqlpassword, false, false, 3); + + $this->service_handle = (function_exists('ibase_service_attach') && $this->server) ? @ibase_service_attach($this->server, $this->user, $sqlpassword) : false; + + return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error(''); + } + + /** + * Version information about used database + * @param bool $raw if true, only return the fetched sql_server_version + * @return string sql server version + */ + function sql_server_info($raw = false) + { + if ($this->service_handle !== false && function_exists('ibase_server_info')) + { + return @ibase_server_info($this->service_handle, IBASE_SVC_SERVER_VERSION); + } + + return ($raw) ? '2.1' : 'Firebird/Interbase'; + } + + /** + * SQL Transaction + * @access private + */ + function _sql_transaction($status = 'begin') + { + switch ($status) + { + case 'begin': + return true; + break; + + case 'commit': + return @ibase_commit(); + break; + + case 'rollback': + return @ibase_rollback(); + break; + } + + return true; + } + + /** + * 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 When casted to bool the returned value returns true on success and false on failure + * + * @access public + */ + function sql_query($query = '', $cache_ttl = 0) + { + if ($query != '') + { + global $cache; + + // EXPLAIN only in extra debug mode + if (defined('DEBUG_EXTRA')) + { + $this->sql_report('start', $query); + } + + $this->last_query_text = $query; + $this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false; + $this->sql_add_num_queries($this->query_result); + + if ($this->query_result === false) + { + $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) + { + if (!empty($value) && $value[0] === "'" && strlen($value) > 32769) // check to see if this thing is greater than the max + 'x2 + { + $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) + { + if (!empty($value[2]) && $value[2][0] === "'" && strlen($value[2]) > 32769) // check to see if this thing is greater than the max + 'x2 + { + $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 (!function_exists('ibase_affected_rows') && (preg_match('/^UPDATE ([\w_]++)\s+SET [\w_]++\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+)(?:,\s*[\w_]++\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+))*+\s+(WHERE.*)?$/s', $query, $regs) || preg_match('/^DELETE FROM ([\w_]++)\s*(WHERE\s*.*)?$/s', $query, $regs))) + { + $affected_sql = 'SELECT COUNT(*) as num_rows_affected FROM ' . $regs[1]; + if (!empty($regs[2])) + { + $affected_sql .= ' ' . $regs[2]; + } + + if (!($temp_q_id = @ibase_query($this->db_connect_id, $affected_sql))) + { + return false; + } + + $temp_result = @ibase_fetch_assoc($temp_q_id); + @ibase_free_result($temp_q_id); + + $this->affected_rows = ($temp_result) ? $temp_result['NUM_ROWS_AFFECTED'] : false; + } + + if (sizeof($array)) + { + $p_query = @ibase_prepare($this->db_connect_id, $query); + array_unshift($array, $p_query); + $this->query_result = call_user_func_array('ibase_execute', $array); + unset($array); + + if ($this->query_result === false) + { + $this->sql_error($query); + } + } + else if (($this->query_result = @ibase_query($this->db_connect_id, $query)) === false) + { + $this->sql_error($query); + } + + if (defined('DEBUG_EXTRA')) + { + $this->sql_report('stop', $query); + } + + if (!$this->transaction) + { + if (function_exists('ibase_commit_ret')) + { + @ibase_commit_ret(); + } + else + { + // way cooler than ibase_commit_ret :D + @ibase_query('COMMIT RETAIN;'); + } + } + + if ($cache_ttl && method_exists($cache, 'sql_save')) + { + $this->open_queries[(int) $this->query_result] = $this->query_result; + $cache->sql_save($query, $this->query_result, $cache_ttl); + } + else if (strpos($query, 'SELECT') === 0 && $this->query_result) + { + $this->open_queries[(int) $this->query_result] = $this->query_result; + } + } + else if (defined('DEBUG_EXTRA')) + { + $this->sql_report('fromcache', $query); + } + } + else + { + return false; + } + + return $this->query_result; + } + + /** + * Build LIMIT query + */ + function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) + { + $this->query_result = false; + + $query = 'SELECT FIRST ' . $total . ((!empty($offset)) ? ' SKIP ' . $offset : '') . substr($query, 6); + + return $this->sql_query($query, $cache_ttl); + } + + /** + * Return number of affected rows + */ + function sql_affectedrows() + { + // PHP 5+ function + if (function_exists('ibase_affected_rows')) + { + return ($this->db_connect_id) ? @ibase_affected_rows($this->db_connect_id) : false; + } + else + { + return $this->affected_rows; + } + } + + /** + * Fetch current row + */ + function sql_fetchrow($query_id = false) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_fetchrow($query_id); + } + + if ($query_id === false) + { + return false; + } + + $row = array(); + $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; + } + + /** + * Seek to given row number + * rownum is zero-based + */ + function sql_rowseek($rownum, &$query_id) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_rowseek($rownum, $query_id); + } + + if ($query_id === false) + { + return; + } + + $this->sql_freeresult($query_id); + $query_id = $this->sql_query($this->last_query_text); + + if ($query_id === false) + { + return false; + } + + // We do not fetch the row for rownum == 0 because then the next resultset would be the second row + for ($i = 0; $i < $rownum; $i++) + { + if (!$this->sql_fetchrow($query_id)) + { + return false; + } + } + + return true; + } + + /** + * Get last inserted id after insert statement + */ + function sql_nextid() + { + $query_id = $this->query_result; + + if ($query_id !== false && $this->last_query_text != '') + { + if ($this->query_result && 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; + } + + /** + * Free sql result + */ + function sql_freeresult($query_id = false) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_freeresult($query_id); + } + + if (isset($this->open_queries[(int) $query_id])) + { + unset($this->open_queries[(int) $query_id]); + return @ibase_free_result($query_id); + } + + return false; + } + + /** + * Escape string used in sql query + */ + function sql_escape($msg) + { + return str_replace(array("'", "\0"), array("''", ''), $msg); + } + + /** + * Build LIKE expression + * @access private + */ + function _sql_like_expression($expression) + { + return $expression . " ESCAPE '\\'"; + } + + /** + * Build db-specific query data + * @access private + */ + function _sql_custom_build($stage, $data) + { + return $data; + } + + function _sql_bit_and($column_name, $bit, $compare = '') + { + return 'BIN_AND(' . $column_name . ', ' . (1 << $bit) . ')' . (($compare) ? ' ' . $compare : ''); + } + + /** + * return sql error array + * @access private + */ + function _sql_error() + { + return array( + 'message' => @ibase_errmsg(), + 'code' => (@function_exists('ibase_errcode') ? @ibase_errcode() : '') + ); + } + + /** + * Close sql connection + * @access private + */ + function _sql_close() + { + if ($this->service_handle !== false) + { + @ibase_service_detach($this->service_handle); + } + + return @ibase_close($this->db_connect_id); + } + + /** + * Build db-specific report + * @access private + */ + 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/index.htm b/phpBB/includes/db/index.htm new file mode 100644 index 0000000000..ee1f723a7d --- /dev/null +++ b/phpBB/includes/db/index.htm @@ -0,0 +1,10 @@ +<html> +<head> +<title></title> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> +</head> + +<body bgcolor="#FFFFFF" text="#000000"> + +</body> +</html> diff --git a/phpBB/includes/db/mssql.php b/phpBB/includes/db/mssql.php new file mode 100644 index 0000000000..7134574691 --- /dev/null +++ b/phpBB/includes/db/mssql.php @@ -0,0 +1,449 @@ +<?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.' . $phpEx); + +/** +* MSSQL Database Abstraction Layer +* Minimum Requirement is MSSQL 2000+ +* @package dbal +*/ +class dbal_mssql extends dbal +{ + /** + * Connect to server + */ + function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) + { + $this->persistency = $persistency; + $this->user = $sqluser; + $this->dbname = $database; + + $port_delimiter = (defined('PHP_OS') && substr(PHP_OS, 0, 3) === 'WIN') ? ',' : ':'; + $this->server = $sqlserver . (($port) ? $port_delimiter . $port : ''); + + @ini_set('mssql.charset', 'UTF-8'); + @ini_set('mssql.textlimit', 2147483647); + @ini_set('mssql.textsize', 2147483647); + + if (version_compare(PHP_VERSION, '5.1.0', '>=') || (version_compare(PHP_VERSION, '5.0.0-dev', '<=') && version_compare(PHP_VERSION, '4.4.1', '>='))) + { + $this->db_connect_id = ($this->persistency) ? @mssql_pconnect($this->server, $this->user, $sqlpassword, $new_link) : @mssql_connect($this->server, $this->user, $sqlpassword, $new_link); + } + else + { + $this->db_connect_id = ($this->persistency) ? @mssql_pconnect($this->server, $this->user, $sqlpassword) : @mssql_connect($this->server, $this->user, $sqlpassword); + } + + if ($this->db_connect_id && $this->dbname != '') + { + if (!@mssql_select_db($this->dbname, $this->db_connect_id)) + { + @mssql_close($this->db_connect_id); + return false; + } + } + + return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error(''); + } + + /** + * Version information about used database + * @param bool $raw if true, only return the fetched sql_server_version + * @return string sql server version + */ + function sql_server_info($raw = false) + { + global $cache; + + if (empty($cache) || ($this->sql_server_version = $cache->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 (!empty($cache)) + { + $cache->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'; + } + + /** + * SQL Transaction + * @access private + */ + function _sql_transaction($status = 'begin') + { + 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; + } + + /** + * 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 When casted to bool the returned value returns true on success and false on failure + * + * @access public + */ + function sql_query($query = '', $cache_ttl = 0) + { + if ($query != '') + { + global $cache; + + // EXPLAIN only in extra debug mode + if (defined('DEBUG_EXTRA')) + { + $this->sql_report('start', $query); + } + + $this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false; + $this->sql_add_num_queries($this->query_result); + + if ($this->query_result === false) + { + if (($this->query_result = @mssql_query($query, $this->db_connect_id)) === false) + { + $this->sql_error($query); + } + + if (defined('DEBUG_EXTRA')) + { + $this->sql_report('stop', $query); + } + + if ($cache_ttl && method_exists($cache, 'sql_save')) + { + $this->open_queries[(int) $this->query_result] = $this->query_result; + $cache->sql_save($query, $this->query_result, $cache_ttl); + } + else if (strpos($query, 'SELECT') === 0 && $this->query_result) + { + $this->open_queries[(int) $this->query_result] = $this->query_result; + } + } + else if (defined('DEBUG_EXTRA')) + { + $this->sql_report('fromcache', $query); + } + } + else + { + return false; + } + + return $this->query_result; + } + + /** + * Build LIMIT query + */ + function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) + { + $this->query_result = false; + + // 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) + { + $this->sql_rowseek($offset, $result); + } + + return $result; + } + + /** + * Return number of affected rows + */ + function sql_affectedrows() + { + return ($this->db_connect_id) ? @mssql_rows_affected($this->db_connect_id) : false; + } + + /** + * Fetch current row + */ + function sql_fetchrow($query_id = false) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_fetchrow($query_id); + } + + if ($query_id === false) + { + return false; + } + + $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; + } + + /** + * Seek to given row number + * rownum is zero-based + */ + function sql_rowseek($rownum, &$query_id) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_rowseek($rownum, $query_id); + } + + return ($query_id !== false) ? @mssql_data_seek($query_id, $rownum) : false; + } + + /** + * Get last inserted id after insert statement + */ + 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; + } + + /** + * Free sql result + */ + function sql_freeresult($query_id = false) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_freeresult($query_id); + } + + if (isset($this->open_queries[$query_id])) + { + unset($this->open_queries[$query_id]); + return @mssql_free_result($query_id); + } + + return false; + } + + /** + * Escape string used in sql query + */ + function sql_escape($msg) + { + return str_replace(array("'", "\0"), array("''", ''), $msg); + } + + /** + * Build LIKE expression + * @access private + */ + function _sql_like_expression($expression) + { + return $expression . " ESCAPE '\\'"; + } + + /** + * return sql error array + * @access private + */ + 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; + } + + /** + * Build db-specific query data + * @access private + */ + function _sql_custom_build($stage, $data) + { + return $data; + } + + /** + * Close sql connection + * @access private + */ + function _sql_close() + { + return @mssql_close($this->db_connect_id); + } + + /** + * Build db-specific report + * @access private + */ + 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_odbc.php b/phpBB/includes/db/mssql_odbc.php new file mode 100644 index 0000000000..14c4831010 --- /dev/null +++ b/phpBB/includes/db/mssql_odbc.php @@ -0,0 +1,426 @@ +<?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.' . $phpEx); + +/** +* 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 dbal_mssql_odbc extends dbal +{ + var $last_query_text = ''; + + /** + * Connect to server + */ + function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) + { + $this->persistency = $persistency; + $this->user = $sqluser; + $this->dbname = $database; + + $port_delimiter = (defined('PHP_OS') && substr(PHP_OS, 0, 3) === 'WIN') ? ',' : ':'; + $this->server = $sqlserver . (($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, $sqlpassword) : @odbc_connect($this->server, $this->user, $sqlpassword); + + return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error(''); + } + + /** + * Version information about used database + * @param bool $raw if true, only return the fetched sql_server_version + * @return string sql server version + */ + function sql_server_info($raw = false) + { + global $cache; + + if (empty($cache) || ($this->sql_server_version = $cache->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 (!empty($cache)) + { + $cache->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)'; + } + + /** + * SQL Transaction + * @access private + */ + function _sql_transaction($status = 'begin') + { + 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; + } + + /** + * 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 When casted to bool the returned value returns true on success and false on failure + * + * @access public + */ + function sql_query($query = '', $cache_ttl = 0) + { + if ($query != '') + { + global $cache; + + // EXPLAIN only in extra debug mode + if (defined('DEBUG_EXTRA')) + { + $this->sql_report('start', $query); + } + + $this->last_query_text = $query; + $this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false; + $this->sql_add_num_queries($this->query_result); + + if ($this->query_result === false) + { + if (($this->query_result = @odbc_exec($this->db_connect_id, $query)) === false) + { + $this->sql_error($query); + } + + if (defined('DEBUG_EXTRA')) + { + $this->sql_report('stop', $query); + } + + if ($cache_ttl && method_exists($cache, 'sql_save')) + { + $this->open_queries[(int) $this->query_result] = $this->query_result; + $cache->sql_save($query, $this->query_result, $cache_ttl); + } + else if (strpos($query, 'SELECT') === 0 && $this->query_result) + { + $this->open_queries[(int) $this->query_result] = $this->query_result; + } + } + else if (defined('DEBUG_EXTRA')) + { + $this->sql_report('fromcache', $query); + } + } + else + { + return false; + } + + return $this->query_result; + } + + /** + * Build LIMIT query + */ + function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) + { + $this->query_result = false; + + // 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) + { + $this->sql_rowseek($offset, $result); + } + + return $result; + } + + /** + * Return number of affected rows + */ + function sql_affectedrows() + { + return ($this->db_connect_id) ? @odbc_num_rows($this->query_result) : false; + } + + /** + * Fetch current row + * @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. + */ + function sql_fetchrow($query_id = false, $debug = false) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_fetchrow($query_id); + } + + return ($query_id !== false) ? @odbc_fetch_array($query_id) : false; + } + + /** + * Seek to given row number + * rownum is zero-based + */ + function sql_rowseek($rownum, &$query_id) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_rowseek($rownum, $query_id); + } + + if ($query_id === false) + { + return false; + } + + $this->sql_freeresult($query_id); + $query_id = $this->sql_query($this->last_query_text); + + if ($query_id === false) + { + return false; + } + + // We do not fetch the row for rownum == 0 because then the next resultset would be the second row + for ($i = 0; $i < $rownum; $i++) + { + if (!$this->sql_fetchrow($query_id)) + { + return false; + } + } + + return true; + } + + /** + * Get last inserted id after insert statement + */ + 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; + } + + /** + * Free sql result + */ + function sql_freeresult($query_id = false) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_freeresult($query_id); + } + + if (isset($this->open_queries[(int) $query_id])) + { + unset($this->open_queries[(int) $query_id]); + return @odbc_free_result($query_id); + } + + return false; + } + + /** + * Escape string used in sql query + */ + function sql_escape($msg) + { + return str_replace(array("'", "\0"), array("''", ''), $msg); + } + + /** + * Build LIKE expression + * @access private + */ + function _sql_like_expression($expression) + { + return $expression . " ESCAPE '\\'"; + } + + /** + * Build db-specific query data + * @access private + */ + function _sql_custom_build($stage, $data) + { + return $data; + } + + /** + * return sql error array + * @access private + */ + function _sql_error() + { + return array( + 'message' => @odbc_errormsg(), + 'code' => @odbc_error() + ); + } + + /** + * Close sql connection + * @access private + */ + function _sql_close() + { + return @odbc_close($this->db_connect_id); + } + + /** + * Build db-specific report + * @access private + */ + 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 new file mode 100644 index 0000000000..c03b38708c --- /dev/null +++ b/phpBB/includes/db/mysql.php @@ -0,0 +1,491 @@ +<?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.' . $phpEx); + +/** +* MySQL4 Database Abstraction Layer +* Compatible with: +* MySQL 3.23+ +* MySQL 4.0+ +* MySQL 4.1+ +* MySQL 5.0+ +* @package dbal +*/ +class dbal_mysql extends dbal +{ + var $multi_insert = true; + + /** + * Connect to server + * @access public + */ + function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) + { + $this->persistency = $persistency; + $this->user = $sqluser; + $this->server = $sqlserver . (($port) ? ':' . $port : ''); + $this->dbname = $database; + + $this->sql_layer = 'mysql4'; + + $this->db_connect_id = ($this->persistency) ? @mysql_pconnect($this->server, $this->user, $sqlpassword, $new_link) : @mysql_connect($this->server, $this->user, $sqlpassword, $new_link); + + if ($this->db_connect_id && $this->dbname != '') + { + if (@mysql_select_db($this->dbname, $this->db_connect_id)) + { + // Determine what version we are using and if it natively supports UNICODE + if (version_compare($this->sql_server_info(true), '4.1.0', '>=')) + { + @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); + } + } + else if (version_compare($this->sql_server_info(true), '4.0.0', '<')) + { + $this->sql_layer = 'mysql'; + } + + return $this->db_connect_id; + } + } + + return $this->sql_error(''); + } + + /** + * Version information about used database + * @param bool $raw if true, only return the fetched sql_server_version + * @return string sql server version + */ + function sql_server_info($raw = false) + { + global $cache; + + if (empty($cache) || ($this->sql_server_version = $cache->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 = $row['version']; + + if (!empty($cache)) + { + $cache->put('mysql_version', $this->sql_server_version); + } + } + + return ($raw) ? $this->sql_server_version : 'MySQL ' . $this->sql_server_version; + } + + /** + * SQL Transaction + * @access private + */ + function _sql_transaction($status = 'begin') + { + 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; + } + + /** + * 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 When casted to bool the returned value returns true on success and false on failure + * + * @access public + */ + function sql_query($query = '', $cache_ttl = 0) + { + if ($query != '') + { + global $cache; + + // EXPLAIN only in extra debug mode + if (defined('DEBUG_EXTRA')) + { + $this->sql_report('start', $query); + } + + $this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false; + $this->sql_add_num_queries($this->query_result); + + if ($this->query_result === false) + { + if (($this->query_result = @mysql_query($query, $this->db_connect_id)) === false) + { + $this->sql_error($query); + } + + if (defined('DEBUG_EXTRA')) + { + $this->sql_report('stop', $query); + } + + if ($cache_ttl && method_exists($cache, 'sql_save')) + { + $this->open_queries[(int) $this->query_result] = $this->query_result; + $cache->sql_save($query, $this->query_result, $cache_ttl); + } + else if (strpos($query, 'SELECT') === 0 && $this->query_result) + { + $this->open_queries[(int) $this->query_result] = $this->query_result; + } + } + else if (defined('DEBUG_EXTRA')) + { + $this->sql_report('fromcache', $query); + } + } + else + { + return false; + } + + return $this->query_result; + } + + /** + * Build LIMIT query + */ + function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) + { + $this->query_result = false; + + // if $total is set to 0 we do not want to limit the number of rows + if ($total == 0) + { + // Having a value of -1 was always a bug + $total = '18446744073709551615'; + } + + $query .= "\n LIMIT " . ((!empty($offset)) ? $offset . ', ' . $total : $total); + + return $this->sql_query($query, $cache_ttl); + } + + /** + * Return number of affected rows + */ + function sql_affectedrows() + { + return ($this->db_connect_id) ? @mysql_affected_rows($this->db_connect_id) : false; + } + + /** + * Fetch current row + */ + function sql_fetchrow($query_id = false) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_fetchrow($query_id); + } + + return ($query_id !== false) ? @mysql_fetch_assoc($query_id) : false; + } + + /** + * Seek to given row number + * rownum is zero-based + */ + function sql_rowseek($rownum, &$query_id) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_rowseek($rownum, $query_id); + } + + return ($query_id !== false) ? @mysql_data_seek($query_id, $rownum) : false; + } + + /** + * Get last inserted id after insert statement + */ + function sql_nextid() + { + return ($this->db_connect_id) ? @mysql_insert_id($this->db_connect_id) : false; + } + + /** + * Free sql result + */ + function sql_freeresult($query_id = false) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_freeresult($query_id); + } + + if (isset($this->open_queries[(int) $query_id])) + { + unset($this->open_queries[(int) $query_id]); + return @mysql_free_result($query_id); + } + + return false; + } + + /** + * Escape string used in sql query + */ + 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); + } + + /** + * Build LIKE expression + * @access private + */ + function _sql_like_expression($expression) + { + return $expression; + } + + /** + * Build db-specific query data + * @access private + */ + function _sql_custom_build($stage, $data) + { + switch ($stage) + { + case 'FROM': + $data = '(' . $data . ')'; + break; + } + + return $data; + } + + /** + * return sql error array + * @access private + */ + 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) + ); + } + + /** + * Close sql connection + * @access private + */ + function _sql_close() + { + return @mysql_close($this->db_connect_id); + } + + /** + * Build db-specific report + * @access private + */ + function _sql_report($mode, $query = '') + { + static $test_prof; + + // current detection method, might just switch to see the existance of INFORMATION_SCHEMA.PROFILING + if ($test_prof === null) + { + $test_prof = false; + if (version_compare($this->sql_server_info(true), '5.0.37', '>=') && version_compare($this->sql_server_info(true), '5.1', '<')) + { + $test_prof = 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 $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_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 new file mode 100644 index 0000000000..f0e58fd148 --- /dev/null +++ b/phpBB/includes/db/mysqli.php @@ -0,0 +1,468 @@ +<?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.' . $phpEx); + +/** +* MySQLi Database Abstraction Layer +* mysqli-extension has to be compiled with: +* MySQL 4.1+ or MySQL 5.0+ +* @package dbal +*/ +class dbal_mysqli extends dbal +{ + var $multi_insert = true; + + /** + * Connect to server + */ + function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false , $new_link = false) + { + $this->persistency = $persistency; + $this->user = $sqluser; + $this->server = $sqlserver; + $this->dbname = $database; + $port = (!$port) ? NULL : $port; + + // Persistant connections not supported by the mysqli extension? + $this->db_connect_id = @mysqli_connect($this->server, $this->user, $sqlpassword, $this->dbname, $port); + + if ($this->db_connect_id && $this->dbname != '') + { + @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; + } + + return $this->sql_error(''); + } + + /** + * Version information about used database + * @param bool $raw if true, only return the fetched sql_server_version + * @return string sql server version + */ + function sql_server_info($raw = false) + { + global $cache; + + if (empty($cache) || ($this->sql_server_version = $cache->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 = $row['version']; + + if (!empty($cache)) + { + $cache->put('mysqli_version', $this->sql_server_version); + } + } + + return ($raw) ? $this->sql_server_version : 'MySQL(i) ' . $this->sql_server_version; + } + + /** + * SQL Transaction + * @access private + */ + function _sql_transaction($status = 'begin') + { + 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; + } + + /** + * 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 When casted to bool the returned value returns true on success and false on failure + * + * @access public + */ + function sql_query($query = '', $cache_ttl = 0) + { + if ($query != '') + { + global $cache; + + // EXPLAIN only in extra debug mode + if (defined('DEBUG_EXTRA')) + { + $this->sql_report('start', $query); + } + + $this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false; + $this->sql_add_num_queries($this->query_result); + + if ($this->query_result === false) + { + if (($this->query_result = @mysqli_query($this->db_connect_id, $query)) === false) + { + $this->sql_error($query); + } + + if (defined('DEBUG_EXTRA')) + { + $this->sql_report('stop', $query); + } + + if ($cache_ttl && method_exists($cache, 'sql_save')) + { + $cache->sql_save($query, $this->query_result, $cache_ttl); + } + } + else if (defined('DEBUG_EXTRA')) + { + $this->sql_report('fromcache', $query); + } + } + else + { + return false; + } + + return $this->query_result; + } + + /** + * Build LIMIT query + */ + function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) + { + $this->query_result = false; + + // 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); + } + + /** + * Return number of affected rows + */ + function sql_affectedrows() + { + return ($this->db_connect_id) ? @mysqli_affected_rows($this->db_connect_id) : false; + } + + /** + * Fetch current row + */ + function sql_fetchrow($query_id = false) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (!is_object($query_id) && isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_fetchrow($query_id); + } + + return ($query_id !== false) ? @mysqli_fetch_assoc($query_id) : false; + } + + /** + * Seek to given row number + * rownum is zero-based + */ + function sql_rowseek($rownum, &$query_id) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (!is_object($query_id) && isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_rowseek($rownum, $query_id); + } + + return ($query_id !== false) ? @mysqli_data_seek($query_id, $rownum) : false; + } + + /** + * Get last inserted id after insert statement + */ + function sql_nextid() + { + return ($this->db_connect_id) ? @mysqli_insert_id($this->db_connect_id) : false; + } + + /** + * Free sql result + */ + function sql_freeresult($query_id = false) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (!is_object($query_id) && isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_freeresult($query_id); + } + + return @mysqli_free_result($query_id); + } + + /** + * Escape string used in sql query + */ + function sql_escape($msg) + { + return @mysqli_real_escape_string($this->db_connect_id, $msg); + } + + /** + * Build LIKE expression + * @access private + */ + function _sql_like_expression($expression) + { + return $expression; + } + + /** + * Build db-specific query data + * @access private + */ + function _sql_custom_build($stage, $data) + { + switch ($stage) + { + case 'FROM': + $data = '(' . $data . ')'; + break; + } + + return $data; + } + + /** + * return sql error array + * @access private + */ + 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) + ); + } + + /** + * Close sql connection + * @access private + */ + function _sql_close() + { + return @mysqli_close($this->db_connect_id); + } + + /** + * Build db-specific report + * @access private + */ + function _sql_report($mode, $query = '') + { + static $test_prof; + + // current detection method, might just switch to see the existance of INFORMATION_SCHEMA.PROFILING + if ($test_prof === null) + { + $test_prof = false; + if (strpos(mysqli_get_server_info($this->db_connect_id), 'community') !== false) + { + $ver = mysqli_get_server_version($this->db_connect_id); + if ($ver >= 50037 && $ver < 50100) + { + $test_prof = 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 $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_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 new file mode 100644 index 0000000000..f7180029b5 --- /dev/null +++ b/phpBB/includes/db/oracle.php @@ -0,0 +1,752 @@ +<?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.' . $phpEx); + +/** +* Oracle Database Abstraction Layer +* @package dbal +*/ +class dbal_oracle extends dbal +{ + var $last_query_text = ''; + + /** + * Connect to server + */ + function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) + { + $this->persistency = $persistency; + $this->user = $sqluser; + $this->server = $sqlserver . (($port) ? ':' . $port : ''); + $this->dbname = $database; + + $connect = $database; + + // support for "easy connect naming" + if ($sqlserver !== '' && $sqlserver !== '/') + { + if (substr($sqlserver, -1, 1) == '/') + { + $sqlserver == substr($sqlserver, 0, -1); + } + $connect = $sqlserver . (($port) ? ':' . $port : '') . '/' . $database; + } + + $this->db_connect_id = ($new_link) ? @ocinlogon($this->user, $sqlpassword, $connect, 'UTF8') : (($this->persistency) ? @ociplogon($this->user, $sqlpassword, $connect, 'UTF8') : @ocilogon($this->user, $sqlpassword, $connect, 'UTF8')); + + return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error(''); + } + + /** + * Version information about used database + * @param bool $raw if true, only return the fetched sql_server_version + * @return string sql server version + */ + function sql_server_info($raw = false) + { +/* + global $cache; + + if (empty($cache) || ($this->sql_server_version = $cache->get('oracle_version')) === false) + { + $result = @ociparse($this->db_connect_id, 'SELECT * FROM v$version WHERE banner LIKE \'Oracle%\''); + @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 = trim($row['BANNER']); + + $cache->put('oracle_version', $this->sql_server_version); + } +*/ + $this->sql_server_version = @ociserverversion($this->db_connect_id); + + return $this->sql_server_version; + } + + /** + * SQL Transaction + * @access private + */ + function _sql_transaction($status = 'begin') + { + switch ($status) + { + case 'begin': + return true; + break; + + case 'commit': + return @ocicommit($this->db_connect_id); + break; + + case 'rollback': + return @ocirollback($this->db_connect_id); + break; + } + + return true; + } + + /** + * Oracle specific code to handle the fact that it does not compare columns properly + * @access 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 + */ + 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; + } + + /** + * 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 When casted to bool the returned value returns true on success and false on failure + * + * @access public + */ + function sql_query($query = '', $cache_ttl = 0) + { + if ($query != '') + { + global $cache; + + // EXPLAIN only in extra debug mode + if (defined('DEBUG_EXTRA')) + { + $this->sql_report('start', $query); + } + + $this->last_query_text = $query; + $this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false; + $this->sql_add_num_queries($this->query_result); + + if ($this->query_result === false) + { + $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[^(]++\\((.*?)\\)$/sU', $query, $regs)) + { + if (strlen($regs[3]) > 4000) + { + $cols = explode(', ', $regs[2]); + + preg_match_all('/\'(?:[^\']++|\'\')*+\'|[\d-.]+/', $regs[3], $vals, PREG_PATTERN_ORDER); + + if (sizeof($cols) !== sizeof($vals)) + { + // Try to replace some common data we know is from our restore script or from other sources + $regs[3] = str_replace("'||chr(47)||'", '/', $regs[3]); + $_vals = explode(', ', $regs[3]); + + $vals = array(); + $is_in_val = false; + $i = 0; + $string = ''; + + foreach ($_vals as $value) + { + if (strpos($value, "'") === false && !$is_in_val) + { + $vals[$i++] = $value; + continue; + } + + if (substr($value, -1) === "'") + { + $vals[$i] = $string . (($is_in_val) ? ', ' : '') . $value; + $string = ''; + $is_in_val = false; + + if ($vals[$i][0] !== "'") + { + $vals[$i] = "''" . $vals[$i]; + } + $i++; + continue; + } + else + { + $string .= (($is_in_val) ? ', ' : '') . $value; + $is_in_val = true; + } + } + + if ($string) + { + // New value if cols != value + $vals[(sizeof($cols) !== sizeof($vals)) ? $i : $i - 1] .= $string; + } + + $vals = array(0 => $vals); + } + + $inserts = $vals[0]; + unset($vals); + + foreach ($inserts as $key => $value) + { + if (!empty($value) && $value[0] === "'" && strlen($value) > 4002) // check to see if this thing is greater than the max + 'x2 + { + $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) + { + if (!empty($value[2]) && $value[2][0] === "'" && strlen($value[2]) > 4002) // check to see if this thing is greater than the max + 'x2 + { + $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; + } + + $this->query_result = @ociparse($this->db_connect_id, $query); + + foreach ($array as $key => $value) + { + @ocibindbyname($this->query_result, $key, $array[$key], -1); + } + + $success = @ociexecute($this->query_result, OCI_DEFAULT); + + if (!$success) + { + $this->sql_error($query); + $this->query_result = false; + } + else + { + if (!$in_transaction) + { + $this->sql_transaction('commit'); + } + } + + if (defined('DEBUG_EXTRA')) + { + $this->sql_report('stop', $query); + } + + if ($cache_ttl && method_exists($cache, 'sql_save')) + { + $this->open_queries[(int) $this->query_result] = $this->query_result; + $cache->sql_save($query, $this->query_result, $cache_ttl); + } + else if (strpos($query, 'SELECT') === 0 && $this->query_result) + { + $this->open_queries[(int) $this->query_result] = $this->query_result; + } + } + else if (defined('DEBUG_EXTRA')) + { + $this->sql_report('fromcache', $query); + } + } + else + { + return false; + } + + return $this->query_result; + } + + /** + * Build LIMIT query + */ + function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) + { + $this->query_result = false; + + $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); + } + + /** + * Return number of affected rows + */ + function sql_affectedrows() + { + return ($this->query_result) ? @ocirowcount($this->query_result) : false; + } + + /** + * Fetch current row + */ + function sql_fetchrow($query_id = false) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_fetchrow($query_id); + } + + if ($query_id !== false) + { + $row = array(); + $result = @ocifetchinto($query_id, $row, OCI_ASSOC + OCI_RETURN_NULLS); + + if (!$result || !$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; + } + + return false; + } + + /** + * Seek to given row number + * rownum is zero-based + */ + function sql_rowseek($rownum, &$query_id) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_rowseek($rownum, $query_id); + } + + if ($query_id === false) + { + return false; + } + + // Reset internal pointer + @ociexecute($query_id, OCI_DEFAULT); + + // We do not fetch the row for rownum == 0 because then the next resultset would be the second row + for ($i = 0; $i < $rownum; $i++) + { + if (!$this->sql_fetchrow($query_id)) + { + return false; + } + } + + return true; + } + + /** + * Get last inserted id after insert statement + */ + function sql_nextid() + { + $query_id = $this->query_result; + + if ($query_id !== false && $this->last_query_text != '') + { + 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 = @ociparse($this->db_connect_id, $query); + @ociexecute($stmt, OCI_DEFAULT); + + $temp_result = @ocifetchinto($stmt, $temp_array, OCI_ASSOC + OCI_RETURN_NULLS); + @ocifreestatement($stmt); + + if ($temp_result) + { + return $temp_array['CURRVAL']; + } + else + { + return false; + } + } + } + + return false; + } + + /** + * Free sql result + */ + function sql_freeresult($query_id = false) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_freeresult($query_id); + } + + if (isset($this->open_queries[(int) $query_id])) + { + unset($this->open_queries[(int) $query_id]); + return @ocifreestatement($query_id); + } + + return false; + } + + /** + * Escape string used in sql query + */ + function sql_escape($msg) + { + return str_replace(array("'", "\0"), array("''", ''), $msg); + } + + /** + * Build LIKE expression + * @access private + */ + function _sql_like_expression($expression) + { + return $expression . " ESCAPE '\\'"; + } + + function _sql_custom_build($stage, $data) + { + return $data; + } + + function _sql_bit_and($column_name, $bit, $compare = '') + { + return 'BITAND(' . $column_name . ', ' . (1 << $bit) . ')' . (($compare) ? ' ' . $compare : ''); + } + + /** + * return sql error array + * @access private + */ + function _sql_error() + { + $error = @ocierror(); + $error = (!$error) ? @ocierror($this->query_result) : $error; + $error = (!$error) ? @ocierror($this->db_connect_id) : $error; + + if ($error) + { + $this->last_error_result = $error; + } + else + { + $error = (isset($this->last_error_result) && $this->last_error_result) ? $this->last_error_result : array(); + } + + return $error; + } + + /** + * Close sql connection + * @access private + */ + function _sql_close() + { + return @ocilogoff($this->db_connect_id); + } + + /** + * Build db-specific report + * @access private + */ + 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 = ociparse($this->db_connect_id, $sql); + ociexecute($stmt); + $result = array(); + + if (ocifetchinto($stmt, $result, 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 = ociparse($this->db_connect_id, "DELETE FROM $table WHERE statement_id='$statement_id'"); + ociexecute($stmt2); + ocifreestatement($stmt2); + + // Explain the plan + $sql = "EXPLAIN PLAN + SET STATEMENT_ID = '$statement_id' + FOR $query"; + $stmt2 = ociparse($this->db_connect_id, $sql); + ociexecute($stmt2); + ocifreestatement($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 = ociparse($this->db_connect_id, $sql); + ociexecute($stmt2); + + $row = array(); + while (ocifetchinto($stmt2, $row, OCI_ASSOC + OCI_RETURN_NULLS)) + { + $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); + } + + ocifreestatement($stmt2); + + // Remove the plan we just made, we delete them on request anyway + $stmt2 = ociparse($this->db_connect_id, "DELETE FROM $table WHERE statement_id='$statement_id'"); + ociexecute($stmt2); + ocifreestatement($stmt2); + } + + ocifreestatement($stmt); + + if ($html_table) + { + $this->html_hold .= '</table>'; + } + + break; + + case 'fromcache': + $endtime = explode(' ', microtime()); + $endtime = $endtime[0] + $endtime[1]; + + $result = @ociparse($this->db_connect_id, $query); + $success = @ociexecute($result, OCI_DEFAULT); + $row = array(); + + while (@ocifetchinto($result, $row, OCI_ASSOC + OCI_RETURN_NULLS)) + { + // Take the time spent on parsing rows into account + } + @ocifreestatement($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/postgres.php b/phpBB/includes/db/postgres.php new file mode 100644 index 0000000000..d117e8c948 --- /dev/null +++ b/phpBB/includes/db/postgres.php @@ -0,0 +1,440 @@ +<?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.' . $phpEx); + +/** +* PostgreSQL Database Abstraction Layer +* Minimum Requirement is Version 7.3+ +* @package dbal +*/ +class dbal_postgres extends dbal +{ + var $last_query_text = ''; + + /** + * Connect to server + */ + function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) + { + $connect_string = ''; + + if ($sqluser) + { + $connect_string .= "user=$sqluser "; + } + + if ($sqlpassword) + { + $connect_string .= "password=$sqlpassword "; + } + + if ($sqlserver) + { + if (strpos($sqlserver, ':') !== false) + { + list($sqlserver, $port) = explode(':', $sqlserver); + } + + if ($sqlserver !== 'localhost') + { + $connect_string .= "host=$sqlserver "; + } + + if ($port) + { + $connect_string .= "port=$port "; + } + } + + $schema = ''; + + if ($database) + { + $this->dbname = $database; + if (strpos($database, '.') !== false) + { + list($database, $schema) = explode('.', $database); + } + $connect_string .= "dbname=$database"; + } + + $this->persistency = $persistency; + + $this->db_connect_id = ($this->persistency) ? @pg_pconnect($connect_string, $new_link) : @pg_connect($connect_string, $new_link); + + if ($this->db_connect_id) + { + if (version_compare($this->sql_server_info(true), '8.2', '>=')) + { + $this->multi_insert = true; + } + + if ($schema !== '') + { + @pg_query($this->db_connect_id, 'SET search_path TO ' . $schema); + } + return $this->db_connect_id; + } + + return $this->sql_error(''); + } + + /** + * Version information about used database + * @param bool $raw if true, only return the fetched sql_server_version + * @return string sql server version + */ + function sql_server_info($raw = false) + { + global $cache; + + if (empty($cache) || ($this->sql_server_version = $cache->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 (!empty($cache)) + { + $cache->put('pgsql_version', $this->sql_server_version); + } + } + + return ($raw) ? $this->sql_server_version : 'PostgreSQL ' . $this->sql_server_version; + } + + /** + * SQL Transaction + * @access private + */ + function _sql_transaction($status = 'begin') + { + 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; + } + + /** + * 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 When casted to bool the returned value returns true on success and false on failure + * + * @access public + */ + function sql_query($query = '', $cache_ttl = 0) + { + if ($query != '') + { + global $cache; + + // EXPLAIN only in extra debug mode + if (defined('DEBUG_EXTRA')) + { + $this->sql_report('start', $query); + } + + $this->last_query_text = $query; + $this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false; + $this->sql_add_num_queries($this->query_result); + + if ($this->query_result === false) + { + if (($this->query_result = @pg_query($this->db_connect_id, $query)) === false) + { + $this->sql_error($query); + } + + if (defined('DEBUG_EXTRA')) + { + $this->sql_report('stop', $query); + } + + if ($cache_ttl && method_exists($cache, 'sql_save')) + { + $this->open_queries[(int) $this->query_result] = $this->query_result; + $cache->sql_save($query, $this->query_result, $cache_ttl); + } + else if (strpos($query, 'SELECT') === 0 && $this->query_result) + { + $this->open_queries[(int) $this->query_result] = $this->query_result; + } + } + else if (defined('DEBUG_EXTRA')) + { + $this->sql_report('fromcache', $query); + } + } + else + { + return false; + } + + return $this->query_result; + } + + /** + * Build db-specific query data + * @access private + */ + function _sql_custom_build($stage, $data) + { + return $data; + } + + /** + * Build LIMIT query + */ + function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) + { + $this->query_result = false; + + // 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); + } + + /** + * Return number of affected rows + */ + function sql_affectedrows() + { + return ($this->query_result) ? @pg_affected_rows($this->query_result) : false; + } + + /** + * Fetch current row + */ + function sql_fetchrow($query_id = false) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_fetchrow($query_id); + } + + return ($query_id !== false) ? @pg_fetch_assoc($query_id, null) : false; + } + + /** + * Seek to given row number + * rownum is zero-based + */ + function sql_rowseek($rownum, &$query_id) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_rowseek($rownum, $query_id); + } + + return ($query_id !== false) ? @pg_result_seek($query_id, $rownum) : false; + } + + /** + * Get last inserted id after insert statement + */ + function sql_nextid() + { + $query_id = $this->query_result; + + if ($query_id !== false && $this->last_query_text != '') + { + if (preg_match("/^INSERT[\t\n ]+INTO[\t\n ]+([a-z0-9\_\-]+)/is", $this->last_query_text, $tablename)) + { + $query = "SELECT currval('" . $tablename[1] . "_seq') 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; + } + } + + return false; + } + + /** + * Free sql result + */ + function sql_freeresult($query_id = false) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_freeresult($query_id); + } + + if (isset($this->open_queries[(int) $query_id])) + { + unset($this->open_queries[(int) $query_id]); + return @pg_free_result($query_id); + } + + return false; + } + + /** + * Escape string used in sql query + * Note: Do not use for bytea values if we may use them at a later stage + */ + function sql_escape($msg) + { + return @pg_escape_string($msg); + } + + /** + * Build LIKE expression + * @access private + */ + function _sql_like_expression($expression) + { + return $expression; + } + + /** + * return sql error array + * @access private + */ + function _sql_error() + { + return array( + 'message' => (!$this->db_connect_id) ? @pg_last_error() : @pg_last_error($this->db_connect_id), + 'code' => '' + ); + } + + /** + * Close sql connection + * @access private + */ + function _sql_close() + { + return @pg_close($this->db_connect_id); + } + + /** + * Build db-specific report + * @access private + */ + 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 new file mode 100644 index 0000000000..288f6e0992 --- /dev/null +++ b/phpBB/includes/db/sqlite.php @@ -0,0 +1,334 @@ +<?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.' . $phpEx); + +/** +* Sqlite Database Abstraction Layer +* Minimum Requirement: 2.8.2+ +* @package dbal +*/ +class dbal_sqlite extends dbal +{ + /** + * Connect to server + */ + function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) + { + $this->persistency = $persistency; + $this->user = $sqluser; + $this->server = $sqlserver . (($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 + * @param bool $raw if true, only return the fetched sql_server_version + * @return string sql server version + */ + function sql_server_info($raw = false) + { + global $cache; + + if (empty($cache) || ($this->sql_server_version = $cache->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; + $cache->put('sqlite_version', $this->sql_server_version); + } + + return ($raw) ? $this->sql_server_version : 'SQLite ' . $this->sql_server_version; + } + + /** + * SQL Transaction + * @access private + */ + function _sql_transaction($status = 'begin') + { + 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; + } + + /** + * 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 When casted to bool the returned value returns true on success and false on failure + * + * @access public + */ + function sql_query($query = '', $cache_ttl = 0) + { + if ($query != '') + { + global $cache; + + // EXPLAIN only in extra debug mode + if (defined('DEBUG_EXTRA')) + { + $this->sql_report('start', $query); + } + + $this->query_result = ($cache_ttl && method_exists($cache, 'sql_load')) ? $cache->sql_load($query) : false; + $this->sql_add_num_queries($this->query_result); + + if ($this->query_result === false) + { + if (($this->query_result = @sqlite_query($query, $this->db_connect_id)) === false) + { + $this->sql_error($query); + } + + if (defined('DEBUG_EXTRA')) + { + $this->sql_report('stop', $query); + } + + if ($cache_ttl && method_exists($cache, 'sql_save')) + { + $this->open_queries[(int) $this->query_result] = $this->query_result; + $cache->sql_save($query, $this->query_result, $cache_ttl); + } + else if (strpos($query, 'SELECT') === 0 && $this->query_result) + { + $this->open_queries[(int) $this->query_result] = $this->query_result; + } + } + else if (defined('DEBUG_EXTRA')) + { + $this->sql_report('fromcache', $query); + } + } + else + { + return false; + } + + return $this->query_result; + } + + /** + * Build LIMIT query + */ + function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) + { + $this->query_result = false; + + // 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); + } + + /** + * Return number of affected rows + */ + function sql_affectedrows() + { + return ($this->db_connect_id) ? @sqlite_changes($this->db_connect_id) : false; + } + + /** + * Fetch current row + */ + function sql_fetchrow($query_id = false) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_fetchrow($query_id); + } + + return ($query_id !== false) ? @sqlite_fetch_array($query_id, SQLITE_ASSOC) : false; + } + + /** + * Seek to given row number + * rownum is zero-based + */ + function sql_rowseek($rownum, &$query_id) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_rowseek($rownum, $query_id); + } + + return ($query_id !== false) ? @sqlite_seek($query_id, $rownum) : false; + } + + /** + * Get last inserted id after insert statement + */ + function sql_nextid() + { + return ($this->db_connect_id) ? @sqlite_last_insert_rowid($this->db_connect_id) : false; + } + + /** + * Free sql result + */ + function sql_freeresult($query_id = false) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_freeresult($query_id); + } + + return true; + } + + /** + * Escape string used in sql query + */ + function sql_escape($msg) + { + return @sqlite_escape_string($msg); + } + + /** + * Correctly adjust LIKE expression for special characters + * For SQLite an underscore is a not-known character... this may change with SQLite3 + */ + 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 on 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) . '\''; + } + + /** + * return sql error array + * @access private + */ + function _sql_error() + { + return array( + 'message' => @sqlite_error_string(@sqlite_last_error($this->db_connect_id)), + 'code' => @sqlite_last_error($this->db_connect_id) + ); + } + + /** + * Build db-specific query data + * @access private + */ + function _sql_custom_build($stage, $data) + { + return $data; + } + + /** + * Close sql connection + * @access private + */ + function _sql_close() + { + return @sqlite_close($this->db_connect_id); + } + + /** + * Build db-specific report + * @access private + */ + 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/diff/diff.php b/phpBB/includes/diff/diff.php new file mode 100644 index 0000000000..60af574b78 --- /dev/null +++ b/phpBB/includes/diff/diff.php @@ -0,0 +1,1148 @@ +<?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 diff(&$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; + + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + { + $edit = $this->_edits[$i]; + + 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; + + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + { + $edit = $this->_edits[$i]; + + 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(); + + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + { + $edit = $this->_edits[$i]; + $rev->_edits[] = $edit->reverse(); + } + + return $rev; + } + + /** + * Checks for an empty diff. + * + * @return boolean True if two sequences were identical. + */ + function is_empty() + { + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + { + $edit = $this->_edits[$i]; + + // skip diff_op_copy + if (is_a($edit, 'diff_op_copy')) + { + continue; + } + + if (is_a($edit, 'diff_op_delete') || is_a($edit, 'diff_op_add')) + { + $orig = $edit->orig; + $final = $edit->final; + + // We can simplify one case where the array is usually supposed to be empty... + if (sizeof($orig) == 1 && trim($orig[0]) === '') $orig = array(); + if (sizeof($final) == 1 && trim($final[0]) === '') $final = array(); + + if (!$orig && !$final) + { + continue; + } + + return false; + } + + 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; + + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + { + $edit = $this->_edits[$i]; + + 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(); + + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + { + $edit = $this->_edits[$i]; + + 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(); + + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + { + $edit = $this->_edits[$i]; + + 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; + + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + { + $edit = $this->_edits[$i]; + + 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, $preserve_cr = true) + { + $diff_engine = new diff_engine(); + + $diff_1 = $diff_engine->diff($orig, $final1, $preserve_cr); + $diff_2 = $diff_engine->diff($orig, $final2, $preserve_cr); + + unset($diff_engine); + + $this->_edits = $this->_diff3($diff_1, $diff_2); + } + + /** + * Return number of conflicts + */ + function get_num_conflicts() + { + $conflicts = 0; + + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + { + $edit = $this->_edits[$i]; + + 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') + { + global $user; + + $label1 = (!empty($user->lang[$label1])) ? $user->lang[$label1] : $label1; + $label2 = (!empty($user->lang[$label2])) ? $user->lang[$label2] : $label2; + $label_sep = (!empty($user->lang[$label_sep])) ? $user->lang[$label_sep] : $label_sep; + + $lines = array(); + + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + { + $edit = $this->_edits[$i]; + + 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); + $this->_conflicting_blocks++; + } + else + { + $lines = array_merge($lines, $edit->merged()); + } + } + + return $lines; + } + + /** + * Return merged output (used by the renderer) + * + * @return mixed the merged output + */ + function merged_output() + { + return $this->get_conflicts_content(); + } + + /** + * Merge the output and use the new file code for conflicts + */ + function merged_new_output() + { + $lines = array(); + + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + { + $edit = $this->_edits[$i]; + + 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(); + + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + { + $edit = $this->_edits[$i]; + + 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(); + + for ($i = 0, $size = sizeof($this->_edits); $i < $size; $i++) + { + $edit = $this->_edits[$i]; + + 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 diff3_op($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)) + { + // Prepare the arrays before we compare them. ;) + $this->solve_prepare(); + + 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 + { + // The following tries to aggressively solve conflicts... + $this->_merged = false; + $this->solve_conflict(); + } + } + + return $this->_merged; + } + + function is_conflict() + { + return ($this->merged() === false) ? true : false; + } + + /** + * Function to prepare the arrays for comparing - we want to skip over newline changes + * @author acydburn + */ + function solve_prepare() + { + // We can simplify one case where the array is usually supposed to be empty... + if (sizeof($this->orig) == 1 && trim($this->orig[0]) === '') $this->orig = array(); + if (sizeof($this->final1) == 1 && trim($this->final1[0]) === '') $this->final1 = array(); + if (sizeof($this->final2) == 1 && trim($this->final2[0]) === '') $this->final2 = array(); + + // Now we only can have the case where the only difference between arrays are newlines, so compare all cases + + // First, some strings we can compare... + $orig = $final1 = $final2 = ''; + + foreach ($this->orig as $null => $line) $orig .= trim($line); + foreach ($this->final1 as $null => $line) $final1 .= trim($line); + foreach ($this->final2 as $null => $line) $final2 .= trim($line); + + // final1 === final2 + if ($final1 === $final2) + { + // We preserve the part which will be used in the merge later + $this->final2 = $this->final1; + } + // final1 === orig + else if ($final1 === $orig) + { + // Here it does not really matter what we choose, but we will use the new code + $this->orig = $this->final1; + } + // final2 === orig + else if ($final2 === $orig) + { + // Here it does not really matter too (final1 will be used), but we will use the new code + $this->orig = $this->final2; + } + } + + /** + * Find code portions from $orig in $final1 and use $final2 as merged instance if provided + * @author acydburn + */ + function _compare_conflict_seq($orig, $final1, $final2 = false) + { + $result = array('merge_found' => false, 'merge' => array()); + + $_orig = &$this->$orig; + $_final1 = &$this->$final1; + + // Ok, we basically search for $orig in $final1 + $compare_seq = sizeof($_orig); + + // Go through the conflict code + for ($i = 0, $j = 0, $size = sizeof($_final1); $i < $size; $i++, $j = $i) + { + $line = $_final1[$i]; + $skip = 0; + + for ($x = 0; $x < $compare_seq; $x++) + { + // Try to skip all matching lines + if (trim($line) === trim($_orig[$x])) + { + $line = (++$j < $size) ? $_final1[$j] : $line; + $skip++; + } + } + + if ($skip === $compare_seq) + { + $result['merge_found'] = true; + + if ($final2 !== false) + { + $result['merge'] = array_merge($result['merge'], $this->$final2); + } + $i += ($skip - 1); + } + else if ($final2 !== false) + { + $result['merge'][] = $line; + } + } + + return $result; + } + + /** + * Tries to solve conflicts aggressively based on typical "assumptions" + * @author acydburn + */ + function solve_conflict() + { + $this->_merged = false; + + // CASE ONE: orig changed into final2, but modified/unknown code in final1. + // IF orig is found "as is" in final1 we replace the code directly in final1 and populate this as final2/merge + if (sizeof($this->orig) && sizeof($this->final2)) + { + $result = $this->_compare_conflict_seq('orig', 'final1', 'final2'); + + if ($result['merge_found']) + { + $this->final2 = $result['merge']; + $this->_merged = &$this->final2; + return; + } + + $result = $this->_compare_conflict_seq('final2', 'final1'); + + if ($result['merge_found']) + { + $this->_merged = &$this->final1; + return; + } + + // Try to solve $Id$ issues. ;) + if (sizeof($this->orig) == 1 && sizeof($this->final1) == 1 && sizeof($this->final2) == 1) + { + $match = '#^' . preg_quote('* @version $Id: ', '#') . '[a-z\._\- ]+[0-9]+ [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9\:Z]+ [a-z0-9_\- ]+\$$#'; + + if (preg_match($match, $this->orig[0]) && preg_match($match, $this->final1[0]) && preg_match($match, $this->final2[0])) + { + $this->_merged = &$this->final2; + return; + } + } + + $second_run = false; + + // Try to solve issues where the only reason why the above did not work is a newline being removed in the final1 code but exist in the orig/final2 code + if (trim($this->orig[0]) === '' && trim($this->final2[0]) === '') + { + unset($this->orig[0], $this->final2[0]); + $this->orig = array_values($this->orig); + $this->final2 = array_values($this->final2); + + $second_run = true; + } + + // The same is true for a line at the end. ;) + if (sizeof($this->orig) && sizeof($this->final2) && sizeof($this->orig) === sizeof($this->final2) && trim($this->orig[sizeof($this->orig)-1]) === '' && trim($this->final2[sizeof($this->final2)-1]) === '') + { + unset($this->orig[sizeof($this->orig)-1], $this->final2[sizeof($this->final2)-1]); + $this->orig = array_values($this->orig); + $this->final2 = array_values($this->final2); + + $second_run = true; + } + + if ($second_run) + { + $result = $this->_compare_conflict_seq('orig', 'final1', 'final2'); + + if ($result['merge_found']) + { + $this->final2 = $result['merge']; + $this->_merged = &$this->final2; + return; + } + + $result = $this->_compare_conflict_seq('final2', 'final1'); + + if ($result['merge_found']) + { + $this->_merged = &$this->final1; + return; + } + } + + return; + } + + // CASE TWO: Added lines from orig to final2 but final1 had added lines too. Just merge them. + if (!sizeof($this->orig) && $this->final1 !== $this->final2 && sizeof($this->final1) && sizeof($this->final2)) + { + $result = $this->_compare_conflict_seq('final2', 'final1'); + + if ($result['merge_found']) + { + $this->final2 = $this->final1; + $this->_merged = &$this->final1; + } + else + { + $result = $this->_compare_conflict_seq('final1', 'final2'); + + if (!$result['merge_found']) + { + $this->final2 = array_merge($this->final1, $this->final2); + $this->_merged = &$this->final2; + } + else + { + $this->final2 = $this->final1; + $this->_merged = &$this->final1; + } + } + + return; + } + + // CASE THREE: Removed lines (orig has the to-remove line(s), but final1 has additional lines which does not need to be removed). Just remove orig from final1 and then use final1 as final2/merge + if (!sizeof($this->final2) && sizeof($this->orig) && sizeof($this->final1) && $this->orig !== $this->final1) + { + $result = $this->_compare_conflict_seq('orig', 'final1'); + + if (!$result['merge_found']) + { + return; + } + + // First of all, try to find the code in orig in final1. ;) + $compare_seq = sizeof($this->orig); + $begin = $end = -1; + $j = 0; + + for ($i = 0, $size = sizeof($this->final1); $i < $size; $i++) + { + $line = $this->final1[$i]; + + if (trim($line) === trim($this->orig[$j])) + { + // Mark begin + if ($begin === -1) + { + $begin = $i; + } + + // End is always $i, the last found line + $end = $i; + + if (isset($this->orig[$j+1])) + { + $j++; + } + } + } + + if ($begin !== -1 && $begin + ($compare_seq - 1) == $end) + { + foreach ($this->final1 as $i => $line) + { + if ($i < $begin || $i > $end) + { + $merged[] = $line; + } + } + + $this->final2 = $merged; + $this->_merged = &$this->final2; + } + + return; + } + + return; + } +} + +/** +* @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 diff3_block_builder() + { + $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/diff/engine.php b/phpBB/includes/diff/engine.php new file mode 100644 index 0000000000..982149457d --- /dev/null +++ b/phpBB/includes/diff/engine.php @@ -0,0 +1,554 @@ +<?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 +{ + /** + * If set to true we trim all lines before we compare them. This ensures that sole space/tab changes do not trigger diffs. + */ + var $skip_whitespace_changes = true; + + 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 (trim($from_lines[$skip]) !== trim($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 (trim($from_lines[$xi]) !== trim($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++) + { + if ($this->skip_whitespace_changes) $xhash[trim($from_lines[$xi])] = 1; else $xhash[$from_lines[$xi]] = 1; + } + + for ($yi = $skip; $yi < $n_to - $endskip; $yi++) + { + $line = ($this->skip_whitespace_changes) ? trim($to_lines[$yi]) : $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 = ($this->skip_whitespace_changes) ? trim($from_lines[$xi]) : $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. + if ($this->skip_whitespace_changes) + { + $from_lines_clean = array_map('trim', $from_lines); + $to_lines_clean = array_map('trim', $to_lines); + + $this->_shift_boundaries($from_lines_clean, $this->xchanged, $this->ychanged); + $this->_shift_boundaries($to_lines_clean, $this->ychanged, $this->xchanged); + + unset($from_lines_clean, $to_lines_clean); + } + else + { + $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/diff/renderer.php b/phpBB/includes/diff/renderer.php new file mode 100644 index 0000000000..5cb1b6ada9 --- /dev/null +++ b/phpBB/includes/diff/renderer.php @@ -0,0 +1,860 @@ +<?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 diff_renderer($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;" rows="15" cols="76" 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) + { + global $user; + + $output = ''; + $output .= '<table cellspacing="0" class="hrdiff"> +<caption> + <span class="unmodified"> </span> ' . $user->lang['LINE_UNMODIFIED'] . ' + <span class="added"> </span> ' . $user->lang['LINE_ADDED'] . ' + <span class="modified"> </span> ' . $user->lang['LINE_MODIFIED'] . ' + <span class="removed"> </span> ' . $user->lang['LINE_REMOVED'] . ' +</caption> +<tbody> +'; + + $this->render($diff); + + // Is the diff empty? + if (!sizeof($this->lines)) + { + $output .= '<tr><th colspan="2">' . $user->lang['NO_VISIBLE_CHANGES'] . '</th></tr>'; + } + else + { + // Iterate through every header block of changes + foreach ($this->lines as $header) + { + $output .= '<tr><th>' . $user->lang['LINE'] . ' ' . $header['oldline'] . '</th><th>' . $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/functions.php b/phpBB/includes/functions.php new file mode 100644 index 0000000000..e787932441 --- /dev/null +++ b/phpBB/includes/functions.php @@ -0,0 +1,4367 @@ +<?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; +} + +// Common global functions + +/** +* set_var +* +* Set variable, used by {@link request_var the request_var function} +* +* @access private +*/ +function set_var(&$result, $var, $type, $multibyte = false) +{ + settype($var, $type); + $result = $var; + + if ($type == 'string') + { + $result = trim(htmlspecialchars(str_replace(array("\r\n", "\r", "\0"), array("\n", "\n", ''), $result), ENT_COMPAT, 'UTF-8')); + + 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; + } +} + +/** +* request_var +* +* Used to get passed variable +*/ +function request_var($var_name, $default, $multibyte = false, $cookie = false) +{ + if (!$cookie && isset($_COOKIE[$var_name])) + { + if (!isset($_GET[$var_name]) && !isset($_POST[$var_name])) + { + return (is_array($default)) ? array() : $default; + } + $_REQUEST[$var_name] = isset($_POST[$var_name]) ? $_POST[$var_name] : $_GET[$var_name]; + } + + $super_global = ($cookie) ? '_COOKIE' : '_REQUEST'; + if (!isset($GLOBALS[$super_global][$var_name]) || is_array($GLOBALS[$super_global][$var_name]) != is_array($default)) + { + return (is_array($default)) ? array() : $default; + } + + $var = $GLOBALS[$super_global][$var_name]; + if (!is_array($default)) + { + $type = gettype($default); + } + else + { + list($key_type, $type) = each($default); + $type = gettype($type); + $key_type = gettype($key_type); + if ($type == 'array') + { + reset($default); + $default = current($default); + list($sub_key_type, $sub_type) = each($default); + $sub_type = gettype($sub_type); + $sub_type = ($sub_type == 'array') ? 'NULL' : $sub_type; + $sub_key_type = gettype($sub_key_type); + } + } + + if (is_array($var)) + { + $_var = $var; + $var = array(); + + foreach ($_var as $k => $v) + { + set_var($k, $k, $key_type); + if ($type == 'array' && is_array($v)) + { + foreach ($v as $_k => $_v) + { + if (is_array($_v)) + { + $_v = null; + } + set_var($_k, $_k, $sub_key_type); + set_var($var[$k][$_k], $_v, $sub_type, $multibyte); + } + } + else + { + if ($type == 'array' || is_array($v)) + { + $v = null; + } + set_var($var[$k], $v, $type, $multibyte); + } + } + } + else + { + set_var($var, $var, $type, $multibyte); + } + + return $var; +} + +/** +* Set config value. Creates missing config entry. +*/ +function set_config($config_name, $config_value, $is_dynamic = false) +{ + global $db, $cache, $config; + + $sql = 'UPDATE ' . CONFIG_TABLE . " + SET config_value = '" . $db->sql_escape($config_value) . "' + WHERE config_name = '" . $db->sql_escape($config_name) . "'"; + $db->sql_query($sql); + + if (!$db->sql_affectedrows() && !isset($config[$config_name])) + { + $sql = 'INSERT INTO ' . CONFIG_TABLE . ' ' . $db->sql_build_array('INSERT', array( + 'config_name' => $config_name, + 'config_value' => $config_value, + 'is_dynamic' => ($is_dynamic) ? 1 : 0)); + $db->sql_query($sql); + } + + $config[$config_name] = $config_value; + + if (!$is_dynamic) + { + $cache->destroy('config'); + } +} + +/** +* Set dynamic config value with arithmetic operation. +*/ +function set_config_count($config_name, $increment, $is_dynamic = false) +{ + global $db, $cache; + + switch ($db->sql_layer) + { + case 'firebird': + $sql_update = 'CAST(CAST(config_value as integer) + ' . (int) $increment . ' as VARCHAR(255))'; + 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; + } + + $db->sql_query('UPDATE ' . CONFIG_TABLE . ' SET config_value = ' . $sql_update . " WHERE config_name = '" . $db->sql_escape($config_name) . "'"); + + if (!$is_dynamic) + { + $cache->destroy('config'); + } +} + +/** +* Generates an alphanumeric random string of given length +*/ +function gen_rand_string($num_chars = 8) +{ + $rand_str = 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 +*/ +function unique_id($extra = 'c') +{ + static $dss_seeded = false; + global $config; + + $val = $config['rand_seed'] . microtime(); + $val = md5($val); + $config['rand_seed'] = md5($config['rand_seed'] . $val . $extra); + + if ($dss_seeded !== true && ($config['rand_seed_last_update'] < time() - rand(1,10))) + { + set_config('rand_seed', $config['rand_seed'], true); + set_config('rand_seed_last_update', time(), true); + $dss_seeded = true; + } + + return substr($val, 4, 16); +} + +/** +* Return formatted string for filesizes +* +* @param int $value filesize in bytes +* @param bool $string_only true if language string should be returned +* @param array $allowed_units only allow these units (data array indexes) +* +* @return mixed data array if $string_only is false +* @author bantu +*/ +function get_formatted_filesize($value, $string_only = true, $allowed_units = false) +{ + global $user; + + $available_units = array( + 'gb' => array( + 'min' => 1073741824, // pow(2, 30) + 'index' => 3, + 'si_unit' => 'GB', + 'iec_unit' => 'GIB', + ), + 'mb' => array( + 'min' => 1048576, // pow(2, 20) + 'index' => 2, + 'si_unit' => 'MB', + 'iec_unit' => 'MIB', + ), + 'kb' => array( + 'min' => 1024, // pow(2, 10) + 'index' => 1, + 'si_unit' => 'KB', + 'iec_unit' => 'KIB', + ), + 'b' => array( + 'min' => 0, + 'index' => 0, + 'si_unit' => 'BYTES', // Language index + 'iec_unit' => 'BYTES', // Language index + ), + ); + + foreach ($available_units as $si_identifier => $unit_info) + { + if (!empty($allowed_units) && $si_identifier != 'b' && !in_array($si_identifier, $allowed_units)) + { + continue; + } + + if ($value >= $unit_info['min']) + { + $unit_info['si_identifier'] = $si_identifier; + + break; + } + } + unset($available_units); + + for ($i = 0; $i < $unit_info['index']; $i++) + { + $value /= 1024; + } + $value = round($value, 2); + + // Lookup units in language dictionary + $unit_info['si_unit'] = (isset($user->lang[$unit_info['si_unit']])) ? $user->lang[$unit_info['si_unit']] : $unit_info['si_unit']; + $unit_info['iec_unit'] = (isset($user->lang[$unit_info['iec_unit']])) ? $user->lang[$unit_info['iec_unit']] : $unit_info['iec_unit']; + + // Default to IEC + $unit_info['unit'] = $unit_info['iec_unit']; + + if (!$string_only) + { + $unit_info['value'] = $value; + + return $unit_info; + } + + return $value . ' ' . $unit_info['unit']; +} + +/** +* 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. +*/ +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; +} + +/** +* +* @version Version 0.1 / slightly modified for phpBB 3.0.x (using $H$ as hash type identifier) +* +* 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. +* +* +* Hash the password +*/ +function phpbb_hash($password) +{ + $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + + $random_state = 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(unique_id() . $random_state); + $random .= pack('H*', md5($random_state)); + } + $random = substr($random, 0, $count); + } + + $hash = _hash_crypt_private($password, _hash_gensalt_private($random, $itoa64), $itoa64); + + if (strlen($hash) == 34) + { + return $hash; + } + + return md5($password); +} + +/** +* Check for correct password +* +* @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. +*/ +function phpbb_check_hash($password, $hash) +{ + $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + if (strlen($hash) == 34) + { + return (_hash_crypt_private($password, $hash, $itoa64) === $hash) ? true : false; + } + + return (md5($password) === $hash) ? true : false; +} + +/** +* Generate salt for hash generation +*/ +function _hash_gensalt_private($input, &$itoa64, $iteration_count_log2 = 6) +{ + if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31) + { + $iteration_count_log2 = 8; + } + + $output = '$H$'; + $output .= $itoa64[min($iteration_count_log2 + ((PHP_VERSION >= 5) ? 5 : 3), 30)]; + $output .= _hash_encode64($input, 6, $itoa64); + + return $output; +} + +/** +* Encode hash +*/ +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 +*/ +function _hash_crypt_private($password, $setting, &$itoa64) +{ + $output = '*'; + + // Check for correct hash + if (substr($setting, 0, 3) != '$H$') + { + 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). + */ + if (PHP_VERSION >= 5) + { + $hash = md5($salt . $password, true); + do + { + $hash = md5($hash . $password, true); + } + while (--$count); + } + else + { + $hash = pack('H*', md5($salt . $password)); + do + { + $hash = pack('H*', md5($hash . $password)); + } + while (--$count); + } + + $output = substr($setting, 0, 12); + $output .= _hash_encode64($hash, 16, $itoa64); + + return $output; +} + +/** +* Hashes an email address to a big integer +* +* @param string $email Email address +* +* @return string Big Integer +*/ +function phpbb_email_hash($email) +{ + return crc32(strtolower($email)) . strlen($email); +} + +/** +* Global function 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: +* +* CHMOD_ALL - all permissions (7) +* CHMOD_READ - read permission (4) +* CHMOD_WRITE - write permission (2) +* 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 +*/ +function phpbb_chmod($filename, $perms = CHMOD_READ) +{ + static $_chmod_info; + + // Return if the file no longer exists. + if (!file_exists($filename)) + { + return false; + } + + // Determine some common vars + if (empty($_chmod_info)) + { + if (!function_exists('fileowner') || !function_exists('filegroup')) + { + // No need to further determine owner/group - it is unknown + $_chmod_info['process'] = false; + } + else + { + global $phpbb_root_path, $phpEx; + + // Determine owner/group of common.php file and the filename we want to change here + $common_php_owner = @fileowner($phpbb_root_path . 'common.' . $phpEx); + $common_php_group = @filegroup($phpbb_root_path . 'common.' . $phpEx); + + // 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 we are unable to get owner/group, then do not try to set them by guessing + if (!$php_uid || empty($php_gids) || !$common_php_owner || !$common_php_group) + { + $_chmod_info['process'] = false; + } + else + { + $_chmod_info = array( + 'process' => true, + 'common_owner' => $common_php_owner, + 'common_group' => $common_php_group, + 'php_uid' => $php_uid, + 'php_gids' => $php_gids, + ); + } + } + } + + if ($_chmod_info['process']) + { + $file_uid = @fileowner($filename); + $file_gid = @filegroup($filename); + + // Change owner + if (@chown($filename, $_chmod_info['common_owner'])) + { + clearstatcache(); + $file_uid = @fileowner($filename); + } + + // Change group + if (@chgrp($filename, $_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 != $_chmod_info['common_owner'] || $file_gid != $_chmod_info['common_group']) + { + $_chmod_info['process'] = false; + } + } + + // Still able to process? + if ($_chmod_info['process']) + { + if ($file_uid == $_chmod_info['php_uid']) + { + $php = 'owner'; + } + else if (in_array($file_gid, $_chmod_info['php_gids'])) + { + $php = 'group'; + } + else + { + // Since we are setting the everyone bit anyway, no need to do expensive operations + $_chmod_info['process'] = false; + } + } + + // We are not able to determine or change something + if (!$_chmod_info['process']) + { + $php = 'other'; + } + + // Owner always has read/write permission + $owner = CHMOD_READ | CHMOD_WRITE; + if (is_dir($filename)) + { + $owner |= CHMOD_EXECUTE; + + // Only add execute bit to the permission if the dir needs to be readable + if ($perms & CHMOD_READ) + { + $perms |= CHMOD_EXECUTE; + } + } + + switch ($php) + { + case 'owner': + $result = @chmod($filename, ($owner << 6) + (0 << 3) + (0 << 0)); + + clearstatcache(); + + if (is_readable($filename) && is_writable($filename)) + { + break; + } + + case 'group': + $result = @chmod($filename, ($owner << 6) + ($perms << 3) + (0 << 0)); + + clearstatcache(); + + if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename))) + { + break; + } + + case 'other': + $result = @chmod($filename, ($owner << 6) + ($perms << 3) + ($perms << 0)); + + clearstatcache(); + + if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename))) + { + break; + } + + default: + return false; + break; + } + + return $result; +} + +/** +* Test if a file/directory is writable +* +* This function calls the native is_writable() when not running under +* Windows and it is not disabled. +* +* @param string $file Path to perform write test on +* @return bool True when the path is writable, otherwise false. +*/ +function phpbb_is_writable($file) +{ + if (strtolower(substr(PHP_OS, 0, 3)) === 'win' || !function_exists('is_writable')) + { + if (file_exists($file)) + { + // Canonicalise path to absolute path + $file = phpbb_realpath($file); + + if (is_dir($file)) + { + // Test directory by creating a file inside the directory + $result = @tempnam($file, 'i_w'); + + if (is_string($result) && file_exists($result)) + { + unlink($result); + + // Ensure the file is actually in the directory (returned realpathed) + return (strpos($result, $file) === 0) ? true : false; + } + } + else + { + $handle = @fopen($file, 'r+'); + + if (is_resource($handle)) + { + fclose($handle); + return true; + } + } + } + else + { + // file does not exist test if we can write to the directory + $dir = dirname($file); + + if (file_exists($dir) && is_dir($dir) && phpbb_is_writable($dir)) + { + return true; + } + } + + return false; + } + else + { + return is_writable($file); + } +} + +// Compatibility functions + +if (!function_exists('array_combine')) +{ + /** + * A wrapper for the PHP5 function array_combine() + * @param array $keys contains keys for the resulting array + * @param array $values contains values for the resulting array + * + * @return Returns an array by using the values from the keys array as keys and the + * values from the values array as the corresponding values. Returns false if the + * number of elements for each array isn't equal or if the arrays are empty. + */ + function array_combine($keys, $values) + { + $keys = array_values($keys); + $values = array_values($values); + + $n = sizeof($keys); + $m = sizeof($values); + if (!$n || !$m || ($n != $m)) + { + return false; + } + + $combined = array(); + for ($i = 0; $i < $n; $i++) + { + $combined[$keys[$i]] = $values[$i]; + } + return $combined; + } +} + +if (!function_exists('str_split')) +{ + /** + * A wrapper for the PHP5 function str_split() + * @param array $string contains the string to be converted + * @param array $split_length contains the length of each chunk + * + * @return Converts a string to an array. If the optional split_length parameter is specified, + * the returned array will be broken down into chunks with each being split_length in length, + * otherwise each chunk will be one character in length. FALSE is returned if split_length is + * less than 1. If the split_length length exceeds the length of string, the entire string is + * returned as the first (and only) array element. + */ + function str_split($string, $split_length = 1) + { + if ($split_length < 1) + { + return false; + } + else if ($split_length >= strlen($string)) + { + return array($string); + } + else + { + preg_match_all('#.{1,' . $split_length . '}#s', $string, $matches); + return $matches[0]; + } + } +} + +if (!function_exists('stripos')) +{ + /** + * A wrapper for the PHP5 function stripos + * Find position of first occurrence of a case-insensitive string + * + * @param string $haystack is the string to search in + * @param string $needle is the string to search for + * + * @return mixed Returns the numeric position of the first occurrence of needle in the haystack string. Unlike strpos(), stripos() is case-insensitive. + * Note that the needle may be a string of one or more characters. + * If needle is not found, stripos() will return boolean FALSE. + */ + function stripos($haystack, $needle) + { + if (preg_match('#' . preg_quote($needle, '#') . '#i', $haystack, $m)) + { + return strpos($haystack, $m[0]); + } + + return false; + } +} + +/** +* Checks if a path ($path) is absolute or relative +* +* @param string $path Path to check absoluteness of +* @return boolean +*/ +function is_absolute($path) +{ + return ($path[0] == '/' || (DIRECTORY_SEPARATOR == '\\' && preg_match('#^[a-z]:[/\\\]#i', $path))) ? true : false; +} + +/** +* @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 +*/ +function phpbb_own_realpath($path) +{ + // Now to perform funky shizzle + + // Switch to use UNIX slashes + $path = str_replace(DIRECTORY_SEPARATOR, '/', $path); + $path_prefix = ''; + + // Determine what sort of path we have + if (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 (isset($_SERVER['SCRIPT_FILENAME']) && !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); + } + + return $resolved; // We got here, in the end! +} + +if (!function_exists('realpath')) +{ + /** + * A wrapper for realpath + * @ignore + */ + function phpbb_realpath($path) + { + return phpbb_own_realpath($path); + } +} +else +{ + /** + * A wrapper for realpath + */ + function phpbb_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) + { + return phpbb_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; + } +} + +if (!function_exists('htmlspecialchars_decode')) +{ + /** + * A wrapper for htmlspecialchars_decode + * @ignore + */ + function htmlspecialchars_decode($string, $quote_style = ENT_COMPAT) + { + return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style))); + } +} + +// functions used for building option fields + +/** +* Pick a language, any language ... +*/ +function language_select($default = '') +{ + global $db; + + $sql = 'SELECT lang_iso, lang_local_name + FROM ' . LANG_TABLE . ' + ORDER BY lang_english_name'; + $result = $db->sql_query($sql); + + $lang_options = ''; + while ($row = $db->sql_fetchrow($result)) + { + $selected = ($row['lang_iso'] == $default) ? ' selected="selected"' : ''; + $lang_options .= '<option value="' . $row['lang_iso'] . '"' . $selected . '>' . $row['lang_local_name'] . '</option>'; + } + $db->sql_freeresult($result); + + return $lang_options; +} + +/** +* Pick a template/theme combo, +*/ +function style_select($default = '', $all = false) +{ + global $db; + + $sql_where = (!$all) ? 'WHERE style_active = 1 ' : ''; + $sql = 'SELECT style_id, style_name + FROM ' . STYLES_TABLE . " + $sql_where + ORDER BY style_name"; + $result = $db->sql_query($sql); + + $style_options = ''; + while ($row = $db->sql_fetchrow($result)) + { + $selected = ($row['style_id'] == $default) ? ' selected="selected"' : ''; + $style_options .= '<option value="' . $row['style_id'] . '"' . $selected . '>' . $row['style_name'] . '</option>'; + } + $db->sql_freeresult($result); + + return $style_options; +} + +/** +* Pick a timezone +*/ +function tz_select($default = '', $truncate = false) +{ + global $user; + + $tz_select = ''; + foreach ($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; +} + +// Functions handling topic/post tracking/marking + +/** +* Marks a topic/forum as read +* Marks a topic as posted to +* +* @param int $user_id can only be used with $mode == 'post' +*/ +function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $user_id = 0) +{ + global $db, $user, $config; + + if ($mode == 'all') + { + if ($forum_id === false || !sizeof($forum_id)) + { + if ($config['load_db_lastread'] && $user->data['is_registered']) + { + // Mark all forums read (index page) + $db->sql_query('DELETE FROM ' . TOPICS_TRACK_TABLE . " WHERE user_id = {$user->data['user_id']}"); + $db->sql_query('DELETE FROM ' . FORUMS_TRACK_TABLE . " WHERE user_id = {$user->data['user_id']}"); + $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_lastmark = ' . time() . " WHERE user_id = {$user->data['user_id']}"); + } + else if ($config['load_anon_lastread'] || $user->data['is_registered']) + { + $tracking_topics = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : ''; + $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() - $config['board_startdate'], 10, 36); + + $user->set_cookie('track', tracking_serialize($tracking_topics), time() + 31536000); + $_COOKIE[$config['cookie_name'] . '_track'] = (STRIP) ? addslashes(tracking_serialize($tracking_topics)) : tracking_serialize($tracking_topics); + + unset($tracking_topics); + + if ($user->data['is_registered']) + { + $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_lastmark = ' . time() . " WHERE user_id = {$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 ($config['load_db_lastread'] && $user->data['is_registered']) + { + $sql = 'DELETE FROM ' . TOPICS_TRACK_TABLE . " + WHERE user_id = {$user->data['user_id']} + AND " . $db->sql_in_set('forum_id', $forum_id); + $db->sql_query($sql); + + $sql = 'SELECT forum_id + FROM ' . FORUMS_TRACK_TABLE . " + WHERE user_id = {$user->data['user_id']} + AND " . $db->sql_in_set('forum_id', $forum_id); + $result = $db->sql_query($sql); + + $sql_update = array(); + while ($row = $db->sql_fetchrow($result)) + { + $sql_update[] = (int) $row['forum_id']; + } + $db->sql_freeresult($result); + + if (sizeof($sql_update)) + { + $sql = 'UPDATE ' . FORUMS_TRACK_TABLE . ' + SET mark_time = ' . time() . " + WHERE user_id = {$user->data['user_id']} + AND " . $db->sql_in_set('forum_id', $sql_update); + $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) $user->data['user_id'], + 'forum_id' => (int) $f_id, + 'mark_time' => time() + ); + } + + $db->sql_multi_insert(FORUMS_TRACK_TABLE, $sql_ary); + } + } + else if ($config['load_anon_lastread'] || $user->data['is_registered']) + { + $tracking = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : ''; + $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() - $config['board_startdate'], 10, 36); + } + + if (isset($tracking['tf']) && empty($tracking['tf'])) + { + unset($tracking['tf']); + } + + $user->set_cookie('track', tracking_serialize($tracking), time() + 31536000); + $_COOKIE[$config['cookie_name'] . '_track'] = (STRIP) ? addslashes(tracking_serialize($tracking)) : tracking_serialize($tracking); + + unset($tracking); + } + + return; + } + else if ($mode == 'topic') + { + if ($topic_id === false || $forum_id === false) + { + return; + } + + if ($config['load_db_lastread'] && $user->data['is_registered']) + { + $sql = 'UPDATE ' . TOPICS_TRACK_TABLE . ' + SET mark_time = ' . (($post_time) ? $post_time : time()) . " + WHERE user_id = {$user->data['user_id']} + AND topic_id = $topic_id"; + $db->sql_query($sql); + + // insert row + if (!$db->sql_affectedrows()) + { + $db->sql_return_on_error(true); + + $sql_ary = array( + 'user_id' => (int) $user->data['user_id'], + 'topic_id' => (int) $topic_id, + 'forum_id' => (int) $forum_id, + 'mark_time' => ($post_time) ? (int) $post_time : time(), + ); + + $db->sql_query('INSERT INTO ' . TOPICS_TRACK_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + + $db->sql_return_on_error(false); + } + } + else if ($config['load_anon_lastread'] || $user->data['is_registered']) + { + $tracking = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : ''; + $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 - $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 (isset($_COOKIE[$config['cookie_name'] . '_track']) && strlen($_COOKIE[$config['cookie_name'] . '_track']) > 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 ($user->data['is_registered']) + { + $user->data['user_lastmark'] = intval(base_convert(max($time_keys) + $config['board_startdate'], 36, 10)); + $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_lastmark = ' . $user->data['user_lastmark'] . " WHERE user_id = {$user->data['user_id']}"); + } + else + { + $tracking['l'] = max($time_keys); + } + } + + $user->set_cookie('track', tracking_serialize($tracking), time() + 31536000); + $_COOKIE[$config['cookie_name'] . '_track'] = (STRIP) ? addslashes(tracking_serialize($tracking)) : tracking_serialize($tracking); + } + + return; + } + else if ($mode == 'post') + { + if ($topic_id === false) + { + return; + } + + $use_user_id = (!$user_id) ? $user->data['user_id'] : $user_id; + + if ($config['load_db_track'] && $use_user_id != ANONYMOUS) + { + $db->sql_return_on_error(true); + + $sql_ary = array( + 'user_id' => (int) $use_user_id, + 'topic_id' => (int) $topic_id, + 'topic_posted' => 1 + ); + + $db->sql_query('INSERT INTO ' . TOPICS_POSTED_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + + $db->sql_return_on_error(false); + } + + return; + } +} + +/** +* Get topic tracking info by using already fetched info +*/ +function get_topic_tracking($forum_id, $topic_ids, &$rowset, $forum_mark_time, $global_announce_list = false) +{ + global $config, $user; + + $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])) + { + global $db; + + $sql = 'SELECT mark_time + FROM ' . FORUMS_TRACK_TABLE . " + WHERE user_id = {$user->data['user_id']} + AND forum_id = 0"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $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] : $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) +*/ +function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_list = false) +{ + global $config, $user; + + $last_read = array(); + + if (!is_array($topic_ids)) + { + $topic_ids = array($topic_ids); + } + + if ($config['load_db_lastread'] && $user->data['is_registered']) + { + global $db; + + $sql = 'SELECT topic_id, mark_time + FROM ' . TOPICS_TRACK_TABLE . " + WHERE user_id = {$user->data['user_id']} + AND " . $db->sql_in_set('topic_id', $topic_ids); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $last_read[$row['topic_id']] = $row['mark_time']; + } + $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 = {$user->data['user_id']} + AND forum_id " . + (($global_announce_list && sizeof($global_announce_list)) ? "IN (0, $forum_id)" : "= $forum_id"); + $result = $db->sql_query($sql); + + $mark_time = array(); + while ($row = $db->sql_fetchrow($result)) + { + $mark_time[$row['forum_id']] = $row['mark_time']; + } + $db->sql_freeresult($result); + + $user_lastmark = (isset($mark_time[$forum_id])) ? $mark_time[$forum_id] : $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 ($config['load_anon_lastread'] || $user->data['is_registered']) + { + global $tracking_topics; + + if (!isset($tracking_topics) || !sizeof($tracking_topics)) + { + $tracking_topics = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : ''; + $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array(); + } + + if (!$user->data['is_registered']) + { + $user_lastmark = (isset($tracking_topics['l'])) ? base_convert($tracking_topics['l'], 36, 10) + $config['board_startdate'] : 0; + } + else + { + $user_lastmark = $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) + $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) + $config['board_startdate']; + } + } + + if (isset($tracking_topics['f'][$forum_id])) + { + $mark_time[$forum_id] = base_convert($tracking_topics['f'][$forum_id], 36, 10) + $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; +} + +/** +* Get list of unread topics +* +* @param int $user_id User ID (or false for current user) +* @param string $sql_extra Extra WHERE SQL statement +* @param string $sql_sort ORDER BY SQL sorting statement +* @param string $sql_limit Limits the size of unread topics list, 0 for unlimited query +* +* @return array[int][int] Topic ids as keys, mark_time of topic as value +*/ +function get_unread_topics($user_id = false, $sql_extra = '', $sql_sort = '', $sql_limit = 1001) +{ + global $config, $db, $user; + + $user_id = ($user_id === false) ? (int) $user->data['user_id'] : (int) $user_id; + + // Data array we're going to return + $unread_topics = array(); + + if (empty($sql_sort)) + { + $sql_sort = 'ORDER BY t.topic_last_post_time DESC'; + } + + if ($config['load_db_lastread'] && $user->data['is_registered']) + { + // Get list of the unread topics + $last_mark = $user->data['user_lastmark']; + + $sql_array = array( + 'SELECT' => 't.topic_id, t.topic_last_post_time, tt.mark_time as topic_mark_time, ft.mark_time as forum_mark_time', + + 'FROM' => array(TOPICS_TABLE => 't'), + + 'LEFT_JOIN' => array( + array( + 'FROM' => array(TOPICS_TRACK_TABLE => 'tt'), + 'ON' => "tt.user_id = $user_id AND t.topic_id = tt.topic_id", + ), + array( + 'FROM' => array(FORUMS_TRACK_TABLE => 'ft'), + 'ON' => "ft.user_id = $user_id AND t.forum_id = ft.forum_id", + ), + ), + + 'WHERE' => " + ( + (tt.mark_time IS NOT NULL AND t.topic_last_post_time > tt.mark_time) OR + (tt.mark_time IS NULL AND ft.mark_time IS NOT NULL AND t.topic_last_post_time > ft.mark_time) OR + (tt.mark_time IS NULL AND ft.mark_time IS NULL AND t.topic_last_post_time > $last_mark) + ) + $sql_extra + $sql_sort", + ); + + $sql = $db->sql_build_query('SELECT', $sql_array); + $result = $db->sql_query_limit($sql, $sql_limit); + + while ($row = $db->sql_fetchrow($result)) + { + $topic_id = (int) $row['topic_id']; + $unread_topics[$topic_id] = ($row['topic_mark_time']) ? (int) $row['topic_mark_time'] : (($row['forum_mark_time']) ? (int) $row['forum_mark_time'] : $last_mark); + } + $db->sql_freeresult($result); + } + else if ($config['load_anon_lastread'] || $user->data['is_registered']) + { + global $tracking_topics; + + if (empty($tracking_topics)) + { + $tracking_topics = request_var($config['cookie_name'] . '_track', '', false, true); + $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array(); + } + + if (!$user->data['is_registered']) + { + $user_lastmark = (isset($tracking_topics['l'])) ? base_convert($tracking_topics['l'], 36, 10) + $config['board_startdate'] : 0; + } + else + { + $user_lastmark = (int) $user->data['user_lastmark']; + } + + $sql = 'SELECT t.topic_id, t.forum_id, t.topic_last_post_time + FROM ' . TOPICS_TABLE . ' t + WHERE t.topic_last_post_time > ' . $user_lastmark . " + $sql_extra + $sql_sort"; + $result = $db->sql_query_limit($sql, $sql_limit); + + while ($row = $db->sql_fetchrow($result)) + { + $forum_id = (int) $row['forum_id']; + $topic_id = (int) $row['topic_id']; + $topic_id36 = base_convert($topic_id, 10, 36); + + if (isset($tracking_topics['t'][$topic_id36])) + { + $last_read = base_convert($tracking_topics['t'][$topic_id36], 36, 10) + $config['board_startdate']; + + if ($row['topic_last_post_time'] > $last_read) + { + $unread_topics[$topic_id] = $last_read; + } + } + else if (isset($tracking_topics['f'][$forum_id])) + { + $mark_time = base_convert($tracking_topics['f'][$forum_id], 36, 10) + $config['board_startdate']; + + if ($row['topic_last_post_time'] > $mark_time) + { + $unread_topics[$topic_id] = $mark_time; + } + } + else + { + $unread_topics[$topic_id] = $user_lastmark; + } + } + $db->sql_freeresult($result); + } + + return $unread_topics; +} + +/** +* 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. +*/ +function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_time = false, $mark_time_forum = false) +{ + global $db, $tracking_topics, $user, $config; + + // Determine the users last forum mark time if not given. + if ($mark_time_forum === false) + { + if ($config['load_db_lastread'] && $user->data['is_registered']) + { + $mark_time_forum = (!empty($f_mark_time)) ? $f_mark_time : $user->data['user_lastmark']; + } + else if ($config['load_anon_lastread'] || $user->data['is_registered']) + { + $tracking_topics = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : ''; + $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array(); + + if (!$user->data['is_registered']) + { + $user->data['user_lastmark'] = (isset($tracking_topics['l'])) ? (int) (base_convert($tracking_topics['l'], 36, 10) + $config['board_startdate']) : 0; + } + + $mark_time_forum = (isset($tracking_topics['f'][$forum_id])) ? (int) (base_convert($tracking_topics['f'][$forum_id], 36, 10) + $config['board_startdate']) : $user->data['user_lastmark']; + } + } + + // Check the forum for any left unread topics. + // If there are none, we mark the forum as read. + if ($config['load_db_lastread'] && $user->data['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 = ' . $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 = $db->sql_query_limit($sql, 1); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + } + } + else if ($config['load_anon_lastread'] || $user->data['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 = $db->sql_query($sql); + + $check_forum = $tracking_topics['tf'][$forum_id]; + $unread = false; + + while ($row = $db->sql_fetchrow($result)) + { + if (!isset($check_forum[base_convert($row['topic_id'], 10, 36)])) + { + $unread = true; + break; + } + } + $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 +*/ +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 +*/ +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 +*/ +function generate_pagination($base_url, $num_items, $per_page, $start_item, $add_prevnext_text = false, $tpl_prefix = '') +{ + global $template, $user; + + // Make sure $per_page is a valid value + $per_page = ($per_page <= 0) ? 1 : $per_page; + + $seperator = '<span class="page-sep">' . $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) ? '?' : ((strpos($base_url, '?') === strlen($base_url) - 1) ? '' : '&'); + + $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) . '">' . $user->lang['PREVIOUS'] . '</a> ' . $page_string; + } + + if ($on_page != $total_pages) + { + $page_string .= ' <a href="' . $base_url . "{$url_delim}start=" . ($on_page * $per_page) . '">' . $user->lang['NEXT'] . '</a>'; + } + } + + $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) +*/ +function on_page($num_items, $per_page, $start) +{ + global $template, $user; + + // Make sure $per_page is a valid value + $per_page = ($per_page <= 0) ? 1 : $per_page; + + $on_page = floor($start / $per_page) + 1; + + $template->assign_vars(array( + 'ON_PAGE' => $on_page) + ); + + return sprintf($user->lang['PAGE_OF'], $on_page, max(ceil($num_items / $per_page), 1)); +} + +// Server functions (building urls, redirecting...) + +/** +* Append session id to url. +* This function supports hooks. +* +* @param string $url The url the session id needs to be appended to (can have params) +* @param mixed $params String or array of additional url parameters +* @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 +* +* Examples: +* <code> +* append_sid("{$phpbb_root_path}viewtopic.$phpEx?t=1&f=2"); +* append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=1&f=2'); +* append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=1&f=2', false); +* append_sid("{$phpbb_root_path}viewtopic.$phpEx", array('t' => 1, 'f' => 2)); +* </code> +* +*/ +function append_sid($url, $params = false, $is_amp = true, $session_id = false) +{ + global $_SID, $_EXTRA_URL, $phpbb_hook; + + // Developers using the hook function need to globalise the $_SID and $_EXTRA_URL on their own and also handle it appropiatly. + // They could mimick most of what is within this function + if (!empty($phpbb_hook) && $phpbb_hook->call_hook(__FUNCTION__, $url, $params, $is_amp, $session_id)) + { + if ($phpbb_hook->hook_return(__FUNCTION__)) + { + return $phpbb_hook->hook_return_result(__FUNCTION__); + } + } + + $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 ($_SID == '' && $session_id === false && empty($_EXTRA_URL) && !$params_is_array && !$anchor) + { + if ($params === false) + { + return $url; + } + + $url_delim = (strpos($url, '?') === false) ? '?' : (($is_amp) ? '&' : '&'); + return $url . ($params !== false ? $url_delim. $params : ''); + } + + // Assign sid if session id is not specified + if ($session_id === false) + { + $session_id = $_SID; + } + + $amp_delim = ($is_amp) ? '&' : '&'; + $url_delim = (strpos($url, '?') === false) ? '?' : $amp_delim; + + // Appending custom url parameter? + $append_url = (!empty($_EXTRA_URL)) ? implode($amp_delim, $_EXTRA_URL) : ''; + + // Use the short variant if possible ;) + if ($params === false) + { + // Append session id + if (!$session_id) + { + return $url . (($append_url) ? $url_delim . $append_url : '') . $anchor; + } + else + { + return $url . (($append_url) ? $url_delim . $append_url . $amp_delim : $url_delim) . 'sid=' . $session_id . $anchor; + } + } + + // Build string if parameters are specified as array + if (is_array($params)) + { + $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 parameters (even if they are empty) + // If parameters are empty, the developer can still append his/her parameters without caring about the delimiter + return $url . (($append_url) ? $url_delim . $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) +*/ +function generate_board_url($without_script_path = false) +{ + global $config, $user; + + $server_name = $user->host; + $server_port = (!empty($_SERVER['SERVER_PORT'])) ? (int) $_SERVER['SERVER_PORT'] : (int) getenv('SERVER_PORT'); + + // Forcing server vars is the only way to specify/override the protocol + if ($config['force_server_vars'] || !$server_name) + { + $server_protocol = ($config['server_protocol']) ? $config['server_protocol'] : (($config['cookie_secure']) ? 'https://' : 'http://'); + $server_name = $config['server_name']; + $server_port = (int) $config['server_port']; + $script_path = $config['script_path']; + + $url = $server_protocol . $server_name; + $cookie_secure = $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 = $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->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. Default is no return. +* @param bool $disable_cd_check If true, redirect() will redirect to an external domain. If false, the redirect point to the boards url if it does not match the current domain. Default is false. +*/ +function redirect($url, $return = false, $disable_cd_check = false) +{ + global $db, $cache, $config, $user, $phpbb_root_path; + + if (empty($user->lang)) + { + $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 = generate_board_url() . '/' . $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'] !== $user->host) + { + $url = generate_board_url(); + } + } + else if ($url[0] == '/') + { + // Absolute uri, prepend direct url... + $url = 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 ($user->page['page_dir']) + { + $url = generate_board_url() . '/' . $user->page['page_dir'] . '/' . $url; + } + else + { + $url = 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('\\', '/', phpbb_realpath($phpbb_root_path))); + $page_dirs = explode('/', str_replace('\\', '/', phpbb_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 = 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="' . $user->lang['DIRECTION'] . '" lang="' . $user->lang['USER_LANG'] . '" xml:lang="' . $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>' . $user->lang['REDIRECT'] . '</title>'; + echo '</head>'; + echo '<body>'; + echo '<div style="text-align: center;">' . sprintf($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; +} + +/** +* Re-Apply session id after page reloads +*/ +function reapply_sid($url) +{ + global $phpEx, $phpbb_root_path; + + if ($url === "index.$phpEx") + { + return append_sid("index.$phpEx"); + } + else if ($url === "{$phpbb_root_path}index.$phpEx") + { + return append_sid("{$phpbb_root_path}index.$phpEx"); + } + + // Remove previously added sid + if (strpos($url, 'sid=') !== false) + { + // All kind of links + $url = preg_replace('/(\?)?(&|&)?sid=[a-z0-9]+/', '', $url); + // if the sid was the first param, make the old second as first ones + $url = preg_replace("/$phpEx(&|&)+?/", "$phpEx?", $url); + } + + return append_sid($url); +} + +/** +* Returns url from the session/current page with an re-appended SID with optionally stripping vars from the url +*/ +function build_url($strip_vars = false) +{ + global $user, $phpbb_root_path; + + // Append SID + $redirect = append_sid($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 : ''; + } + + // We need to be cautious here. + // On some situations, the redirect path is an absolute URL, sometimes a relative path + // For a relative path, let's prefix it with $phpbb_root_path to point to the correct location, + // else we use the URL directly. + $url_parts = @parse_url($redirect); + + // URL + if ($url_parts !== false && !empty($url_parts['scheme']) && !empty($url_parts['host'])) + { + return str_replace('&', '&', $redirect); + } + + return $phpbb_root_path . str_replace('&', '&', $redirect); +} + +/** +* Meta refresh assignment +* Adds META template variable with meta http tag. +* +* @param int $time Time in seconds for meta refresh tag +* @param string $url URL to redirect to. The url will go through redirect() first before the template variable is assigned +* @param bool $disable_cd_check If true, meta_refresh() will redirect to an external domain. If false, the redirect point to the boards url if it does not match the current domain. Default is false. +*/ +function meta_refresh($time, $url, $disable_cd_check = false) +{ + global $template; + + $url = redirect($url, true, $disable_cd_check); + $url = str_replace('&', '&', $url); + + // For XHTML compatibility we change back & to & + $template->assign_vars(array( + 'META' => '<meta http-equiv="refresh" content="' . $time . ';url=' . $url . '" />') + ); + + return $url; +} + +//Form validation + + +/** +* 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 + +*/ +function generate_link_hash($link_name) +{ + global $user; + + if (!isset($user->data["hash_$link_name"])) + { + $user->data["hash_$link_name"] = substr(sha1($user->data['user_form_salt'] . $link_name), 0, 8); + } + + return $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 +*/ +function check_link_hash($token, $link_name) +{ + return $token === generate_link_hash($link_name); +} + +/** +* 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 +*/ +function add_form_key($form_name) +{ + global $config, $template, $user; + + $now = time(); + $token_sid = ($user->data['user_id'] == ANONYMOUS && !empty($config['form_token_sid_guests'])) ? $user->session_id : ''; + $token = sha1($now . $user->data['user_form_salt'] . $form_name . $token_sid); + + $s_fields = build_hidden_fields(array( + 'creation_time' => $now, + 'form_token' => $token, + )); + + $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 +*/ +function check_form_key($form_name, $timespan = false, $return_page = '', $trigger = false) +{ + global $config, $user; + + if ($timespan === false) + { + // we enforce a minimum value of half a minute here. + $timespan = ($config['form_token_lifetime'] == -1) ? -1 : max(30, $config['form_token_lifetime']); + } + + if (isset($_POST['creation_time']) && isset($_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 = ($user->data['user_id'] == ANONYMOUS && !empty($config['form_token_sid_guests'])) ? $user->session_id : ''; + $key = sha1($creation_time . $user->data['user_form_salt'] . $form_name . $token_sid); + + if ($key === $token) + { + return true; + } + } + } + + if ($trigger) + { + trigger_error($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 = '') +{ + global $user, $template, $db; + global $phpEx, $phpbb_root_path; + + if (isset($_POST['cancel'])) + { + return false; + } + + $confirm = false; + if (isset($_POST['confirm'])) + { + // language frontier + if ($_POST['confirm'] === $user->lang['YES']) + { + $confirm = true; + } + } + + if ($check && $confirm) + { + $user_id = request_var('confirm_uid', 0); + $session_id = request_var('sess', ''); + $confirm_key = request_var('confirm_key', ''); + + if ($user_id != $user->data['user_id'] || $session_id != $user->session_id || !$confirm_key || !$user->data['user_last_confirm_key'] || $confirm_key != $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 = " . $user->data['user_id']; + $db->sql_query($sql); + + return true; + } + else if ($check) + { + return false; + } + + $s_hidden_fields = build_hidden_fields(array( + 'confirm_uid' => $user->data['user_id'], + 'sess' => $user->session_id, + 'sid' => $user->session_id, + )); + + // generate activation key + $confirm_key = gen_rand_string(10); + + if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin']) + { + adm_page_header((!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title]); + } + else + { + page_header(((!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title]), false); + } + + $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('&', '&', $user->page['page']); + $u_action = reapply_sid($use_page); + $u_action .= ((strpos($u_action, '?') === false) ? '?' : '&') . 'confirm_key=' . $confirm_key; + + $template->assign_vars(array( + 'MESSAGE_TITLE' => (!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title], + 'MESSAGE_TEXT' => (!isset($user->lang[$title . '_CONFIRM'])) ? $title : $user->lang[$title . '_CONFIRM'], + + 'YES_VALUE' => $user->lang['YES'], + 'S_CONFIRM_ACTION' => $u_action, + 'S_HIDDEN_FIELDS' => $hidden . $s_hidden_fields) + ); + + $sql = 'UPDATE ' . USERS_TABLE . " SET user_last_confirm_key = '" . $db->sql_escape($confirm_key) . "' + WHERE user_id = " . $user->data['user_id']; + $db->sql_query($sql); + + if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin']) + { + adm_page_footer(); + } + else + { + page_footer(); + } +} + +/** +* Generate login box or verify password +*/ +function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = false, $s_display = true) +{ + global $db, $user, $template, $auth, $phpEx, $phpbb_root_path, $config; + + if (!class_exists('phpbb_captcha_factory')) + { + include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); + } + + $err = ''; + + // Make sure user->setup() has been called + if (empty($user->lang)) + { + $user->setup(); + } + + // Print out error if user tries to authenticate as an administrator without having the privileges... + if ($admin && !$auth->acl_get('a_')) + { + // Not authd + // anonymous/inactive users are never able to go to the ACP even if they have the relevant permissions + if ($user->data['is_registered']) + { + add_log('admin', 'LOG_ADMIN_AUTH_FAIL'); + } + trigger_error('NO_AUTH_ADMIN'); + } + + if (isset($_POST['login'])) + { + // Get credential + if ($admin) + { + $credential = request_var('credential', ''); + + if (strspn($credential, 'abcdef0123456789') !== strlen($credential) || strlen($credential) != 32) + { + if ($user->data['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 = (!empty($_POST['autologin'])) ? true : false; + $viewonline = (!empty($_POST['viewonline'])) ? 0 : 1; + $admin = ($admin) ? 1 : 0; + $viewonline = ($admin) ? $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($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 = $auth->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 ($user->data['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_root_path}index.$phpEx"); + $message = ($l_success) ? $l_success : $user->lang['LOGIN_REDIRECT']; + $l_redirect = ($admin) ? $user->lang['PROCEED_TO_ACP'] : (($redirect === "{$phpbb_root_path}index.$phpEx" || $redirect === "index.$phpEx") ? $user->lang['RETURN_INDEX'] : $user->lang['RETURN_PAGE']); + + // append/replace SID (may change during the session for AOL users) + $redirect = 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'] != USER_FOUNDER) + { + return; + } + + $redirect = 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($config['captcha_plugin']); + $captcha->init(CONFIRM_LOGIN); + // $captcha->reset(); + + $template->assign_vars(array( + 'CAPTCHA_TEMPLATE' => $captcha->get_template(), + )); + + $err = $user->lang[$result['error_msg']]; + break; + + case LOGIN_ERROR_PASSWORD_CONVERT: + $err = sprintf( + $user->lang[$result['error_msg']], + ($config['email_enable']) ? '<a href="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=sendpassword') . '">' : '', + ($config['email_enable']) ? '</a>' : '', + ($config['board_contact']) ? '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">' : '', + ($config['board_contact']) ? '</a>' : '' + ); + break; + + // Username, password, etc... + default: + $err = $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 = (!$config['board_contact']) ? sprintf($user->lang[$result['error_msg']], '', '') : sprintf($user->lang[$result['error_msg']], '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'); + } + + break; + } + } + + // Assign credential for username/password pair + $credential = ($admin) ? md5(unique_id()) : false; + + $s_hidden_fields = array( + 'sid' => $user->session_id, + ); + + if ($redirect) + { + $s_hidden_fields['redirect'] = $redirect; + } + + if ($admin) + { + $s_hidden_fields['credential'] = $credential; + } + + $s_hidden_fields = build_hidden_fields($s_hidden_fields); + + $template->assign_vars(array( + 'LOGIN_ERROR' => $err, + 'LOGIN_EXPLAIN' => $l_explain, + + 'U_SEND_PASSWORD' => ($config['email_enable']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=sendpassword') : '', + 'U_RESEND_ACTIVATION' => ($config['require_activation'] == USER_ACTIVATION_SELF && $config['email_enable']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=resend_act') : '', + 'U_TERMS_USE' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=terms'), + 'U_PRIVACY' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=privacy'), + + 'S_DISPLAY_FULL_LOGIN' => ($s_display) ? true : false, + 'S_HIDDEN_FIELDS' => $s_hidden_fields, + + 'S_ADMIN_AUTH' => $admin, + 'USERNAME' => ($admin) ? $user->data['username'] : '', + + 'USERNAME_CREDENTIAL' => 'username', + 'PASSWORD_CREDENTIAL' => ($admin) ? 'password_' . $credential : 'password', + )); + + page_header($user->lang['LOGIN'], false); + + $template->set_filenames(array( + 'body' => 'login_body.html') + ); + make_jumpbox(append_sid("{$phpbb_root_path}viewforum.$phpEx")); + + page_footer(); +} + +/** +* Generate forum login box +*/ +function login_forum_box($forum_data) +{ + global $db, $config, $user, $template, $phpEx; + + $password = request_var('password', '', true); + + $sql = 'SELECT forum_id + FROM ' . FORUMS_ACCESS_TABLE . ' + WHERE forum_id = ' . $forum_data['forum_id'] . ' + AND user_id = ' . $user->data['user_id'] . " + AND session_id = '" . $db->sql_escape($user->session_id) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $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 = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + $sql_in = array(); + do + { + $sql_in[] = (string) $row['session_id']; + } + while ($row = $db->sql_fetchrow($result)); + + // Remove expired sessions + $sql = 'DELETE FROM ' . FORUMS_ACCESS_TABLE . ' + WHERE ' . $db->sql_in_set('session_id', $sql_in); + $db->sql_query($sql); + } + $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) $user->data['user_id'], + 'session_id' => (string) $user->session_id, + ); + + $db->sql_query('INSERT INTO ' . FORUMS_ACCESS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + + return true; + } + + $template->assign_var('LOGIN_ERROR', $user->lang['WRONG_PASSWORD']); + } + + page_header($user->lang['LOGIN'], false); + + $template->assign_vars(array( + 'S_LOGIN_ACTION' => build_url(array('f')), + 'S_HIDDEN_FIELDS' => build_hidden_fields(array('f' => $forum_data['forum_id']))) + ); + + $template->set_filenames(array( + 'body' => 'login_forum.html') + ); + + page_footer(); +} + +// Little helpers + +/** +* Little helper for the build_hidden_fields function +*/ +function _build_hidden_fields($key, $value, $specialchar, $stripslashes) +{ + $hidden_fields = ''; + + if (!is_array($value)) + { + $value = ($stripslashes) ? stripslashes($value) : $value; + $value = ($specialchar) ? htmlspecialchars($value, ENT_COMPAT, 'UTF-8') : $value; + + $hidden_fields .= '<input type="hidden" name="' . $key . '" value="' . $value . '" />' . "\n"; + } + else + { + foreach ($value as $_key => $_value) + { + $_key = ($stripslashes) ? stripslashes($_key) : $_key; + $_key = ($specialchar) ? htmlspecialchars($_key, ENT_COMPAT, 'UTF-8') : $_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 +*/ +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) ? htmlspecialchars($name, ENT_COMPAT, 'UTF-8') : $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 +*/ +function add_log() +{ + global $db, $user; + + // In phpBB 3.1.x i want to have logging in a class to be able to control it + // For now, we need a quite hakish approach to circumvent logging for some actions + // @todo implement cleanly + if (!empty($GLOBALS['skip_add_log'])) + { + return false; + } + + $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($user->data)) ? ANONYMOUS : $user->data['user_id'], + 'log_ip' => $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; + } + + $db->sql_query('INSERT INTO ' . LOG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + + return $db->sql_nextid(); +} + +/** +* Return a nicely formatted backtrace (parts from the php manual by diz at ysagoon dot com) +*/ +function get_backtrace() +{ + global $phpbb_root_path; + + $output = '<div style="font-family: monospace;">'; + $backtrace = debug_backtrace(); + $path = phpbb_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; + } + + // 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 +*/ +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 +*/ +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 $cache, $db, $auth, $template, $config, $user; + global $phpEx, $phpbb_root_path, $msg_title, $msg_long_text; + + // Do not display notices if we suppress them via @ + if (error_reporting() == 0 && $errno != E_USER_ERROR && $errno != E_USER_WARNING && $errno != E_USER_NOTICE) + { + return; + } + + // Message handler is stripping text. In case we need it, we are possible to define long text... + if (isset($msg_long_text) && $msg_long_text && !$msg_text) + { + $msg_text = $msg_long_text; + } + + if (!defined('E_DEPRECATED')) + { + define('E_DEPRECATED', 8192); + } + + switch ($errno) + { + case E_NOTICE: + case E_WARNING: + + // 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 & ((defined('DEBUG')) ? E_ALL : 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($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 + $errfile = str_replace(array(phpbb_realpath($phpbb_root_path), '\\'), array('', '/'), $errfile); + $msg_text = str_replace(array(phpbb_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"; + + // we are writing an image - the user won't see the debug, so let's place it in the log + if (defined('IMAGE_OUTPUT') || defined('IN_CRON')) + { + add_log('critical', 'LOG_IMAGE_GENERATION_ERROR', $errfile, $errline, $msg_text); + } + // echo '<br /><br />BACKTRACE<br />' . get_backtrace() . '<br />' . "\n"; + } + + return; + + break; + + case E_USER_ERROR: + + if (!empty($user) && !empty($user->lang)) + { + $msg_text = (!empty($user->lang[$msg_text])) ? $user->lang[$msg_text] : $msg_text; + $msg_title = (!isset($msg_title)) ? $user->lang['GENERAL_ERROR'] : ((!empty($user->lang[$msg_title])) ? $user->lang[$msg_title] : $msg_title); + + $l_return_index = sprintf($user->lang['RETURN_INDEX'], '<a href="' . $phpbb_root_path . '">', '</a>'); + $l_notify = ''; + + if (!empty($config['board_contact'])) + { + $l_notify = '<p>' . sprintf($user->lang['NOTIFY_ADMIN_EMAIL'], $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($config['board_contact'])) + { + $l_notify = '<p>Please notify the board administrator or webmaster: <a href="mailto:' . $config['board_contact'] . '">' . $config['board_contact'] . '</a></p>'; + } + } + + if (defined('DEBUG') || defined('IN_CRON') || defined('IMAGE_OUTPUT')) + { + // let's avoid loops + $db->sql_return_on_error(true); + add_log('critical', 'LOG_GENERAL_ERROR', $msg_title, $msg_text); + $db->sql_return_on_error(false); + } + + // Do not send 200 OK, but service unavailable on errors + header('HTTP/1.1 503 Service Unavailable'); + + garbage_collection(); + + // Try to not call the adm page data... + + 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 . '</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($user->data)) + { + $user->session_begin(); + } + + // We re-init the auth array to get correct results on login/logout + $auth->acl($user->data); + + if (empty($user->lang)) + { + $user->setup(); + } + + $msg_text = (!empty($user->lang[$msg_text])) ? $user->lang[$msg_text] : $msg_text; + $msg_title = (!isset($msg_title)) ? $user->lang['INFORMATION'] : ((!empty($user->lang[$msg_title])) ? $user->lang[$msg_title] : $msg_title); + + if (!defined('HEADER_INC')) + { + if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin']) + { + adm_page_header($msg_title); + } + else + { + page_header($msg_title, false); + } + } + + $template->set_filenames(array( + 'body' => 'message_body.html') + ); + + $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); + + if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin']) + { + adm_page_footer(); + } + else + { + page_footer(); + } + + exit_handler(); + break; + + // PHP4 compatibility + case E_DEPRECATED: + return true; + 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; +} + +/** +* Queries the session table to get information about online guests +* @param int $item_id Limits the search to the item with this id +* @param string $item The name of the item which is stored in the session table as session_{$item}_id +* @return int The number of active distinct guest sessions +*/ +function obtain_guest_count($item_id = 0, $item = 'forum') +{ + global $db, $config; + + if ($item_id) + { + $reading_sql = ' AND s.session_' . $item . '_id = ' . (int) $item_id; + } + else + { + $reading_sql = ''; + } + $time = (time() - (intval($config['load_online_time']) * 60)); + + // Get number of online guests + + if ($db->sql_layer === 'sqlite') + { + $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 - ((int) ($time % 60))) . + $reading_sql . + ')'; + } + else + { + $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 - ((int) ($time % 60))) . + $reading_sql; + } + $result = $db->sql_query($sql); + $guests_online = (int) $db->sql_fetchfield('num_guests'); + $db->sql_freeresult($result); + + return $guests_online; +} + +/** +* Queries the session table to get information about online users +* @param int $item_id Limits the search to the item with this id +* @param string $item The name of the item which is stored in the session table as session_{$item}_id +* @return array An array containing the ids of online, hidden and visible users, as well as statistical info +*/ +function obtain_users_online($item_id = 0, $item = 'forum') +{ + global $db, $config, $user; + + $reading_sql = ''; + if ($item_id !== 0) + { + $reading_sql = ' AND s.session_' . $item . '_id = ' . (int) $item_id; + } + + $online_users = array( + 'online_users' => array(), + 'hidden_users' => array(), + 'total_online' => 0, + 'visible_online' => 0, + 'hidden_online' => 0, + 'guests_online' => 0, + ); + + if ($config['load_online_guests']) + { + $online_users['guests_online'] = obtain_guest_count($item_id, $item); + } + + // a little discrete magic to cache this for 30 seconds + $time = (time() - (intval($config['load_online_time']) * 60)); + + $sql = 'SELECT s.session_user_id, s.session_ip, s.session_viewonline + FROM ' . SESSIONS_TABLE . ' s + WHERE s.session_time >= ' . ($time - ((int) ($time % 30))) . + $reading_sql . + ' AND s.session_user_id <> ' . ANONYMOUS; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + // Skip multiple sessions for one user + if (!isset($online_users['online_users'][$row['session_user_id']])) + { + $online_users['online_users'][$row['session_user_id']] = (int) $row['session_user_id']; + if ($row['session_viewonline']) + { + $online_users['visible_online']++; + } + else + { + $online_users['hidden_users'][$row['session_user_id']] = (int) $row['session_user_id']; + $online_users['hidden_online']++; + } + } + } + $online_users['total_online'] = $online_users['guests_online'] + $online_users['visible_online'] + $online_users['hidden_online']; + $db->sql_freeresult($result); + + return $online_users; +} + +/** +* Uses the result of obtain_users_online to generate a localized, readable representation. +* @param mixed $online_users result of obtain_users_online - array with user_id lists for total, hidden and visible users, and statistics +* @param int $item_id Indicate that the data is limited to one item and not global +* @param string $item The name of the item which is stored in the session table as session_{$item}_id +* @return array An array containing the string for output to the template +*/ +function obtain_users_online_string($online_users, $item_id = 0, $item = 'forum') +{ + global $config, $db, $user, $auth; + + $user_online_link = $online_userlist = ''; + // Need caps version of $item for language-strings + $item_caps = strtoupper($item); + + if (sizeof($online_users['online_users'])) + { + $sql = 'SELECT username, username_clean, user_id, user_type, user_allow_viewonline, user_colour + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', $online_users['online_users']) . ' + ORDER BY username_clean ASC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + // User is logged in and therefore not a guest + if ($row['user_id'] != ANONYMOUS) + { + if (isset($online_users['hidden_users'][$row['user_id']])) + { + $row['username'] = '<em>' . $row['username'] . '</em>'; + } + + if (!isset($online_users['hidden_users'][$row['user_id']]) || $auth->acl_get('u_viewonline')) + { + $user_online_link = get_username_string(($row['user_type'] <> USER_IGNORE) ? 'full' : 'no_profile', $row['user_id'], $row['username'], $row['user_colour']); + $online_userlist .= ($online_userlist != '') ? ', ' . $user_online_link : $user_online_link; + } + } + } + $db->sql_freeresult($result); + } + + if (!$online_userlist) + { + $online_userlist = $user->lang['NO_ONLINE_USERS']; + } + + if ($item_id === 0) + { + $online_userlist = $user->lang['REGISTERED_USERS'] . ' ' . $online_userlist; + } + else if ($config['load_online_guests']) + { + $l_online = ($online_users['guests_online'] === 1) ? $user->lang['BROWSING_' . $item_caps . '_GUEST'] : $user->lang['BROWSING_' . $item_caps . '_GUESTS']; + $online_userlist = sprintf($l_online, $online_userlist, $online_users['guests_online']); + } + else + { + $online_userlist = sprintf($user->lang['BROWSING_' . $item_caps], $online_userlist); + } + // Build online listing + $vars_online = array( + 'ONLINE' => array('total_online', 'l_t_user_s', 0), + 'REG' => array('visible_online', 'l_r_user_s', !$config['load_online_guests']), + 'HIDDEN' => array('hidden_online', 'l_h_user_s', $config['load_online_guests']), + 'GUEST' => array('guests_online', 'l_g_user_s', 0) + ); + + foreach ($vars_online as $l_prefix => $var_ary) + { + if ($var_ary[2]) + { + $l_suffix = '_AND'; + } + else + { + $l_suffix = ''; + } + switch ($online_users[$var_ary[0]]) + { + case 0: + ${$var_ary[1]} = $user->lang[$l_prefix . '_USERS_ZERO_TOTAL' . $l_suffix]; + break; + + case 1: + ${$var_ary[1]} = $user->lang[$l_prefix . '_USER_TOTAL' . $l_suffix]; + break; + + default: + ${$var_ary[1]} = $user->lang[$l_prefix . '_USERS_TOTAL' . $l_suffix]; + break; + } + } + unset($vars_online); + + $l_online_users = sprintf($l_t_user_s, $online_users['total_online']); + $l_online_users .= sprintf($l_r_user_s, $online_users['visible_online']); + $l_online_users .= sprintf($l_h_user_s, $online_users['hidden_online']); + + if ($config['load_online_guests']) + { + $l_online_users .= sprintf($l_g_user_s, $online_users['guests_online']); + } + + + + return array( + 'online_userlist' => $online_userlist, + 'l_online_users' => $l_online_users, + ); +} + +/** +* Get option bitfield from custom data +* +* @param int $bit The bit/value to get +* @param int $data Current bitfield to check +* @return bool Returns true if value of constant is set in bitfield, else false +*/ +function phpbb_optionget($bit, $data) +{ + return ($data & 1 << (int) $bit) ? true : false; +} + +/** +* Set option bitfield +* +* @param int $bit The bit/value to set/unset +* @param bool $set True if option should be set, false if option should be unset. +* @param int $data Current bitfield to change +* +* @return int The new bitfield +*/ +function phpbb_optionset($bit, $set, $data) +{ + if ($set && !($data & 1 << $bit)) + { + $data += 1 << $bit; + } + else if (!$set && ($data & 1 << $bit)) + { + $data -= 1 << $bit; + } + + return $data; +} + +/** +* Generate page header +*/ +function page_header($page_title = '', $display_online_list = true, $item_id = 0, $item = 'forum') +{ + global $db, $config, $template, $SID, $_SID, $user, $auth, $phpEx, $phpbb_root_path; + + if (defined('HEADER_INC')) + { + return; + } + + define('HEADER_INC', true); + + // gzip_compression + if ($config['gzip_compress']) + { + if (@extension_loaded('zlib') && !headers_sent()) + { + ob_start('ob_gzhandler'); + } + } + + // Generate logged in/logged out status + if ($user->data['user_id'] != ANONYMOUS) + { + $u_login_logout = append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=logout', true, $user->session_id); + $l_login_logout = sprintf($user->lang['LOGOUT_USER'], $user->data['username']); + } + else + { + $u_login_logout = append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login'); + $l_login_logout = $user->lang['LOGIN']; + } + + // Last visit date/time + $s_last_visit = ($user->data['user_id'] != ANONYMOUS) ? $user->format_date($user->data['session_last_visit']) : ''; + + // Get users online list ... if required + $l_online_users = $online_userlist = $l_online_record = ''; + + if ($config['load_online'] && $config['load_online_time'] && $display_online_list) + { + /** + * Load online data: + * For obtaining another session column use $item and $item_id in the function-parameter, whereby the column is session_{$item}_id. + */ + $item_id = max($item_id, 0); + + $online_users = obtain_users_online($item_id, $item); + $user_online_strings = obtain_users_online_string($online_users, $item_id, $item); + + $l_online_users = $user_online_strings['l_online_users']; + $online_userlist = $user_online_strings['online_userlist']; + $total_online_users = $online_users['total_online']; + + if ($total_online_users > $config['record_online_users']) + { + set_config('record_online_users', $total_online_users, true); + set_config('record_online_date', time(), true); + } + + $l_online_record = sprintf($user->lang['RECORD_ONLINE_USERS'], $config['record_online_users'], $user->format_date($config['record_online_date'])); + + $l_online_time = ($config['load_online_time'] == 1) ? 'VIEW_ONLINE_TIME' : 'VIEW_ONLINE_TIMES'; + $l_online_time = sprintf($user->lang[$l_online_time], $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($user->data['is_registered'])) + { + if ($user->data['user_new_privmsg']) + { + $l_message_new = ($user->data['user_new_privmsg'] == 1) ? $user->lang['NEW_PM'] : $user->lang['NEW_PMS']; + $l_privmsgs_text = sprintf($l_message_new, $user->data['user_new_privmsg']); + + if (!$user->data['user_last_privmsg'] || $user->data['user_last_privmsg'] > $user->data['session_last_visit']) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_last_privmsg = ' . $user->data['session_last_visit'] . ' + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + + $s_privmsg_new = true; + } + else + { + $s_privmsg_new = false; + } + } + else + { + $l_privmsgs_text = $user->lang['NO_NEW_PM']; + $s_privmsg_new = false; + } + + $l_privmsgs_text_unread = ''; + + if ($user->data['user_unread_privmsg'] && $user->data['user_unread_privmsg'] != $user->data['user_new_privmsg']) + { + $l_message_unread = ($user->data['user_unread_privmsg'] == 1) ? $user->lang['UNREAD_PM'] : $user->lang['UNREAD_PMS']; + $l_privmsgs_text_unread = sprintf($l_message_unread, $user->data['user_unread_privmsg']); + } + } + + $forum_id = request_var('f', 0); + $topic_id = request_var('t', 0); + + $s_feed_news = false; + + // Get option for news + if ($config['feed_enable']) + { + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_bit_and('forum_options', FORUM_OPTION_FEED_NEWS, '<> 0'); + $result = $db->sql_query_limit($sql, 1, 0, 600); + $s_feed_news = (int) $db->sql_fetchfield('forum_id'); + $db->sql_freeresult($result); + } + + // Determine board url - we may need it later + $board_url = generate_board_url() . '/'; + $web_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? $board_url : $phpbb_root_path; + + // Which timezone? + $tz = ($user->data['user_id'] != ANONYMOUS) ? strval(doubleval($user->data['user_timezone'])) : strval(doubleval($config['board_timezone'])); + + // Send a proper content-language to the output + $user_lang = $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. + $template->assign_vars(array( + 'SITENAME' => $config['sitename'], + 'SITE_DESCRIPTION' => $config['site_desc'], + 'PAGE_TITLE' => $page_title, + 'SCRIPT_NAME' => str_replace('.' . $phpEx, '', $user->page['page_name']), + 'LAST_VISIT_DATE' => sprintf($user->lang['YOU_LAST_VISIT'], $s_last_visit), + 'LAST_VISIT_YOU' => $s_last_visit, + 'CURRENT_TIME' => sprintf($user->lang['CURRENT_TIME'], $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' => $user->data['user_new_privmsg'], + 'S_USER_UNREAD_PRIVMSG' => $user->data['user_unread_privmsg'], + 'S_USER_NEW' => $user->data['user_new'], + + 'SID' => $SID, + '_SID' => $_SID, + 'SESSION_ID' => $user->session_id, + 'ROOT_PATH' => $phpbb_root_path, + 'BOARD_URL' => $board_url, + + 'L_LOGIN_LOGOUT' => $l_login_logout, + 'L_INDEX' => $user->lang['FORUM_INDEX'], + 'L_ONLINE_EXPLAIN' => $l_online_time, + + 'U_PRIVATEMSGS' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=inbox'), + 'U_RETURN_INBOX' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=inbox'), + 'U_POPUP_PM' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&mode=popup'), + 'UA_POPUP_PM' => addslashes(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&mode=popup')), + 'U_MEMBERLIST' => append_sid("{$phpbb_root_path}memberlist.$phpEx"), + 'U_VIEWONLINE' => ($auth->acl_gets('u_viewprofile', 'a_user', 'a_useradd', 'a_userdel')) ? append_sid("{$phpbb_root_path}viewonline.$phpEx") : '', + 'U_LOGIN_LOGOUT' => $u_login_logout, + 'U_INDEX' => append_sid("{$phpbb_root_path}index.$phpEx"), + 'U_SEARCH' => append_sid("{$phpbb_root_path}search.$phpEx"), + 'U_REGISTER' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register'), + 'U_PROFILE' => append_sid("{$phpbb_root_path}ucp.$phpEx"), + 'U_MODCP' => append_sid("{$phpbb_root_path}mcp.$phpEx", false, true, $user->session_id), + 'U_FAQ' => append_sid("{$phpbb_root_path}faq.$phpEx"), + 'U_SEARCH_SELF' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=egosearch'), + 'U_SEARCH_NEW' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=newposts'), + 'U_SEARCH_UNANSWERED' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=unanswered'), + 'U_SEARCH_UNREAD' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=unreadposts'), + 'U_SEARCH_ACTIVE_TOPICS'=> append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=active_topics'), + 'U_DELETE_COOKIES' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=delete_cookies'), + 'U_TEAM' => ($user->data['user_id'] != ANONYMOUS && !$auth->acl_get('u_viewprofile')) ? '' : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=leaders'), + 'U_TERMS_USE' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=terms'), + 'U_PRIVACY' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=privacy'), + 'U_RESTORE_PERMISSIONS' => ($user->data['user_perm_from'] && $auth->acl_get('a_switchperm')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=restore_perm') : '', + 'U_FEED' => generate_board_url() . "/feed.$phpEx", + + 'S_USER_LOGGED_IN' => ($user->data['user_id'] != ANONYMOUS) ? true : false, + 'S_AUTOLOGIN_ENABLED' => ($config['allow_autologin']) ? true : false, + 'S_BOARD_DISABLED' => ($config['board_disable']) ? true : false, + 'S_REGISTERED_USER' => (!empty($user->data['is_registered'])) ? true : false, + 'S_IS_BOT' => (!empty($user->data['is_bot'])) ? true : false, + 'S_USER_PM_POPUP' => $user->optionget('popuppm'), + 'S_USER_LANG' => $user_lang, + 'S_USER_BROWSER' => (isset($user->data['session_browser'])) ? $user->data['session_browser'] : $user->lang['UNKNOWN_BROWSER'], + 'S_USERNAME' => $user->data['username'], + 'S_CONTENT_DIRECTION' => $user->lang['DIRECTION'], + 'S_CONTENT_FLOW_BEGIN' => ($user->lang['DIRECTION'] == 'ltr') ? 'left' : 'right', + 'S_CONTENT_FLOW_END' => ($user->lang['DIRECTION'] == 'ltr') ? 'right' : 'left', + 'S_CONTENT_ENCODING' => 'UTF-8', + 'S_TIMEZONE' => ($user->data['user_dst'] || ($user->data['user_id'] == ANONYMOUS && $config['board_dst'])) ? sprintf($user->lang['ALL_TIMES'], $user->lang['tz'][$tz], $user->lang['tz']['dst']) : sprintf($user->lang['ALL_TIMES'], $user->lang['tz'][$tz], ''), + 'S_DISPLAY_ONLINE_LIST' => ($l_online_time) ? 1 : 0, + 'S_DISPLAY_SEARCH' => (!$config['load_search']) ? 0 : (isset($auth) ? ($auth->acl_get('u_search') && $auth->acl_getf_global('f_search')) : 1), + 'S_DISPLAY_PM' => ($config['allow_privmsg'] && !empty($user->data['is_registered']) && ($auth->acl_get('u_readpm') || $auth->acl_get('u_sendpm'))) ? true : false, + 'S_DISPLAY_MEMBERLIST' => (isset($auth)) ? $auth->acl_get('u_viewprofile') : 0, + 'S_NEW_PM' => ($s_privmsg_new) ? 1 : 0, + 'S_REGISTER_ENABLED' => ($config['require_activation'] != USER_ACTIVATION_DISABLE) ? true : false, + 'S_FORUM_ID' => $forum_id, + 'S_TOPIC_ID' => $topic_id, + + 'S_LOGIN_ACTION' => (!defined('ADMIN_START')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login') . '&redirect=' . urlencode(str_replace('&', '&', build_url())) : append_sid("index.$phpEx", false, true, $user->session_id) . '&redirect=' . urlencode(str_replace('&', '&', build_url())), + + 'S_ENABLE_FEEDS' => ($config['feed_enable']) ? true : false, + 'S_ENABLE_FEEDS_FORUMS' => ($config['feed_overall_forums']) ? true : false, + 'S_ENABLE_FEEDS_TOPICS' => ($config['feed_overall_topics']) ? true : false, + 'S_ENABLE_FEEDS_NEWS' => ($s_feed_news) ? true : false, + + 'T_THEME_PATH' => "{$web_path}styles/" . $user->theme['theme_path'] . '/theme', + 'T_TEMPLATE_PATH' => "{$web_path}styles/" . $user->theme['template_path'] . '/template', + 'T_SUPER_TEMPLATE_PATH' => (isset($user->theme['template_inherit_path']) && $user->theme['template_inherit_path']) ? "{$web_path}styles/" . $user->theme['template_inherit_path'] . '/template' : "{$web_path}styles/" . $user->theme['template_path'] . '/template', + 'T_IMAGESET_PATH' => "{$web_path}styles/" . $user->theme['imageset_path'] . '/imageset', + 'T_IMAGESET_LANG_PATH' => "{$web_path}styles/" . $user->theme['imageset_path'] . '/imageset/' . $user->data['user_lang'], + 'T_IMAGES_PATH' => "{$web_path}images/", + 'T_SMILIES_PATH' => "{$web_path}{$config['smilies_path']}/", + 'T_AVATAR_PATH' => "{$web_path}{$config['avatar_path']}/", + 'T_AVATAR_GALLERY_PATH' => "{$web_path}{$config['avatar_gallery_path']}/", + 'T_ICONS_PATH' => "{$web_path}{$config['icons_path']}/", + 'T_RANKS_PATH' => "{$web_path}{$config['ranks_path']}/", + 'T_UPLOAD_PATH' => "{$web_path}{$config['upload_path']}/", + 'T_STYLESHEET_LINK' => (!$user->theme['theme_storedb']) ? "{$web_path}styles/" . $user->theme['theme_path'] . '/theme/stylesheet.css' : append_sid("{$phpbb_root_path}style.$phpEx", 'id=' . $user->theme['style_id'] . '&lang=' . $user->data['user_lang']), + 'T_STYLESHEET_NAME' => $user->theme['theme_name'], + + 'T_THEME_NAME' => $user->theme['theme_path'], + 'T_TEMPLATE_NAME' => $user->theme['template_path'], + 'T_SUPER_TEMPLATE_NAME' => (isset($user->theme['template_inherit_path']) && $user->theme['template_inherit_path']) ? $user->theme['template_inherit_path'] : $user->theme['template_path'], + 'T_IMAGESET_NAME' => $user->theme['imageset_path'], + 'T_IMAGESET_LANG_NAME' => $user->data['user_lang'], + 'T_IMAGES' => 'images', + 'T_SMILIES' => $config['smilies_path'], + 'T_AVATAR' => $config['avatar_path'], + 'T_AVATAR_GALLERY' => $config['avatar_gallery_path'], + 'T_ICONS' => $config['icons_path'], + 'T_RANKS' => $config['ranks_path'], + 'T_UPLOAD' => $config['upload_path'], + + 'SITE_LOGO_IMG' => $user->img('site_logo'), + + 'A_COOKIE_SETTINGS' => addslashes('; path=' . $config['cookie_path'] . ((!$config['cookie_domain'] || $config['cookie_domain'] == 'localhost' || $config['cookie_domain'] == '127.0.0.1') ? '' : '; domain=' . $config['cookie_domain']) . ((!$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'); + + return; +} + +/** +* Generate page footer +*/ +function page_footer($run_cron = true) +{ + global $db, $config, $template, $user, $auth, $cache, $starttime, $phpbb_root_path, $phpEx; + + // Output page creation time + if (defined('DEBUG')) + { + $mtime = explode(' ', microtime()); + $totaltime = $mtime[0] + $mtime[1] - $starttime; + + if (!empty($_REQUEST['explain']) && $auth->acl_get('a_') && defined('DEBUG_EXTRA') && method_exists($db, 'sql_report')) + { + $db->sql_report('display'); + } + + $debug_output = sprintf('Time : %.3fs | ' . $db->sql_num_queries() . ' Queries | GZIP : ' . (($config['gzip_compress'] && @extension_loaded('zlib')) ? 'On' : 'Off') . (($user->load) ? ' | Load : ' . $user->load : ''), $totaltime); + + if ($auth->acl_get('a_') && defined('DEBUG_EXTRA')) + { + if (function_exists('memory_get_usage')) + { + if ($memory_usage = memory_get_usage()) + { + global $base_memory_usage; + $memory_usage -= $base_memory_usage; + $memory_usage = get_formatted_filesize($memory_usage); + + $debug_output .= ' | Memory Usage: ' . $memory_usage; + } + } + + $debug_output .= ' | <a href="' . build_url() . '&explain=1">Explain</a>'; + } + } + + $template->assign_vars(array( + 'DEBUG_OUTPUT' => (defined('DEBUG')) ? $debug_output : '', + 'TRANSLATION_INFO' => (!empty($user->lang['TRANSLATION_INFO'])) ? $user->lang['TRANSLATION_INFO'] : '', + + 'U_ACP' => ($auth->acl_get('a_') && !empty($user->data['is_registered'])) ? append_sid("{$phpbb_root_path}adm/index.$phpEx", false, true, $user->session_id) : '') + ); + + // Call cron-type script + $call_cron = false; + if (!defined('IN_CRON') && $run_cron && !$config['board_disable']) + { + $call_cron = true; + $time_now = (!empty($user->time_now) && is_int($user->time_now)) ? $user->time_now : time(); + + // Any old lock present? + if (!empty($config['cron_lock'])) + { + $cron_time = explode(' ', $config['cron_lock']); + + // If 1 hour lock is present we do not call cron.php + if ($cron_time[0] + 3600 >= $time_now) + { + $call_cron = false; + } + } + } + + // Call cron job? + if ($call_cron) + { + $cron_type = ''; + + if ($time_now - $config['queue_interval'] > $config['last_queue_run'] && !defined('IN_ADMIN') && file_exists($phpbb_root_path . 'cache/queue.' . $phpEx)) + { + // Process email queue + $cron_type = 'queue'; + } + else if (method_exists($cache, 'tidy') && $time_now - $config['cache_gc'] > $config['cache_last_gc']) + { + // Tidy the cache + $cron_type = 'tidy_cache'; + } + else if ($config['warnings_expire_days'] && ($time_now - $config['warnings_gc'] > $config['warnings_last_gc'])) + { + $cron_type = 'tidy_warnings'; + } + else if ($time_now - $config['database_gc'] > $config['database_last_gc']) + { + // Tidy the database + $cron_type = 'tidy_database'; + } + else if ($time_now - $config['search_gc'] > $config['search_last_gc']) + { + // Tidy the search + $cron_type = 'tidy_search'; + } + else if ($time_now - $config['session_gc'] > $config['session_last_gc']) + { + $cron_type = 'tidy_sessions'; + } + + if ($cron_type) + { + $template->assign_var('RUN_CRON_TASK', '<img src="' . append_sid($phpbb_root_path . 'cron.' . $phpEx, 'cron_type=' . $cron_type) . '" width="1" height="1" alt="cron" />'); + } + } + + $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() +{ + global $cache, $db; + + // Unload cache, must be done before the DB connection if closed + if (!empty($cache)) + { + $cache->unload(); + } + + // Close our DB connection. + if (!empty($db)) + { + $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() +{ + global $phpbb_hook, $config; + + if (!empty($phpbb_hook) && $phpbb_hook->call_hook(__FUNCTION__)) + { + if ($phpbb_hook->hook_return(__FUNCTION__)) + { + return $phpbb_hook->hook_return_result(__FUNCTION__); + } + } + + // As a pre-caution... some setups display a blank page if the flush() is not there. + (empty($config['gzip_compress'])) ? @flush() : @ob_flush(); + + exit; +} + +/** +* Handler for init calls in phpBB. This function is called in user::setup(); +* This function supports hooks. +*/ +function phpbb_user_session_handler() +{ + global $phpbb_hook; + + if (!empty($phpbb_hook) && $phpbb_hook->call_hook(__FUNCTION__)) + { + if ($phpbb_hook->hook_return(__FUNCTION__)) + { + return $phpbb_hook->hook_return_result(__FUNCTION__); + } + } + + return; +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php new file mode 100644 index 0000000000..c0db64dbfb --- /dev/null +++ b/phpBB/includes/functions_admin.php @@ -0,0 +1,3303 @@ +<?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 Nested Sets +* +* @param int $new_id first left_id (should start with 1) +* @param string $pkey primary key-column (containing the id for the parent_id of the children) +* @param string $table constant or fullname of the table +* @param int $parent_id parent_id of the current set (default = 0) +* @param array $where contains strings to compare closer on the where statement (additional) +* +* @author EXreaction +*/ +function recalc_nested_sets(&$new_id, $pkey, $table, $parent_id = 0, $where = array()) +{ + global $db; + + $sql = 'SELECT * + FROM ' . $table . ' + WHERE parent_id = ' . (int) $parent_id . + ((!empty($where)) ? ' AND ' . implode(' AND ', $where) : '') . ' + ORDER BY left_id ASC'; + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + // First we update the left_id for this module + if ($row['left_id'] != $new_id) + { + $db->sql_query('UPDATE ' . $table . ' SET ' . $db->sql_build_array('UPDATE', array('left_id' => $new_id)) . " WHERE $pkey = {$row[$pkey]}"); + } + $new_id++; + + // Then we go through any children and update their left/right id's + recalc_nested_sets($new_id, $pkey, $table, $row[$pkey], $where); + + // Then we come back and update the right_id for this module + if ($row['right_id'] != $new_id) + { + $db->sql_query('UPDATE ' . $table . ' SET ' . $db->sql_build_array('UPDATE', array('right_id' => $new_id)) . " WHERE $pkey = {$row[$pkey]}"); + } + $new_id++; + } + $db->sql_freeresult($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) +{ + global $db, $user, $auth; + + $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, forum_flags, forum_options, left_id, right_id + FROM ' . FORUMS_TABLE . ' + ORDER BY left_id ASC'; + $result = $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 = $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 && !$auth->acl_gets($acl, $row['forum_id'])) + { + // List permission? + if ($auth->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>'; + } + } + $db->sql_freeresult($result); + unset($padding_store); + + return $forum_list; +} + +/** +* Generate size select options +*/ +function size_select_options($size_compare) +{ + global $user; + + $size_types_text = array($user->lang['BYTES'], $user->lang['KIB'], $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) +{ + global $db, $user, $config; + + $exclude_sql = ($exclude_ids !== false && sizeof($exclude_ids)) ? 'WHERE ' . $db->sql_in_set('group_id', array_map('intval', $exclude_ids), true) : ''; + $sql_and = (!$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 = $db->sql_query($sql); + + $s_group_options = ''; + while ($row = $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) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>'; + } + $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) +{ + global $db, $auth; + 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 = $db->sql_query($sql, $expire_time); + + $forum_rows = array(); + + $right = $padding = 0; + $padding_store = array('0' => 0); + + while ($row = $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; + } + $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 != '' && $auth->acl_gets($acl_list, $row['forum_id']))) + { + $rowset[] = ($id_only) ? (int) $row['forum_id'] : $row; + } + } + + return $rowset; +} + +/** +* Get forum branch +*/ +function get_forum_branch($forum_id, $type = 'all', $order = 'descending', $include_forum = true) +{ + global $db; + + 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 = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if (!$include_forum && $row['forum_id'] == $forum_id) + { + continue; + } + + $rows[] = $row; + } + $db->sql_freeresult($result); + + return $rows; +} + +/** +* Copies permissions from one forum to others +* +* @param int $src_forum_id The source forum we want to copy permissions from +* @param array $dest_forum_ids The destination forum(s) we want to copy to +* @param bool $clear_dest_perms True if destination permissions should be deleted +* @param bool $add_log True if log entry should be added +* +* @return bool False on error +* +* @author bantu +*/ +function copy_forum_permissions($src_forum_id, $dest_forum_ids, $clear_dest_perms = true, $add_log = true) +{ + global $db; + + // Only one forum id specified + if (!is_array($dest_forum_ids)) + { + $dest_forum_ids = array($dest_forum_ids); + } + + // Make sure forum ids are integers + $src_forum_id = (int) $src_forum_id; + $dest_forum_ids = array_map('intval', $dest_forum_ids); + + // No source forum or no destination forums specified + if (empty($src_forum_id) || empty($dest_forum_ids)) + { + return false; + } + + // Check if source forum exists + $sql = 'SELECT forum_name + FROM ' . FORUMS_TABLE . ' + WHERE forum_id = ' . $src_forum_id; + $result = $db->sql_query($sql); + $src_forum_name = $db->sql_fetchfield('forum_name'); + $db->sql_freeresult($result); + + // Source forum doesn't exist + if (empty($src_forum_name)) + { + return false; + } + + // Check if destination forums exists + $sql = 'SELECT forum_id, forum_name + FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $dest_forum_ids); + $result = $db->sql_query($sql); + + $dest_forum_ids = $dest_forum_names = array(); + while ($row = $db->sql_fetchrow($result)) + { + $dest_forum_ids[] = (int) $row['forum_id']; + $dest_forum_names[] = $row['forum_name']; + } + $db->sql_freeresult($result); + + // No destination forum exists + if (empty($dest_forum_ids)) + { + return false; + } + + // From the mysql documentation: + // Prior to MySQL 4.0.14, the target table of the INSERT statement cannot appear + // in the FROM clause of the SELECT part of the query. This limitation is lifted in 4.0.14. + // Due to this we stay on the safe side if we do the insertion "the manual way" + + // Rowsets we're going to insert + $users_sql_ary = $groups_sql_ary = array(); + + // Query acl users table for source forum data + $sql = 'SELECT user_id, auth_option_id, auth_role_id, auth_setting + FROM ' . ACL_USERS_TABLE . ' + WHERE forum_id = ' . $src_forum_id; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $row = array( + 'user_id' => (int) $row['user_id'], + 'auth_option_id' => (int) $row['auth_option_id'], + 'auth_role_id' => (int) $row['auth_role_id'], + 'auth_setting' => (int) $row['auth_setting'], + ); + + foreach ($dest_forum_ids as $dest_forum_id) + { + $users_sql_ary[] = $row + array('forum_id' => $dest_forum_id); + } + } + $db->sql_freeresult($result); + + // Query acl groups table for source forum data + $sql = 'SELECT group_id, auth_option_id, auth_role_id, auth_setting + FROM ' . ACL_GROUPS_TABLE . ' + WHERE forum_id = ' . $src_forum_id; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $row = array( + 'group_id' => (int) $row['group_id'], + 'auth_option_id' => (int) $row['auth_option_id'], + 'auth_role_id' => (int) $row['auth_role_id'], + 'auth_setting' => (int) $row['auth_setting'], + ); + + foreach ($dest_forum_ids as $dest_forum_id) + { + $groups_sql_ary[] = $row + array('forum_id' => $dest_forum_id); + } + } + $db->sql_freeresult($result); + + $db->sql_transaction('begin'); + + // Clear current permissions of destination forums + if ($clear_dest_perms) + { + $sql = 'DELETE FROM ' . ACL_USERS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $dest_forum_ids); + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $dest_forum_ids); + $db->sql_query($sql); + } + + $db->sql_multi_insert(ACL_USERS_TABLE, $users_sql_ary); + $db->sql_multi_insert(ACL_GROUPS_TABLE, $groups_sql_ary); + + if ($add_log) + { + add_log('admin', 'LOG_FORUM_COPIED_PERMISSIONS', $src_forum_name, implode(', ', $dest_forum_names)); + } + + $db->sql_transaction('commit'); + + return true; +} + +/** +* Get physical file listing +*/ +function filelist($rootdir, $dir = '', $type = 'gif|jpg|jpeg|png') +{ + $matches = array($dir => 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) +{ + global $db; + + 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 ' . $db->sql_in_set('topic_moved_id', $topic_ids) . ' + AND forum_id = ' . $forum_id; + $db->sql_query($sql); + + if ($auto_sync) + { + $sql = 'SELECT DISTINCT forum_id + FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', $topic_ids); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $forum_ids[] = $row['forum_id']; + } + $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 " . $db->sql_in_set('topic_id', $topic_ids); + $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) +{ + global $db; + + 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 ' . $db->sql_in_set('post_id', $post_ids); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $forum_ids[] = $row['forum_id']; + $topic_ids[] = $row['topic_id']; + } + $db->sql_freeresult($result); + + $sql = 'SELECT forum_id + FROM ' . TOPICS_TABLE . ' + WHERE topic_id = ' . $topic_id; + $result = $db->sql_query($sql); + $forum_row = $db->sql_fetchrow($result); + $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 " . $db->sql_in_set('post_id', $post_ids); + $db->sql_query($sql); + + $sql = 'UPDATE ' . ATTACHMENTS_TABLE . " + SET topic_id = $topic_id, in_message = 0 + WHERE " . $db->sql_in_set('post_msg_id', $post_ids); + $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) +{ + global $db, $config; + + $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 = $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 = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $forum_ids[] = $row['forum_id']; + $topic_ids[] = $row['topic_id']; + + if ($row['topic_approved'] && !$row['topic_moved_id']) + { + $approved_topics++; + } + } + $db->sql_freeresult($result); + + $return['topics'] = sizeof($topic_ids); + + if (!sizeof($topic_ids)) + { + return $return; + } + + $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 " . $db->sql_in_set('topic_id', $topic_ids); + $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 ' . $db->sql_in_set('topic_moved_id', $topic_ids); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $forum_ids[] = $row['forum_id']; + $moved_topic_ids[] = $row['topic_id']; + } + $db->sql_freeresult($result); + + if (sizeof($moved_topic_ids)) + { + $sql = 'DELETE FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', $moved_topic_ids); + $db->sql_query($sql); + } + + $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) +{ + global $db, $config, $phpbb_root_path, $phpEx; + + 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); + +/* Possible code for splitting post deletion + if (sizeof($where_ids) >= 1001) + { + // Split into chunks of 1000 + $chunks = array_chunk($where_ids, 1000); + + foreach ($chunks as $_where_ids) + { + delete_posts($where_type, $_where_ids, $auto_sync, $posted_sync, $post_count_sync, $call_delete_topics); + } + + return; + }*/ + + $where_clause = $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 = $db->sql_query($sql); + + while ($row = $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++; + } + } + $db->sql_freeresult($result); + + if (!sizeof($post_ids)) + { + return false; + } + + $db->sql_transaction('begin'); + + $table_ary = array(POSTS_TABLE, REPORTS_TABLE); + + foreach ($table_ary as $table) + { + $sql = "DELETE FROM $table + WHERE " . $db->sql_in_set('post_id', $post_ids); + $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; + $db->sql_query($sql); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_posts = user_posts - ' . $substract . ' + WHERE user_id = ' . $poster_id . ' + AND user_posts >= ' . $substract; + $db->sql_query($sql); + } + } + + // Remove topics now having no posts? + if (sizeof($topic_ids)) + { + $sql = 'SELECT topic_id + FROM ' . POSTS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . ' + GROUP BY topic_id'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $remove_topics[] = $row['topic_id']; + } + $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($config['search_type']); + + if (!file_exists($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx)) + { + trigger_error('NO_SUCH_SEARCH_MODULE'); + } + + include_once("{$phpbb_root_path}includes/search/$search_type.$phpEx"); + + $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); + + $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) +{ + global $db, $config; + + 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 ' . $db->sql_in_set($sql_id, $ids); + + $sql .= $sql_where; + + $result = $db->sql_query($sql); + + while ($row = $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']); + } + $db->sql_freeresult($result); + + // Delete attachments + $sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . ' + WHERE ' . $db->sql_in_set($sql_id, $ids); + + $sql .= $sql_where; + + $db->sql_query($sql); + $num_deleted = $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)) + { + // Just check which posts are still having an assigned attachment not orphaned by querying the attachments table + $sql = 'SELECT post_msg_id + FROM ' . ATTACHMENTS_TABLE . ' + WHERE ' . $db->sql_in_set('post_msg_id', $post_ids) . ' + AND in_message = 0 + AND is_orphan = 0'; + $result = $db->sql_query($sql); + + $remaining_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $remaining_ids[] = $row['post_msg_id']; + } + $db->sql_freeresult($result); + + // Now only unset those ids remaining + $post_ids = array_diff($post_ids, $remaining_ids); + + if (sizeof($post_ids)) + { + $sql = 'UPDATE ' . POSTS_TABLE . ' + SET post_attachment = 0 + WHERE ' . $db->sql_in_set('post_id', $post_ids); + $db->sql_query($sql); + } + } + + // Update message table if messages are affected + if (sizeof($message_ids)) + { + // Just check which messages are still having an assigned attachment not orphaned by querying the attachments table + $sql = 'SELECT post_msg_id + FROM ' . ATTACHMENTS_TABLE . ' + WHERE ' . $db->sql_in_set('post_msg_id', $message_ids) . ' + AND in_message = 1 + AND is_orphan = 0'; + $result = $db->sql_query($sql); + + $remaining_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $remaining_ids[] = $row['post_msg_id']; + } + $db->sql_freeresult($result); + + // Now only unset those ids remaining + $message_ids = array_diff($message_ids, $remaining_ids); + + if (sizeof($message_ids)) + { + $sql = 'UPDATE ' . PRIVMSGS_TABLE . ' + SET message_attachment = 0 + WHERE ' . $db->sql_in_set('msg_id', $message_ids); + $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 ' . $db->sql_in_set('topic_id', $topic_ids) . ' + AND is_orphan = 0'; + $result = $db->sql_query($sql); + + $remaining_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $remaining_ids[] = $row['topic_id']; + } + $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 ' . $db->sql_in_set('topic_id', $topic_ids); + $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 ' . $db->sql_in_set('t.forum_id', array_map('intval', $forum_id)) : (($forum_id) ? 'AND t.forum_id = ' . (int) $forum_id : ''); + + switch ($db->sql_layer) + { + case 'mysql4': + case 'mysqli': + $sql = 'DELETE t.* + FROM ' . TOPICS_TABLE . ' t, ' . TOPICS_TABLE . ' t2 + WHERE t.topic_moved_id = t2.topic_id + AND t.topic_time < ' . (time() - $max_age) + . $where; + $db->sql_query($sql); + break; + + default: + $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 = $db->sql_query($sql); + + $topic_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $topic_ids[] = $row['topic_id']; + } + $db->sql_freeresult($result); + + if (sizeof($topic_ids)) + { + $sql = 'DELETE FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', $topic_ids); + $db->sql_query($sql); + } + break; + } + + 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) +{ + global $db, $config; + + if (empty($topic_ids) || !$config['load_db_track']) + { + return; + } + + // First of all, let us remove any posted information for these topics + $sql = 'DELETE FROM ' . TOPICS_POSTED_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', $topic_ids); + $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 ' . $db->sql_in_set('topic_id', $topic_ids) . ' + AND poster_id <> ' . ANONYMOUS . ' + GROUP BY poster_id, topic_id'; + $result = $db->sql_query($sql); + + $posted = array(); + while ($row = $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']; + } + $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); + + $db->sql_multi_insert(TOPICS_POSTED_TABLE, $sql_ary); +} + +/** +* Delete attached file +*/ +function phpbb_unlink($filename, $mode = 'file', $entry_removed = false) +{ + global $db, $phpbb_root_path, $config; + + // 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 = '" . $db->sql_escape(utf8_basename($filename)) . "'"; + $result = $db->sql_query($sql); + $num_entries = (int) $db->sql_fetchfield('num_entries'); + $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_' . utf8_basename($filename) : utf8_basename($filename); + return @unlink($phpbb_root_path . $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) +{ + global $db; + + 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 ' . $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 ' . $db->sql_in_set($mode[0] . '.' . $where_type, $where_ids); + $where_sql_and = $where_sql . "\n\tAND"; + } + + switch ($mode) + { + case 'topic_moved': + $db->sql_transaction('begin'); + switch ($db->sql_layer) + { + case 'mysql4': + case 'mysqli': + $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"; + $db->sql_query($sql); + break; + + default: + $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 = $db->sql_query($sql); + + $topic_id_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $topic_id_ary[] = $row['topic_id']; + } + $db->sql_freeresult($result); + + if (!sizeof($topic_id_ary)) + { + return; + } + + $sql = 'DELETE FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', $topic_id_ary); + $db->sql_query($sql); + + break; + } + + $db->sql_transaction('commit'); + break; + + case 'topic_approved': + + $db->sql_transaction('begin'); + switch ($db->sql_layer) + { + case 'mysql4': + case 'mysqli': + $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"; + $db->sql_query($sql); + break; + + default: + $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 = $db->sql_query($sql); + + $topic_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $topic_ids[] = $row['topic_id']; + } + $db->sql_freeresult($result); + + if (!sizeof($topic_ids)) + { + return; + } + + $sql = 'UPDATE ' . TOPICS_TABLE . ' + SET topic_approved = 1 - topic_approved + WHERE ' . $db->sql_in_set('topic_id', $topic_ids); + $db->sql_query($sql); + break; + } + + $db->sql_transaction('commit'); + break; + + case 'post_reported': + $post_ids = $post_reported = array(); + + $db->sql_transaction('begin'); + + $sql = 'SELECT p.post_id, p.post_reported + FROM ' . POSTS_TABLE . " p + $where_sql + GROUP BY p.post_id, p.post_reported"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $post_ids[$row['post_id']] = $row['post_id']; + if ($row['post_reported']) + { + $post_reported[$row['post_id']] = 1; + } + } + $db->sql_freeresult($result); + + $sql = 'SELECT DISTINCT(post_id) + FROM ' . REPORTS_TABLE . ' + WHERE ' . $db->sql_in_set('post_id', $post_ids) . ' + AND report_closed = 0'; + $result = $db->sql_query($sql); + + $post_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + if (!isset($post_reported[$row['post_id']])) + { + $post_ids[] = $row['post_id']; + } + else + { + unset($post_reported[$row['post_id']]); + } + } + $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 ' . $db->sql_in_set('post_id', $post_ids); + $db->sql_query($sql); + } + + $db->sql_transaction('commit'); + break; + + case 'topic_reported': + if ($sync_extra) + { + sync('post_reported', $where_type, $where_ids); + } + + $topic_ids = $topic_reported = array(); + + $db->sql_transaction('begin'); + + $sql = 'SELECT DISTINCT(t.topic_id) + FROM ' . POSTS_TABLE . " t + $where_sql_and t.post_reported = 1"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $topic_reported[$row['topic_id']] = 1; + } + $db->sql_freeresult($result); + + $sql = 'SELECT t.topic_id, t.topic_reported + FROM ' . TOPICS_TABLE . " t + $where_sql"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if ($row['topic_reported'] ^ isset($topic_reported[$row['topic_id']])) + { + $topic_ids[] = $row['topic_id']; + } + } + $db->sql_freeresult($result); + + if (sizeof($topic_ids)) + { + $sql = 'UPDATE ' . TOPICS_TABLE . ' + SET topic_reported = 1 - topic_reported + WHERE ' . $db->sql_in_set('topic_id', $topic_ids); + $db->sql_query($sql); + } + + $db->sql_transaction('commit'); + break; + + case 'post_attachment': + $post_ids = $post_attachment = array(); + + $db->sql_transaction('begin'); + + $sql = 'SELECT p.post_id, p.post_attachment + FROM ' . POSTS_TABLE . " p + $where_sql + GROUP BY p.post_id, p.post_attachment"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $post_ids[$row['post_id']] = $row['post_id']; + if ($row['post_attachment']) + { + $post_attachment[$row['post_id']] = 1; + } + } + $db->sql_freeresult($result); + + $sql = 'SELECT DISTINCT(post_msg_id) + FROM ' . ATTACHMENTS_TABLE . ' + WHERE ' . $db->sql_in_set('post_msg_id', $post_ids) . ' + AND in_message = 0'; + $result = $db->sql_query($sql); + + $post_ids = array(); + while ($row = $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']]); + } + } + $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 ' . $db->sql_in_set('post_id', $post_ids); + $db->sql_query($sql); + } + + $db->sql_transaction('commit'); + break; + + case 'topic_attachment': + if ($sync_extra) + { + sync('post_attachment', $where_type, $where_ids); + } + + $topic_ids = $topic_attachment = array(); + + $db->sql_transaction('begin'); + + $sql = 'SELECT DISTINCT(t.topic_id) + FROM ' . POSTS_TABLE . " t + $where_sql_and t.post_attachment = 1"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $topic_attachment[$row['topic_id']] = 1; + } + $db->sql_freeresult($result); + + $sql = 'SELECT t.topic_id, t.topic_attachment + FROM ' . TOPICS_TABLE . " t + $where_sql"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if ($row['topic_attachment'] ^ isset($topic_attachment[$row['topic_id']])) + { + $topic_ids[] = $row['topic_id']; + } + } + $db->sql_freeresult($result); + + if (sizeof($topic_ids)) + { + $sql = 'UPDATE ' . TOPICS_TABLE . ' + SET topic_attachment = 1 - topic_attachment + WHERE ' . $db->sql_in_set('topic_id', $topic_ids); + $db->sql_query($sql); + } + + $db->sql_transaction('commit'); + + break; + + case 'forum': + + $db->sql_transaction('begin'); + + // 1: Get the list of all forums + $sql = 'SELECT f.* + FROM ' . FORUMS_TABLE . " f + $where_sql"; + $result = $db->sql_query($sql); + + $forum_data = $forum_ids = $post_ids = $last_post_id = $post_info = array(); + while ($row = $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'] = ''; + } + $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 ' . $db->sql_in_set('forum_id', $forum_ids) . ' + GROUP BY forum_id, topic_approved'; + $result = $db->sql_query($sql); + + while ($row = $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']; + } + } + $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 ' . $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 ' . $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 = $db->sql_query($sql); + + while ($row = $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']; + } + $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 ' . $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 ' . $db->sql_in_set('t.forum_id', $forum_ids) . ' + AND t.topic_approved = 1 + GROUP BY t.forum_id'; + } + + $result = $db->sql_query($sql); + + while ($row = $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']; + } + $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 ' . $db->sql_in_set('p.post_id', $post_ids) . ' + AND p.poster_id = u.user_id'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $post_info[$row['post_id']] = $row; + } + $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 ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE forum_id = ' . $forum_id; + $db->sql_query($sql); + } + } + + $db->sql_transaction('commit'); + break; + + case 'topic': + $topic_data = $post_ids = $approved_unapproved_ids = $resync_forums = $delete_topics = $delete_posts = $moved_topics = array(); + + $db->sql_transaction('begin'); + + $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 = $db->sql_query($sql); + + while ($row = $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; + } + } + $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 = $db->sql_query($sql); + + while ($row = $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']; + } + } + } + $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 ' . $db->sql_in_set('p.post_id', $post_ids) . ' + AND u.user_id = p.poster_id'; + $result = $db->sql_query($sql); + + $post_ids = array(); + while ($row = $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']; + } + } + $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 ' . $db->sql_in_set('t1.topic_id', $moved_topics) . ' + AND t2.topic_id IS NULL'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $delete_topics[] = $row['topic_id']; + } + $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 ' . $db->sql_in_set('topic_id', $moved_topics) . ' + AND topic_last_post_time = 0'; + $result = $db->sql_query($sql); + + $shadow_topic_data = $post_ids = array(); + while ($row = $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']; + } + $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 ' . $db->sql_in_set('p.post_id', $post_ids) . ' + AND u.user_id = p.poster_id'; + $result = $db->sql_query($sql); + + $post_ids = array(); + while ($row = $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']; + } + } + } + $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 ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE topic_id = ' . $sync_topic_id; + $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 ' . $db->sql_in_set('topic_id', $approved_unapproved_ids); + $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 = $db->sql_query($sql); + + $fieldnames[] = 'reported'; + while ($row = $db->sql_fetchrow($result)) + { + $topic_data[intval($row['topic_id'])]['reported'] = 1; + } + $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 = $db->sql_query($sql); + + $fieldnames[] = 'attachment'; + while ($row = $db->sql_fetchrow($result)) + { + $topic_data[intval($row['topic_id'])]['attachment'] = 1; + } + $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 ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE topic_id = ' . $topic_id; + $db->sql_query($sql); + + $resync_forums[$row['forum_id']] = $row['forum_id']; + } + } + unset($topic_data); + + $db->sql_transaction('commit'); + + // 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) +{ + global $db; + + 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 ' . $db->sql_in_set('forum_id', $forum_id) . " + AND poll_start = 0 + $sql_and"; + $result = $db->sql_query($sql); + + $topic_list = array(); + while ($row = $db->sql_fetchrow($result)) + { + $topic_list[] = $row['topic_id']; + } + $db->sql_freeresult($result); + + if ($prune_flags & FORUM_FLAG_PRUNE_POLL) + { + $sql = 'SELECT topic_id + FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_id) . " + AND poll_start > 0 + AND poll_last_vote < $prune_date + $sql_and"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $topic_list[] = $row['topic_id']; + } + $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) +{ + global $db; + + $sql = 'SELECT forum_name + FROM ' . FORUMS_TABLE . " + WHERE forum_id = $forum_id"; + $result = $db->sql_query($sql, 3600); + $row = $db->sql_fetchrow($result); + $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"; + $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() +{ + global $db, $cache, $auth, $phpbb_root_path, $phpEx; + + // Remove cached sql results + $cache->destroy('sql', MODERATOR_CACHE_TABLE); + + // Clear table + switch ($db->sql_layer) + { + case 'sqlite': + case 'firebird': + $db->sql_query('DELETE FROM ' . MODERATOR_CACHE_TABLE); + break; + + default: + $db->sql_query('TRUNCATE TABLE ' . MODERATOR_CACHE_TABLE); + break; + } + + // 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 = $auth->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 = $db->sql_build_query('SELECT', array( + 'SELECT' => 'a.forum_id, ug.user_id, g.group_id', + + 'FROM' => array( + ACL_OPTIONS_TABLE => 'o', + USER_GROUP_TABLE => 'ug', + ACL_GROUPS_TABLE => 'a', + GROUPS_TABLE => 'g', + ), + + '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 = ' . ACL_NEVER . ' AND r.auth_setting IS NULL) + OR r.auth_setting = ' . ACL_NEVER . ') + AND a.group_id = ug.group_id + AND g.group_id = ug.group_id + AND NOT (ug.group_leader = 1 AND g.group_skip_auth = 1) + AND ' . $db->sql_in_set('ug.user_id', $ug_id_ary) . " + AND ug.user_pending = 0 + AND o.auth_option " . $db->sql_like_expression('m_' . $db->any_char), + )); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if (isset($hold_ary[$row['user_id']][$row['forum_id']])) + { + unset($hold_ary[$row['user_id']][$row['forum_id']]); + } + } + $db->sql_freeresult($result); + + if (sizeof($hold_ary)) + { + // Get usernames... + $sql = 'SELECT user_id, username + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', array_keys($hold_ary)); + $result = $db->sql_query($sql); + + $usernames_ary = array(); + while ($row = $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 = $auth->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 ' . $db->sql_in_set('group_id', $ug_id_ary); + $result = $db->sql_query($sql); + + $groupnames_ary = array(); + while ($row = $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']; + } + $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 == 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] + ); + } + } + } + + $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', $keywords = '') +{ + global $db, $user, $auth, $phpEx, $phpbb_root_path, $phpbb_admin_path; + + $topic_id_list = $reportee_id_list = $is_auth = $is_mod = array(); + + $profile_url = (defined('IN_ADMIN')) ? append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&mode=overview') : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile'); + + switch ($mode) + { + case 'admin': + $log_type = LOG_ADMIN; + $sql_forum = ''; + break; + + case 'mod': + $log_type = LOG_MOD; + $sql_forum = ''; + + if ($topic_id) + { + $sql_forum = 'AND l.topic_id = ' . (int) $topic_id; + } + else if (is_array($forum_id)) + { + $sql_forum = 'AND ' . $db->sql_in_set('l.forum_id', array_map('intval', $forum_id)); + } + else if ($forum_id) + { + $sql_forum = 'AND l.forum_id = ' . (int) $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; + } + + $keywords = preg_split('#[\s+\-|*()]+#u', utf8_strtolower(preg_quote($keywords, '#')), 0, PREG_SPLIT_NO_EMPTY); + $sql_keywords = ''; + + if (!empty($keywords)) + { + $keywords_pattern = '#' . implode('|', $keywords) . '#ui'; + for ($i = 0, $num_keywords = sizeof($keywords); $i < $num_keywords; $i++) + { + $keywords[$i] = $db->sql_like_expression($db->any_char . $keywords[$i] . $db->any_char); + } + + $operations = array(); + foreach ($user->lang as $key => $value) + { + if (substr($key, 0, 4) == 'LOG_' && preg_match($keywords_pattern, $value)) + { + $operations[] = $key; + } + } + + $sql_keywords = 'AND ('; + if (!empty($operations)) + { + $sql_keywords .= $db->sql_in_set('l.log_operation', $operations) . ' OR '; + } + $sql_keywords .= 'LOWER(l.log_data) ' . implode(' OR LOWER(l.log_data) ', $keywords) . ')'; + } + + $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_keywords + $sql_forum + ORDER BY $sort_by"; + $result = $db->sql_query_limit($sql, $limit, $offset); + + $i = 0; + $log = array(); + while ($row = $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'] && $auth->acl_get('f_read', $row['forum_id'])) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id']) : false, + 'action' => (isset($user->lang[$row['log_operation']])) ? $user->lang[$row['log_operation']] : '{' . ucfirst(str_replace('_', ' ', $row['log_operation'])) . '}', + ); + + if (!empty($row['log_data'])) + { + $log_data_ary = @unserialize($row['log_data']); + $log_data_ary = ($log_data_ary === false) ? array() : $log_data_ary; + + if (isset($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 if (!empty($log_data_ary)) + { + $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++; + } + $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 ' . $db->sql_in_set('topic_id', array_map('intval', $topic_id_list)); + $result = $db->sql_query($sql); + + $default_forum_id = 0; + + while ($row = $db->sql_fetchrow($result)) + { + if (!$row['forum_id']) + { + if ($auth->acl_getf_global('f_read')) + { + if (!$default_forum_id) + { + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE . ' + WHERE forum_type = ' . FORUM_POST; + $f_result = $db->sql_query_limit($sql, 1); + $default_forum_id = (int) $db->sql_fetchfield('forum_id', false, $f_result); + $db->sql_freeresult($f_result); + } + + $is_auth[$row['topic_id']] = $default_forum_id; + } + } + else + { + if ($auth->acl_get('f_read', $row['forum_id'])) + { + $is_auth[$row['topic_id']] = $row['forum_id']; + } + } + + if ($auth->acl_gets('a_', 'm_', $row['forum_id'])) + { + $is_mod[$row['topic_id']] = $row['forum_id']; + } + } + $db->sql_freeresult($result); + + foreach ($log as $key => $row) + { + $log[$key]['viewtopic'] = (isset($is_auth[$row['topic_id']])) ? append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $is_auth[$row['topic_id']] . '&t=' . $row['topic_id']) : false; + $log[$key]['viewlogs'] = (isset($is_mod[$row['topic_id']])) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=logs&mode=topic_logs&t=' . $row['topic_id'], true, $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 ' . $db->sql_in_set('user_id', $reportee_id_list); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $reportee_names_list[$row['user_id']] = $row; + } + $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, ' . USERS_TABLE . " u + WHERE l.log_type = $log_type + AND l.user_id = u.user_id + AND l.log_time >= $limit_days + $sql_keywords + $sql_forum"; + $result = $db->sql_query($sql); + $log_count = (int) $db->sql_fetchfield('total_entries'); + $db->sql_freeresult($result); + + return; +} + +/** +* Update foes - remove moderators and administrators from foe lists... +*/ +function update_foes($group_id = false, $user_id = false) +{ + global $db, $auth; + + // update foes for some user + if (is_array($user_id) && sizeof($user_id)) + { + $sql = 'DELETE FROM ' . ZEBRA_TABLE . ' + WHERE ' . $db->sql_in_set('zebra_id', $user_id) . ' + AND foe = 1'; + $db->sql_query($sql); + return; + } + + // update foes for some group + if (is_array($group_id) && sizeof($group_id)) + { + // Grab group settings... + $sql = $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 ' . $db->sql_in_set('a.group_id', $group_id) . " + AND ao.auth_option IN ('a_', 'm_')", + + 'GROUP_BY' => 'a.group_id' + )); + $result = $db->sql_query($sql); + + $groups = array(); + while ($row = $db->sql_fetchrow($result)) + { + $groups[] = (int) $row['group_id']; + } + $db->sql_freeresult($result); + + if (!sizeof($groups)) + { + return; + } + + switch ($db->sql_layer) + { + case 'mysqli': + case 'mysql4': + $sql = 'DELETE ' . (($db->sql_layer === 'mysqli' || version_compare($db->sql_server_info(true), '4.1', '>=')) ? 'z.*' : ZEBRA_TABLE) . ' + FROM ' . ZEBRA_TABLE . ' z, ' . USER_GROUP_TABLE . ' ug + WHERE z.zebra_id = ug.user_id + AND z.foe = 1 + AND ' . $db->sql_in_set('ug.group_id', $groups); + $db->sql_query($sql); + break; + + default: + $sql = 'SELECT user_id + FROM ' . USER_GROUP_TABLE . ' + WHERE ' . $db->sql_in_set('group_id', $groups); + $result = $db->sql_query($sql); + + $users = array(); + while ($row = $db->sql_fetchrow($result)) + { + $users[] = (int) $row['user_id']; + } + $db->sql_freeresult($result); + + if (sizeof($users)) + { + $sql = 'DELETE FROM ' . ZEBRA_TABLE . ' + WHERE ' . $db->sql_in_set('zebra_id', $users) . ' + AND foe = 1'; + $db->sql_query($sql); + } + break; + } + + return; + } + + // update foes for everyone + $perms = array(); + foreach ($auth->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 ' . $db->sql_in_set('zebra_id', array_unique($perms)) . ' + AND foe = 1'; + $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') +{ + global $db, $user; + + $sql = 'SELECT COUNT(user_id) AS user_count + FROM ' . USERS_TABLE . ' + WHERE user_type = ' . USER_INACTIVE . + (($limit_days) ? " AND user_inactive_time >= $limit_days" : ''); + $result = $db->sql_query($sql); + $user_count = (int) $db->sql_fetchfield('user_count'); + $db->sql_freeresult($result); + + if ($offset >= $user_count) + { + $offset = ($offset - $limit < 0) ? 0 : $offset - $limit; + } + + $sql = 'SELECT * + FROM ' . USERS_TABLE . ' + WHERE user_type = ' . USER_INACTIVE . + (($limit_days) ? " AND user_inactive_time >= $limit_days" : '') . " + ORDER BY $sort_by"; + $result = $db->sql_query_limit($sql, $limit, $offset); + + while ($row = $db->sql_fetchrow($result)) + { + $row['inactive_reason'] = $user->lang['INACTIVE_REASON_UNKNOWN']; + switch ($row['user_inactive_reason']) + { + case INACTIVE_REGISTER: + $row['inactive_reason'] = $user->lang['INACTIVE_REASON_REGISTER']; + break; + + case INACTIVE_PROFILE: + $row['inactive_reason'] = $user->lang['INACTIVE_REASON_PROFILE']; + break; + + case INACTIVE_MANUAL: + $row['inactive_reason'] = $user->lang['INACTIVE_REASON_MANUAL']; + break; + + case INACTIVE_REMIND: + $row['inactive_reason'] = $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') +{ + global $db; + + $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 = $db->sql_query_limit($sql, $limit, $offset); + $users = $db->sql_fetchrowset($result); + $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 = $db->sql_query($sql); + $user_count = (int) $db->sql_fetchfield('user_count'); + $db->sql_freeresult($result); + + return; +} + +/** +* Get database size +* Currently only mysql and mssql are supported +*/ +function get_database_size() +{ + global $db, $user, $table_prefix; + + $database_size = false; + + // This code is heavily influenced by a similar routine in phpMyAdmin 2.2.0 + switch ($db->sql_layer) + { + case 'mysql': + case 'mysql4': + case 'mysqli': + $sql = 'SELECT VERSION() AS mysql_version'; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $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)) ? "`{$db->dbname}`" : $db->dbname; + + $sql = 'SHOW TABLE STATUS + FROM ' . $db_name; + $result = $db->sql_query($sql, 7200); + + $database_size = 0; + while ($row = $db->sql_fetchrow($result)) + { + if ((isset($row['Type']) && $row['Type'] != 'MRG_MyISAM') || (isset($row['Engine']) && ($row['Engine'] == 'MyISAM' || $row['Engine'] == 'InnoDB'))) + { + if ($table_prefix != '') + { + if (strpos($row['Name'], $table_prefix) !== false) + { + $database_size += $row['Data_length'] + $row['Index_length']; + } + } + else + { + $database_size += $row['Data_length'] + $row['Index_length']; + } + } + } + $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': + case 'mssql_odbc': + $sql = 'SELECT ((SUM(size) * 8.0) * 1024.0) as dbsize + FROM sysfiles'; + $result = $db->sql_query($sql, 7200); + $database_size = ($row = $db->sql_fetchrow($result)) ? $row['dbsize'] : false; + $db->sql_freeresult($result); + break; + + case 'postgres': + $sql = "SELECT proname + FROM pg_proc + WHERE proname = 'pg_database_size'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row['proname'] == 'pg_database_size') + { + $database = $db->dbname; + if (strpos($database, '.') !== false) + { + list($database, ) = explode('.', $database); + } + + $sql = "SELECT oid + FROM pg_database + WHERE datname = '$database'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $oid = $row['oid']; + + $sql = 'SELECT pg_database_size(' . $oid . ') as size'; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $database_size = $row['size']; + } + break; + + case 'oracle': + $sql = 'SELECT SUM(bytes) as dbsize + FROM user_segments'; + $result = $db->sql_query($sql, 7200); + $database_size = ($row = $db->sql_fetchrow($result)) ? $row['dbsize'] : false; + $db->sql_freeresult($result); + break; + } + + $database_size = ($database_size !== false) ? get_formatted_filesize($database_size) : $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) +{ + global $user; + + 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 = $user->lang['FILE_NOT_FOUND'] . ': ' . $filename; + return false; + } + } + } + @fclose($fsock); + } + else + { + if ($errstr) + { + $errstr = utf8_convert_message($errstr); + return false; + } + else + { + $errstr = $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() +{ + global $db, $config; + + $expire_date = time() - ($config['warnings_expire_days'] * 86400); + $warning_list = $user_list = array(); + + $sql = 'SELECT * FROM ' . WARNINGS_TABLE . " + WHERE warning_time < $expire_date"; + $result = $db->sql_query($sql); + + while ($row = $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; + } + $db->sql_freeresult($result); + + if (sizeof($warning_list)) + { + $db->sql_transaction('begin'); + + $sql = 'DELETE FROM ' . WARNINGS_TABLE . ' + WHERE ' . $db->sql_in_set('warning_id', $warning_list); + $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"; + $db->sql_query($sql); + } + + $db->sql_transaction('commit'); + } + + set_config('warnings_last_gc', time(), true); +} + +/** +* Tidy database, doing some maintanance tasks +*/ +function tidy_database() +{ + global $db; + + // 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 = $db->sql_query($sql); + + $forum_ids = array(0); + while ($row = $db->sql_fetchrow($result)) + { + $forum_ids[] = $row['forum_id']; + } + $db->sql_freeresult($result); + + // Delete those rows from the acl tables not having listed the forums above + $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_ids, true); + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_USERS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_ids, true); + $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() +{ + global $user, $phpEx; + + // First of all, our own file. We need to include it as the first file because it presets all relevant variables. + $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($user->lang_path . $user->lang_name . '/' . $path); + + if ($dh) + { + while (($file = readdir($dh)) !== false) + { + if ($file !== 'permissions_phpbb.' . $phpEx && strpos($file, 'permissions_') === 0 && substr($file, -(strlen($phpEx) + 1)) === '.' . $phpEx) + { + $files_to_add[] = $path . substr($file, 0, -(strlen($phpEx) + 1)); + } + } + closedir($dh); + } + } + + if (!sizeof($files_to_add)) + { + return false; + } + + $user->add_lang($files_to_add); + return true; +} + +/** + * Obtains the latest version information + * + * @param bool $force_update Ignores cached data. Defaults to false. + * @param bool $warn_fail Trigger a warning if obtaining the latest version information fails. Defaults to false. + * @param int $ttl Cache version information for $ttl seconds. Defaults to 86400 (24 hours). + * + * @return string | false Version info on success, false on failure. + */ +function obtain_latest_version_info($force_update = false, $warn_fail = false, $ttl = 86400) +{ + global $cache; + + $info = $cache->get('versioncheck'); + + if ($info === false || $force_update) + { + $errstr = ''; + $errno = 0; + + $info = get_remote_file('www.phpbb.com', '/updatecheck', + ((defined('PHPBB_QA')) ? '30x_qa.txt' : '30x.txt'), $errstr, $errno); + + if ($info === false) + { + $cache->destroy('versioncheck'); + if ($warn_fail) + { + trigger_error($errstr, E_USER_WARNING); + } + return false; + } + + $cache->put('versioncheck', $info, $ttl); + } + + return $info; +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/functions_compress.php b/phpBB/includes/functions_compress.php new file mode 100644 index 0000000000..590daabf1d --- /dev/null +++ b/phpBB/includes/functions_compress.php @@ -0,0 +1,723 @@ +<?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 +{ + var $fp = 0; + + /** + * Add file to archive + */ + function add_file($src, $src_rm_prefix = '', $src_add_prefix = '', $skip_files = '') + { + global $phpbb_root_path; + + $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) + */ + function add_custom_file($src, $filename) + { + $this->data($filename, file_get_contents($src), false, stat($src)); + return true; + } + + /** + * Add file data + */ + 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 + */ + 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 +{ + var $datasec = array(); + var $ctrl_dir = array(); + var $eof_cdh = "\x50\x4b\x05\x06\x00\x00\x00\x00"; + + var $old_offset = 0; + var $datasec_len = 0; + + /** + * Constructor + */ + function compress_zip($mode, $file) + { + $this->fp = @fopen($file, $mode . 'b'); + + if (!$this->fp) + { + trigger_error('Unable to open file ' . $file . ' [' . $mode . 'b]'); + } + } + + /** + * Convert unix to dos time + */ + 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 + */ + 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_chmod($str, CHMOD_READ | 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_chmod($str, CHMOD_READ | 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 + */ + 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 + */ + function data($name, $data, $is_dir = false, $stat) + { + $name = str_replace('\\', '/', $name); + + $hexdtime = pack('V', $this->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 + */ + function file() + { + $ctrldir = implode('', $this->ctrl_dir); + + return $ctrldir . $this->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 + */ + function download($filename, $download_name = false) + { + global $phpbb_root_path; + + 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 +{ + var $isgz = false; + var $isbz = false; + var $filename = ''; + var $mode = ''; + var $type = ''; + var $wrote = false; + + /** + * Constructor + */ + function compress_tar($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 + */ + 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_chmod($str, CHMOD_READ | 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_chmod($str, CHMOD_READ | CHMOD_WRITE); + } + } + + // Write out the files + if (!($fp = fopen($target_filename, 'wb'))) + { + trigger_error("Couldn't create file $filename"); + } + phpbb_chmod($target_filename, CHMOD_READ); + + // Grab the file contents + fwrite($fp, ($filesize) ? $fzread($this->fp, ($filesize + 511) &~ 511) : '', $filesize); + fclose($fp); + } + } + } + } + + /** + * Close archive + */ + 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 + */ + 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 + */ + 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 + */ + function download($filename, $download_name = false) + { + global $phpbb_root_path; + + 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 new file mode 100644 index 0000000000..c265d0ae41 --- /dev/null +++ b/phpBB/includes/functions_content.php @@ -0,0 +1,1357 @@ +<?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 +*/ +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) +{ + global $user; + + $sort_dir_text = array('a' => $user->lang['ASCENDING'], 'd' => $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) +{ + global $config, $auth, $template, $user, $db; + + // We only return if the jumpbox is not forced to be displayed (in case it is needed for functionality) + if (!$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 = $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 = $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 (!$auth->acl_get('f_list', $row['forum_id'])) + { + // if the user does not have permissions to list this forum skip + continue; + } + + if ($acl_list && !$auth->acl_gets($acl_list, $row['forum_id'])) + { + continue; + } + + if (!$display_jumpbox) + { + $template->assign_block_vars('jumpbox_forums', array( + 'FORUM_ID' => ($select_all) ? 0 : -1, + 'FORUM_NAME' => ($select_all) ? $user->lang['ALL_FORUMS'] : $user->lang['SELECT_FORUM'], + 'S_FORUM_COUNT' => $iteration) + ); + + $iteration++; + $display_jumpbox = true; + } + + $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++) + { + $template->assign_block_vars('jumpbox_forums.level', array()); + } + $iteration++; + } + $db->sql_freeresult($result); + unset($padding_store); + + $template->assign_vars(array( + 'S_DISPLAY_JUMPBOX' => $display_jumpbox, + 'S_JUMPBOX_ACTION' => $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) +{ + global $config, $auth, $user; + + // Check permission and make sure the last post was not already bumped + if (!$auth->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 = ($config['bump_type'] == 'm') ? $config['bump_interval'] * 60 : (($config['bump_type'] == 'h') ? $config['bump_interval'] * 3600 : $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 != $user->data['user_id'] && $last_topic_poster != $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 ", ' ')); + + // we need to turn the entities back into their original form, to not cut the message in between them + $entities = array('<', '>', '[', ']', '.', ':', ':'); + $characters = array('<', '>', '[', ']', '.', ':', ':'); + $text = str_replace($entities, $characters, $text); + + $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)) + { + if (empty($match[1])) + { + continue; + } + + $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 str_replace($characters, $entities, $final_text); + } + } + + if (!sizeof($words) || !sizeof($word_indizes)) + { + return str_replace($characters, $entities, ((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 = '') +{ + global $config; + + 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')) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/bbcode.' . $phpEx); + } + + 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) +{ + global $phpbb_root_path, $phpEx; + + $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.' . $phpEx); + } + + $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) +{ + global $phpbb_root_path, $phpEx; + + 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; + + // Nothing to do? + if ($text === '') + { + return ''; + } + + // 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)) + { + global $config, $user, $auth, $cache; + + // We check here if the user is having viewing censors disabled (and also allowed to do so). + if (!$user->optionget('viewcensors') && $config['allow_nocensors'] && $auth->acl_get('u_chgcensors')) + { + $censors = array(); + } + else + { + $censors = $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) +{ + global $config, $user, $phpbb_root_path; + + if ($force_option || !$config['allow_smilies'] || !$user->optionget('viewsmilies')) + { + return preg_replace('#<!\-\- s(.*?) \-\-><img src="\{SMILIES_PATH\}\/.*? \/><!\-\- s\1 \-\->#', '\1', $text); + } + else + { + $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path; + return preg_replace('#<!\-\- s(.*?) \-\-><img src="\{SMILIES_PATH\}\/(.*?) \/><!\-\- s\1 \-\->#', '<img src="' . $root_path . $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 $template, $cache, $user; + global $extensions, $config, $phpbb_root_path, $phpEx; + + // + $compiled_attachments = array(); + + if (!isset($template->filename['attachment_tpl'])) + { + $template->set_filenames(array( + 'attachment_tpl' => 'attachment.html') + ); + } + + if (empty($extensions) || !is_array($extensions)) + { + $extensions = $cache->obtain_attach_extensions($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)) + { + global $db; + + $new_attachment_data = array(); + + $sql = 'SELECT * + FROM ' . ATTACHMENTS_TABLE . ' + WHERE ' . $db->sql_in_set('attach_id', array_keys($attach_ids)); + $result = $db->sql_query($sql); + + while ($row = $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; + } + $db->sql_freeresult($result); + + $attachments = $new_attachment_data; + unset($new_attachment_data); + } + + // Sort correctly + if ($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 + $template->destroy_block_vars('_file'); + + $block_array = array(); + + // Some basics... + $attachment['extension'] = strtolower(trim($attachment['extension'])); + $filename = $phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($attachment['physical_filename']); + $thumbnail_filename = $phpbb_root_path . $config['upload_path'] . '/thumb_' . utf8_basename($attachment['physical_filename']); + + $upload_icon = ''; + + if (isset($extensions[$attachment['extension']])) + { + if ($user->img('icon_topic_attach', '') && !$extensions[$attachment['extension']]['upload_icon']) + { + $upload_icon = $user->img('icon_topic_attach', ''); + } + else if ($extensions[$attachment['extension']]['upload_icon']) + { + $upload_icon = '<img src="' . $phpbb_root_path . $config['upload_icons_path'] . '/' . trim($extensions[$attachment['extension']]['upload_icon']) . '" alt="" />'; + } + } + + $filesize = get_formatted_filesize($attachment['filesize'], false); + + $comment = bbcode_nl2br(censor_text($attachment['attach_comment'])); + + $block_array += array( + 'UPLOAD_ICON' => $upload_icon, + 'FILESIZE' => $filesize['value'], + 'SIZE_LANG' => $filesize['unit'], + 'DOWNLOAD_NAME' => utf8_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' => sprintf($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 ($config['img_display_inlined']) + { + if ($config['img_link_width'] || $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] <= $config['img_link_width'] && $dimension[1] <= $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) && !$user->optionget('viewimg')) + { + $display_cat = ATTACHMENT_CATEGORY_NONE; + } + + if ($display_cat == ATTACHMENT_CATEGORY_FLASH && !$user->optionget('viewflash')) + { + $display_cat = ATTACHMENT_CATEGORY_NONE; + } + + $download_link = append_sid("{$phpbb_root_path}download/file.$phpEx", 'id=' . $attachment['attach_id']); + + switch ($display_cat) + { + // Images + case ATTACHMENT_CATEGORY_IMAGE: + $l_downloaded_viewed = 'VIEWED_COUNT'; + $inline_link = append_sid("{$phpbb_root_path}download/file.$phpEx", '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("{$phpbb_root_path}download/file.$phpEx", '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; + } + + $l_download_count = (!isset($attachment['download_count']) || $attachment['download_count'] == 0) ? $user->lang[$l_downloaded_viewed . '_NONE'] : (($attachment['download_count'] == 1) ? sprintf($user->lang[$l_downloaded_viewed], $attachment['download_count']) : sprintf($user->lang[$l_downloaded_viewed . 'S'], $attachment['download_count'])); + + $block_array += array( + 'U_DOWNLOAD_LINK' => $download_link, + 'L_DOWNLOAD_COUNT' => $l_download_count + ); + } + + $template->assign_block_vars('_file', $block_array); + + $compiled_attachments[] = $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 = ($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($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)) + { + global $cache; + $extensions = $cache->obtain_attach_extensions($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 and anonymous user - determined by $user_id. +* +* @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)) + { + global $phpbb_root_path, $phpEx; + + $_profile_cache['base_url'] = append_sid("{$phpbb_root_path}memberlist.$phpEx", '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>'; + } + + global $user, $auth; + + // 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 : $user->lang['GUEST']; + } + else + { + $username = ($user_id && $user_id != ANONYMOUS) ? $username : ((!empty($guest_username)) ? $guest_username : $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 && ($user->data['user_id'] == ANONYMOUS || $auth->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 bitfield($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 new file mode 100644 index 0000000000..82ec114c09 --- /dev/null +++ b/phpBB/includes/functions_convert.php @@ -0,0 +1,2454 @@ +<?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) ? USER_NORMAL : 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 $config, $convert, $phpbb_root_path, $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($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($config['avatar_gallery_path']) . $dir, true, false, false, $relative_path); + } + } + } +} + +function import_attachment_files($category_name = '') +{ + global $config, $convert, $phpbb_root_path, $db, $user; + + $sql = 'SELECT config_value AS upload_path + FROM ' . CONFIG_TABLE . " + WHERE config_name = 'upload_path'"; + $result = $db->sql_query($sql); + $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($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, $config; + + $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 = $config[$config_var] . '/' . utf8_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'] = utf8_basename($target); + } + else + { + $result['target'] = ($use_target !== false) ? $result['orig_source'] : utf8_basename($target); + } + + return $result; +} + +function import_attachment($source, $use_target = false) +{ + if (empty($source)) + { + return ''; + } + + global $convert, $phpbb_root_path, $config, $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 . utf8_basename($result['source']); + + if (strpos($thumb_source, $convert->convertor['upload_path']) !== 0) + { + $thumb_source = $convert->convertor['upload_path'] . $thumb_source; + } + $thumb_target = $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, $phpbb_root_path, $config, $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, $phpbb_root_path, $config, $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, $phpbb_root_path, $config, $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 = $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, $phpbb_root_path, $config, $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, $phpbb_root_path, $config, $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, $phpbb_root_path, $config, $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, $phpbb_root_path, $config, $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, $phpbb_root_path, $config, $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 = '" . $db->sql_escape(strtoupper($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, $phpbb_root_path, $config; + 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, $config; + + $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) +{ + global $config, $phpbb_root_path, $phpEx; + + $board_config = get_config(); + + $test_file = preg_replace('/\.php$/i', ".$phpEx", $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 ACL_YES|ACL_NO|ACL_NEVER +*/ +function mass_auth($ug_type, $forum_id, $ug_id, $acl_list, $setting = ACL_NO) +{ + global $db, $convert, $user, $config; + 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 = '" . $db->sql_escape(strtoupper($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->sql_layer) + { + case 'mysql': + case 'mysql4': + $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), + 'NEWLY_REGISTERED' => array('', 0, 0), + ); + + $sql = 'SELECT * + FROM ' . GROUPS_TABLE . ' + WHERE ' . $db->sql_in_set('group_name', 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_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, $config, $phpbb_root_path, $phpEx; + + $db->sql_query($convert->truncate_statement . BOTS_TABLE); + + $sql = 'SELECT group_id FROM ' . GROUPS_TABLE . " WHERE group_name = 'BOTS'"; + $result = $db->sql_query($sql); + $group_id = (int) $db->sql_fetchfield('group_id', false, $result); + $db->sql_freeresult($result); + + if (!$group_id) + { + add_default_groups(); + + $sql = 'SELECT group_id FROM ' . GROUPS_TABLE . " WHERE group_name = 'BOTS'"; + $result = $db->sql_query($sql); + $group_id = (int) $db->sql_fetchfield('group_id', false, $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.' . $phpEx); + } + + foreach ($bots as $bot_name => $bot_ary) + { + $user_row = array( + 'user_type' => USER_IGNORE, + 'group_id' => $group_id, + 'username' => $bot_name, + 'user_regdate' => time(), + 'user_password' => '', + 'user_colour' => '9E8DA7', + 'user_email' => '', + 'user_lang' => $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, $config; + + // Get latest username + $sql = 'SELECT user_id, username, user_colour + FROM ' . USERS_TABLE . ' + WHERE user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')'; + + if (!empty($config['increment_user_id'])) + { + $sql .= ' AND user_id <> ' . $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 (' . USER_NORMAL . ',' . 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, $config; + + switch ($db->sql_layer) + { + case 'sqlite': + case 'firebird': + $db->sql_query('DELETE FROM ' . TOPICS_POSTED_TABLE); + break; + + default: + $db->sql_query('TRUNCATE TABLE ' . TOPICS_POSTED_TABLE); + break; + } + + // 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 = ' . USER_INACTIVE; + $db->sql_query($sql); + + $sql = 'UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('registered') . ' + WHERE group_id = 0 AND user_type = ' . 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, $phpEx, $phpbb_root_path; + + // 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.' . $phpEx); + } + + 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, $phpbb_root_path, $config, $user, $db; + + if (substr($trg, -1) == '/') + { + $trg .= utf8_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, $phpbb_root_path, $config, $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($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, $phpbb_root_path, $config, $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) +{ + global $config; + + return ((empty($user_dateformat)) ? $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 new file mode 100644 index 0000000000..cec1becb6e --- /dev/null +++ b/phpBB/includes/functions_display.php @@ -0,0 +1,1277 @@ +<?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) +{ + global $db, $auth, $user, $template; + global $phpbb_root_path, $phpEx, $config; + + $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 ($config['load_db_lastread'] && $user->data['is_registered']) + { + $sql_array['LEFT_JOIN'][] = array('FROM' => array(FORUMS_TRACK_TABLE => 'ft'), 'ON' => 'ft.user_id = ' . $user->data['user_id'] . ' AND ft.forum_id = f.forum_id'); + $sql_array['SELECT'] .= ', ft.mark_time'; + } + else if ($config['load_anon_lastread'] || $user->data['is_registered']) + { + $tracking_topics = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : ''; + $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array(); + + if (!$user->data['is_registered']) + { + $user->data['user_lastmark'] = (isset($tracking_topics['l'])) ? (int) (base_convert($tracking_topics['l'], 36, 10) + $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 = '" . $db->sql_escape($user->session_id) . "'" + ); + + $sql_array['SELECT'] .= ', fa.user_id'; + } + + $sql = $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 = $db->sql_query($sql); + + $forum_tracking_info = array(); + $branch_root_id = $root_data['forum_id']; + + // Check for unread global announcements (index page only) + $ga_unread = false; + if ($root_data['forum_id'] == 0) + { + $unread_ga_list = get_unread_topics($user->data['user_id'], 'AND t.forum_id = 0', '', 1); + + if (!empty($unread_ga_list)) + { + $ga_unread = true; + } + } + + while ($row = $db->sql_fetchrow($result)) + { + $forum_id = $row['forum_id']; + + // Mark forums read? + if ($mark_read == 'forums' || $mark_read == 'all') + { + if ($auth->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 (!$auth->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 ($config['load_db_lastread'] && $user->data['is_registered']) + { + $forum_tracking_info[$forum_id] = (!empty($row['mark_time'])) ? $row['mark_time'] : $user->data['user_lastmark']; + } + else if ($config['load_anon_lastread'] || $user->data['is_registered']) + { + if (!$user->data['is_registered']) + { + $user->data['user_lastmark'] = (isset($tracking_topics['l'])) ? (int) (base_convert($tracking_topics['l'], 36, 10) + $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) + $config['board_startdate']) : $user->data['user_lastmark']; + } + + // Count the difference of real to public topics, so we can display an information to moderators + $row['forum_id_unapproved_topics'] = ($auth->acl_get('m_approve', $forum_id) && ($row['forum_topics_real'] != $row['forum_topics'])) ? $forum_id : 0; + $row['forum_topics'] = ($auth->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 && $auth->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'] != $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; + } + + if (!$forum_rows[$parent_id]['forum_id_unapproved_topics'] && $row['forum_id_unapproved_topics']) + { + $forum_rows[$parent_id]['forum_id_unapproved_topics'] = $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; + } + } + } + $db->sql_freeresult($result); + + // Handle marking posts + if ($mark_read == 'forums' || $mark_read == 'all') + { + $redirect = build_url(array('mark', 'hash')); + $token = request_var('hash', ''); + if (check_link_hash($token, 'global')) + { + if ($mark_read == 'all') + { + markread('all'); + $message = sprintf($user->lang['RETURN_INDEX'], '<a href="' . $redirect . '">', '</a>'); + } + else + { + // Add 0 to forums array to mark global announcements correctly + $forum_ids[] = 0; + markread('topics', $forum_ids); + $message = sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect . '">', '</a>'); + } + meta_refresh(3, $redirect); + trigger_error($user->lang['FORUMS_MARKED'] . '<br /><br />' . $message); + } + else + { + $message = sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>'); + 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) + { + $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="' . $user->lang['FORUM_CAT'] . '" />' : '', + 'FORUM_IMAGE_SRC' => ($row['forum_image']) ? $phpbb_root_path . $row['forum_image'] : '', + 'U_VIEWFORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", '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; + + // Mark the first visible forum on index as unread if there's any unread global announcement + if (($forum_id == $forum_ids_moderator[0]) && ($root_data['forum_id'] == 0) && $ga_unread) + { + $forum_unread = true; + } + + $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' => append_sid("{$phpbb_root_path}viewforum.$phpEx", '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; + } + } + + $l_subforums = (sizeof($subforums[$forum_id]) == 1) ? $user->lang['SUBFORUM'] . ': ' : $user->lang['SUBFORUMS'] . ': '; + $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 = $user->format_date($row['forum_last_post_time']); + $last_post_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", '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 + $l_moderator = $moderators_list = ''; + if ($display_moderators && !empty($forum_moderators[$forum_id])) + { + $l_moderator = (sizeof($forum_moderators[$forum_id]) == 1) ? $user->lang['MODERATOR'] : $user->lang['MODERATORS']; + $moderators_list = implode(', ', $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']) ? $user->lang['NEW_POSTS'] : $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 = append_sid("{$phpbb_root_path}viewforum.$phpEx", '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'] || !$auth->acl_get('f_read', $forum_id)) + { + $u_viewforum = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id']); + } + else + { + $u_viewforum = $row['forum_link']; + } + } + + $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, + 'S_FEED_ENABLED' => ($config['feed_forum'] && !phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $row['forum_options'])) ? 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' => $user->img($folder_image, $folder_alt), + 'FORUM_FOLDER_IMG_SRC' => $user->img($folder_image, $folder_alt, false, '', 'src'), + 'FORUM_FOLDER_IMG_ALT' => isset($user->lang[$folder_alt]) ? $user->lang[$folder_alt] : '', + 'FORUM_IMAGE' => ($row['forum_image']) ? '<img src="' . $phpbb_root_path . $row['forum_image'] . '" alt="' . $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' => $moderators_list, + 'SUBFORUMS' => $s_subforums_list, + + 'L_SUBFORUM_STR' => $l_subforums, + 'L_FORUM_FOLDER_ALT' => $folder_alt, + 'L_MODERATOR_STR' => $l_moderator, + + 'U_UNAPPROVED_TOPICS' => ($row['forum_id_unapproved_topics']) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&mode=unapproved_topics&f=' . $row['forum_id_unapproved_topics']) : '', + '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) + { + $template->assign_block_vars('forumrow.subforum', array( + 'U_SUBFORUM' => $subforum['link'], + 'SUBFORUM_NAME' => $subforum['name'], + 'S_UNREAD' => $subforum['unread']) + ); + } + + $last_catless = $catless; + } + + $template->assign_vars(array( + 'U_MARK_FORUMS' => ($user->data['is_registered'] || $config['load_anon_lastread']) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'hash=' . generate_link_hash('global') . '&f=' . $root_data['forum_id'] . '&mark=forums') : '', + 'S_HAS_SUBFORUM' => ($visible_forums) ? true : false, + 'L_SUBFORUM' => ($visible_forums == 1) ? $user->lang['SUBFORUM'] : $user->lang['SUBFORUMS'], + 'LAST_POST_IMG' => $user->img('icon_topic_latest', 'VIEW_LATEST_POST'), + 'UNAPPROVED_IMG' => $user->img('icon_topic_unapproved', 'TOPICS_UNAPPROVED'), + )); + + 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; + } + + global $template, $phpbb_root_path, $phpEx; + + 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']); + } + + $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) +{ + global $db, $user, $template, $auth, $config; + global $phpEx, $phpbb_root_path; + + if (!$auth->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 (!$auth->acl_get('f_list', $parent_forum_id)) + { + continue; + } + + $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' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $parent_forum_id)) + ); + } + } + + $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' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_data['forum_id'])) + ); + + $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']), + + 'S_ENABLE_FEEDS_FORUM' => ($config['feed_forum'] && !phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $forum_data['forum_options'])) ? true : false, + )); + + 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) +{ + global $db; + + $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 = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $forum_parents[$row['forum_id']] = array($row['forum_name'], (int) $row['forum_type']); + } + $db->sql_freeresult($result); + + $forum_data['forum_parents'] = serialize($forum_parents); + + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET forum_parents = '" . $db->sql_escape($forum_data['forum_parents']) . "' + WHERE parent_id = " . $forum_data['parent_id']; + $db->sql_query($sql); + } + else + { + $forum_parents = unserialize($forum_data['forum_parents']); + } + } + + return $forum_parents; +} + +/** +* Generate topic pagination +*/ +function topic_generate_pagination($replies, $url) +{ + global $config, $user; + + // Make sure $per_page is a valid value + $per_page = ($config['posts_per_page'] <= 0) ? 1 : $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">' . $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) +{ + global $config, $template, $db, $phpbb_root_path, $phpEx, $user, $auth; + + $forum_id_ary = array(); + + if ($forum_id !== false) + { + if (!is_array($forum_id)) + { + $forum_id = array($forum_id); + } + + // Exchange key/value pair to be able to faster check for the forum id existence + $forum_id_ary = array_flip($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', + ); + + // We query every forum here because for caching we should not have any parameter. + $sql = $db->sql_build_query('SELECT', $sql_array); + $result = $db->sql_query($sql, 3600); + + while ($row = $db->sql_fetchrow($result)) + { + $f_id = (int) $row['forum_id']; + + if (!isset($forum_id_ary[$f_id])) + { + continue; + } + + if (!empty($row['user_id'])) + { + $forum_moderators[$f_id][] = get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']); + } + else + { + $group_name = (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']); + + if ($user->data['user_id'] != ANONYMOUS && !$auth->acl_get('u_viewprofile')) + { + $forum_moderators[$f_id][] = '<span' . (($row['group_colour']) ? ' style="color:#' . $row['group_colour'] . ';"' : '') . '>' . $group_name . '</span>'; + } + else + { + $forum_moderators[$f_id][] = '<a' . (($row['group_colour']) ? ' style="color:#' . $row['group_colour'] . ';"' : '') . ' href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&g=' . $row['group_id']) . '">' . $group_name . '</a>'; + } + } + } + $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) +{ + global $template, $auth, $user, $config; + + $locked = ($forum_status == ITEM_LOCKED && !$auth->acl_get('m_edit', $forum_id)) ? true : false; + + $rules = array( + ($auth->acl_get('f_post', $forum_id) && !$locked) ? $user->lang['RULES_POST_CAN'] : $user->lang['RULES_POST_CANNOT'], + ($auth->acl_get('f_reply', $forum_id) && !$locked) ? $user->lang['RULES_REPLY_CAN'] : $user->lang['RULES_REPLY_CANNOT'], + ($user->data['is_registered'] && $auth->acl_gets('f_edit', 'm_edit', $forum_id) && !$locked) ? $user->lang['RULES_EDIT_CAN'] : $user->lang['RULES_EDIT_CANNOT'], + ($user->data['is_registered'] && $auth->acl_gets('f_delete', 'm_delete', $forum_id) && !$locked) ? $user->lang['RULES_DELETE_CAN'] : $user->lang['RULES_DELETE_CANNOT'], + ); + + if ($config['allow_attachments']) + { + $rules[] = ($auth->acl_get('f_attach', $forum_id) && $auth->acl_get('u_attach') && !$locked) ? $user->lang['RULES_ATTACH_CAN'] : $user->lang['RULES_ATTACH_CANNOT']; + } + + foreach ($rules as $rule) + { + $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) +{ + global $user, $config; + + $folder = $folder_new = ''; + + if ($topic_row['topic_status'] == ITEM_MOVED) + { + $topic_type = $user->lang['VIEW_TOPIC_MOVED']; + $folder_img = 'topic_moved'; + $folder_alt = 'TOPIC_MOVED'; + } + else + { + switch ($topic_row['topic_type']) + { + case POST_GLOBAL: + $topic_type = $user->lang['VIEW_TOPIC_GLOBAL']; + $folder = 'global_read'; + $folder_new = 'global_unread'; + break; + + case POST_ANNOUNCE: + $topic_type = $user->lang['VIEW_TOPIC_ANNOUNCEMENT']; + $folder = 'announce_read'; + $folder_new = 'announce_unread'; + break; + + case POST_STICKY: + $topic_type = $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 ($config['hot_threshold'] && ($replies + 1) >= $config['hot_threshold'] && $topic_row['topic_status'] != ITEM_LOCKED) + { + $folder .= '_hot'; + $folder_new .= '_hot'; + } + break; + } + + if ($topic_row['topic_status'] == ITEM_LOCKED) + { + $topic_type = $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 = $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() +{ + global $db, $template, $user; + + // 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 = $db->sql_query($sql); + + $i = 0; + while ($row = $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($user->lang[strtoupper($row['bbcode_helpline'])])) + { + $row['bbcode_helpline'] = $user->lang[strtoupper($row['bbcode_helpline'])]; + } + + $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++; + } + $db->sql_freeresult($result); +} + +/** +* Display reasons +*/ +function display_reasons($reason_id = 0) +{ + global $db, $user, $template; + + $sql = 'SELECT * + FROM ' . REPORTS_REASONS_TABLE . ' + ORDER BY reason_order ASC'; + $result = $db->sql_query($sql); + + while ($row = $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($user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]) && isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])])) + { + $row['reason_description'] = $user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])]; + $row['reason_title'] = $user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]; + } + + $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) + ); + } + $db->sql_freeresult($result); +} + +/** +* Display user activity (action forum/topic) +*/ +function display_user_activity(&$userdata) +{ + global $auth, $template, $db, $user; + global $phpbb_root_path, $phpEx; + + // 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 = $auth->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 ' . $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 = $db->sql_query_limit($sql, 1); + $active_f_row = $db->sql_fetchrow($result); + $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 = $db->sql_query($sql, 3600); + $active_f_row['forum_name'] = (string) $db->sql_fetchfield('forum_name'); + $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 = $db->sql_query_limit($sql, 1); + $active_t_row = $db->sql_fetchrow($result); + $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 = $db->sql_query($sql); + $active_t_row['topic_title'] = (string) $db->sql_fetchfield('topic_title'); + $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'] == $user->data['user_id']) ? $user->lang['POST_PCT_ACTIVE_OWN'] : $user->lang['POST_PCT_ACTIVE']; + + $template->assign_vars(array( + 'ACTIVE_FORUM' => $active_f_name, + 'ACTIVE_FORUM_POSTS' => ($active_f_count == 1) ? sprintf($user->lang['USER_POST'], 1) : sprintf($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($user->lang['USER_POST'], 1) : sprintf($user->lang['USER_POSTS'], $active_t_count), + 'ACTIVE_TOPIC_PCT' => sprintf($l_active_pct, $active_t_pct), + 'U_ACTIVE_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $active_f_id), + 'U_ACTIVE_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", '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 $template, $db, $user, $phpEx, $start, $phpbb_root_path; + + $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={$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 = $db->sql_query($sql); + + $notify_status = ($row = $db->sql_fetchrow($result)) ? $row['notify_status'] : NULL; + $db->sql_freeresult($result); + } + + if (!is_null($notify_status) && $notify_status !== '') + { + + if (isset($_GET['unwatch'])) + { + $uid = request_var('uid', 0); + if ($uid != $user_id) + { + $redirect_url = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&start=$start"); + $message = $user->lang['ERR_UNWATCHING'] . '<br /><br />' . sprintf($user->lang['RETURN_' . strtoupper($mode)], '<a href="' . $redirect_url . '">', '</a>'); + trigger_error($message); + } + if ($_GET['unwatch'] == $mode) + { + $is_watching = 0; + + $sql = 'DELETE FROM ' . $table_sql . " + WHERE $where_sql = $match_id + AND user_id = $user_id"; + $db->sql_query($sql); + } + + $redirect_url = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&start=$start"); + + meta_refresh(3, $redirect_url); + + $message = $user->lang['NOT_WATCHING_' . strtoupper($mode)] . '<br /><br />' . sprintf($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"; + $db->sql_query($sql); + } + } + } + else + { + if (isset($_GET['watch'])) + { + $token = request_var('hash', ''); + $redirect_url = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&start=$start"); + + if ($_GET['watch'] == $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)"; + $db->sql_query($sql); + $message = $user->lang['ARE_WATCHING_' . strtoupper($mode)] . '<br /><br />' . sprintf($user->lang['RETURN_' . strtoupper($mode)], '<a href="' . $redirect_url . '">', '</a>'); + } + else + { + $message = $user->lang['ERR_WATCHING'] . '<br /><br />' . sprintf($user->lang['RETURN_' . strtoupper($mode)], '<a href="' . $redirect_url . '">', '</a>'); + } + + meta_refresh(3, $redirect_url); + + trigger_error($message); + } + else + { + $is_watching = 0; + } + } + } + else + { + if (isset($_GET['unwatch']) && $_GET['unwatch'] == $mode) + { + login_box(); + } + else + { + $can_watch = 0; + $is_watching = 0; + } + } + + if ($can_watch) + { + $s_watching['link'] = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&" . (($is_watching) ? 'unwatch' : 'watch') . "=$mode&start=$start&hash=" . generate_link_hash("{$mode}_$match_id")); + $s_watching['title'] = $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_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 +* +* Note: since we do not want to break backwards-compatibility, this function will only properly assign ranks to guests if you call it for them with user_posts == false +*/ +function get_user_rank($user_rank, $user_posts, &$rank_title, &$rank_img, &$rank_img_src) +{ + global $ranks, $config, $phpbb_root_path; + + if (empty($ranks)) + { + global $cache; + $ranks = $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 . $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 . $config['ranks_path'] . '/' . $ranks['special'][$user_rank]['rank_image'] : ''; + } + else if ($user_posts !== false) + { + 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 . $config['ranks_path'] . '/' . $rank['rank_image'] . '" alt="' . $rank['rank_title'] . '" title="' . $rank['rank_title'] . '" />' : ''; + $rank_img_src = (!empty($rank['rank_image'])) ? $phpbb_root_path . $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 +* @param bool $ignore_config Ignores the config-setting, to be still able to view the avatar in the UCP +* +* @return string Avatar image +*/ +function get_user_avatar($avatar, $avatar_type, $avatar_width, $avatar_height, $alt = 'USER_AVATAR', $ignore_config = false) +{ + global $user, $config, $phpbb_root_path, $phpEx; + + if (empty($avatar) || !$avatar_type || (!$config['allow_avatar'] && !$ignore_config)) + { + return ''; + } + + $avatar_img = ''; + + switch ($avatar_type) + { + case AVATAR_UPLOAD: + if (!$config['allow_avatar_upload'] && !$ignore_config) + { + return ''; + } + $avatar_img = $phpbb_root_path . "download/file.$phpEx?avatar="; + break; + + case AVATAR_GALLERY: + if (!$config['allow_avatar_local'] && !$ignore_config) + { + return ''; + } + $avatar_img = $phpbb_root_path . $config['avatar_gallery_path'] . '/'; + break; + + case AVATAR_REMOTE: + if (!$config['allow_avatar_remote'] && !$ignore_config) + { + return ''; + } + break; + } + + $avatar_img .= $avatar; + return '<img src="' . (str_replace(' ', '%20', $avatar_img)) . '" width="' . $avatar_width . '" height="' . $avatar_height . '" alt="' . ((!empty($user->lang[$alt])) ? $user->lang[$alt] : $alt) . '" />'; +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php new file mode 100644 index 0000000000..a5889224a1 --- /dev/null +++ b/phpBB/includes/functions_install.php @@ -0,0 +1,540 @@ +<?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 +*/ +function can_load_dll($dll) +{ + // SQLite2 is a tricky thing, from 5.0.0 it requires PDO; if PDO is not loaded we must state that SQLite is unavailable + // as the installer doesn't understand that the extension has a prerequisite. + if ($dll == 'sqlite' && version_compare(PHP_VERSION, '5.0.0', '>=') && !extension_loaded('pdo')) + { + return false; + } + return ((@ini_get('enable_dl') || strtolower(@ini_get('enable_dl')) == 'on') && (!@ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == 'off') && function_exists('dl') && @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_20x_options = false) +{ + global $lang; + $available_dbms = array( + 'firebird' => array( + 'LABEL' => 'FireBird', + 'SCHEMA' => 'firebird', + 'MODULE' => 'interbase', + 'DELIM' => ';;', + 'COMMENTS' => 'remove_remarks', + 'DRIVER' => 'firebird', + 'AVAILABLE' => true, + '2.0.x' => false, + ), + 'mysqli' => array( + 'LABEL' => 'MySQL with MySQLi Extension', + 'SCHEMA' => 'mysql_41', + 'MODULE' => 'mysqli', + 'DELIM' => ';', + 'COMMENTS' => 'remove_remarks', + 'DRIVER' => 'mysqli', + 'AVAILABLE' => true, + '2.0.x' => true, + ), + 'mysql' => array( + 'LABEL' => 'MySQL', + 'SCHEMA' => 'mysql', + 'MODULE' => 'mysql', + 'DELIM' => ';', + 'COMMENTS' => 'remove_remarks', + 'DRIVER' => 'mysql', + 'AVAILABLE' => true, + '2.0.x' => true, + ), + 'mssql' => array( + 'LABEL' => 'MS SQL Server 2000+', + 'SCHEMA' => 'mssql', + 'MODULE' => 'mssql', + 'DELIM' => 'GO', + 'COMMENTS' => 'remove_comments', + 'DRIVER' => 'mssql', + 'AVAILABLE' => true, + '2.0.x' => true, + ), + 'mssql_odbc'=> array( + 'LABEL' => 'MS SQL Server [ ODBC ]', + 'SCHEMA' => 'mssql', + 'MODULE' => 'odbc', + 'DELIM' => 'GO', + 'COMMENTS' => 'remove_comments', + 'DRIVER' => 'mssql_odbc', + 'AVAILABLE' => true, + '2.0.x' => true, + ), + 'oracle' => array( + 'LABEL' => 'Oracle', + 'SCHEMA' => 'oracle', + 'MODULE' => 'oci8', + 'DELIM' => '/', + 'COMMENTS' => 'remove_comments', + 'DRIVER' => 'oracle', + 'AVAILABLE' => true, + '2.0.x' => false, + ), + 'postgres' => array( + 'LABEL' => 'PostgreSQL 7.x/8.x', + 'SCHEMA' => 'postgres', + 'MODULE' => 'pgsql', + 'DELIM' => ';', + 'COMMENTS' => 'remove_comments', + 'DRIVER' => 'postgres', + 'AVAILABLE' => true, + '2.0.x' => true, + ), + 'sqlite' => array( + 'LABEL' => 'SQLite', + 'SCHEMA' => 'sqlite', + 'MODULE' => 'sqlite', + 'DELIM' => ';', + 'COMMENTS' => 'remove_remarks', + 'DRIVER' => 'sqlite', + 'AVAILABLE' => true, + '2.0.x' => false, + ), + ); + + if ($dbms) + { + if (isset($available_dbms[$dbms])) + { + $available_dbms = array($dbms => $available_dbms[$dbms]); + } + else + { + return array(); + } + } + + // now perform some checks whether they are really available + foreach ($available_dbms as $db_name => $db_ary) + { + if ($only_20x_options && !$db_ary['2.0.x']) + { + if ($return_unavailable) + { + $available_dbms[$db_name]['AVAILABLE'] = false; + } + else + { + unset($available_dbms[$db_name]); + } + continue; + } + + $dll = $db_ary['MODULE']; + + if (!@extension_loaded($dll)) + { + if (!can_load_dll($dll)) + { + 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_20x_options = false) +{ + global $lang; + + $available_dbms = get_available_dbms(false, false, $only_20x_options); + $dbms_options = ''; + foreach ($available_dbms as $dbms_name => $details) + { + $selected = ($dbms_name == $default) ? ' selected="selected"' : ''; + $dbms_options .= '<option value="' . $dbms_name . '"' . $selected .'>' . $lang['DLL_' . strtoupper($dbms_name)] . '</option>'; + } + return $dbms_options; +} + +/** +* Get tables of a database +*/ +function get_tables($db) +{ + switch ($db->sql_layer) + { + case 'mysql': + case 'mysql4': + case 'mysqli': + $sql = 'SHOW TABLES'; + break; + + case 'sqlite': + $sql = 'SELECT name + FROM sqlite_master + WHERE type = "table"'; + break; + + case 'mssql': + case 'mssql_odbc': + $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 '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($error_connect, &$error, $dbms_details, $table_prefix, $dbhost, $dbuser, $dbpasswd, $dbname, $dbport, $prefix_may_exist = false, $load_dbal = true, $unicode_check = true) +{ + global $phpbb_root_path, $phpEx, $config, $lang; + + $dbms = $dbms_details['DRIVER']; + + if ($load_dbal) + { + // Include the DB layer + include($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx); + } + + // Instantiate it and set return on error true + $sql_db = 'dbal_' . $dbms; + $db = new $sql_db(); + $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[] = $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_realpath($dbhost), phpbb_realpath('../')) === 0) + { + $error[] = $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[] = $lang['INST_ERR_PREFIX_INVALID']; + return false; + } + + // no break; + + case 'postgres': + $prefix_length = 36; + break; + + case 'mssql': + case 'mssql_odbc': + $prefix_length = 90; + break; + + case 'sqlite': + $prefix_length = 200; + break; + + case 'firebird': + case 'oracle': + $prefix_length = 6; + break; + } + + if (strlen($table_prefix) > $prefix_length) + { + $error[] = sprintf($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[] = $lang['INST_ERR_DB_CONNECT'] . '<br />' . (($db_error['message']) ? $db_error['message'] : $lang['INST_ERR_DB_NO_ERROR']); + } + else + { + // 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[] = $lang['INST_ERR_PREFIX']; + } + } + + // Make sure that the user has selected a sensible DBAL for the DBMS actually installed + switch ($dbms_details['DRIVER']) + { + case 'mysqli': + if (version_compare(mysqli_get_server_info($db->db_connect_id), '4.1.3', '<')) + { + $error[] = $lang['INST_ERR_DB_NO_MYSQLI']; + } + break; + + case 'sqlite': + if (version_compare(sqlite_libversion(), '2.8.2', '<')) + { + $error[] = $lang['INST_ERR_DB_NO_SQLITE']; + } + 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 && function_exists('ibase_server_info')) + { + $val = @ibase_server_info($db->service_handle, IBASE_SVC_SERVER_VERSION); + preg_match('#V([\d.]+)#', $val, $match); + if ($match[1] < 2) + { + $error[] = $lang['INST_ERR_DB_NO_FIREBIRD']; + } + $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[] = $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[] = $lang['INST_ERR_DB_NO_FIREBIRD']; + } + else + { + $sql = 'SELECT 1 FROM RDB$DATABASE + WHERE BIN_AND(10, 1) = 0'; + $result = $db->sql_query($sql); + if (!$result) // This can only fail if BIN_AND is not defined + { + $error[] = $lang['INST_ERR_DB_NO_FIREBIRD']; + } + $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[] = $lang['INST_ERR_DB_NO_FIREBIRD_PS']; + } + else + { + // Kill the old table + $db->sql_query('DROP TABLE ' . $final . ';'); + } + unset($final); + } + break; + + case 'oracle': + if ($unicode_check) + { + $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', '<') && $stats['NLS_CHARACTERSET'] !== 'UTF8') + { + $error[] = $lang['INST_ERR_DB_NO_ORACLE']; + } + } + break; + + case 'postgres': + if ($unicode_check) + { + $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[] = $lang['INST_ERR_DB_NO_POSTGRES']; + } + } + break; + } + + } + + if ($error_connect && (!isset($error) || !sizeof($error))) + { + return true; + } + return false; +} + +/** +* remove_remarks will strip the sql comment lines out of an uploaded sql file +*/ +function remove_remarks(&$sql) +{ + $sql = preg_replace('/\n{2,}/', "\n", preg_replace('/^#.*$/m', "\n", $sql)); +} + +/** +* split_sql_file will split an uploaded sql file into single sql statements. +* Note: expects trim() to have already been run on $sql. +*/ +function split_sql_file($sql, $delimiter) +{ + $sql = str_replace("\r" , '', $sql); + $data = preg_split('/' . preg_quote($delimiter, '/') . '$/m', $sql); + + $data = array_map('trim', $data); + + // The empty case + $end_data = end($data); + + if (empty($end_data)) + { + unset($data[key($data)]); + } + + return $data; +} + +/** +* For replacing {L_*} strings with preg_replace_callback +*/ +function adjust_language_keys_callback($matches) +{ + if (!empty($matches[1])) + { + global $lang, $db; + + return (!empty($lang[$matches[1]])) ? $db->sql_escape($lang[$matches[1]]) : $db->sql_escape($matches[1]); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/functions_jabber.php b/phpBB/includes/functions_jabber.php new file mode 100644 index 0000000000..6d5021b9aa --- /dev/null +++ b/phpBB/includes/functions_jabber.php @@ -0,0 +1,872 @@ +<?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 +{ + var $connection = null; + var $session = array(); + var $timeout = 10; + + var $server; + var $connect_server; + var $port; + var $username; + var $password; + var $use_ssl; + var $resource = 'functions_jabber.phpbb.php'; + + var $enable_logging; + var $log_array; + + var $features = array(); + + /** + */ + function jabber($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 && $this->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? + */ + 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? + */ + 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 + */ + function set_resource($name) + { + $this->resource = $name; + } + + /** + * Connect + */ + 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 + */ + 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? + */ + 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 + */ + 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 public + * @return bool + */ + 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 public + * @return bool + */ + 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 + */ + function get_log() + { + if ($this->enable_logging && sizeof($this->log_array)) + { + return implode("<br /><br />", $this->log_array); + } + + return ''; + } + + /** + * Add information to log + */ + 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 public + * @return mixed either false for timeout or an array with the received data + */ + 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 $this->xmlize($data); + } + else + { + $this->add_to_log('Timeout, no response from server.'); + return false; + } + } + + /** + * Initiates account registration (based on data used for contructor) + * @access public + * @return bool + */ + 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 public + * @return bool + */ + 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 public + * @return bool + */ + 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'] && $this->can_use_tls() && $this->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 = $this->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; + } + } + + 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 + */ + 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 public + * @return array a => b ... + */ + 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 public + * @return string + */ + 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/ + */ + 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]['#'] = $this->_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/ + */ + 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]['#'] = $this->_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 new file mode 100644 index 0000000000..8f4e582b3c --- /dev/null +++ b/phpBB/includes/functions_messenger.php @@ -0,0 +1,1558 @@ +<?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 +{ + var $vars, $msg, $extra_headers, $replyto, $from, $subject; + var $addresses = array(); + + var $mail_priority = MAIL_NORMAL_PRIORITY; + var $use_queue = true; + + var $tpl_obj = NULL; + var $tpl_msg = array(); + var $eol = "\n"; + + /** + * Constructor + */ + function messenger($use_queue = true) + { + global $config; + + $this->use_queue = (!$config['email_package_size']) ? false : $use_queue; + $this->subject = ''; + + // Determine EOL character (\n for UNIX, \r\n for Windows and \r for Mac) + $this->eol = (!defined('PHP_EOL')) ? (($eol = strtolower(substr(PHP_OS, 0, 3))) == 'win') ? "\r\n" : (($eol == 'mac') ? "\r" : "\n") : PHP_EOL; + $this->eol = (!$this->eol) ? "\n" : $this->eol; + } + + /** + * Resets all the data (address, template file, etc etc) to default + */ + 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 = '') + { + global $config; + + 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 (!$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 = '', $template_path = '') + { + global $config, $phpbb_root_path, $user; + + if (!trim($template_file)) + { + trigger_error('No template file for emailing set.', E_USER_ERROR); + } + + if (!trim($template_lang)) + { + $template_lang = basename($config['default_lang']); + } + + // tpl_msg now holds a template object we can use to parse the template file + if (!isset($this->tpl_msg[$template_lang . $template_file])) + { + $this->tpl_msg[$template_lang . $template_file] = new template(); + $tpl = &$this->tpl_msg[$template_lang . $template_file]; + + if (!$template_path) + { + $template_path = (!empty($user->lang_path)) ? $user->lang_path : $phpbb_root_path . 'language/'; + $template_path .= $template_lang . '/email'; + } + + $tpl->set_custom_template($template_path, $template_lang . '_email', 'email'); + + $tpl->set_filenames(array( + 'body' => $template_file . '.txt', + )); + } + + $this->tpl_obj = &$this->tpl_msg[$template_lang . $template_file]; + $this->vars = &$this->tpl_obj->_rootref; + $this->tpl_msg = ''; + + return true; + } + + /** + * assign variables to email template + */ + function assign_vars($vars) + { + if (!is_object($this->tpl_obj)) + { + return; + } + + $this->tpl_obj->assign_vars($vars); + } + + function assign_block_vars($blockname, $vars) + { + if (!is_object($this->tpl_obj)) + { + return; + } + + $this->tpl_obj->assign_block_vars($blockname, $vars); + } + + /** + * Send the mail out to the recipients set previously in var $this->addresses + */ + function send($method = NOTIFY_EMAIL, $break = false) + { + global $config, $user; + + // We add some standard variables we always use, no need to specify them always + if (!isset($this->vars['U_BOARD'])) + { + $this->assign_vars(array( + 'U_BOARD' => generate_board_url(), + )); + } + + if (!isset($this->vars['EMAIL_SIG'])) + { + $this->assign_vars(array( + 'EMAIL_SIG' => str_replace('<br />', "\n", "-- \n" . htmlspecialchars_decode($config['board_email_sig'])), + )); + } + + if (!isset($this->vars['SITENAME'])) + { + $this->assign_vars(array( + 'SITENAME' => htmlspecialchars_decode($config['sitename']), + )); + } + + // Parse message through template + $this->msg = trim($this->tpl_obj->assign_display('body')); + + // Because we use \n for newlines in the body message we need to fix line encoding errors for those admins who uploaded email template files in the wrong encoding + $this->msg = str_replace("\r\n", "\n", $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 : $user->lang['NO_EMAIL_SUBJECT']); + $drop_header .= '[\r\n]*?' . preg_quote($match[1], '#'); + } + else + { + $this->subject = (($this->subject != '') ? $this->subject : $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 + */ + function error($type, $msg) + { + global $user, $phpEx, $phpbb_root_path, $config; + + // Session doesn't exist, create it + if (!isset($user->session_id) || $user->session_id === '') + { + $user->session_begin(); + } + + $calling_page = (!empty($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : $_ENV['PHP_SELF']; + + $message = ''; + switch ($type) + { + case 'EMAIL': + $message = '<strong>EMAIL/' . (($config['smtp_delivery']) ? 'SMTP' : 'PHP/' . $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() + { + global $config; + + if ($config['email_package_size'] && $this->use_queue && !empty($this->queue)) + { + $this->queue->save(); + return; + } + } + + /** + * Return email header + */ + function build_header($to, $cc, $bcc) + { + global $config; + + // We could use keys here, but we won't do this for 3.0.x to retain backwards compatibility + $headers = array(); + + $headers[] = 'From: ' . $this->from; + + if ($cc) + { + $headers[] = 'Cc: ' . $cc; + } + + if ($bcc) + { + $headers[] = 'Bcc: ' . $bcc; + } + + $headers[] = 'Reply-To: ' . $this->replyto; + $headers[] = 'Return-Path: <' . $config['board_email'] . '>'; + $headers[] = 'Sender: <' . $config['board_email'] . '>'; + $headers[] = 'MIME-Version: 1.0'; + $headers[] = 'Message-ID: <' . md5(unique_id(time())) . '@' . $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 + */ + function msg_email() + { + global $config, $user; + + if (empty($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 ($config['email_package_size'] && $this->use_queue) + { + if (empty($this->queue)) + { + $this->queue = new queue(); + $this->queue->init('email', $config['email_package_size']); + } + $use_queue = true; + } + + if (empty($this->replyto)) + { + $this->replyto = '<' . $config['board_contact'] . '>'; + } + + if (empty($this->from)) + { + $this->from = '<' . $config['board_contact'] . '>'; + } + + $encode_eol = ($config['smtp_delivery']) ? "\r\n" : $this->eol; + + // 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'], $encode_eol) . ' <' . $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 ($config['smtp_delivery']) + { + $result = smtpmail($this->addresses, mail_encode($this->subject), wordwrap(utf8_wordwrap($this->msg), 997, "\n", true), $err_msg, $headers); + } + else + { + $result = phpbb_mail($mail_to, $this->subject, $this->msg, $headers, $this->eol, $err_msg); + } + + if (!$result) + { + $this->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 + */ + function msg_jabber() + { + global $config, $db, $user, $phpbb_root_path, $phpEx; + + if (empty($config['jab_enable']) || empty($config['jab_host']) || empty($config['jab_username']) || empty($config['jab_password'])) + { + return false; + } + + if (empty($this->addresses['im'])) + { + // Send was successful. ;) + return true; + } + + $use_queue = false; + if ($config['jab_package_size'] && $this->use_queue) + { + if (empty($this->queue)) + { + $this->queue = new queue(); + $this->queue->init('jabber', $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.' . $phpEx); + $this->jabber = new jabber($config['jab_host'], $config['jab_port'], $config['jab_username'], $config['jab_password'], $config['jab_use_ssl']); + + if (!$this->jabber->connect()) + { + $this->error('JABBER', $user->lang['ERR_JAB_CONNECT'] . '<br />' . $this->jabber->get_log()); + return false; + } + + if (!$this->jabber->login()) + { + $this->error('JABBER', $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 +{ + var $data = array(); + var $queue_data = array(); + var $package_size = 0; + var $cache_file = ''; + var $eol = "\n"; + + /** + * constructor + */ + function queue() + { + global $phpEx, $phpbb_root_path; + + $this->data = array(); + $this->cache_file = "{$phpbb_root_path}cache/queue.$phpEx"; + + // Determine EOL character (\n for UNIX, \r\n for Windows and \r for Mac) + $this->eol = (!defined('PHP_EOL')) ? (($eol = strtolower(substr(PHP_OS, 0, 3))) == 'win') ? "\r\n" : (($eol == 'mac') ? "\r" : "\n") : PHP_EOL; + $this->eol = (!$this->eol) ? "\n" : $this->eol; + } + + /** + * Init a queue object + */ + 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 + */ + function put($object, $scope) + { + $this->data[$object]['data'][] = $scope; + } + + /** + * Process queue + * Using lock file + */ + function process() + { + global $db, $config, $phpEx, $phpbb_root_path, $user; + + 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() - $config['queue_interval'])) + { + return; + } + + $fp = @fopen($this->cache_file . '.lock', 'wb'); + fclose($fp); + @chmod($this->cache_file . '.lock', 0777); + + 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 (!$config['email_enable']) + { + unset($this->queue_data['email']); + continue 2; + } + break; + + case 'jabber': + if (!$config['jab_enable']) + { + unset($this->queue_data['jabber']); + continue 2; + } + + include_once($phpbb_root_path . 'includes/functions_jabber.' . $phpEx); + $this->jabber = new jabber($config['jab_host'], $config['jab_port'], $config['jab_username'], $config['jab_password'], $config['jab_use_ssl']); + + if (!$this->jabber->connect()) + { + messenger::error('JABBER', $user->lang['ERR_JAB_CONNECT']); + continue 2; + } + + if (!$this->jabber->login()) + { + messenger::error('JABBER', $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 ($config['smtp_delivery']) + { + $result = smtpmail($addresses, mail_encode($subject), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $err_msg, $headers); + } + else + { + $result = phpbb_mail($to, $subject, $msg, $headers, $this->eol, $err_msg); + } + + 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_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE); + } + } + + @unlink($this->cache_file . '.lock'); + } + + /** + * Save queue + */ + 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_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE); + } + } +} + +/** +* Replacement or substitute for PHP's mail command +*/ +function smtpmail($addresses, $subject, $message, &$err_msg, $headers = false) +{ + global $config, $user; + + // 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($user->lang['NO_EMAIL_SUBJECT'])) ? $user->lang['NO_EMAIL_SUBJECT'] : 'No email subject specified'; + return false; + } + + if (trim($message) == '') + { + $err_msg = (isset($user->lang['NO_EMAIL_MESSAGE'])) ? $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 ' . $config['smtp_host'] . ':' . $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($config['smtp_host'], $config['smtp_port'], $errno, $errstr, 20); + $error_contents = ob_get_clean(); + + if (!$smtp->socket) + { + if ($errstr) + { + $errstr = utf8_convert_message($errstr); + } + + $err_msg = (isset($user->lang['NO_CONNECT_TO_SMTP_HOST'])) ? sprintf($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($config['smtp_host'], $config['smtp_username'], $config['smtp_password'], $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:<' . $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) + { + $user->session_begin(); + $err_msg .= '<br /><br />'; + $err_msg .= (isset($user->lang['INVALID_EMAIL_LOG'])) ? sprintf($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 +{ + var $server_response = ''; + var $socket = 0; + var $responses = array(); + var $commands = array(); + var $numeric_response_code = 0; + + var $backtrace = false; + var $backtrace_log = array(); + + function smtp_class() + { + // Always create a backtrace for admins to identify SMTP problems + $this->backtrace = true; + $this->backtrace_log = array(); + } + + /** + * Add backtrace message for debugging + */ + function add_backtrace($message) + { + if ($this->backtrace) + { + $this->backtrace_log[] = utf8_htmlspecialchars($message); + } + } + + /** + * Send command to smtp server + */ + 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 + */ + function server_parse($response, $line) + { + global $user; + + $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($user->lang['NO_EMAIL_RESPONSE_CODE'])) ? $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($user->lang['EMAIL_SMTP_ERROR_RESPONSE'])) ? sprintf($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 + */ + 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 + */ + function log_into_server($hostname, $username, $password, $default_auth_method) + { + global $user; + + $err_msg = ''; + + // Here we try to determine the *real* hostname (reverse DNS entry preferrably) + $local_host = $user->host; + + if (function_exists('php_uname')) + { + $local_host = php_uname('n'); + + // Able to resolve name to IP + if (($addr = @gethostbyname($local_host)) !== $local_host) + { + // Able to resolve IP back to name + if (($name = @gethostbyaddr($addr)) !== $addr) + { + $local_host = $name; + } + } + } + + // 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) + { + global $config; + + $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($config['smtp_host'], $config['smtp_port'], $errno, $errstr, 10)) + { + if ($errstr) + { + $errstr = utf8_convert_message($errstr); + } + + $err_msg = (isset($user->lang['NO_CONNECT_TO_SMTP_HOST'])) ? sprintf($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($user->lang['SMTP_NO_AUTH_SUPPORT'])) ? $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($user->lang['NO_SUPPORTED_AUTH_METHODS'])) ? $user->lang['NO_SUPPORTED_AUTH_METHODS'] : 'No supported authentication methods'; + } + + $method = strtolower(str_replace('-', '_', $method)); + return $this->$method($username, $password); + } + + /** + * Pop before smtp authentication + */ + function pop_before_smtp($hostname, $username, $password) + { + global $user; + + if (!$this->socket = @fsockopen($hostname, 110, $errno, $errstr, 10)) + { + if ($errstr) + { + $errstr = utf8_convert_message($errstr); + } + + return (isset($user->lang['NO_CONNECT_TO_SMTP_HOST'])) ? sprintf($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 + */ + 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 + */ + 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 + */ + 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 *** + */ + function digest_md5($username, $password) + { + global $config, $user; + + $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') : $user->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/' . $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($user->lang['INVALID_DIGEST_CHALLENGE'])) ? $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. +* +* @param string $eol End of line we are using (optional to be backwards compatible) +*/ +function mail_encode($str, $eol = "\r\n") +{ + // define start delimimter, end delimiter and spacer + $start = "=?UTF-8?B?"; + $end = "?="; + $delimiter = "$eol "; + + // 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)); +} + +/** +* Wrapper for sending out emails with the PHP's mail function +*/ +function phpbb_mail($to, $subject, $msg, $headers, $eol, &$err_msg) +{ + global $config; + + // 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($eol, $headers); + + ob_start(); + // On some PHP Versions mail() *may* fail if there are newlines within the subject. + // Newlines are used as a delimiter for lines in mail_encode() according to RFC 2045 section 6.8. + // Because PHP can't decide what is wanted we revert back to the non-RFC-compliant way of separating by one space (Use '' as parameter to mail_encode() results in SPACE used) + $result = $config['email_function_name']($to, mail_encode($subject, ''), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $headers); + $err_msg = ob_get_clean(); + + return $result; +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/functions_module.php b/phpBB/includes/functions_module.php new file mode 100644 index 0000000000..d0e7c8cfc8 --- /dev/null +++ b/phpBB/includes/functions_module.php @@ -0,0 +1,883 @@ +<?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 + */ + function p_master($include_path = false) + { + global $phpbb_root_path; + + $this->include_path = ($include_path !== false) ? $include_path : $phpbb_root_path . 'includes/'; + + // 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 + */ + 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) + { + global $auth, $db, $user, $cache; + global $config, $phpbb_root_path, $phpEx; + + // 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 = $cache->get('_modules_' . $this->p_class)) === false) + { + // Get modules + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_class = '" . $db->sql_escape($this->p_class) . "' + ORDER BY left_id ASC"; + $result = $db->sql_query($sql); + + $rows = array(); + while ($row = $db->sql_fetchrow($result)) + { + $rows[$row['module_id']] = $row; + } + $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); + + $cache->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']) : ((!empty($user->lang[$row['module_langname']])) ? $user->lang[$row['module_langname']] : $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) + { + global $auth, $config; + + $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) $auth->acl_get(\'\\1\'\\2)', '(int) $forum_id', '(int) $auth->acl_getf_global(\'\\1\')', '(int) $config[\'\\1\']', '!empty($_REQUEST[\'\\1\'])'), $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) + { + global $phpbb_root_path, $phpbb_admin_path, $phpEx, $user; + + $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.$phpEx")) + { + trigger_error("Cannot find module $module_path/{$this->p_class}_$this->p_name.$phpEx", E_USER_ERROR); + } + + include("$module_path/{$this->p_class}_$this->p_name.$phpEx"); + + if (!class_exists("{$this->p_class}_$this->p_name")) + { + trigger_error("Module file $module_path/{$this->p_class}_$this->p_name.$phpEx 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 = append_sid("{$phpbb_admin_path}index.$phpEx", "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 . (($user->page['page_dir']) ? $user->page['page_dir'] . '/' : '') . $user->page['page_name']; + } + + $this->module->u_action = 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) + { + global $db; + + $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) + { + global $template; + + $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 + ); + + $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 + ); + + $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() + { + global $user; + + if (!isset($this->module->page_title)) + { + return ''; + } + + return (isset($user->lang[$this->module->page_title])) ? $user->lang[$this->module->page_title] : $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) + { + global $template, $user; + + // Generate the page + if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin']) + { + adm_page_header($page_title); + } + else + { + page_header($page_title, $display_online_list); + } + + $template->set_filenames(array( + 'body' => $this->get_tpl_name()) + ); + + if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin']) + { + adm_page_footer(); + } + else + { + 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) + { + global $user, $phpEx; + + if (file_exists($user->lang_path . $user->lang_name . '/mods')) + { + $add_files = array(); + + $dir = @opendir($user->lang_path . $user->lang_name . '/mods'); + + if ($dir) + { + while (($entry = readdir($dir)) !== false) + { + if (strpos($entry, 'info_' . strtolower($module_class) . '_') === 0 && substr(strrchr($entry, '.'), 1) == $phpEx) + { + $add_files[] = 'mods/' . substr(basename($entry), 0, -(strlen($phpEx) + 1)); + } + } + closedir($dir); + } + + if (sizeof($add_files)) + { + $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 new file mode 100644 index 0000000000..069740ebda --- /dev/null +++ b/phpBB/includes/functions_posting.php @@ -0,0 +1,2614 @@ +<?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) +{ + global $auth, $db, $user, $config, $template; + global $phpEx, $phpbb_root_path; + + $start = request_var('start', 0); + + if ($mode == 'window') + { + if ($forum_id) + { + $sql = 'SELECT forum_style + FROM ' . FORUMS_TABLE . " + WHERE forum_id = $forum_id"; + $result = $db->sql_query_limit($sql, 1); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $user->setup('posting', (int) $row['forum_style']); + } + else + { + $user->setup('posting'); + } + + page_header($user->lang['SMILIES']); + + $sql = 'SELECT COUNT(smiley_id) AS count + FROM ' . SMILIES_TABLE . ' + GROUP BY smiley_url'; + $result = $db->sql_query($sql, 3600); + + $smiley_count = 0; + while ($row = $db->sql_fetchrow($result)) + { + ++$smiley_count; + } + $db->sql_freeresult($result); + + $template->set_filenames(array( + 'body' => 'posting_smilies.html') + ); + + $template->assign_var('PAGINATION', + generate_pagination(append_sid("{$phpbb_root_path}posting.$phpEx", 'mode=smilies&f=' . $forum_id), + $smiley_count, $config['smilies_per_page'], $start, true) + ); + } + + $display_link = false; + if ($mode == 'inline') + { + $sql = 'SELECT smiley_id + FROM ' . SMILIES_TABLE . ' + WHERE display_on_posting = 0'; + $result = $db->sql_query_limit($sql, 1, 0, 3600); + + if ($row = $db->sql_fetchrow($result)) + { + $display_link = true; + } + $db->sql_freeresult($result); + } + + if ($mode == 'window') + { + $sql = 'SELECT smiley_url, MIN(emotion) as emotion, MIN(code) AS code, smiley_width, smiley_height + FROM ' . SMILIES_TABLE . ' + GROUP BY smiley_url, smiley_width, smiley_height + ORDER BY smiley_order'; + $result = $db->sql_query_limit($sql, $config['smilies_per_page'], $start, 3600); + } + else + { + $sql = 'SELECT * + FROM ' . SMILIES_TABLE . ' + WHERE display_on_posting = 1 + ORDER BY smiley_order'; + $result = $db->sql_query($sql, 3600); + } + + $smilies = array(); + while ($row = $db->sql_fetchrow($result)) + { + if (empty($smilies[$row['smiley_url']])) + { + $smilies[$row['smiley_url']] = $row; + } + } + $db->sql_freeresult($result); + + if (sizeof($smilies)) + { + $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path; + + foreach ($smilies as $row) + { + $template->assign_block_vars('smiley', array( + 'SMILEY_CODE' => $row['code'], + 'A_SMILEY_CODE' => addslashes($row['code']), + 'SMILEY_IMG' => $root_path . $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) + { + $template->assign_vars(array( + 'S_SHOW_SMILEY_LINK' => true, + 'U_MORE_SMILIES' => append_sid("{$phpbb_root_path}posting.$phpEx", '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) +{ + global $db; + + 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 " . $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 " . $db->sql_in_set('p.' . $type . '_id', $ids) . " + $topic_condition + AND p.post_approved = 1 + GROUP BY p.{$type}_id"; + } + $result = $db->sql_query($sql); + + $last_post_ids = array(); + while ($row = $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']; + } + $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 ' . $db->sql_in_set('p.post_id', $last_post_ids); + $result = $db->sql_query($sql); + + while ($row = $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 = '" . $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 = '" . $db->sql_escape($row['user_colour']) . "'"; + $update_sql[$row["{$type}_id"]][] = "{$type}_last_poster_name = '" . (($row['poster_id'] == ANONYMOUS) ? $db->sql_escape($row['post_username']) : $db->sql_escape($row['username'])) . "'"; + } + $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"; + $db->sql_query($sql); + } + + return; +} + +/** +* Generate Topic Icons for display +*/ +function posting_gen_topic_icons($mode, $icon_id) +{ + global $phpbb_root_path, $config, $template, $cache; + + // Grab icons + $icons = $cache->obtain_icons(); + + if (!$icon_id) + { + $template->assign_var('S_NO_ICON_CHECKED', ' checked="checked"'); + } + + if (sizeof($icons)) + { + foreach ($icons as $id => $data) + { + if ($data['display']) + { + $template->assign_block_vars('topic_icon', array( + 'ICON_ID' => $id, + 'ICON_IMG' => $phpbb_root_path . $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 $auth, $user, $template, $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 ($auth->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' => $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' => $user->lang['POST_NORMAL'])), + + $topic_type_array + ); + + foreach ($topic_type_array as $array) + { + $template->assign_block_vars('topic_type', $array); + } + + $template->assign_vars(array( + 'S_TOPIC_TYPE_STICKY' => ($auth->acl_get('f_sticky', $forum_id)), + 'S_TOPIC_TYPE_ANNOUNCE' => ($auth->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) +{ + global $auth, $user, $config, $db, $cache; + global $phpbb_root_path, $phpEx; + + $filedata = array( + 'error' => array() + ); + + include_once($phpbb_root_path . 'includes/functions_upload.' . $phpEx); + $upload = new fileupload(); + + if ($config['check_attachment_content']) + { + $upload->set_disallowed_content(explode('|', $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'][] = $user->lang['NO_UPLOAD_FORM_FOUND']; + return $filedata; + } + + $extensions = $cache->obtain_attach_extensions((($is_message) ? false : (int) $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($user->lang['ATTACHED_IMAGE_NOT_IMAGE']); + } + + // Do we have to create a thumbnail? + $filedata['thumbnail'] = ($cat_id == ATTACHMENT_CATEGORY_IMAGE && $config['img_create_thumbnail']) ? 1 : 0; + + // Check Image Size, if it is an image + if (!$auth->acl_get('a_') && !$auth->acl_get('m_', $forum_id) && $cat_id == ATTACHMENT_CATEGORY_IMAGE) + { + $file->upload->set_allowed_dimensions(0, 0, $config['img_max_width'], $config['img_max_height']); + } + + // Admins and mods are allowed to exceed the allowed filesize + if (!$auth->acl_get('a_') && !$auth->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) ? $config['max_filesize_pm'] : $config['max_filesize']; + } + + $file->upload->set_max_filesize($allowed_filesize); + } + + $file->clean_filename('unique', $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($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 ($config['attachment_quota']) + { + if ($config['upload_dir_size'] + $file->get('filesize') > $config['attachment_quota']) + { + $filedata['error'][] = $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 . $config['upload_path'])) + { + if ($free_space <= $file->get('filesize')) + { + $filedata['error'][] = $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) +{ + global $config; + + // Maximum Width the Image can take + $max_width = ($config['img_max_thumb_width']) ? $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) +{ + global $config; + + $min_filesize = (int) $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 ($config['img_imagick'] && function_exists('passthru')) + { + if (substr($config['img_imagick'], -1) !== '/') + { + $config['img_imagick'] .= '/'; + } + + @passthru(escapeshellcmd($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: + @ini_set('gd.jpeg_ignore_warning', 1); + $image = @imagecreatefromjpeg($source); + break; + + case IMG_PNG: + $image = @imagecreatefrompng($source); + break; + + case IMG_WBMP: + $image = @imagecreatefromwbmp($source); + break; + } + + if (empty($image)) + { + return false; + } + + 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_chmod($destination, CHMOD_READ | CHMOD_WRITE); + + return true; +} + +/** +* Assign Inline attachments (build option fields) +*/ +function posting_gen_inline_attachments(&$attachment_data) +{ + global $template; + + if (sizeof($attachment_data)) + { + $s_inline_attachment_options = ''; + + foreach ($attachment_data as $i => $attachment) + { + $s_inline_attachment_options .= '<option value="' . $i . '">' . utf8_basename($attachment['real_filename']) . '</option>'; + } + + $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) +{ + global $template, $config, $phpbb_root_path, $phpEx, $user, $auth; + + // Some default template variables + $template->assign_vars(array( + 'S_SHOW_ATTACH_BOX' => $show_attach_box, + 'S_HAS_ATTACHMENTS' => sizeof($attachment_data), + 'FILESIZE' => $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. + ($config['display_order']) ? krsort($attachment_data) : ksort($attachment_data); + + foreach ($attachment_data as $count => $attach_row) + { + $hidden = ''; + $attach_row['real_filename'] = utf8_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("{$phpbb_root_path}download/file.$phpEx", 'mode=view&id=' . (int) $attach_row['attach_id'], true, ($attach_row['is_orphan']) ? $user->session_id : false); + + $template->assign_block_vars('attach_row', array( + 'FILENAME' => utf8_basename($attach_row['real_filename']), + 'A_FILENAME' => addslashes(utf8_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, $pm_action = '', $msg_id = 0) +{ + global $user, $db, $template, $auth; + global $phpbb_root_path, $phpEx; + + $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 = ' . $user->data['user_id'] . " + $sql_and + ORDER BY d.save_time DESC"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if ($row['topic_id']) + { + $topic_ids[] = (int) $row['topic_id']; + } + $draft_rows[] = $row; + } + $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 ' . $db->sql_in_set('topic_id', array_unique($topic_ids)); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $topic_rows[$row['topic_id']] = $row; + } + $db->sql_freeresult($result); + } + unset($topic_ids); + + $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'] && $auth->acl_get('f_read', $topic_rows[$draft['topic_id']]['forum_id'])) + || + (!$topic_rows[$draft['topic_id']]['forum_id'] && $auth->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("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $topic_forum_id . '&t=' . $draft['topic_id']); + $title = $topic_rows[$draft['topic_id']]['topic_title']; + + $insert_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'f=' . $topic_forum_id . '&t=' . $draft['topic_id'] . '&mode=reply&d=' . $draft['draft_id']); + } + else if ($draft['forum_id'] && $auth->acl_get('f_read', $draft['forum_id'])) + { + $link_forum = true; + $view_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $draft['forum_id']); + $title = $draft['forum_name']; + + $insert_url = append_sid("{$phpbb_root_path}posting.$phpEx", '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("{$phpbb_root_path}ucp.$phpEx", "i=$id&mode=compose&d={$draft['draft_id']}" . (($pm_action) ? "&action=$pm_action" : '') . (($msg_id) ? "&p=$msg_id" : '')); + } + + $template->assign_block_vars('draftrow', array( + 'DRAFT_ID' => $draft['draft_id'], + 'DATE' => $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 $user, $auth, $db, $template, $bbcode, $cache; + global $config, $phpbb_root_path, $phpEx; + + // Go ahead and pull all data for this topic + $sql = 'SELECT p.post_id + FROM ' . POSTS_TABLE . ' p' . " + WHERE p.topic_id = $topic_id + " . ((!$auth->acl_get('m_approve', $forum_id)) ? 'AND p.post_approved = 1' : '') . ' + ' . (($mode == 'post_review') ? " AND p.post_id > $cur_post_id" : '') . ' + ' . (($mode == 'post_review_edit') ? " AND p.post_id = $cur_post_id" : '') . ' + ORDER BY p.post_time '; + $sql .= ($mode == 'post_review') ? 'ASC' : 'DESC'; + $result = $db->sql_query_limit($sql, $config['posts_per_page']); + + $post_list = array(); + + while ($row = $db->sql_fetchrow($result)) + { + $post_list[] = $row['post_id']; + } + + $db->sql_freeresult($result); + + if (!sizeof($post_list)) + { + return false; + } + + // Handle 'post_review_edit' like 'post_review' from now on + if ($mode == 'post_review_edit') + { + $mode = 'post_review'; + } + + $sql = $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 = ' . $user->data['user_id'] . ' AND z.zebra_id = p.poster_id' + ) + ), + + 'WHERE' => $db->sql_in_set('p.post_id', $post_list) . ' + AND u.user_id = p.poster_id' + )); + + $result = $db->sql_query($sql); + + $bbcode_bitfield = ''; + $rowset = array(); + $has_attachments = false; + while ($row = $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; + } + } + $db->sql_freeresult($result); + + // Instantiate BBCode class + if (!isset($bbcode) && $bbcode_bitfield !== '') + { + include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx); + $bbcode = new bbcode(base64_encode($bbcode_bitfield)); + } + + // Grab extensions + $extensions = $attachments = array(); + if ($has_attachments && $auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id)) + { + $extensions = $cache->obtain_attach_extensions($forum_id); + + // Get attachments... + $sql = 'SELECT * + FROM ' . ATTACHMENTS_TABLE . ' + WHERE ' . $db->sql_in_set('post_msg_id', $post_list) . ' + AND in_message = 0 + ORDER BY filetime DESC, post_msg_id ASC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $attachments[$row['post_msg_id']][] = $row; + } + $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 && $auth->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($phpbb_root_path . 'viewtopic.' . $phpEx, "f=$forum_id&t=$topic_id&p={$row['post_id']}&view=show#p{$row['post_id']}"); + + $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']) ? sprintf($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' => $user->img('icon_post_target', $user->lang['POST']), + 'POST_DATE' => $user->format_date($row['post_time']), + 'MESSAGE' => $message, + 'DECODED_MESSAGE' => $decoded_message, + 'POST_ID' => $row['post_id'], + 'U_MINI_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'p=' . $row['post_id']) . '#p' . $row['post_id'], + 'U_MCP_DETAILS' => ($auth->acl_get('m_info', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&mode=post_details&f=' . $forum_id . '&p=' . $row['post_id'], true, $user->session_id) : '', + 'POSTER_QUOTE' => ($show_quote_button && $auth->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) + { + $template->assign_block_vars($mode . '_row.attachment', array( + 'DISPLAY_ATTACHMENT' => $attachment) + ); + } + } + + unset($rowset[$i]); + } + + if ($mode == 'topic_review') + { + $template->assign_var('QUOTE_IMG', $user->img('icon_post_quote', $user->lang['REPLY_WITH_QUOTE'])); + } + + return true; +} + +/** +* User Notification +*/ +function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id, $topic_id, $post_id) +{ + global $db, $user, $config, $phpbb_root_path, $phpEx, $auth; + + $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 && !$config['allow_topic_notify']) || ($forum_notification && !$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 = $db->sql_query($sql); + + $sql_ignore_users = ANONYMOUS . ', ' . $user->data['user_id']; + while ($row = $db->sql_fetchrow($result)) + { + $sql_ignore_users .= ', ' . (int) $row['ban_userid']; + } + $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 (" . USER_NORMAL . ', ' . USER_FOUNDER . ') + AND u.user_id = w.user_id'; + $result = $db->sql_query($sql); + + while ($row = $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 + ); + } + $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 (" . USER_NORMAL . ', ' . USER_FOUNDER . ') + AND u.user_id = fw.user_id'; + $result = $db->sql_query($sql); + + while ($row = $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 + ); + } + $db->sql_freeresult($result); + } + + if (!sizeof($notify_rows)) + { + return; + } + + // Make sure users are allowed to read the forum + foreach ($auth->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.' . $phpEx); + $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.$phpEx?f=$forum_id", + 'U_TOPIC' => generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&t=$topic_id", + 'U_NEWEST_POST' => generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&t=$topic_id&p=$post_id&e=$post_id", + 'U_STOP_WATCHING_TOPIC' => generate_board_url() . "/viewtopic.$phpEx?uid={$addr['user_id']}&f=$forum_id&t=$topic_id&unwatch=topic", + 'U_STOP_WATCHING_FORUM' => generate_board_url() . "/viewforum.$phpEx?uid={$addr['user_id']}&f=$forum_id&unwatch=forum", + )); + + $messenger->send($addr['method']); + } + } + unset($msg_list_ary); + + $messenger->save_queue(); + } + + // Handle the DB updates + $db->sql_transaction('begin'); + + if (!empty($update_notification['topic'])) + { + $sql = 'UPDATE ' . TOPICS_WATCH_TABLE . " + SET notify_status = 1 + WHERE topic_id = $topic_id + AND " . $db->sql_in_set('user_id', $update_notification['topic']); + $db->sql_query($sql); + } + + if (!empty($update_notification['forum'])) + { + $sql = 'UPDATE ' . FORUMS_WATCH_TABLE . " + SET notify_status = 1 + WHERE forum_id = $forum_id + AND " . $db->sql_in_set('user_id', $update_notification['forum']); + $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 " . $db->sql_in_set('user_id', $delete_ids['topic']); + $db->sql_query($sql); + } + + if (!empty($delete_ids['forum'])) + { + $sql = 'DELETE FROM ' . FORUMS_WATCH_TABLE . " + WHERE forum_id = $forum_id + AND " . $db->sql_in_set('user_id', $delete_ids['forum']); + $db->sql_query($sql); + } + + $db->sql_transaction('commit'); +} + +// +// Post handling functions +// + +/** +* Delete Post +*/ +function delete_post($forum_id, $topic_id, $post_id, &$data) +{ + global $db, $user, $auth; + global $config, $phpEx, $phpbb_root_path; + + // 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.' . $phpEx); + + $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 ' . $db->sql_in_set('topic_moved_id', $topic_id); + $result = $db->sql_query($sql); + while ($row = $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']]++; + } + } + $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'); + } + + $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) + $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 = $db->sql_query_limit($sql, 1); + $row = $db->sql_fetchrow($result); + $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 = '" . $db->sql_escape($row['user_colour']) . "', topic_first_poster_name = '" . (($row['poster_id'] == ANONYMOUS) ? $db->sql_escape($row['post_username']) : $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 " . + ((!$auth->acl_get('m_approve', $forum_id)) ? 'AND post_approved = 1' : ''); + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $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 " . + ((!$auth->acl_get('m_approve', $forum_id)) ? 'AND post_approved = 1' : '') . ' + AND post_time > ' . $data['post_time'] . ' + ORDER BY post_time ASC'; + $result = $db->sql_query_limit($sql, 1); + $row = $db->sql_fetchrow($result); + $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; + } + + if (($post_mode == 'delete') || ($post_mode == 'delete_last_post') || ($post_mode == 'delete_first_post')) + { + $sql = 'SELECT 1 AS has_attachments + FROM ' . ATTACHMENTS_TABLE . ' + WHERE topic_id = ' . $topic_id; + $result = $db->sql_query_limit($sql, 1); + $has_attachments = (int) $db->sql_fetchfield('has_attachments'); + $db->sql_freeresult($result); + + if (!$has_attachments) + { + $sql_data[TOPICS_TABLE] .= ', topic_attachment = 0'; + } + } + +// $sql_data[USERS_TABLE] = ($data['post_postcount']) ? 'user_posts = user_posts - 1' : ''; + + $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) + { + $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' && $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 = $db->sql_query_limit($sql, 1); + $poster_id = (int) $db->sql_fetchfield('poster_id'); + $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']; + $db->sql_query($sql); + } + } + + $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 +* @todo Split up and create lightweight, simple API for this. +*/ +function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true, $update_search_index = true) +{ + global $db, $auth, $user, $config, $phpEx, $template, $phpbb_root_path; + + // 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) $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 = $db->sql_query($sql); + $topic_row = $db->sql_fetchrow($result); + $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 + // The variable name should be $post_approved, because it indicates if the post is approved or not + $post_approval = 1; + + // Check the permissions for post approval. Moderators are not affected. + if (!$auth->acl_get('f_noapprove', $data['forum_id']) && !$auth->acl_get('m_approve', $data['forum_id'])) + { + // Post not approved, but in queue + $post_approval = 0; + } + + // Mods are able to force approved/unapproved posts. True means the post is approved, false the post is unapproved + if (isset($data['force_approved_state'])) + { + $post_approval = ($data['force_approved_state']) ? 1 : 0; + } + + // Start the transaction here + $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) $user->data['user_id'], + 'icon_id' => $data['icon_id'], + 'poster_ip' => $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' => (!$user->data['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' => ($auth->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'] || (!$auth->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' && $auth->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 ($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 : $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) $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' => (!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : ''), + 'topic_first_poster_colour' => $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" . (($auth->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" . (($auth->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 = $db->sql_query($sql); + $topic_row = $db->sql_fetchrow($result); + $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 ($auth->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 ($auth->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 . ' ' . + $db->sql_build_array('INSERT', $sql_data[TOPICS_TABLE]['sql']); + $db->sql_query($sql); + + $data['topic_id'] = $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 . ' ' . $db->sql_build_array('INSERT', $sql_data[POSTS_TABLE]['sql']); + $db->sql_query($sql); + $data['post_id'] = $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) $user->data['user_id'], + 'topic_last_poster_name' => (!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : ''), + 'topic_last_poster_colour' => $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 = $db->sql_query($sql); + $topic_row = $db->sql_fetchrow($result); + $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'])) + { + $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']; + $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']; + $db->sql_query($sql); + } + } + + // Update the topics table + if (isset($sql_data[TOPICS_TABLE]['sql'])) + { + $sql = 'UPDATE ' . TOPICS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_data[TOPICS_TABLE]['sql']) . ' + WHERE topic_id = ' . $data['topic_id']; + $db->sql_query($sql); + } + + // Update the posts table + if (isset($sql_data[POSTS_TABLE]['sql'])) + { + $sql = 'UPDATE ' . POSTS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_data[POSTS_TABLE]['sql']) . ' + WHERE post_id = ' . $data['post_id']; + $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 = $db->sql_query($sql); + + $cur_poll_options = array(); + while ($row = $db->sql_fetchrow($result)) + { + $cur_poll_options[] = $row; + } + $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 = '" . $db->sql_escape($poll['poll_options'][$i]) . "' + WHERE poll_option_id = " . $cur_poll_options[$i]['poll_option_id'] . ' + AND topic_id = ' . $data['topic_id']; + $db->sql_query($sql); + } + } + } + + $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']; + $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)) + { + $db->sql_query('DELETE FROM ' . POLL_VOTES_TABLE . ' WHERE topic_id = ' . $data['topic_id']); + $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 ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . ' + AND is_orphan = 1 + AND poster_id = ' . $user->data['user_id']; + $result = $db->sql_query($sql); + + $orphan_rows = array(); + while ($row = $db->sql_fetchrow($result)) + { + $orphan_rows[$row['attach_id']] = $row; + } + $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 = '" . $db->sql_escape($attach_row['attach_comment']) . "' + WHERE attach_id = " . (int) $attach_row['attach_id'] . ' + AND is_orphan = 0'; + $db->sql_query($sql); + } + else + { + // insert attachment into db + if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . utf8_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 ' . $db->sql_build_array('UPDATE', $attach_sql) . ' + WHERE attach_id = ' . $attach_row['attach_id'] . ' + AND is_orphan = 1 + AND poster_id = ' . $user->data['user_id']; + $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 = '" . $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) $user->data['user_id']; + $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape((!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : '')) . "'"; + $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($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 = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $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 = \'' . $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 = '" . $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 = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $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 = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $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 = '" . $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 = '" . $db->sql_escape(($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']) . "'"; + $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $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 = $db->sql_query($sql); + $forum_row = $db->sql_fetchrow($result); + $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 = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $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 = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $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 = '" . $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 = '" . $db->sql_escape(($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']) . "'"; + $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $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 = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $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 = '" . $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 = '" . $db->sql_escape(($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']) . "'"; + $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $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) $user->data['user_id']; + $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape((!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : '')) . "'"; + $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_colour = '" . (($user->data['user_id'] != ANONYMOUS) ? $db->sql_escape($user->data['user_colour']) : '') . "'"; + $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $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 = '" . $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 = '" . $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 = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $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 = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $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 = '" . $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 = '" . $db->sql_escape(($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']) . "'"; + $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_colour = '" . $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]; + $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']; + $db->sql_query($sql); + } + + // Committing the transaction before updating search index + $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 = {$user->data['user_id']}"; + $db->sql_query($sql); + } + + // Index message contents + if ($update_search_index && $data['enable_indexing']) + { + // Select the search method and do some additional checks to ensure it can actually be utilised + $search_type = basename($config['search_type']); + + if (!file_exists($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx)) + { + trigger_error('NO_SUCH_SEARCH_MODULE'); + } + + if (!class_exists($search_type)) + { + include("{$phpbb_root_path}includes/search/$search_type.$phpEx"); + } + + $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 ($user->data['user_id'] == $poster_id) + { + if (!$data['notify_set'] && $data['notify']) + { + $sql = 'INSERT INTO ' . TOPICS_WATCH_TABLE . ' (user_id, topic_id) + VALUES (' . $user->data['user_id'] . ', ' . $data['topic_id'] . ')'; + $db->sql_query($sql); + } + else if ($data['notify_set'] && !$data['notify']) + { + $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . ' + WHERE user_id = ' . $user->data['user_id'] . ' + AND topic_id = ' . $data['topic_id']; + $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', (($topic_type == POST_GLOBAL) ? 0 : $data['forum_id']), $data['topic_id'], time()); + + // + if ($config['load_db_lastread'] && $user->data['is_registered']) + { + $sql = 'SELECT mark_time + FROM ' . FORUMS_TRACK_TABLE . ' + WHERE user_id = ' . $user->data['user_id'] . ' + AND forum_id = ' . (($topic_type == POST_GLOBAL) ? 0 : $data['forum_id']); + $result = $db->sql_query($sql); + $f_mark_time = (int) $db->sql_fetchfield('mark_time'); + $db->sql_freeresult($result); + } + else if ($config['load_anon_lastread'] || $user->data['is_registered']) + { + $f_mark_time = false; + } + + if (($config['load_db_lastread'] && $user->data['is_registered']) || $config['load_anon_lastread'] || $user->data['is_registered']) + { + // Update forum info + if ($topic_type == POST_GLOBAL) + { + $sql = 'SELECT MAX(topic_last_post_time) as forum_last_post_time + FROM ' . TOPICS_TABLE . ' + WHERE forum_id = 0'; + } + else + { + $sql = 'SELECT forum_last_post_time + FROM ' . FORUMS_TABLE . ' + WHERE forum_id = ' . $data['forum_id']; + } + $result = $db->sql_query($sql); + $forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time'); + $db->sql_freeresult($result); + + update_forum_tracking_info((($topic_type == POST_GLOBAL) ? 0 : $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) ? "{$phpbb_root_path}viewforum.$phpEx" : "{$phpbb_root_path}viewtopic.$phpEx"; + $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 new file mode 100644 index 0000000000..c93b6a6bba --- /dev/null +++ b/phpBB/includes/functions_privmsgs.php @@ -0,0 +1,1981 @@ +<?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) +{ + global $db, $user, $template; + global $phpbb_root_path, $phpEx; + + $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 = $db->sql_query($sql); + + $num_messages = $num_unread = array(); + while ($row = $db->sql_fetchrow($result)) + { + $num_messages[(int) $row['folder_id']] = $row['num_messages']; + $num_unread[(int) $row['folder_id']] = $row['num_unread']; + } + $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' => $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 = $db->sql_query($sql); + + while ($row = $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) + ); + } + $db->sql_freeresult($result); + + $folder[PRIVMSGS_OUTBOX] = array( + 'folder_name' => $user->lang['PM_OUTBOX'], + 'num_messages' => $num_messages[PRIVMSGS_OUTBOX], + 'unread_messages' => $num_unread[PRIVMSGS_OUTBOX] + ); + + $folder[PRIVMSGS_SENTBOX] = array( + 'folder_name' => $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'); + + $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("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=' . $f_id) : append_sid("{$phpbb_root_path}ucp.$phpEx", '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) +{ + global $db, $user, $config; + + // Check Message Limit + if ($user->data['message_limit'] && $num_sentbox_messages > $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 = ' . $user->data['user_id'] . ' + AND t.folder_id = ' . PRIVMSGS_SENTBOX . ' + ORDER BY p.message_time ASC'; + $result = $db->sql_query_limit($sql, ($num_sentbox_messages - $user->data['message_limit'])); + + $delete_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $delete_ids[] = $row['msg_id']; + } + $db->sql_freeresult($result); + delete_pm($user->data['user_id'], $delete_ids, PRIVMSGS_SENTBOX); + } +} + +/** +* Check Rule against Message Information +*/ +function check_rule(&$rules, &$rule_row, &$message_row, $user_id) +{ + global $user, $config; + + 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: + global $db, $auth; + + // 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 = $db->sql_query($sql); + $userdata = $db->sql_fetchrow($result); + $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() +{ + global $user, $db; + + // 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 = ' . $user->data['user_id']; + $result = $db->sql_query($sql); + $user->data['user_unread_privmsg'] = (int) $db->sql_fetchfield('num_messages'); + $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 = ' . $user->data['user_id']; + $result = $db->sql_query($sql); + $user->data['user_new_privmsg'] = (int) $db->sql_fetchfield('num_messages'); + $db->sql_freeresult($result); + + $db->sql_query('UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array( + 'user_unread_privmsg' => (int) $user->data['user_unread_privmsg'], + 'user_new_privmsg' => (int) $user->data['user_new_privmsg'], + )) . ' WHERE user_id = ' . $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 (!$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 = ' . $user->data['user_id']; + $db->sql_query($sql); + } +} + +/** +* Place new messages into appropriate folder +*/ +function place_pm_into_folder(&$global_privmsgs_rules, $release = false) +{ + global $db, $user, $config; + + if (!$user->data['user_new_privmsg']) + { + return array('not_moved' => 0, 'removed' => 0); + } + + $user_message_rules = (int) $user->data['user_message_rules']; + $user_id = (int) $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"; + $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 = $db->sql_query($retrieve_sql); + + while ($row = $db->sql_fetchrow($result)) + { + $action_ary[$row['msg_id']][] = array('action' => false); + } + $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 = $db->sql_query($sql); + $user_rules = $db->sql_fetchrowset($result); + $db->sql_freeresult($result); + + if (sizeof($user_rules)) + { + $sql = 'SELECT zebra_id, friend, foe + FROM ' . ZEBRA_TABLE . " + WHERE user_id = $user_id"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $zebra[$row['zebra_id']] = $row; + } + $db->sql_freeresult($result); + } + + // Now build a bare-bone check_row array + $result = $db->sql_query($retrieve_sql); + + while ($row = $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($user->data['group_id']), + 'author_in_group' => array()) + ); + + $user_ids[] = $row['user_id']; + } + $db->sql_freeresult($result); + + // Retrieve user memberships + if (sizeof($user_ids)) + { + $sql = 'SELECT * + FROM ' . USER_GROUP_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', $user_ids) . ' + AND user_pending = 0'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $memberships[$row['user_id']][] = $row['group_id']; + } + $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 ' . $db->sql_in_set('msg_id', $unread_ids) . " + AND user_id = $user_id + AND folder_id = " . PRIVMSGS_NO_BOX; + $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 " . $db->sql_in_set('msg_id', $important_ids); + $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 = ($user->data['user_full_folder'] == FULL_FOLDER_NONE) ? ($config['full_folder_action'] - (FULL_FOLDER_NONE*(-1))) : $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 ' . $db->sql_in_set('folder_id', $sql_folder) . " + AND user_id = $user_id"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $folder[(int) $row['folder_id']] = (int) $row['pm_count']; + } + $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 = $db->sql_query($sql); + $folder[PRIVMSGS_INBOX] = (int) $db->sql_fetchfield('num_messages'); + $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 ($user->data['message_limit'] && $folder[$folder_id] && ($folder[$folder_id] + sizeof($msg_ary)) > $user->data['message_limit']) + { + $full_folder_action = ($user->data['user_full_folder'] == FULL_FOLDER_NONE) ? ($config['full_folder_action'] - (FULL_FOLDER_NONE*(-1))) : $user->data['user_full_folder']; + + // If destination folder itself is full... + if ($full_folder_action >= 0 && ($folder[$full_folder_action] + sizeof($msg_ary)) > $user->data['message_limit']) + { + $full_folder_action = $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 = $db->sql_query_limit($sql, (($folder[$dest_folder] + sizeof($msg_ary)) - $user->data['message_limit'])); + + $delete_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $delete_ids[] = $row['msg_id']; + } + $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 " . $db->sql_in_set('msg_id', $msg_ary); + $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 " . $db->sql_in_set('msg_id', $msg_ary); + $db->sql_query($sql); + + if ($dest_folder != PRIVMSGS_INBOX) + { + $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . ' + SET pm_count = pm_count + ' . (int) $db->sql_affectedrows() . " + WHERE folder_id = $dest_folder + AND user_id = $user_id"; + $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 ' . $db->sql_in_set('msg_id', array_keys($action_ary)); + $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 = $db->sql_query($sql); + $num_not_moved = (int) $db->sql_fetchfield('num_messages'); + $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) +{ + global $db, $user; + global $phpbb_root_path, $phpEx; + + $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 = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error('NOT_AUTHORISED'); + } + + if ($message_limit && $row['pm_count'] + sizeof($move_msg_ids) > $message_limit) + { + $message = sprintf($user->lang['NOT_ENOUGH_SPACE_FOLDER'], $row['folder_name']) . '<br /><br />'; + $message .= sprintf($user->lang['CLICK_RETURN_FOLDER'], '<a href="' . append_sid("{$phpbb_root_path}ucp.$phpEx", '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 = $db->sql_query($sql); + $num_messages = (int) $db->sql_fetchfield('num_messages'); + $db->sql_freeresult($result); + + if ($message_limit && $num_messages + sizeof($move_msg_ids) > $message_limit) + { + $message = sprintf($user->lang['NOT_ENOUGH_SPACE_FOLDER'], $user->lang['PM_INBOX']) . '<br /><br />'; + $message .= sprintf($user->lang['CLICK_RETURN_FOLDER'], '<a href="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=inbox') . '">', '</a>', $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 " . $db->sql_in_set('msg_id', $move_msg_ids); + $db->sql_query($sql); + $num_moved = $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"; + $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"; + $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; + } + + global $db, $user; + + $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . " + SET pm_unread = 0 + WHERE msg_id = $msg_id + AND user_id = $user_id + AND folder_id = $folder_id"; + $db->sql_query($sql); + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_unread_privmsg = user_unread_privmsg - 1 + WHERE user_id = $user_id"; + $db->sql_query($sql); + + if ($user->data['user_id'] == $user_id) + { + $user->data['user_unread_privmsg']--; + + // Try to cope with previous wrong conversions... + if ($user->data['user_unread_privmsg'] < 0) + { + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_unread_privmsg = 0 + WHERE user_id = $user_id"; + $db->sql_query($sql); + + $user->data['user_unread_privmsg'] = 0; + } + } +} + +/** +* Handle all actions possible with marked messages +*/ +function handle_mark_actions($user_id, $mark_action) +{ + global $db, $user, $phpbb_root_path, $phpEx; + + $msg_ids = request_var('marked_msg_id', array(0)); + $cur_folder_id = request_var('cur_folder_id', PRIVMSGS_NO_BOX); + $confirm = (isset($_POST['confirm'])) ? true : false; + + 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 " . $db->sql_in_set('msg_id', $msg_ids); + $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("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=' . $cur_folder_id); + + meta_refresh(3, $redirect); + trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($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) +{ + global $db, $user, $phpbb_root_path, $phpEx; + + $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 ' . $db->sql_in_set('msg_id', array_map('intval', $msg_ids)) . " + AND folder_id = $folder_id + AND user_id = $user_id"; + $result = $db->sql_query($sql); + + $delete_rows = array(); + $num_unread = $num_new = $num_deleted = 0; + while ($row = $db->sql_fetchrow($result)) + { + $num_unread += (int) $row['pm_unread']; + $num_new += (int) $row['pm_new']; + + $delete_rows[$row['msg_id']] = 1; + } + $db->sql_freeresult($result); + unset($msg_ids); + + if (!sizeof($delete_rows)) + { + return false; + } + + $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 ' . $db->sql_in_set('msg_id', array_keys($delete_rows)); + $db->sql_query($sql); + + // Update PM Information for safety + $sql = 'UPDATE ' . PRIVMSGS_TABLE . " SET message_text = '' + WHERE " . $db->sql_in_set('msg_id', array_keys($delete_rows)); + $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 ' . $db->sql_in_set('msg_id', array_keys($delete_rows)); + $db->sql_query($sql); + + $num_deleted = $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 " . $db->sql_in_set('msg_id', array_keys($delete_rows)); + $db->sql_query($sql); + $num_deleted = $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"; + $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; + } + + $db->sql_query('UPDATE ' . USERS_TABLE . " SET $set_sql WHERE user_id = $user_id"); + + $user->data['user_new_privmsg'] -= $num_new; + $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 ' . $db->sql_in_set('msg_id', array_keys($delete_rows)); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + unset($delete_rows[$row['msg_id']]); + } + $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.' . $phpEx); + } + + delete_attachments('message', $delete_ids, false); + + $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . ' + WHERE ' . $db->sql_in_set('msg_id', $delete_ids); + $db->sql_query($sql); + } + + $db->sql_transaction('commit'); + + return true; +} + +/** +* Rebuild message header +*/ +function rebuild_header($check_ary) +{ + global $db; + + $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) +{ + global $db, $user, $template, $phpbb_root_path, $phpEx; + + $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 ' . $db->sql_in_set('user_id', $u); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id']) + { + if ($plaintext) + { + $address[] = $row['username']; + } + else + { + $address['user'][$row['user_id']] = array('name' => $row['username'], 'colour' => $row['user_colour']); + } + } + } + $db->sql_freeresult($result); + } + + if (sizeof($g)) + { + if ($plaintext) + { + $sql = 'SELECT group_name, group_type + FROM ' . GROUPS_TABLE . ' + WHERE ' . $db->sql_in_set('group_id', $g); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id']) + { + $address[] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; + } + } + $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 ' . $db->sql_in_set('g.group_id', $g) . ' + AND g.group_id = ug.group_id + AND ug.user_pending = 0'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if (!isset($address['group'][$row['group_id']])) + { + if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id']) + { + $row['group_name'] = ($row['group_type'] == GROUP_SPECIAL) ? $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']; + } + } + $db->sql_freeresult($result); + } + } + + if (sizeof($address) && !$plaintext) + { + $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("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&g=' . $id), + )); + } + + $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) +{ + global $db, $user, $config; + + if (isset($folder[$folder_id])) + { + $folder = $folder[$folder_id]; + } + else + { + return false; + } + + $return = array( + 'folder_name' => $folder['folder_name'], + 'cur' => $folder['num_messages'], + 'remaining' => ($user->data['message_limit']) ? $user->data['message_limit'] - $folder['num_messages'] : 0, + 'max' => $user->data['message_limit'], + 'percent' => ($user->data['message_limit']) ? (($user->data['message_limit'] > 0) ? round(($folder['num_messages'] / $user->data['message_limit']) * 100) : 100) : 0, + ); + + $return['message'] = sprintf($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) +{ + global $db, $auth, $config, $phpEx, $template, $user, $phpbb_root_path; + + // 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 = (!$auth->acl_gets('a_', 'm_') && !$auth->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 ' . $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 (' . USER_NORMAL . ', ' . USER_FOUNDER . ')' . + $sql_allow_pm; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + // Additionally, do not include the sender if he is in the group he wants to send to. ;) + if ($row['user_id'] === $user->data['user_id']) + { + continue; + } + + $field = ($data['address_list']['g'][$row['group_id']] == 'to') ? 'to' : 'bcc'; + $recipients[$row['user_id']] = $field; + } + $db->sql_freeresult($result); + } + + if (!sizeof($recipients)) + { + trigger_error('NO_RECIPIENT'); + } + } + + $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), + 'message_reported' => 0, + ); + 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') + { + $db->sql_query('INSERT INTO ' . PRIVMSGS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data)); + $data['msg_id'] = $db->sql_nextid(); + } + else if ($mode == 'edit') + { + $sql = 'UPDATE ' . PRIVMSGS_TABLE . ' + SET message_edit_count = message_edit_count + 1, ' . $db->sql_build_array('UPDATE', $sql_data) . ' + WHERE msg_id = ' . $data['msg_id']; + $db->sql_query($sql); + } + } + + if ($mode != 'edit') + { + if ($sql) + { + $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 + ); + } + + $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 ' . $db->sql_in_set('user_id', array_keys($recipients)); + $db->sql_query($sql); + + // Put PM into outbox + if ($put_in_outbox) + { + $db->sql_query('INSERT INTO ' . PRIVMSGS_TO_TABLE . ' ' . $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']; + $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 ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . ' + AND in_message = 1 + AND is_orphan = 1 + AND poster_id = ' . $user->data['user_id']; + $result = $db->sql_query($sql); + + $orphan_rows = array(); + while ($row = $db->sql_fetchrow($result)) + { + $orphan_rows[$row['attach_id']] = $row; + } + $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 = '" . $db->sql_escape($attach_row['attach_comment']) . "' + WHERE attach_id = " . (int) $attach_row['attach_id'] . ' + AND is_orphan = 0'; + $db->sql_query($sql); + } + else + { + // insert attachment into db + if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . utf8_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 ' . $db->sql_build_array('UPDATE', $attach_sql) . ' + WHERE attach_id = ' . $attach_row['attach_id'] . ' + AND is_orphan = 1 + AND poster_id = ' . $user->data['user_id']; + $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']; + $db->sql_query($sql); + } + + $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) +{ + global $db, $user, $config, $phpbb_root_path, $phpEx, $auth; + + $subject = censor_text($subject); + + unset($recipients[ANONYMOUS], $recipients[$user->data['user_id']]); + + if (!sizeof($recipients)) + { + return; + } + + // Get banned User ID's + $sql = 'SELECT ban_userid + FROM ' . BANLIST_TABLE . ' + WHERE ' . $db->sql_in_set('ban_userid', array_map('intval', array_keys($recipients))) . ' + AND ban_exclude = 0'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + unset($recipients[$row['ban_userid']]); + } + $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 ' . $db->sql_in_set('user_id', array_map('intval', array_keys($recipients))); + $result = $db->sql_query($sql); + + $msg_list_ary = array(); + while ($row = $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'] + ); + } + } + $db->sql_freeresult($result); + + if (!sizeof($msg_list_ary)) + { + return; + } + + include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + $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.$phpEx?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 $db, $user, $config, $template, $phpbb_root_path, $phpEx, $auth, $bbcode; + + // Select all receipts and the author from the pm we currently view, to only display their pm-history + $sql = 'SELECT author_id, user_id + FROM ' . PRIVMSGS_TO_TABLE . " + WHERE msg_id = $msg_id + AND folder_id <> " . PRIVMSGS_HOLD_BOX; + $result = $db->sql_query($sql); + + $recipients = array(); + while ($row = $db->sql_fetchrow($result)) + { + $recipients[] = (int) $row['user_id']; + $recipients[] = (int) $row['author_id']; + } + $db->sql_freeresult($result); + $recipients = array_unique($recipients); + + // 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 ' . $db->sql_in_set('t.author_id', $recipients, false, true) . " + AND t.user_id = $user_id"; + + // We no longer need those. + unset($recipients); + + 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 = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + + if (!$row) + { + $db->sql_freeresult($result); + return false; + } + + $rowset = array(); + $bbcode_bitfield = ''; + $folder_url = append_sid("{$phpbb_root_path}ucp.$phpEx", '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>' : $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>' : $user->lang['UNKNOWN_FOLDER']; + } + else + { + $rowset[$row['msg_id']] = $row; + $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']); + } + } + while ($row = $db->sql_fetchrow($result)); + $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.' . $phpEx); + } + $bbcode = new bbcode(base64_encode($bbcode_bitfield)); + } + + $title = censor_text($title); + + $url = append_sid("{$phpbb_root_path}ucp.$phpEx", '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 && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) + { + $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; + } + + $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' => $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 && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&mode=compose&action=quote&f=" . $folder_id . "&p=" . $row['msg_id'] : '', + 'U_POST_REPLY_PM' => ($author_id != $user->data['user_id'] && $author_id != ANONYMOUS && $auth->acl_get('u_sendpm')) ? "$url&mode=compose&action=reply&f=$folder_id&p=" . $row['msg_id'] : '') + ); + unset($rowset[$i]); + $prev_id = $id; + } + + $template->assign_vars(array( + 'QUOTE_IMG' => $user->img('icon_post_quote', $user->lang['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() +{ + global $user, $db, $config; + + // 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 = ' . $user->data['user_id'] . ' + AND ug.user_pending = 0 + AND ug.group_id = g.group_id'; + $result = $db->sql_query($sql); + $message_limit = (int) $db->sql_fetchfield('max_message_limit'); + $db->sql_freeresult($result); + + $user->data['message_limit'] = (!$message_limit) ? $config['pm_max_msgs'] : $message_limit; +} + +/** +* Generates an array of coloured recipient names from a list of PMs - (groups & users) +* +* @param array $pm_by_id An array of rows from PRIVMSGS_TABLE, keys are the msg_ids. +* +* @return array 2D Array: array(msg_id => array('username or group string', ...), ...) +* Usernames are generated with {@link get_username_string get_username_string} +* Groups are coloured and have a link to the membership page +*/ +function get_recipient_strings($pm_by_id) +{ + global $db, $phpbb_root_path, $phpEx, $user; + + $address_list = $recipient_list = $address = array(); + + $_types = array('u', 'g'); + + foreach ($pm_by_id as $message_id => $row) + { + $address[$message_id] = rebuild_header(array('to' => $row['to_address'], 'bcc' => $row['bcc_address'])); + + foreach ($_types as $ug_type) + { + if (isset($address[$message_id][$ug_type]) && sizeof($address[$message_id][$ug_type])) + { + foreach ($address[$message_id][$ug_type] as $ug_id => $in_to) + { + $recipient_list[$ug_type][$ug_id] = array('name' => $user->lang['NA'], 'colour' => ''); + } + } + } + } + + foreach ($_types as $ug_type) + { + if (!empty($recipient_list[$ug_type])) + { + if ($ug_type == 'u') + { + $sql = 'SELECT user_id as id, username as name, user_colour as colour + FROM ' . USERS_TABLE . ' + WHERE '; + } + else + { + $sql = 'SELECT group_id as id, group_name as name, group_colour as colour, group_type + FROM ' . GROUPS_TABLE . ' + WHERE '; + } + $sql .= $db->sql_in_set(($ug_type == 'u') ? 'user_id' : 'group_id', array_map('intval', array_keys($recipient_list[$ug_type]))); + + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if ($ug_type == 'g') + { + $row['name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['name']] : $row['name']; + } + + $recipient_list[$ug_type][$row['id']] = array('name' => $row['name'], 'colour' => $row['colour']); + } + $db->sql_freeresult($result); + } + } + + foreach ($address as $message_id => $adr_ary) + { + foreach ($adr_ary as $type => $id_ary) + { + foreach ($id_ary as $ug_id => $_id) + { + if ($type == 'u') + { + $address_list[$message_id][] = get_username_string('full', $ug_id, $recipient_list[$type][$ug_id]['name'], $recipient_list[$type][$ug_id]['colour']); + } + else + { + $user_colour = ($recipient_list[$type][$ug_id]['colour']) ? ' style="font-weight: bold; color:#' . $recipient_list[$type][$ug_id]['colour'] . '"' : ''; + $link = '<a href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&g=' . $ug_id) . '"' . $user_colour . '>'; + $address_list[$message_id][] = $link . $recipient_list[$type][$ug_id]['name'] . (($link) ? '</a>' : ''); + } + } + } + } + + return $address_list; +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/functions_profile_fields.php b/phpBB/includes/functions_profile_fields.php new file mode 100644 index 0000000000..9e356414a9 --- /dev/null +++ b/phpBB/includes/functions_profile_fields.php @@ -0,0 +1,1143 @@ +<?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 +{ + var $profile_types = array(FIELD_INT => 'int', FIELD_STRING => 'string', FIELD_TEXT => 'text', FIELD_BOOL => 'bool', FIELD_DROPDOWN => 'dropdown', FIELD_DATE => 'date'); + var $profile_cache = array(); + var $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 + */ + function generate_profile_fields($mode, $lang_id) + { + global $db, $template, $auth; + + $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 (!$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_')) + { + $sql_where .= ' AND f.field_show_profile = 1'; + } + 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 = $db->sql_query($sql); + + while ($row = $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']; + + $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) + ); + } + $db->sql_freeresult($result); + } + + /** + * Validate entered profile field data + * @access public + */ + function validate_profile_field($field_type, &$field_value, $field_data) + { + 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: + $field_value = (bool) $field_value; + + if (!$field_value && $field_data['field_required']) + { + return 'FIELD_REQUIRED'; + } + break; + + case FIELD_INT: + if (trim($field_value) === '' && !$field_data['field_required']) + { + return false; + } + + $field_value = (int) $field_value; + + 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: + $field_value = (int) $field_value; + + 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 + */ + function build_cache() + { + global $db, $user, $auth; + + $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 = ' . $user->get_iso_lang_id() . ' + AND f.field_active = 1 ' . + ((!$auth->acl_gets('a_', 'm_') && !$auth->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 = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $this->profile_cache[$row['field_ident']] = $row; + } + $db->sql_freeresult($result); + } + + /** + * Get language entries for options and store them here for later use + */ + function get_option_lang($field_id, $lang_id, $field_type, $preview) + { + global $db; + + if ($preview) + { + $lang_options = (!is_array($this->vars['lang_options'])) ? explode("\n", $this->vars['lang_options']) : $this->vars['lang_options']; + + 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 = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $this->options_lang[$field_id][$lang_id][($row['option_id'] + 1)] = $row['lang_value']; + } + $db->sql_freeresult($result); + } + } + + /** + * Submit profile field for validation + * @access public + */ + function submit_cp_field($mode, $lang_id, &$cp_data, &$cp_error) + { + global $auth, $db, $user; + + $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 (!$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_')) + { + $sql_where .= ' AND f.field_show_profile = 1'; + } + 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 = $db->sql_query($sql); + + while ($row = $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($user->lang[$cp_result], $row['lang_name']); + break; + + case 'FIELD_TOO_SHORT': + case 'FIELD_TOO_SMALL': + $error = sprintf($user->lang[$cp_result], $row['lang_name'], $row['field_minlen']); + break; + + case 'FIELD_TOO_LONG': + case 'FIELD_TOO_LARGE': + $error = sprintf($user->lang[$cp_result], $row['lang_name'], $row['field_maxlen']); + break; + + case 'FIELD_INVALID_CHARS': + switch ($row['field_validation']) + { + case '[0-9]+': + $error = sprintf($user->lang[$cp_result . '_NUMBERS_ONLY'], $row['lang_name']); + break; + + case '[\w]+': + $error = sprintf($user->lang[$cp_result . '_ALPHA_ONLY'], $row['lang_name']); + break; + + case '[\w_\+\. \-\[\]]+': + $error = sprintf($user->lang[$cp_result . '_SPACERS_ONLY'], $row['lang_name']); + break; + } + break; + } + + if ($error != '') + { + $cp_error[] = $error; + } + } + } + $db->sql_freeresult($result); + } + + /** + * Update profile field data directly + */ + function update_profile_field_data($user_id, &$cp_data) + { + global $db; + + if (!sizeof($cp_data)) + { + return; + } + + switch ($db->sql_layer) + { + case 'oracle': + case 'firebird': + case 'postgres': + $right_delim = $left_delim = '"'; + break; + + case 'sqlite': + case 'mssql': + case 'mssql_odbc': + $right_delim = ']'; + $left_delim = '['; + break; + + case 'mysql': + case 'mysql4': + case 'mysqli': + $right_delim = $left_delim = '`'; + break; + } + + // use new array for the UPDATE; changes in the key do not affect the original array + $cp_data_sql = array(); + foreach ($cp_data as $key => $value) + { + // Firebird is case sensitive with delimiter + $cp_data_sql[$left_delim . (($db->sql_layer == 'firebird' || $db->sql_layer == 'oracle') ? strtoupper($key) : $key) . $right_delim] = $value; + } + + $sql = 'UPDATE ' . PROFILE_FIELDS_DATA_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $cp_data_sql) . " + WHERE user_id = $user_id"; + $db->sql_query($sql); + + if (!$db->sql_affectedrows()) + { + $cp_data_sql['user_id'] = (int) $user_id; + + $db->sql_return_on_error(true); + + $sql = 'INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $cp_data_sql); + $db->sql_query($sql); + + $db->sql_return_on_error(false); + } + } + + /** + * 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 + */ + function generate_profile_fields_template($mode, $user_id = 0, $profile_row = false) + { + global $db; + + 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 ' . $db->sql_in_set('user_id', array_map('intval', $user_id)); + $result = $db->sql_query($sql); + + $field_data = array(); + while ($row = $db->sql_fetchrow($result)) + { + $field_data[$row['user_id']] = $row; + } + $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 + */ + function get_profile_value($ident_ary) + { + $value = $ident_ary['value']; + $field_type = $ident_ary['data']['field_type']; + + switch ($this->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) + { + global $user; + // 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 $user->format_date(gmmktime(0, 0, 0, $month, $day, $year) + $user->timezone + $user->dst, $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 + */ + function get_var($field_validation, &$profile_row, $default_value, $preview) + { + global $user; + + $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 = (isset($_REQUEST[$profile_row['field_ident']])) ? true : ((!isset($user->profile_fields[$user_ident]) || $preview) ? $default_value : $user->profile_fields[$user_ident]); + } + else if ($profile_row['field_type'] == FIELD_INT) + { + if (isset($_REQUEST[$profile_row['field_ident']])) + { + $value = ($_REQUEST[$profile_row['field_ident']] === '') ? NULL : request_var($profile_row['field_ident'], $default_value); + } + else + { + if (!$preview && isset($user->profile_fields[$user_ident]) && is_null($user->profile_fields[$user_ident])) + { + $value = NULL; + } + else if (!isset($user->profile_fields[$user_ident]) || $preview) + { + $value = $default_value; + } + else + { + $value = $user->profile_fields[$user_ident]; + } + } + + return (is_null($value) || $value === '') ? '' : (int) $value; + } + else + { + $value = (isset($_REQUEST[$profile_row['field_ident']])) ? request_var($profile_row['field_ident'], $default_value, true) : ((!isset($user->profile_fields[$user_ident]) || $preview) ? $default_value : $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 + */ + function generate_int($profile_row, $preview = false) + { + global $template; + + $profile_row['field_value'] = $this->get_var('int', $profile_row, $profile_row['field_default_value'], $preview); + $template->assign_block_vars($this->profile_types[$profile_row['field_type']], array_change_key_case($profile_row, CASE_UPPER)); + } + + /** + * Process date-type + * @access private + */ + function generate_date($profile_row, $preview = false) + { + global $user, $template; + + $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 (!isset($_REQUEST[$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($user->profile_fields[$user_ident]) || $preview) ? $profile_row['field_default_value'] : $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($user->profile_fields[$user_ident]) || $preview) ? $profile_row['field_default_value'] : $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; + $template->assign_block_vars($this->profile_types[$profile_row['field_type']], array_change_key_case($profile_row, CASE_UPPER)); + } + + /** + * Process bool-type + * @access private + */ + function generate_bool($profile_row, $preview = false) + { + global $template; + + $value = $this->get_var('int', $profile_row, $profile_row['field_default_value'], $preview); + + $profile_row['field_value'] = $value; + $template->assign_block_vars($this->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) + { + $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 + */ + function generate_string($profile_row, $preview = false) + { + global $template; + + $profile_row['field_value'] = $this->get_var('string', $profile_row, $profile_row['lang_default_value'], $preview); + $template->assign_block_vars($this->profile_types[$profile_row['field_type']], array_change_key_case($profile_row, CASE_UPPER)); + } + + /** + * Process text-type + * @access private + */ + function generate_text($profile_row, $preview = false) + { + global $template; + global $user, $phpEx, $phpbb_root_path; + + $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); + $template->assign_block_vars($this->profile_types[$profile_row['field_type']], array_change_key_case($profile_row, CASE_UPPER)); + } + + /** + * Process dropdown-type + * @access private + */ + function generate_dropdown($profile_row, $preview = false) + { + global $user, $template; + + $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; + $template->assign_block_vars($this->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) + { + $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 + */ + function process_field_row($mode, $profile_row) + { + global $template; + + $preview = ($mode == 'preview') ? true : false; + + // set template filename + $template->set_filenames(array( + 'cp_body' => 'custom_profile_fields.html') + ); + + // empty previously filled blockvars + foreach ($this->profile_types as $field_case => $field_type) + { + $template->destroy_block_vars($field_type); + } + + // Assign template variables + $type_func = 'generate_' . $this->profile_types[$profile_row['field_type']]; + $this->$type_func($profile_row, $preview); + + // Return templated data + return $template->assign_display('cp_body'); + } + + /** + * Build Array for user insertion into custom profile fields table + */ + function build_insert_sql_array($cp_data) + { + global $db, $user, $auth; + + $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 = ' . $user->get_iso_lang_id() . ' + ' . ((sizeof($sql_not_in)) ? ' AND ' . $db->sql_in_set('f.field_ident', $sql_not_in, true) : '') . ' + AND l.field_id = f.field_id'; + $result = $db->sql_query($sql); + + while ($row = $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']; + } + $db->sql_freeresult($result); + + return $cp_data; + } + + /** + * Get profile field value on submit + * @access private + */ + function get_profile_field($profile_row) + { + global $phpbb_root_path, $phpEx; + global $config; + + $var_name = 'pf_' . $profile_row['field_ident']; + + switch ($profile_row['field_type']) + { + case FIELD_DATE: + + if (!isset($_REQUEST[$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 = (isset($_REQUEST[$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 (isset($_REQUEST[$var_name]) && $_REQUEST[$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 +{ + var $vars = array(); + + /** + * Return possible validation options + */ + function validate_options() + { + global $user; + + $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 . '>' . $user->lang[$lang] . '</option>'; + } + + return $validate_options; + } + + /** + * Get string options for second step in ACP + */ + function get_string_options() + { + global $user; + + $options = array( + 0 => array('TITLE' => $user->lang['FIELD_LENGTH'], 'FIELD' => '<input type="text" name="field_length" size="5" value="' . $this->vars['field_length'] . '" />'), + 1 => array('TITLE' => $user->lang['MIN_FIELD_CHARS'], 'FIELD' => '<input type="text" name="field_minlen" size="5" value="' . $this->vars['field_minlen'] . '" />'), + 2 => array('TITLE' => $user->lang['MAX_FIELD_CHARS'], 'FIELD' => '<input type="text" name="field_maxlen" size="5" value="' . $this->vars['field_maxlen'] . '" />'), + 3 => array('TITLE' => $user->lang['FIELD_VALIDATION'], 'FIELD' => '<select name="field_validation">' . $this->validate_options() . '</select>') + ); + + return $options; + } + + /** + * Get text options for second step in ACP + */ + function get_text_options() + { + global $user; + + $options = array( + 0 => array('TITLE' => $user->lang['FIELD_LENGTH'], 'FIELD' => '<input name="rows" size="5" value="' . $this->vars['rows'] . '" /> ' . $user->lang['ROWS'] . '</dd><dd><input name="columns" size="5" value="' . $this->vars['columns'] . '" /> ' . $user->lang['COLUMNS'] . ' <input type="hidden" name="field_length" value="' . $this->vars['field_length'] . '" />'), + 1 => array('TITLE' => $user->lang['MIN_FIELD_CHARS'], 'FIELD' => '<input type="text" name="field_minlen" size="10" value="' . $this->vars['field_minlen'] . '" />'), + 2 => array('TITLE' => $user->lang['MAX_FIELD_CHARS'], 'FIELD' => '<input type="text" name="field_maxlen" size="10" value="' . $this->vars['field_maxlen'] . '" />'), + 3 => array('TITLE' => $user->lang['FIELD_VALIDATION'], 'FIELD' => '<select name="field_validation">' . $this->validate_options() . '</select>') + ); + + return $options; + } + + /** + * Get int options for second step in ACP + */ + function get_int_options() + { + global $user; + + $options = array( + 0 => array('TITLE' => $user->lang['FIELD_LENGTH'], 'FIELD' => '<input type="text" name="field_length" size="5" value="' . $this->vars['field_length'] . '" />'), + 1 => array('TITLE' => $user->lang['MIN_FIELD_NUMBER'], 'FIELD' => '<input type="text" name="field_minlen" size="5" value="' . $this->vars['field_minlen'] . '" />'), + 2 => array('TITLE' => $user->lang['MAX_FIELD_NUMBER'], 'FIELD' => '<input type="text" name="field_maxlen" size="5" value="' . $this->vars['field_maxlen'] . '" />'), + 3 => array('TITLE' => $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 + */ + function get_bool_options() + { + global $user, $config, $lang_defs; + + $default_lang_id = $lang_defs['iso'][$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' => $user->lang['FIELD_TYPE'], 'EXPLAIN' => $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();" /> ' . $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();" /> ' . $user->lang['CHECKBOX'] . '</label>'), + 1 => array('TITLE' => $user->lang['DEFAULT_VALUE'], 'FIELD' => $this->process_field_row('preview', $profile_row)) + ); + + return $options; + } + + /** + * Get dropdown options for second step in ACP + */ + function get_dropdown_options() + { + global $user, $config, $lang_defs; + + $default_lang_id = $lang_defs['iso'][$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' => $user->lang['DEFAULT_VALUE'], 'FIELD' => $this->process_field_row('preview', $profile_row[0])), + 1 => array('TITLE' => $user->lang['NO_VALUE_OPTION'], 'EXPLAIN' => $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 + */ + function get_date_options() + { + global $user, $config, $lang_defs; + + $default_lang_id = $lang_defs['iso'][$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' => $user->lang['DEFAULT_VALUE'], 'FIELD' => $this->process_field_row('preview', $profile_row)), + 1 => array('TITLE' => $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();" /> ' . $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();" /> ' . $user->lang['NO'] . '</label>'), + ); + + return $options; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/functions_template.php b/phpBB/includes/functions_template.php new file mode 100644 index 0000000000..1d3a4d74f8 --- /dev/null +++ b/phpBB/includes/functions_template.php @@ -0,0 +1,814 @@ +<?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; +} + +/** +* 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 +*/ +class template_compile +{ + var $template; + + // Various storage arrays + var $block_names = array(); + var $block_else_level = array(); + + /** + * constuctor + */ + function template_compile(&$template) + { + $this->template = &$template; + } + + /** + * Load template source from file + * @access private + */ + function _tpl_load_file($handle, $store_in_db = false) + { + // 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); + } + + $this->template->compiled_code[$handle] = $this->compile(trim(@file_get_contents($this->template->files[$handle]))); + + // Actually compile the code now. + $this->compile_write($handle, $this->template->compiled_code[$handle]); + + // Store in database if required... + if ($store_in_db) + { + global $db, $user; + + $sql_ary = array( + 'template_id' => $this->template->files_template[$handle], + 'template_filename' => $this->template->filename[$handle], + 'template_included' => '', + 'template_mtime' => time(), + 'template_data' => trim(@file_get_contents($this->template->files[$handle])), + ); + + $sql = 'INSERT INTO ' . STYLES_TEMPLATE_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); + $db->sql_query($sql); + } + } + + /** + * Remove any PHP tags that do not belong, these regular expressions are derived from + * the ones that exist in zend_language_scanner.l + * @access private + */ + function remove_php_tags(&$code) + { + // This matches the information gathered from the internal PHP lexer + $match = array( + '#<([\?%])=?.*?\1>#s', + '#<script\s+language\s*=\s*(["\']?)php\1\s*>.*?</script\s*>#s', + '#<\?php(?:\r\n?|[ \n\t]).*?\?>#s' + ); + + $code = preg_replace($match, '', $code); + } + + /** + * The all seeing all doing compile method. Parts are inspired by or directly from Smarty + * @access private + */ + function compile($code, $no_echo = false, $echo_var = '') + { + global $config; + + if ($echo_var) + { + global $$echo_var; + } + + // Remove any "loose" php ... we want to give admins the ability + // to switch on/off PHP for a given template. Allowing unchecked + // php is a no-no. There is a potential issue here in that non-php + // content may be removed ... however designers should use entities + // if they wish to display < and > + $this->remove_php_tags($code); + + // Pull out all block/statement level elements and separate plain text + preg_match_all('#<!-- PHP -->(.*?)<!-- ENDPHP -->#s', $code, $matches); + $php_blocks = $matches[1]; + $code = preg_replace('#<!-- PHP -->.*?<!-- ENDPHP -->#s', '<!-- PHP -->', $code); + + preg_match_all('#<!-- INCLUDE (\{\$?[A-Z0-9\-_]+\}|[a-zA-Z0-9\_\-\+\./]+) -->#', $code, $matches); + $include_blocks = $matches[1]; + $code = preg_replace('#<!-- INCLUDE (?:\{\$?[A-Z0-9\-_]+\}|[a-zA-Z0-9\_\-\+\./]+) -->#', '<!-- INCLUDE -->', $code); + + preg_match_all('#<!-- INCLUDEPHP ([a-zA-Z0-9\_\-\+\./]+) -->#', $code, $matches); + $includephp_blocks = $matches[1]; + $code = preg_replace('#<!-- INCLUDEPHP [a-zA-Z0-9\_\-\+\./]+ -->#', '<!-- INCLUDEPHP -->', $code); + + preg_match_all('#<!-- ([^<].*?) (.*?)? ?-->#', $code, $blocks, PREG_SET_ORDER); + + $text_blocks = preg_split('#<!-- [^<].*? (?:.*?)? ?-->#', $code); + + for ($i = 0, $j = sizeof($text_blocks); $i < $j; $i++) + { + $this->compile_var_tags($text_blocks[$i]); + } + $compile_blocks = array(); + + for ($curr_tb = 0, $tb_size = sizeof($blocks); $curr_tb < $tb_size; $curr_tb++) + { + $block_val = &$blocks[$curr_tb]; + + switch ($block_val[1]) + { + case 'BEGIN': + $this->block_else_level[] = false; + $compile_blocks[] = '<?php ' . $this->compile_tag_block($block_val[2]) . ' ?>'; + break; + + case 'BEGINELSE': + $this->block_else_level[sizeof($this->block_else_level) - 1] = true; + $compile_blocks[] = '<?php }} else { ?>'; + break; + + case 'END': + array_pop($this->block_names); + $compile_blocks[] = '<?php ' . ((array_pop($this->block_else_level)) ? '}' : '}}') . ' ?>'; + break; + + case 'IF': + $compile_blocks[] = '<?php ' . $this->compile_tag_if($block_val[2], false) . ' ?>'; + break; + + case 'ELSE': + $compile_blocks[] = '<?php } else { ?>'; + break; + + case 'ELSEIF': + $compile_blocks[] = '<?php ' . $this->compile_tag_if($block_val[2], true) . ' ?>'; + break; + + case 'ENDIF': + $compile_blocks[] = '<?php } ?>'; + break; + + case 'DEFINE': + $compile_blocks[] = '<?php ' . $this->compile_tag_define($block_val[2], true) . ' ?>'; + break; + + case 'UNDEFINE': + $compile_blocks[] = '<?php ' . $this->compile_tag_define($block_val[2], false) . ' ?>'; + break; + + case 'INCLUDE': + $temp = array_shift($include_blocks); + + // Dynamic includes + // Cheap match rather than a full blown regexp, we already know + // the format of the input so just use string manipulation. + if ($temp[0] == '{') + { + $file = false; + + if ($temp[1] == '$') + { + $var = substr($temp, 2, -1); + //$file = $this->template->_tpldata['DEFINE']['.'][$var]; + $temp = "\$this->_tpldata['DEFINE']['.']['$var']"; + } + else + { + $var = substr($temp, 1, -1); + //$file = $this->template->_rootref[$var]; + $temp = "\$this->_rootref['$var']"; + } + } + else + { + $file = $temp; + } + + $compile_blocks[] = '<?php ' . $this->compile_tag_include($temp) . ' ?>'; + + // No point in checking variable includes + if ($file) + { + $this->template->_tpl_include($file, false); + } + break; + + case 'INCLUDEPHP': + $compile_blocks[] = ($config['tpl_allow_php']) ? '<?php ' . $this->compile_tag_include_php(array_shift($includephp_blocks)) . ' ?>' : ''; + break; + + case 'PHP': + $compile_blocks[] = ($config['tpl_allow_php']) ? '<?php ' . array_shift($php_blocks) . ' ?>' : ''; + break; + + default: + $this->compile_var_tags($block_val[0]); + $trim_check = trim($block_val[0]); + $compile_blocks[] = (!$no_echo) ? ((!empty($trim_check)) ? $block_val[0] : '') : ((!empty($trim_check)) ? $block_val[0] : ''); + break; + } + } + + $template_php = ''; + for ($i = 0, $size = sizeof($text_blocks); $i < $size; $i++) + { + $trim_check_text = trim($text_blocks[$i]); + $template_php .= (!$no_echo) ? (($trim_check_text != '') ? $text_blocks[$i] : '') . ((isset($compile_blocks[$i])) ? $compile_blocks[$i] : '') : (($trim_check_text != '') ? $text_blocks[$i] : '') . ((isset($compile_blocks[$i])) ? $compile_blocks[$i] : ''); + } + + // Remove unused opening/closing tags + $template_php = str_replace(' ?><?php ', ' ', $template_php); + + // Now add a newline after each php closing tag which already has a newline + // PHP itself strips a newline if a closing tag is used (this is documented behaviour) and it is mostly not intended by style authors to remove newlines + $template_php = preg_replace('#\?\>([\r\n])#', '?>\1\1', $template_php); + + // There will be a number of occasions where we switch into and out of + // PHP mode instantaneously. Rather than "burden" the parser with this + // we'll strip out such occurences, minimising such switching + if ($no_echo) + { + return "\$$echo_var .= '" . $template_php . "'"; + } + + return $template_php; + } + + /** + * Compile variables + * @access 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('#\{((?:[a-z0-9\-_]+\.)+)(\$)?([A-Z0-9\-_]+)\}#', $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); + } + + // This will handle the remaining root-level varrefs + // 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_([A-Z0-9\-_]+)\}#', "<?php echo ((isset(\$this->_rootref['L_\\1'])) ? \$this->_rootref['L_\\1'] : ((isset(\$user->lang['\\1'])) ? \$user->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_([A-Z0-9\-_]+)\}#', "<?php echo ((isset(\$this->_rootref['LA_\\1'])) ? \$this->_rootref['LA_\\1'] : ((isset(\$this->_rootref['L_\\1'])) ? addslashes(\$this->_rootref['L_\\1']) : ((isset(\$user->lang['\\1'])) ? addslashes(\$user->lang['\\1']) : '{ \\1 }'))); ?>", $text_blocks); + } + + // Handle remaining varrefs + $text_blocks = preg_replace('#\{([A-Z0-9\-_]+)\}#', "<?php echo (isset(\$this->_rootref['\\1'])) ? \$this->_rootref['\\1'] : ''; ?>", $text_blocks); + $text_blocks = preg_replace('#\{\$([A-Z0-9\-_]+)\}#', "<?php echo (isset(\$this->_tpldata['DEFINE']['.']['\\1'])) ? \$this->_tpldata['DEFINE']['.']['\\1'] : ''; ?>", $text_blocks); + + return; + } + + /** + * Compile blocks + * @access private + */ + function compile_tag_block($tag_args) + { + $no_nesting = false; + + // Is the designer wanting to call another loop in a loop? + 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 + 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 (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(\$this->_tpldata['$tag_args'])) ? sizeof(\$this->_tpldata['$tag_args']) : 0;"; + $varref = "\$this->_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 IF tags - much of this is from Smarty with + * some adaptions for our block level methods + * @access private + */ + function compile_tag_if($tag_args, $elseif) + { + // Tokenize args for 'if' tag. + 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: + if (preg_match('#^((?:[a-z0-9\-_]+\.)+)?(\$)?(?=[A-Z])([A-Z0-9\-_]+)#s', $token, $varrefs)) + { + $token = (!empty($varrefs[1])) ? $this->generate_block_data_ref(substr($varrefs[1], 0, -1), true, $varrefs[2]) . '[\'' . $varrefs[3] . '\']' : (($varrefs[2]) ? '$this->_tpldata[\'DEFINE\'][\'.\'][\'' . $varrefs[3] . '\']' : '$this->_rootref[\'' . $varrefs[3] . '\']'); + } + else if (preg_match('#^\.((?:[a-z0-9\-_]+\.?)+)$#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 = '$this->_tpldata'; + + // Add the block reference for the last child. + $varref .= "['" . $blocks[0] . "']"; + } + $token = "sizeof($varref)"; + } + else if (!empty($token)) + { + $token = '(' . $token . ')'; + } + + break; + } + } + + // If there are no valid tokens left or only control/compare characters left, we do skip this statement + if (!sizeof($tokens) || str_replace(array(' ', '=', '!', '<', '>', '&', '|', '%', '(', ')'), '', implode('', $tokens)) == '') + { + $tokens = array('false'); + } + return (($elseif) ? '} else if (' : 'if (') . (implode(' ', $tokens) . ') { '); + } + + /** + * Compile DEFINE tags + * @access private + */ + function compile_tag_define($tag_args, $op) + { + preg_match('#^((?:[a-z0-9\-_]+\.)+)?\$(?=[A-Z])([A-Z0-9_\-]*)(?: = (\'?)([^\']*)(\'?))?$#', $tag_args, $match); + + if (empty($match[2]) || (!isset($match[4]) && $op)) + { + return ''; + } + + if (!$op) + { + return 'unset(' . (($match[1]) ? $this->generate_block_data_ref(substr($match[1], 0, -1), true, true) . '[\'' . $match[2] . '\']' : '$this->_tpldata[\'DEFINE\'][\'.\'][\'' . $match[2] . '\']') . ');'; + } + + // Are we a string? + if ($match[3] && $match[5]) + { + $match[4] = str_replace(array('\\\'', '\\\\', '\''), array('\'', '\\', '\\\''), $match[4]); + + // Compile reference, we allow template variables in defines... + $match[4] = $this->compile($match[4]); + + // Now replace the php code + $match[4] = "'" . str_replace(array('<?php echo ', '; ?>'), array("' . ", " . '"), $match[4]) . "'"; + } + else + { + preg_match('#true|false|\.#i', $match[4], $type); + + switch (strtolower($type[0])) + { + case 'true': + case 'false': + $match[4] = strtoupper($match[4]); + break; + + case '.': + $match[4] = doubleval($match[4]); + break; + + default: + $match[4] = intval($match[4]); + break; + } + } + + return (($match[1]) ? $this->generate_block_data_ref(substr($match[1], 0, -1), true, true) . '[\'' . $match[2] . '\']' : '$this->_tpldata[\'DEFINE\'][\'.\'][\'' . $match[2] . '\']') . ' = ' . $match[4] . ';'; + } + + /** + * Compile INCLUDE tag + * @access private + */ + function compile_tag_include($tag_args) + { + // Process dynamic includes + if ($tag_args[0] == '$') + { + return "if (isset($tag_args)) { \$this->_tpl_include($tag_args); }"; + } + + return "\$this->_tpl_include('$tag_args');"; + } + + /** + * Compile INCLUDE_PHP tag + * @access private + */ + function compile_tag_include_php($tag_args) + { + return "\$this->_php_include('$tag_args');"; + } + + /** + * parse expression + * This is from Smarty + * @access 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 (@$tokens[$expr_end] == 'by') + { + $expr_end++; + $expr_arg = $tokens[$expr_end++]; + $expr = "!(($is_arg / $expr_arg) % $expr_arg)"; + } + else + { + $expr = "!($is_arg & 1)"; + } + break; + + case 'odd': + if (@$tokens[$expr_end] == 'by') + { + $expr_end++; + $expr_arg = $tokens[$expr_end++]; + $expr = "(($is_arg / $expr_arg) % $expr_arg)"; + } + else + { + $expr = "($is_arg & 1)"; + } + break; + + case 'div': + if (@$tokens[$expr_end] == 'by') + { + $expr_end++; + $expr_arg = $tokens[$expr_end++]; + $expr = "!($is_arg % $expr_arg)"; + } + break; + } + + if ($negate_expr) + { + $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: + * ' . $this->_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. + * NOTE: expects a trailing "." on the namespace. + * @access private + */ + function generate_block_varref($namespace, $varname, $echo = true, $defop = false) + { + // Strip the trailing period. + $namespace = substr($namespace, 0, -1); + + // 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']"; + $varref = ($echo) ? "<?php echo $varref; ?>" : ((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: + * $this->_tpldata['parent'][$_parent_i]['$child1'][$_child1_i]['$child2'][$_child2_i]...['$childN'] + * + * If $include_last_iterator is true, then [$_childN_i] will be appended to the form shown above. + * NOTE: does not expect a trailing "." on the blockname. + * @access 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 = '$this->_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]. '\']'; + } + } + + /** + * Write compiled file to cache directory + * @access private + */ + function compile_write($handle, $data) + { + global $phpEx; + + $filename = $this->template->cachepath . str_replace('/', '.', $this->template->filename[$handle]) . '.' . $phpEx; + + $data = "<?php if (!defined('IN_PHPBB')) exit;" . ((strpos($data, '<?php') === 0) ? substr($data, 5) : ' ?>' . $data); + + if ($fp = @fopen($filename, 'wb')) + { + @flock($fp, LOCK_EX); + @fwrite ($fp, $data); + @flock($fp, LOCK_UN); + @fclose($fp); + + phpbb_chmod($filename, CHMOD_READ | CHMOD_WRITE); + } + + return; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/functions_transfer.php b/phpBB/includes/functions_transfer.php new file mode 100644 index 0000000000..046abede8e --- /dev/null +++ b/phpBB/includes/functions_transfer.php @@ -0,0 +1,873 @@ +<?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; +} + +/** +* 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 transfer() + { + global $phpbb_root_path; + + $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 + */ + function write_file($destination_file = '', $contents = '') + { + global $phpbb_root_path; + + $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 + */ + 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 + */ + function make_dir($dir) + { + global $phpbb_root_path; + + $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 + */ + function copy_file($from_loc, $to_loc) + { + global $phpbb_root_path; + + $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 + */ + function delete_file($file) + { + global $phpbb_root_path; + + $file = $this->root_path . str_replace($phpbb_root_path, '', $file); + + return $this->_delete($file); + } + + /** + * Remove directory + * @todo remove child directories? + */ + function remove_dir($dir) + { + global $phpbb_root_path; + + $dir = $this->root_path . str_replace($phpbb_root_path, '', $dir); + + return $this->_rmdir($dir); + } + + /** + * Rename a file or folder + */ + function rename($old_handle, $new_handle) + { + global $phpbb_root_path; + + $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... + */ + function file_exists($directory, $filename) + { + global $phpbb_root_path; + + $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 + */ + function open_session() + { + return $this->_init(); + } + + /** + * Close current session + */ + function close_session() + { + return $this->_close(); + } + + /** + * Determine methods able to be used + */ + 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'; + } + + return $methods; + } +} + +/** +* FTP transfer class +* @package phpBB3 +*/ +class ftp extends transfer +{ + /** + * Standard parameters for FTP session + */ + function ftp($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 $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 + transfer::transfer(); + + return; + } + + /** + * Requests data + */ + function data() + { + global $user; + + return array( + 'host' => 'localhost', + 'username' => 'anonymous', + 'password' => '', + 'root_path' => $user->page['root_script_path'], + 'port' => 21, + 'timeout' => 10 + ); + } + + /** + * Init FTP Session + * @access private + */ + function _init() + { + // connect to the server + $this->connection = @ftp_connect($this->host, $this->port, $this->timeout); + + if (!$this->connection) + { + return 'ERR_CONNECTING_SERVER'; + } + + // login to the server + if (!@ftp_login($this->connection, $this->username, $this->password)) + { + return 'ERR_UNABLE_TO_LOGIN'; + } + + // attempt to turn pasv mode on + @ftp_pasv($this->connection, true); + + // change to the root directory + if (!$this->_chdir($this->root_path)) + { + return 'ERR_CHANGING_DIRECTORY'; + } + + return true; + } + + /** + * Create Directory (MKDIR) + * @access private + */ + function _mkdir($dir) + { + return @ftp_mkdir($this->connection, $dir); + } + + /** + * Remove directory (RMDIR) + * @access private + */ + function _rmdir($dir) + { + return @ftp_rmdir($this->connection, $dir); + } + + /** + * Rename file + * @access private + */ + function _rename($old_handle, $new_handle) + { + return @ftp_rename($this->connection, $old_handle, $new_handle); + } + + /** + * Change current working directory (CHDIR) + * @access private + */ + 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 + */ + 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 + */ + 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 + */ + function _delete($file) + { + return @ftp_delete($this->connection, $file); + } + + /** + * Close ftp session (CLOSE) + * @access private + */ + 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 + */ + function _cwd() + { + return @ftp_pwd($this->connection); + } + + /** + * Return list of files in a given directory (LS) + * @access private + */ + function _ls($dir = './') + { + $list = @ftp_nlist($this->connection, $dir); + + // See bug #46295 - Some FTP daemons don't like './' + if ($dir === './') + { + // Let's try some alternatives + $list = (empty($list)) ? @ftp_nlist($this->connection, '.') : $list; + $list = (empty($list)) ? @ftp_nlist($this->connection, '') : $list; + } + + // Return on error + if ($list === false) + { + return false; + } + + // 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 + */ + 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 ftp_fsock($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 $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 + transfer::transfer(); + + return; + } + + /** + * Requests data + */ + function data() + { + global $user; + + return array( + 'host' => 'localhost', + 'username' => 'anonymous', + 'password' => '', + 'root_path' => $user->page['root_script_path'], + 'port' => 21, + 'timeout' => 10 + ); + } + + /** + * Init FTP Session + * @access private + */ + 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 + */ + function _mkdir($dir) + { + return $this->_send_command('MKD', $dir); + } + + /** + * Remove directory (RMDIR) + * @access private + */ + function _rmdir($dir) + { + return $this->_send_command('RMD', $dir); + } + + /** + * Rename File + * @access private + */ + 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 + */ + 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 + */ + 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 + */ + 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 + */ + function _delete($file) + { + return $this->_send_command('DELE', $file); + } + + /** + * Close ftp session (CLOSE) + * @access private + */ + 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 + */ + 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 + */ + function _ls($dir = './') + { + if (!$this->_open_data_connection()) + { + return false; + } + + $this->_send_command('NLST', $dir); + + $list = array(); + while (!@feof($this->data_connection)) + { + $filename = preg_replace('#[\r\n]#', '', @fgets($this->data_connection, 512)); + + if ($filename !== '') + { + $list[] = $filename; + } + } + $this->_close_data_connection(); + + // Clear buffer + $this->_check_command(); + + // See bug #46295 - Some FTP daemons don't like './' + if ($dir === './' && empty($list)) + { + // Let's try some alternatives + $list = $this->_ls('.'); + + if (empty($list)) + { + $list = $this->_ls(''); + } + + return $list; + } + + // 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; + } + + /** + * Send a command to server (FTP fsock only function) + * @access 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 + */ + 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 + */ + function _close_data_connection() + { + return @fclose($this->data_connection); + } + + /** + * Check to make sure command was successful (FTP fsock only function) + * @access private + */ + function _check_command($return = false) + { + $response = ''; + + do + { + $result = @fgets($this->connection, 512); + $response .= $result; + } + while (substr($result, 3, 1) !== ' '); + + if (!preg_match('#^[123]#', $response)) + { + return false; + } + + return ($return) ? $response : true; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/functions_upload.php b/phpBB/includes/functions_upload.php new file mode 100644 index 0000000000..054af29045 --- /dev/null +++ b/phpBB/includes/functions_upload.php @@ -0,0 +1,988 @@ +<?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 filespec($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(utf8_htmlspecialchars(utf8_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 $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 reflects the mode defined by {@link phpbb_chmod()} + * + * @access public + */ + function move_file($destination, $overwrite = false, $skip_image_check = false, $chmod = false) + { + global $user, $phpbb_root_path; + + if (sizeof($this->error)) + { + return false; + } + + $chmod = ($chmod === false) ? CHMOD_READ | 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 . '/' . utf8_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($user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file); + } + } + + break; + + case 'move': + + if (!@move_uploaded_file($this->filename, $this->destination_file)) + { + if (!@copy($this->filename, $this->destination_file)) + { + $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file); + } + } + + break; + + case 'local': + + if (!@copy($this->filename, $this->destination_file)) + { + $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file); + } + + break; + } + + // Remove temporary filename + @unlink($this->filename); + + if (sizeof($this->error)) + { + return false; + } + + phpbb_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($user->lang['IMAGE_FILETYPE_INVALID'], $this->image_info[2], $this->mimetype); + } + else + { + $this->error[] = sprintf($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[] = $user->lang['ATTACHED_IMAGE_NOT_IMAGE']; + } + } + else + { + $this->error[] = $user->lang['UNABLE_GET_IMAGE_SIZE']; + } + } + + $this->file_moved = true; + $this->additional_checks(); + unset($this->upload); + + return true; + } + + /** + * Performing additional checks + */ + function additional_checks() + { + global $user; + + 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)) + { + $max_filesize = get_formatted_filesize($this->upload->max_filesize, false); + + $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']); + + return false; + } + + if (!$this->upload->valid_dimensions($this)) + { + $this->error[] = sprintf($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 fileupload($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) + { + global $user; + + 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[] = $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)) ? $user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : sprintf($user->lang[$this->error_prefix . 'PHP_SIZE_OVERRUN'], $max_filesize, $user->lang[$unit]); + return $file; + } + + // Not correctly uploaded + if (!$file->is_uploaded()) + { + $file->error[] = $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) + { + global $user; + + $form_name = 'local'; + + $_FILES[$form_name]['local_mode'] = true; + $_FILES[$form_name]['tmp_name'] = $source_file; + + if ($filedata === false) + { + $_FILES[$form_name]['name'] = utf8_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)) ? $user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : sprintf($user->lang[$this->error_prefix . 'PHP_SIZE_OVERRUN'], $max_filesize, $user->lang[$unit]); + return $file; + } + + // Not correctly uploaded + if (!$file->is_uploaded()) + { + $file->error[] = $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) + { + global $user, $phpbb_root_path; + + $upload_ary = array(); + $upload_ary['local_mode'] = true; + + if (!preg_match('#^(https?://).*?\.(' . implode('|', $this->allowed_extensions) . ')$#i', $upload_url, $match)) + { + $file = new fileerror($user->lang[$this->error_prefix . 'URL_INVALID']); + return $file; + } + + if (empty($match[2])) + { + $file = new fileerror($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'] = utf8_basename($url['path']) . (($ext) ? '.' . $ext : ''); + $filename = $url['path']; + $filesize = 0; + + $errno = 0; + $errstr = ''; + + if (!($fsock = @fsockopen($host, $port, $errno, $errstr))) + { + $file = new fileerror($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($user->lang[$this->error_prefix . 'URL_NOT_FOUND']); + return $file; + } + } + } + } + @fclose($fsock); + + if (empty($data)) + { + $file = new fileerror($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($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) + { + global $user; + + 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)) ? $user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : sprintf($user->lang[$this->error_prefix . 'PHP_SIZE_OVERRUN'], $max_filesize, $user->lang[$unit]); + break; + + case 2: + $max_filesize = get_formatted_filesize($this->max_filesize, false); + + $error = sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']); + break; + + case 3: + $error = $user->lang[$this->error_prefix . 'PARTIAL_UPLOAD']; + break; + + case 4: + $error = $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) + { + global $user; + + // 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)) + { + $max_filesize = get_formatted_filesize($this->max_filesize, false); + + $file->error[] = sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']); + } + + // check Filename + if (preg_match("#[\\/:*?\"<>|]#i", $file->get('realname'))) + { + $file->error[] = sprintf($user->lang[$this->error_prefix . 'INVALID_FILENAME'], $file->get('realname')); + } + + // Invalid Extension + if (!$this->valid_extension($file)) + { + $file->error[] = sprintf($user->lang[$this->error_prefix . 'DISALLOWED_EXTENSION'], $file->get('extension')); + } + + // MIME Sniffing + if (!$this->valid_content($file)) + { + $file->error[] = sprintf($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 new file mode 100644 index 0000000000..7255d138ab --- /dev/null +++ b/phpBB/includes/functions_user.php @@ -0,0 +1,3582 @@ +<?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) +{ + global $db; + + // 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 ' . $db->sql_in_set($sql_where, $sql_in); + + if ($user_type !== false && !empty($user_type)) + { + $sql .= ' AND ' . $db->sql_in_set('user_type', $user_type); + } + + $result = $db->sql_query($sql); + + if (!($row = $db->sql_fetchrow($result))) + { + $db->sql_freeresult($result); + return 'NO_USERS'; + } + + do + { + $username_ary[$row['user_id']] = $row['username']; + $user_id_ary[] = $row['user_id']; + } + while ($row = $db->sql_fetchrow($result)); + $db->sql_freeresult($result); + + return false; +} + +/** +* Get latest registered username and update database to reflect it +*/ +function update_last_username() +{ + global $db; + + // Get latest username + $sql = 'SELECT user_id, username, user_colour + FROM ' . USERS_TABLE . ' + WHERE user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ') + 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); + } +} + +/** +* 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) +{ + global $config, $db, $cache; + + $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 = '" . $db->sql_escape($new_name) . "' + WHERE $field = '" . $db->sql_escape($old_name) . "'"; + $db->sql_query($sql); + } + } + + if ($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. + $cache->destroy('sql', MODERATOR_CACHE_TABLE); +} + +/** +* Adds an 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) +{ + global $db, $user, $auth, $config, $phpbb_root_path, $phpEx; + + 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' => phpbb_email_hash($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' => $config['board_timezone'], + 'user_dateformat' => $config['default_dateformat'], + 'user_lang' => $config['default_lang'], + 'user_style' => (int) $config['default_style'], + 'user_actkey' => '', + 'user_ip' => '', + 'user_regdate' => time(), + 'user_passchg' => time(), + 'user_options' => 230271, + // We do not set the new flag here - registration scripts need to specify it + 'user_new' => 0, + + '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) $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' => 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 . ' ' . $db->sql_build_array('INSERT', $sql_ary); + $db->sql_query($sql); + + $user_id = $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.' . $phpEx); + } + + $sql = 'INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' ' . + $db->sql_build_array('INSERT', custom_profile::build_insert_sql_array($cp_data)); + $db->sql_query($sql); + } + + // Place into appropriate group... + $sql = 'INSERT INTO ' . USER_GROUP_TABLE . ' ' . $db->sql_build_array('INSERT', array( + 'user_id' => (int) $user_id, + 'group_id' => (int) $user_row['group_id'], + 'user_pending' => 0) + ); + $db->sql_query($sql); + + // Now make it the users default group... + group_set_user_default($user_row['group_id'], array($user_id), false); + + // Add to newly registered users group if user_new is 1 + if ($config['new_member_post_limit'] && $sql_ary['user_new']) + { + $sql = 'SELECT group_id + FROM ' . GROUPS_TABLE . " + WHERE group_name = 'NEWLY_REGISTERED' + AND group_type = " . GROUP_SPECIAL; + $result = $db->sql_query($sql); + $add_group_id = (int) $db->sql_fetchfield('group_id'); + $db->sql_freeresult($result); + + if ($add_group_id) + { + // Because these actions only fill the log unneccessarily we skip the add_log() entry with a little hack. :/ + $GLOBALS['skip_add_log'] = true; + + // Add user to "newly registered users" group and set to default group if admin specified so. + if ($config['new_member_group_default']) + { + group_user_add($add_group_id, $user_id, false, false, true); + } + else + { + group_user_add($add_group_id, $user_id); + } + + unset($GLOBALS['skip_add_log']); + } + } + + // 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'] == USER_NORMAL || $user_row['user_type'] == USER_FOUNDER) + { + 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 = $db->sql_query_limit($sql, 1); + $row = $db->sql_fetchrow($result); + $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) +{ + global $cache, $config, $db, $user, $auth; + global $phpbb_root_path, $phpEx; + + $sql = 'SELECT * + FROM ' . USERS_TABLE . ' + WHERE user_id = ' . $user_id; + $result = $db->sql_query($sql); + $user_row = $db->sql_fetchrow($result); + $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 = $db->sql_query($sql); + + $report_posts = $report_topics = array(); + while ($row = $db->sql_fetchrow($result)) + { + $report_posts[] = $row['post_id']; + $report_topics[] = $row['topic_id']; + } + $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 ' . $db->sql_in_set('topic_id', $report_topics) . ' + AND post_reported = 1 + AND ' . $db->sql_in_set('post_id', $report_posts, true); + $result = $db->sql_query($sql); + + $keep_report_topics = array(); + while ($row = $db->sql_fetchrow($result)) + { + $keep_report_topics[] = $row['topic_id']; + } + $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 ' . $db->sql_in_set('post_id', $report_posts); + $db->sql_query($sql); + + if (sizeof($report_topics)) + { + $sql = 'UPDATE ' . TOPICS_TABLE . ' + SET topic_reported = 0 + WHERE ' . $db->sql_in_set('topic_id', $report_topics); + $db->sql_query($sql); + } + } + + // Remove reports + $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': + + $db->sql_transaction('begin'); + + if ($post_username === false) + { + $post_username = $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'] == 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 = '" . $db->sql_escape($post_username) . "', forum_last_poster_colour = '' + WHERE forum_last_poster_id = $user_id"; + $db->sql_query($sql); + + $sql = 'UPDATE ' . POSTS_TABLE . ' + SET poster_id = ' . ANONYMOUS . ", post_username = '" . $db->sql_escape($post_username) . "' + WHERE poster_id = $user_id"; + $db->sql_query($sql); + + $sql = 'UPDATE ' . POSTS_TABLE . ' + SET post_edit_user = ' . ANONYMOUS . " + WHERE post_edit_user = $user_id"; + $db->sql_query($sql); + + $sql = 'UPDATE ' . TOPICS_TABLE . ' + SET topic_poster = ' . ANONYMOUS . ", topic_first_poster_name = '" . $db->sql_escape($post_username) . "', topic_first_poster_colour = '' + WHERE topic_poster = $user_id"; + $db->sql_query($sql); + + $sql = 'UPDATE ' . TOPICS_TABLE . ' + SET topic_last_poster_id = ' . ANONYMOUS . ", topic_last_poster_name = '" . $db->sql_escape($post_username) . "', topic_last_poster_colour = '' + WHERE topic_last_poster_id = $user_id"; + $db->sql_query($sql); + + $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' + SET poster_id = ' . ANONYMOUS . " + WHERE poster_id = $user_id"; + $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; + $db->sql_query($sql); + } + } + + $db->sql_transaction('commit'); + + break; + + case 'remove': + + if (!function_exists('delete_posts')) + { + include($phpbb_root_path . 'includes/functions_admin.' . $phpEx); + } + + $sql = 'SELECT topic_id, COUNT(post_id) AS total_posts + FROM ' . POSTS_TABLE . " + WHERE poster_id = $user_id + GROUP BY topic_id"; + $result = $db->sql_query($sql); + + $topic_id_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $topic_id_ary[$row['topic_id']] = $row['total_posts']; + } + $db->sql_freeresult($result); + + if (sizeof($topic_id_ary)) + { + $sql = 'SELECT topic_id, topic_replies, topic_replies_real + FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', array_keys($topic_id_ary)); + $result = $db->sql_query($sql); + + $del_topic_ary = array(); + while ($row = $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']; + } + } + $db->sql_freeresult($result); + + if (sizeof($del_topic_ary)) + { + $sql = 'DELETE FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', $del_topic_ary); + $db->sql_query($sql); + } + } + + // Delete posts, attachments, etc. + delete_posts('poster_id', $user_id); + + break; + } + + $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"; + $db->sql_query($sql); + } + + $cache->destroy('sql', MODERATOR_CACHE_TABLE); + + // Delete user log entries about this user + $sql = 'DELETE FROM ' . LOG_TABLE . ' + WHERE reportee_id = ' . $user_id; + $db->sql_query($sql); + + // Change user_id to anonymous for this users triggered events + $sql = 'UPDATE ' . LOG_TABLE . ' + SET user_id = ' . ANONYMOUS . ' + WHERE user_id = ' . $user_id; + $db->sql_query($sql); + + // Delete the user_id from the zebra table + $sql = 'DELETE FROM ' . ZEBRA_TABLE . ' + WHERE user_id = ' . $user_id . ' + OR zebra_id = ' . $user_id; + $db->sql_query($sql); + + // Delete the user_id from the banlist + $sql = 'DELETE FROM ' . BANLIST_TABLE . ' + WHERE ban_userid = ' . $user_id; + $db->sql_query($sql); + + // Delete the user_id from the session table + $sql = 'DELETE FROM ' . SESSIONS_TABLE . ' + WHERE session_user_id = ' . $user_id; + $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 = $db->sql_query($sql); + + $undelivered_msg = $undelivered_user = array(); + while ($row = $db->sql_fetchrow($result)) + { + $undelivered_msg[] = $row['msg_id']; + $undelivered_user[$row['user_id']][] = true; + } + $db->sql_freeresult($result); + + if (sizeof($undelivered_msg)) + { + $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . ' + WHERE ' . $db->sql_in_set('msg_id', $undelivered_msg); + $db->sql_query($sql); + } + + $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . ' + WHERE author_id = ' . $user_id . ' + AND folder_id = ' . PRIVMSGS_NO_BOX; + $db->sql_query($sql); + + // Delete all to-information + $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . ' + WHERE user_id = ' . $user_id; + $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; + $db->sql_query($sql); + + $sql = 'UPDATE ' . PRIVMSGS_TABLE . ' + SET author_id = ' . ANONYMOUS . ' + WHERE author_id = ' . $user_id; + $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; + $db->sql_query($sql); + } + + $db->sql_transaction('commit'); + + // Reset newest user info if appropriate + if ($config['newest_user_id'] == $user_id) + { + update_last_username(); + } + + // Decrement number of users if this user is active + if ($user_row['user_type'] != USER_INACTIVE && $user_row['user_type'] != 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) +{ + global $config, $db, $user, $auth; + + $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 ' . $db->sql_in_set('user_id', $user_id_ary); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $sql_ary = array(); + + if ($row['user_type'] == USER_IGNORE || $row['user_type'] == USER_FOUNDER || + ($mode == 'activate' && $row['user_type'] != USER_INACTIVE) || + ($mode == 'deactivate' && $row['user_type'] == USER_INACTIVE)) + { + continue; + } + + if ($row['user_type'] == USER_INACTIVE) + { + $activated++; + } + else + { + $deactivated++; + + // Remove the users session key... + $user->reset_login_keys($row['user_id']); + } + + $sql_ary += array( + 'user_type' => ($row['user_type'] == USER_NORMAL) ? USER_INACTIVE : USER_NORMAL, + 'user_inactive_time' => ($row['user_type'] == USER_NORMAL) ? time() : 0, + 'user_inactive_reason' => ($row['user_type'] == USER_NORMAL) ? $reason : 0, + ); + + $sql_statements[$row['user_id']] = $sql_ary; + } + $db->sql_freeresult($result); + + if (sizeof($sql_statements)) + { + foreach ($sql_statements as $user_id => $sql_ary) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . $user_id; + $db->sql_query($sql); + } + + $auth->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 = '') +{ + global $db, $user, $auth, $cache; + + // Delete stale bans + $sql = 'DELETE FROM ' . BANLIST_TABLE . ' + WHERE ban_end < ' . time() . ' + AND ban_end <> 0'; + $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 = ' . USER_FOUNDER; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $founder[$row['user_id']] = $row['user_email']; + $founder_names[$row['user_id']] = $row['username_clean']; + } + $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 == $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 ' . $db->sql_in_set('username_clean', $sql_usernames); + + // Do not allow banning yourself + if (sizeof($founder)) + { + $sql .= ' AND ' . $db->sql_in_set('user_id', array_merge(array_keys($founder), array($user->data['user_id'])), true); + } + else + { + $sql .= ' AND user_id <> ' . $user->data['user_id']; + } + + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + do + { + $banlist_ary[] = (int) $row['user_id']; + } + while ($row = $db->sql_fetchrow($result)); + } + else + { + $db->sql_freeresult($result); + trigger_error('NO_USERS'); + } + $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; + } + } + } + } + + if (empty($banlist_ary)) + { + 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 = $db->sql_query($sql); + + // Reset $sql_where, because we use it later... + $sql_where = ''; + + if ($row = $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 = $db->sql_fetchrow($result)); + + $banlist_ary_tmp = array_intersect($banlist_ary, $banlist_ary_tmp); + + if (sizeof($banlist_ary_tmp)) + { + // One or more entities are already banned/excluded, delete the existing bans, so they can be re-inserted with the given new length + $sql = 'DELETE FROM ' . BANLIST_TABLE . ' + WHERE ' . $db->sql_in_set($type, $banlist_ary_tmp) . ' + AND ban_exclude = ' . (int) $ban_exclude; + $db->sql_query($sql); + } + + unset($banlist_ary_tmp); + } + $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, + ); + } + + $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 ' . $db->sql_in_set('session_user_id', $banlist_ary); + break; + + case 'ip': + $sql_where = 'WHERE ' . $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 ' . $db->sql_in_set('user_email', $banlist_ary_sql); + $result = $db->sql_query($sql); + + $sql_in = array(); + + if ($row = $db->sql_fetchrow($result)) + { + do + { + $sql_in[] = $row['user_id']; + } + while ($row = $db->sql_fetchrow($result)); + + $sql_where = 'WHERE ' . $db->sql_in_set('session_user_id', $sql_in); + } + $db->sql_freeresult($result); + break; + } + + if (isset($sql_where) && $sql_where) + { + $sql = 'DELETE FROM ' . SESSIONS_TABLE . " + $sql_where"; + $db->sql_query($sql); + + if ($mode == 'user') + { + $sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . ' ' . ((in_array('*', $banlist_ary)) ? '' : 'WHERE ' . $db->sql_in_set('user_id', $banlist_ary)); + $db->sql_query($sql); + } + } + } + + // Update log + $log_entry = ($ban_exclude) ? 'LOG_BAN_EXCLUDE_' : 'LOG_BAN_'; + + // Add to moderator log, admin log and user notes + 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); + if ($mode == 'user') + { + foreach ($banlist_ary as $user_id) + { + add_log('user', $user_id, $log_entry . strtoupper($mode), $ban_reason, $ban_list_log); + } + } + + $cache->destroy('sql', BANLIST_TABLE); + + return true; + } + + // There was nothing to ban/exclude. But destroying the cache because of the removal of stale bans. + $cache->destroy('sql', BANLIST_TABLE); + + return false; +} + +/** +* Unban User +*/ +function user_unban($mode, $ban) +{ + global $db, $user, $auth, $cache; + + // Delete stale bans + $sql = 'DELETE FROM ' . BANLIST_TABLE . ' + WHERE ban_end < ' . time() . ' + AND ban_end <> 0'; + $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, u.user_id + FROM ' . USERS_TABLE . ' u, ' . BANLIST_TABLE . ' b + WHERE ' . $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 ' . $db->sql_in_set('ban_id', $unban_sql); + break; + + case 'ip': + $sql = 'SELECT ban_ip AS unban_info + FROM ' . BANLIST_TABLE . ' + WHERE ' . $db->sql_in_set('ban_id', $unban_sql); + break; + } + $result = $db->sql_query($sql); + + $l_unban_list = ''; + $user_ids_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $l_unban_list .= (($l_unban_list != '') ? ', ' : '') . $row['unban_info']; + if ($mode == 'user') + { + $user_ids_ary[] = $row['user_id']; + } + } + $db->sql_freeresult($result); + + $sql = 'DELETE FROM ' . BANLIST_TABLE . ' + WHERE ' . $db->sql_in_set('ban_id', $unban_sql); + $db->sql_query($sql); + + // Add to moderator log, admin log and user notes + add_log('admin', 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list); + add_log('mod', 0, 0, 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list); + if ($mode == 'user') + { + foreach ($user_ids_ary as $user_id) + { + add_log('user', $user_id, 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list); + } + } + } + + $cache->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) +{ + global $user; + + $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($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 $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) +{ + global $config, $db, $user, $cache; + + $clean_username = utf8_clean_string($username); + $allowed_username = ($allowed_username === false) ? $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? + if ((version_compare(PHP_VERSION, '5.1.0', '>=') || (version_compare(PHP_VERSION, '5.0.0-dev', '<=') && version_compare(PHP_VERSION, '4.4.0', '>='))) && @preg_match('/\p{L}/u', 'a') !== false) + { + $pcre = true; + } + else if (function_exists('mb_ereg_match')) + { + mb_regex_encoding('UTF-8'); + $mbstring = true; + } + + switch ($config['allow_name_chars']) + { + case 'USERNAME_CHARS_ANY': + $pcre = true; + $regex = '.+'; + break; + + case 'USERNAME_ALPHA_ONLY': + $pcre = true; + $regex = '[A-Za-z0-9]+'; + break; + + case 'USERNAME_ALPHA_SPACERS': + $pcre = true; + $regex = '[A-Za-z0-9-[\]_+ ]+'; + break; + + case 'USERNAME_LETTER_NUM': + if ($pcre) + { + $regex = '[\p{Lu}\p{Ll}\p{N}]+'; + } + else if ($mbstring) + { + $regex = '[[:upper:][:lower:][:digit:]]+'; + } + else + { + $pcre = true; + $regex = '[a-zA-Z0-9]+'; + } + break; + + case 'USERNAME_LETTER_NUM_SPACERS': + if ($pcre) + { + $regex = '[-\]_+ [\p{Lu}\p{Ll}\p{N}]+'; + } + else if ($mbstring) + { + $regex = '[-\]_+ \[[:upper:][:lower:][:digit:]]+'; + } + else + { + $pcre = true; + $regex = '[-\]_+ [a-zA-Z0-9]+'; + } + break; + + case 'USERNAME_ASCII': + default: + $pcre = true; + $regex = '[\x01-\x7F]+'; + break; + } + + if ($pcre) + { + if (!preg_match('#^' . $regex . '$#u', $username)) + { + return 'INVALID_CHARS'; + } + } + else if ($mbstring) + { + mb_ereg_search_init($username, '^' . $regex . '$'); + if (!mb_ereg_search()) + { + return 'INVALID_CHARS'; + } + } + + $sql = 'SELECT username + FROM ' . USERS_TABLE . " + WHERE username_clean = '" . $db->sql_escape($clean_username) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + return 'USERNAME_TAKEN'; + } + + $sql = 'SELECT group_name + FROM ' . GROUPS_TABLE . " + WHERE LOWER(group_name) = '" . $db->sql_escape(utf8_strtolower($username)) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + return 'USERNAME_TAKEN'; + } + + $bad_usernames = $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) +{ + global $config, $db, $user; + + if (!$password) + { + return false; + } + + $pcre = $mbstring = false; + + // generic UTF-8 character types supported? + if ((version_compare(PHP_VERSION, '5.1.0', '>=') || (version_compare(PHP_VERSION, '5.0.0-dev', '<=') && version_compare(PHP_VERSION, '4.4.0', '>='))) && @preg_match('/\p{L}/u', 'a') !== false) + { + $upp = '\p{Lu}'; + $low = '\p{Ll}'; + $let = '\p{L}'; + $num = '\p{N}'; + $sym = '[^\p{Lu}\p{Ll}\p{N}]'; + $pcre = true; + } + else if (function_exists('mb_ereg_match')) + { + mb_regex_encoding('UTF-8'); + $upp = '[[:upper:]]'; + $low = '[[:lower:]]'; + $let = '[[:lower:][:upper:]]'; + $num = '[[:digit:]]'; + $sym = '[^[:upper:][:lower:][:digit:]]'; + $mbstring = true; + } + else + { + $upp = '[A-Z]'; + $low = '[a-z]'; + $let = '[a-zA-Z]'; + $num = '[0-9]'; + $sym = '[^A-Za-z0-9]'; + $pcre = true; + } + + $chars = array(); + + switch ($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 $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) +{ + global $config, $db, $user; + + $email = strtolower($email); + $allowed_email = ($allowed_email === false) ? strtolower($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 ($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 = $user->check_ban(false, false, $email, true)) !== false) + { + return ($ban_reason === true) ? 'EMAIL_BANNED' : $ban_reason; + } + + if (!$config['allow_emailreuse']) + { + $sql = 'SELECT user_email_hash + FROM ' . USERS_TABLE . " + WHERE user_email_hash = " . $db->sql_escape(phpbb_email_hash($email)); + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $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; + + 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) +{ + global $phpbb_root_path, $config, $db, $user; + + // 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 . $config['avatar_path'] . '/' . $filename)) + { + @unlink($phpbb_root_path . $config['avatar_path'] . '/' . $filename); + return true; + } + + return false; +} + +/** +* Remote avatar linkage +*/ +function avatar_remote($data, &$error) +{ + global $config, $db, $user, $phpbb_root_path, $phpEx; + + 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[] = $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[] = $user->lang['UNABLE_GET_IMAGE_SIZE']; + return false; + } + + if (!empty($image_data) && ($image_data[0] < 2 || $image_data[1] < 2)) + { + $error[] = $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[] = $user->lang['AVATAR_NO_SIZE']; + return false; + } + + // Check image type + include_once($phpbb_root_path . 'includes/functions_upload.' . $phpEx); + $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[] = $user->lang['UNABLE_GET_IMAGE_SIZE']; + } + else + { + $error[] = sprintf($user->lang['IMAGE_FILETYPE_MISMATCH'], $types[$image_data[2]][0], $extension); + } + return false; + } + + if ($config['avatar_max_width'] || $config['avatar_max_height']) + { + if ($width > $config['avatar_max_width'] || $height > $config['avatar_max_height']) + { + $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $width, $height); + return false; + } + } + + if ($config['avatar_min_width'] || $config['avatar_min_height']) + { + if ($width < $config['avatar_min_width'] || $height < $config['avatar_min_height']) + { + $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $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) +{ + global $phpbb_root_path, $config, $db, $user, $phpEx; + + // Init upload class + include_once($phpbb_root_path . 'includes/functions_upload.' . $phpEx); + $upload = new fileupload('AVATAR_', array('jpg', 'jpeg', 'gif', 'png'), $config['avatar_filesize'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], explode('|', $config['mime_triggers'])); + + if (!empty($_FILES['uploadfile']['name'])) + { + $file = $upload->form_upload('uploadfile'); + } + else + { + $file = $upload->remote_upload($data['uploadurl']); + } + + $prefix = $config['avatar_salt'] . '_'; + $file->clean_filename('avatar', $prefix, $data['user_id']); + + $destination = $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) +{ + global $config; + + + 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 $config['avatar_salt'] . '_' . (($avatar_group) ? 'g' : '') . $avatar_entry . '.' . $ext; +} + +/** +* Avatar Gallery +*/ +function avatar_gallery($category, $avatar_select, $items_per_column, $block_var = 'avatar_row') +{ + global $user, $cache, $template; + global $config, $phpbb_root_path; + + $avatar_list = array(); + + $path = $phpbb_root_path . $config['avatar_gallery_path']; + + if (!file_exists($path) || !is_dir($path)) + { + $avatar_list = array($user->lang['NO_AVATAR_CATEGORY'] => array()); + } + else + { + // Collect images + $dp = @opendir($path); + + if (!$dp) + { + return array($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' => rawurlencode($file) . '/' . rawurlencode($sub_file), + 'filename' => rawurlencode($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($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>'; + } + + $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) + { + $template->assign_block_vars($block_var, array()); + + foreach ($avatar_row_ary as $avatar_col_ary) + { + $template->assign_block_vars($block_var . '.avatar_column', array( + 'AVATAR_IMAGE' => $phpbb_root_path . $config['avatar_gallery_path'] . '/' . $avatar_col_ary['file'], + 'AVATAR_NAME' => $avatar_col_ary['name'], + 'AVATAR_FILE' => $avatar_col_ary['filename']) + ); + + $template->assign_block_vars($block_var . '.avatar_option_column', array( + 'AVATAR_IMAGE' => $phpbb_root_path . $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) +{ + global $config, $phpbb_root_path, $user; + + switch ($avatar_type) + { + case AVATAR_REMOTE : + break; + + case AVATAR_UPLOAD : + $avatar = $phpbb_root_path . $config['avatar_path'] . '/' . get_avatar_filename($avatar); + break; + + case AVATAR_GALLERY : + $avatar = $phpbb_root_path . $config['avatar_gallery_path'] . '/' . $avatar ; + break; + } + + // Make sure getimagesize works... + if (($image_data = @getimagesize($avatar)) === false) + { + $error[] = $user->lang['UNABLE_GET_IMAGE_SIZE']; + return false; + } + + if ($image_data[0] < 2 || $image_data[1] < 2) + { + $error[] = $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($config['avatar_max_height'], $image_data[1]); + $image_data[1] = max($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($config['avatar_max_width'], $image_data[1]); + $image_data[0] = max($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) +{ + global $config, $phpbb_root_path, $auth, $user, $db; + + $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 = &$user->data; + } + else + { + $userdata = &$custom_userdata; + } + + $data['user_id'] = $userdata['user_id']; + $change_avatar = ($custom_userdata === false) ? $auth->acl_get('u_chgavatar') : true; + $avatar_select = basename(request_var('avatar_select', '')); + + // Can we upload? + $can_upload = ($config['allow_avatar_upload'] && file_exists($phpbb_root_path . $config['avatar_path']) && @is_writable($phpbb_root_path . $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 && $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 && $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 . $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 . $config['avatar_gallery_path'] . '/' . $category . '/' . $sql_ary['user_avatar']); + $sql_ary['user_avatar'] = $category . '/' . $sql_ary['user_avatar']; + } + } + else if (isset($_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 (($config['avatar_max_width'] || $config['avatar_max_height']) && + (($data['width'] != $userdata['user_avatar_width']) || $data['height'] != $userdata['user_avatar_height'])) + { + if ($data['width'] > $config['avatar_max_width'] || $data['height'] > $config['avatar_max_height']) + { + $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $data['width'], $data['height']); + } + } + + if (!sizeof($error)) + { + if ($config['avatar_min_width'] || $config['avatar_min_height']) + { + if ($data['width'] < $config['avatar_min_width'] || $data['height'] < $config['avatar_min_height']) + { + $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $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) ? $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 ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . (($custom_userdata === false) ? $user->data['user_id'] : $custom_userdata['user_id']); + $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 $phpbb_root_path, $config, $db, $user, $file_upload; + + $error = array(); + + // Attributes which also affect the users table + $user_attribute_ary = array('group_colour', 'group_rank', 'group_avatar', 'group_avatar_type', 'group_avatar_width', 'group_avatar_height'); + + // Check data. Limit group name length. + if (!utf8_strlen($name) || utf8_strlen($name) > 60) + { + $error[] = (!utf8_strlen($name)) ? $user->lang['GROUP_ERR_USERNAME'] : $user->lang['GROUP_ERR_USER_LONG']; + } + + $err = group_validate_groupname($group_id, $name); + if (!empty($err)) + { + $error[] = $user->lang[$err]; + } + + if (!in_array($type, array(GROUP_OPEN, GROUP_CLOSED, GROUP_HIDDEN, GROUP_SPECIAL, GROUP_FREE))) + { + $error[] = $user->lang['GROUP_ERR_TYPE']; + } + + if (!sizeof($error)) + { + $user_ary = array(); + $sql_ary = array( + 'group_name' => (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)) + { + // Merge them with $sql_ary to properly update the group + $sql_ary = array_merge($sql_ary, $group_attributes); + } + + // 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 = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $user_ary[] = $row['user_id']; + } + $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 ' . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE group_id = $group_id"; + $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 = '" . $db->sql_escape($sql_ary['group_name']) . "' + WHERE group_id = $group_id"; + $db->sql_query($sql); + + // One special case is the group skip auth setting. If this was changed we need to purge permissions for this group + if (isset($group_attributes['group_skip_auth'])) + { + // Get users within this group... + $sql = 'SELECT user_id + FROM ' . USER_GROUP_TABLE . ' + WHERE group_id = ' . $group_id . ' + AND user_pending = 0'; + $result = $db->sql_query($sql); + + $user_id_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $user_id_ary[] = $row['user_id']; + } + $db->sql_freeresult($result); + + if (!empty($user_id_ary)) + { + global $auth; + + // Clear permissions cache of relevant users + $auth->acl_clear_prefetch($user_id_ary); + } + } + } + else + { + $sql = 'INSERT INTO ' . GROUPS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); + $db->sql_query($sql); + } + + if (!$group_id) + { + $group_id = $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)) + { + // Go through the user attributes array, check if a group attribute matches it and then set it. ;) + foreach ($user_attribute_ary as $attribute) + { + if (!isset($group_attributes[$attribute])) + { + continue; + } + + // 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) ? $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) +{ + global $config, $db, $phpbb_root_path; + + $group_id = (int)$group_id; + $ext = substr(strrchr($old_entry, '.'), 1); + $old_filename = get_avatar_filename($old_entry); + $new_filename = $config['avatar_salt'] . "_g$group_id.$ext"; + $new_entry = 'g' . $group_id . '_' . substr(time(), -5) . ".$ext"; + + $avatar_path = $phpbb_root_path . $config['avatar_path']; + if (@rename($avatar_path . '/'. $old_filename, $avatar_path . '/' . $new_filename)) + { + $sql = 'UPDATE ' . GROUPS_TABLE . ' + SET group_avatar = \'' . $db->sql_escape($new_entry) . "' + WHERE group_id = $group_id"; + $db->sql_query($sql); + } +} + + +/** +* Remove avatar also for users not having the group as default +*/ +function avatar_remove_db($avatar_name) +{ + global $config, $db; + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_avatar = '', + user_avatar_type = 0 + WHERE user_avatar = '" . $db->sql_escape($avatar_name) . '\''; + $db->sql_query($sql); +} + + +/** +* Group Delete +*/ +function group_delete($group_id, $group_name = false) +{ + global $db, $phpbb_root_path, $phpEx; + + 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 = $db->sql_query_limit($sql, 200, $start); + + if ($row = $db->sql_fetchrow($result)) + { + do + { + $user_id_ary[] = $row['user_id']; + $username_ary[] = $row['username']; + + $start++; + } + while ($row = $db->sql_fetchrow($result)); + + group_user_del($group_id, $user_id_ary, $username_ary, $group_name); + } + else + { + $start = 0; + } + $db->sql_freeresult($result); + } + while ($start); + + // Delete group + $sql = 'DELETE FROM ' . GROUPS_TABLE . " + WHERE group_id = $group_id"; + $db->sql_query($sql); + + // Delete auth entries from the groups table + $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . " + WHERE group_id = $group_id"; + $db->sql_query($sql); + + // Re-cache moderators + if (!function_exists('cache_moderators')) + { + include($phpbb_root_path . 'includes/functions_admin.' . $phpEx); + } + + 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) +{ + global $db, $auth; + + // 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 ' . $db->sql_in_set('user_id', $user_id_ary) . " + AND group_id = $group_id"; + $result = $db->sql_query($sql); + + $add_id_ary = $update_id_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $add_id_ary[] = (int) $row['user_id']; + + if ($leader && !$row['group_leader']) + { + $update_id_ary[] = (int) $row['user_id']; + } + } + $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'; + } + + $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, + ); + } + + $db->sql_multi_insert(USER_GROUP_TABLE, $sql_ary); + } + + if (sizeof($update_id_ary)) + { + $sql = 'UPDATE ' . USER_GROUP_TABLE . ' + SET group_leader = 1 + WHERE ' . $db->sql_in_set('user_id', $update_id_ary) . " + AND group_id = $group_id"; + $db->sql_query($sql); + } + + if ($default) + { + group_user_attributes('default', $group_id, $user_id_ary, false, $group_name, $group_attributes); + } + + $db->sql_transaction('commit'); + + // Clear permissions cache of relevant users + $auth->acl_clear_prefetch($user_id_ary); + + if (!$group_name) + { + $group_name = get_group_name($group_id); + } + + $log = ($leader) ? 'LOG_MODS_ADDED' : (($pending) ? 'LOG_USERS_PENDING' : '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) +{ + global $db, $auth, $config; + + if ($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'; + } + + $sql = 'SELECT * + FROM ' . GROUPS_TABLE . ' + WHERE ' . $db->sql_in_set('group_name', $group_order); + $result = $db->sql_query($sql); + + $group_order_id = $special_group_data = array(); + while ($row = $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']) + ); + } + } + $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 ' . $db->sql_in_set('user_id', $user_id_ary); + $result = $db->sql_query($sql); + + $default_groups = array(); + while ($row = $db->sql_fetchrow($result)) + { + $default_groups[$row['user_id']] = $row['group_id']; + } + $db->sql_freeresult($result); + + // What special group memberships exist for these users? + $sql = 'SELECT g.group_id, g.group_name, ug.user_id + FROM ' . USER_GROUP_TABLE . ' ug, ' . GROUPS_TABLE . ' g + WHERE ' . $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 = $db->sql_query($sql); + + $temp_ary = array(); + while ($row = $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']; + } + } + $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($group_id, $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 " . $db->sql_in_set('user_id', $user_id_ary); + $db->sql_query($sql); + + // Clear permissions cache of relevant users + $auth->acl_clear_prefetch($user_id_ary); + + if (!$group_name) + { + $group_name = get_group_name($group_id); + } + + $log = 'LOG_GROUP_REMOVE'; + + if ($group_name) + { + 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) +{ + global $db; + + 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 = $db->sql_query($sql); + if (!$row = $db->sql_fetchrow($result)) + { + $db->sql_freeresult($result); + return false; + } + $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 = '" . $db->sql_escape($row['group_avatar']) . "' + AND " . $db->sql_in_set('user_id', $user_ids); + + $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) +{ + global $db; + + 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 = $db->sql_query($sql); + if (!$row = $db->sql_fetchrow($result)) + { + $db->sql_freeresult($result); + return false; + } + $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 ' . $db->sql_in_set('user_id', $user_ids); + $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) +{ + global $db, $auth, $phpbb_root_path, $phpEx, $config; + + // 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 " . $db->sql_in_set('user_id', $user_id_ary); + $result = $db->sql_query_limit($sql, 1); + $not_empty = ($db->sql_fetchrow($result)); + $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 " . $db->sql_in_set('user_id', $user_id_ary); + $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 ' . $db->sql_in_set('ug.user_id', $user_id_ary); + $result = $db->sql_query($sql); + + $user_id_ary = $email_users = array(); + while ($row = $db->sql_fetchrow($result)) + { + $user_id_ary[] = $row['user_id']; + $email_users[] = $row; + } + $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 " . $db->sql_in_set('user_id', $user_id_ary); + $db->sql_query($sql); + + // Send approved email to users... + include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + $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.$phpEx?i=groups&mode=membership") + ); + + $messenger->send($row['user_notify_type']); + } + + $messenger->save_queue(); + + $log = 'LOG_USERS_APPROVED'; + break; + + case 'default': + // We only set default group for approved members of the group + $sql = 'SELECT user_id + FROM ' . USER_GROUP_TABLE . " + WHERE group_id = $group_id + AND user_pending = 0 + AND " . $db->sql_in_set('user_id', $user_id_ary); + $result = $db->sql_query($sql); + + $user_id_ary = $username_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $user_id_ary[] = $row['user_id']; + } + $db->sql_freeresult($result); + + $result = user_get_id_name($user_id_ary, $username_ary); + if (!sizeof($user_id_ary) || $result !== false) + { + return 'NO_USERS'; + } + + $sql = 'SELECT user_id, group_id FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', $user_id_ary, false, true); + $result = $db->sql_query($sql); + + $groups = array(); + while ($row = $db->sql_fetchrow($result)) + { + if (!isset($groups[$row['group_id']])) + { + $groups[$row['group_id']] = array(); + } + $groups[$row['group_id']][] = $row['user_id']; + } + $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 + $auth->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) +{ + global $config, $db; + + $group_name = utf8_clean_string($group_name); + + if (!empty($group_id)) + { + $sql = 'SELECT group_name + FROM ' . GROUPS_TABLE . ' + WHERE group_id = ' . (int) $group_id; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $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 LOWER(group_name) = '" . $db->sql_escape(utf8_strtolower($group_name)) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $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) +{ + global $cache, $db; + + 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 = $db->sql_query($sql); + $group_attributes = $db->sql_fetchrow($result); + $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 ' . $db->sql_in_set('user_id', $user_id_ary) . ' + AND user_avatar_type = ' . AVATAR_UPLOAD; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + avatar_delete('user', $row); + } + $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 ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE ' . $db->sql_in_set('user_id', $user_id_ary); + $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 = '" . $db->sql_escape($sql_ary['user_colour']) . "' + WHERE " . $db->sql_in_set('forum_last_poster_id', $user_id_ary); + $db->sql_query($sql); + + $sql = 'UPDATE ' . TOPICS_TABLE . " SET topic_first_poster_colour = '" . $db->sql_escape($sql_ary['user_colour']) . "' + WHERE " . $db->sql_in_set('topic_poster', $user_id_ary); + $db->sql_query($sql); + + $sql = 'UPDATE ' . TOPICS_TABLE . " SET topic_last_poster_colour = '" . $db->sql_escape($sql_ary['user_colour']) . "' + WHERE " . $db->sql_in_set('topic_last_poster_id', $user_id_ary); + $db->sql_query($sql); + + global $config; + + if (in_array($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); + } + + // Because some tables/caches use usercolour-specific data we need to purge this here. + $cache->destroy('sql', MODERATOR_CACHE_TABLE); +} + +/** +* Get group name +*/ +function get_group_name($group_id) +{ + global $db, $user; + + $sql = 'SELECT group_name, group_type + FROM ' . GROUPS_TABLE . ' + WHERE group_id = ' . (int) $group_id; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row || ($row['group_type'] == GROUP_SPECIAL && empty($user->lang))) + { + return ''; + } + + return ($row['group_type'] == GROUP_SPECIAL) ? $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) +{ + global $db; + + 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 .= ' ' . $db->sql_in_set('ug.group_id', $group_id_ary); + } + + if ($user_id_ary) + { + $sql .= ($group_id_ary) ? ' AND ' : ' '; + $sql .= $db->sql_in_set('ug.user_id', $user_id_ary); + } + + $result = ($return_bool) ? $db->sql_query_limit($sql, 1) : $db->sql_query($sql); + + $row = $db->sql_fetchrow($result); + + if ($return_bool) + { + $db->sql_freeresult($result); + return ($row) ? true : false; + } + + if (!$row) + { + return false; + } + + $return = array(); + + do + { + $return[] = $row; + } + while ($row = $db->sql_fetchrow($result)); + + $db->sql_freeresult($result); + + return $return; +} + +/** +* Re-cache moderators and foes if group has a_ or m_ permissions +*/ +function group_update_listings($group_id) +{ + global $auth; + + $hold_ary = $auth->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 != 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')) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/functions_admin.' . $phpEx); + } + cache_moderators(); + } + + if ($mod_permissions || $admin_permissions) + { + if (!function_exists('update_foes')) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/functions_admin.' . $phpEx); + } + update_foes(array($group_id)); + } +} + + + +/** +* Funtion to make a user leave the NEWLY_REGISTERED system group. +* @access public +* @param $user_id The id of the user to remove from the group +*/ +function remove_newly_registered($user_id, $user_data = false) +{ + global $db; + + if ($user_data === false) + { + $sql = 'SELECT * + FROM ' . USERS_TABLE . ' + WHERE user_id = ' . $user_id; + $result = $db->sql_query($sql); + $user_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$user_row) + { + return false; + } + else + { + $user_data = $user_row; + } + } + + if (empty($user_data['user_new'])) + { + return false; + } + + $sql = 'SELECT group_id + FROM ' . GROUPS_TABLE . " + WHERE group_name = 'NEWLY_REGISTERED' + AND group_type = " . GROUP_SPECIAL; + $result = $db->sql_query($sql); + $group_id = (int) $db->sql_fetchfield('group_id'); + $db->sql_freeresult($result); + + if (!$group_id) + { + return false; + } + + // We need to call group_user_del here, because this function makes sure everything is correctly changed. + // A downside for a call within the session handler is that the language is not set up yet - so no log entry + group_user_del($group_id, $user_id); + + // Set user_new to 0 to let this not be triggered again + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_new = 0 + WHERE user_id = ' . $user_id; + $db->sql_query($sql); + + // The new users group was the users default group? + if ($user_data['group_id'] == $group_id) + { + // Which group is now the users default one? + $sql = 'SELECT group_id + FROM ' . USERS_TABLE . ' + WHERE user_id = ' . $user_id; + $result = $db->sql_query($sql); + $user_data['group_id'] = $db->sql_fetchfield('group_id'); + $db->sql_freeresult($result); + } + + return $user_data['group_id']; +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/hooks/index.php b/phpBB/includes/hooks/index.php new file mode 100644 index 0000000000..aa85e63f32 --- /dev/null +++ b/phpBB/includes/hooks/index.php @@ -0,0 +1,250 @@ +<?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; +} + +/** +* phpBB Hook Class +* @package phpBB3 +*/ +class phpbb_hook +{ + /** + * Registered hooks + */ + var $hooks = array(); + + /** + * Results returned by functions called + */ + var $hook_result = array(); + + /** + * internal pointer + */ + var $current_hook = NULL; + + /** + * Initialize hook class. + * + * @param array $valid_hooks array containing the hookable functions/methods + */ + function phpbb_hook($valid_hooks) + { + foreach ($valid_hooks as $_null => $method) + { + $this->add_hook($method); + } + + if (function_exists('phpbb_hook_register')) + { + phpbb_hook_register($this); + } + } + + /** + * Register function/method to be called within hook + * This function is normally called by the modification/application to attach/register the functions. + * + * @param mixed $definition Declaring function (with __FUNCTION__) or class with array(__CLASS__, __FUNCTION__) + * @param mixed $hook The replacement function/method to be called. Passing function name or array with object/class definition + * @param string $mode Specify the priority/chain mode. 'normal' -> hook gets appended to the chain. 'standalone' -> only the specified hook gets called - later hooks are not able to overwrite this (E_NOTICE is triggered then). 'first' -> hook is called as the first one within the chain. 'last' -> hook is called as the last one within the chain. + */ + function register($definition, $hook, $mode = 'normal') + { + $class = (!is_array($definition)) ? '__global' : $definition[0]; + $function = (!is_array($definition)) ? $definition : $definition[1]; + + // Method able to be hooked? + if (isset($this->hooks[$class][$function])) + { + switch ($mode) + { + case 'standalone': + if (!isset($this->hooks[$class][$function]['standalone'])) + { + $this->hooks[$class][$function] = array('standalone' => $hook); + } + else + { + trigger_error('Hook not able to be called standalone, previous hook already standalone.', E_NOTICE); + } + break; + + case 'first': + case 'last': + $this->hooks[$class][$function][$mode][] = $hook; + break; + + case 'normal': + default: + $this->hooks[$class][$function]['normal'][] = $hook; + break; + } + } + } + + /** + * Calling all functions/methods attached to a specified hook. + * Called by the function allowing hooks... + * + * @param mixed $definition Declaring function (with __FUNCTION__) or class with array(__CLASS__, __FUNCTION__) + * @return bool False if no hook got executed, true otherwise + */ + function call_hook($definition) + { + $class = (!is_array($definition)) ? '__global' : $definition[0]; + $function = (!is_array($definition)) ? $definition : $definition[1]; + + if (!empty($this->hooks[$class][$function])) + { + // Developer tries to call a hooked function within the hooked function... + if ($this->current_hook !== NULL && $this->current_hook['class'] === $class && $this->current_hook['function'] === $function) + { + return false; + } + + // Call the hook with the arguments attached and store result + $arguments = func_get_args(); + $this->current_hook = array('class' => $class, 'function' => $function); + $arguments[0] = &$this; + + // Call the hook chain... + if (isset($this->hooks[$class][$function]['standalone'])) + { + $this->hook_result[$class][$function] = call_user_func_array($this->hooks[$class][$function]['standalone'], $arguments); + } + else + { + foreach (array('first', 'normal', 'last') as $mode) + { + if (!isset($this->hooks[$class][$function][$mode])) + { + continue; + } + + foreach ($this->hooks[$class][$function][$mode] as $hook) + { + $this->hook_result[$class][$function] = call_user_func_array($hook, $arguments); + } + } + } + + $this->current_hook = NULL; + return true; + } + + $this->current_hook = NULL; + return false; + } + + /** + * Get result from previously called functions/methods for the same hook + * + * @param mixed $definition Declaring function (with __FUNCTION__) or class with array(__CLASS__, __FUNCTION__) + * @return mixed False if nothing returned if there is no result, else array('result' => ... ) + */ + function previous_hook_result($definition) + { + $class = (!is_array($definition)) ? '__global' : $definition[0]; + $function = (!is_array($definition)) ? $definition : $definition[1]; + + if (!empty($this->hooks[$class][$function]) && isset($this->hook_result[$class][$function])) + { + return array('result' => $this->hook_result[$class][$function]); + } + + return false; + } + + /** + * Check if the called functions/methods returned something. + * + * @param mixed $definition Declaring function (with __FUNCTION__) or class with array(__CLASS__, __FUNCTION__) + * @return bool True if results are there, false if not + */ + function hook_return($definition) + { + $class = (!is_array($definition)) ? '__global' : $definition[0]; + $function = (!is_array($definition)) ? $definition : $definition[1]; + + if (!empty($this->hooks[$class][$function]) && isset($this->hook_result[$class][$function])) + { + return true; + } + + return false; + } + + /** + * Give actual result from called functions/methods back. + * + * @param mixed $definition Declaring function (with __FUNCTION__) or class with array(__CLASS__, __FUNCTION__) + * @return mixed The result + */ + function hook_return_result($definition) + { + $class = (!is_array($definition)) ? '__global' : $definition[0]; + $function = (!is_array($definition)) ? $definition : $definition[1]; + + if (!empty($this->hooks[$class][$function]) && isset($this->hook_result[$class][$function])) + { + $result = $this->hook_result[$class][$function]; + unset($this->hook_result[$class][$function]); + return $result; + } + + return; + } + + /** + * Add new function to the allowed hooks. + * + * @param mixed $definition Declaring function (with __FUNCTION__) or class with array(__CLASS__, __FUNCTION__) + */ + function add_hook($definition) + { + if (!is_array($definition)) + { + $definition = array('__global', $definition); + } + + $this->hooks[$definition[0]][$definition[1]] = array(); + } + + /** + * Remove function from the allowed hooks. + * + * @param mixed $definition Declaring function (with __FUNCTION__) or class with array(__CLASS__, __FUNCTION__) + */ + function remove_hook($definition) + { + $class = (!is_array($definition)) ? '__global' : $definition[0]; + $function = (!is_array($definition)) ? $definition : $definition[1]; + + if (isset($this->hooks[$class][$function])) + { + unset($this->hooks[$class][$function]); + + if (isset($this->hook_result[$class][$function])) + { + unset($this->hook_result[$class][$function]); + } + } + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/index.htm b/phpBB/includes/index.htm new file mode 100644 index 0000000000..ee1f723a7d --- /dev/null +++ b/phpBB/includes/index.htm @@ -0,0 +1,10 @@ +<html> +<head> +<title></title> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> +</head> + +<body bgcolor="#FFFFFF" text="#000000"> + +</body> +</html> diff --git a/phpBB/includes/mcp/info/mcp_ban.php b/phpBB/includes/mcp/info/mcp_ban.php new file mode 100644 index 0000000000..383df30498 --- /dev/null +++ b/phpBB/includes/mcp/info/mcp_ban.php @@ -0,0 +1,39 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class mcp_ban_info +{ + function module() + { + return array( + 'filename' => 'mcp_ban', + 'title' => 'MCP_BAN', + 'version' => '1.0.0', + 'modes' => array( + 'user' => array('title' => 'MCP_BAN_USERNAMES', 'auth' => 'acl_m_ban', 'cat' => array('MCP_BAN')), + 'ip' => array('title' => 'MCP_BAN_IPS', 'auth' => 'acl_m_ban', 'cat' => array('MCP_BAN')), + 'email' => array('title' => 'MCP_BAN_EMAILS', 'auth' => 'acl_m_ban', 'cat' => array('MCP_BAN')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/mcp/info/mcp_logs.php b/phpBB/includes/mcp/info/mcp_logs.php new file mode 100644 index 0000000000..fe2f9fa1d7 --- /dev/null +++ b/phpBB/includes/mcp/info/mcp_logs.php @@ -0,0 +1,39 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class mcp_logs_info +{ + function module() + { + return array( + 'filename' => 'mcp_logs', + 'title' => 'MCP_LOGS', + 'version' => '1.0.0', + 'modes' => array( + 'front' => array('title' => 'MCP_LOGS_FRONT', 'auth' => 'acl_m_ || aclf_m_', 'cat' => array('MCP_LOGS')), + 'forum_logs' => array('title' => 'MCP_LOGS_FORUM_VIEW', 'auth' => 'acl_m_,$id', 'cat' => array('MCP_LOGS')), + 'topic_logs' => array('title' => 'MCP_LOGS_TOPIC_VIEW', 'auth' => 'acl_m_,$id', 'cat' => array('MCP_LOGS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/mcp/info/mcp_main.php b/phpBB/includes/mcp/info/mcp_main.php new file mode 100644 index 0000000000..9755cdfc07 --- /dev/null +++ b/phpBB/includes/mcp/info/mcp_main.php @@ -0,0 +1,40 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class mcp_main_info +{ + function module() + { + return array( + 'filename' => 'mcp_main', + 'title' => 'MCP_MAIN', + 'version' => '1.0.0', + 'modes' => array( + 'front' => array('title' => 'MCP_MAIN_FRONT', 'auth' => '', 'cat' => array('MCP_MAIN')), + 'forum_view' => array('title' => 'MCP_MAIN_FORUM_VIEW', 'auth' => 'acl_m_,$id', 'cat' => array('MCP_MAIN')), + 'topic_view' => array('title' => 'MCP_MAIN_TOPIC_VIEW', 'auth' => 'acl_m_,$id', 'cat' => array('MCP_MAIN')), + 'post_details' => array('title' => 'MCP_MAIN_POST_DETAILS', 'auth' => 'acl_m_,$id || (!$id && aclf_m_)', 'cat' => array('MCP_MAIN')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/mcp/info/mcp_notes.php b/phpBB/includes/mcp/info/mcp_notes.php new file mode 100644 index 0000000000..afe232e5b5 --- /dev/null +++ b/phpBB/includes/mcp/info/mcp_notes.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class mcp_notes_info +{ + function module() + { + return array( + 'filename' => 'mcp_notes', + 'title' => 'MCP_NOTES', + 'version' => '1.0.0', + 'modes' => array( + 'front' => array('title' => 'MCP_NOTES_FRONT', 'auth' => '', 'cat' => array('MCP_NOTES')), + 'user_notes' => array('title' => 'MCP_NOTES_USER', 'auth' => '', 'cat' => array('MCP_NOTES')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/mcp/info/mcp_pm_reports.php b/phpBB/includes/mcp/info/mcp_pm_reports.php new file mode 100644 index 0000000000..103f560597 --- /dev/null +++ b/phpBB/includes/mcp/info/mcp_pm_reports.php @@ -0,0 +1,39 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class mcp_pm_reports_info +{ + function module() + { + return array( + 'filename' => 'mcp_pm_reports', + 'title' => 'MCP_PM_REPORTS', + 'version' => '1.0.0', + 'modes' => array( + 'pm_reports' => array('title' => 'MCP_PM_REPORTS_OPEN', 'auth' => 'aclf_m_report', 'cat' => array('MCP_REPORTS')), + 'pm_reports_closed' => array('title' => 'MCP_PM_REPORTS_CLOSED', 'auth' => 'aclf_m_report', 'cat' => array('MCP_REPORTS')), + 'pm_report_details' => array('title' => 'MCP_PM_REPORT_DETAILS', 'auth' => 'aclf_m_report', 'cat' => array('MCP_REPORTS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/mcp/info/mcp_queue.php b/phpBB/includes/mcp/info/mcp_queue.php new file mode 100644 index 0000000000..7a256642b9 --- /dev/null +++ b/phpBB/includes/mcp/info/mcp_queue.php @@ -0,0 +1,39 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class mcp_queue_info +{ + function module() + { + return array( + 'filename' => 'mcp_queue', + 'title' => 'MCP_QUEUE', + 'version' => '1.0.0', + 'modes' => array( + 'unapproved_topics' => array('title' => 'MCP_QUEUE_UNAPPROVED_TOPICS', 'auth' => 'aclf_m_approve', 'cat' => array('MCP_QUEUE')), + 'unapproved_posts' => array('title' => 'MCP_QUEUE_UNAPPROVED_POSTS', 'auth' => 'aclf_m_approve', 'cat' => array('MCP_QUEUE')), + 'approve_details' => array('title' => 'MCP_QUEUE_APPROVE_DETAILS', 'auth' => 'acl_m_approve,$id || (!$id && aclf_m_approve)', 'cat' => array('MCP_QUEUE')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/mcp/info/mcp_reports.php b/phpBB/includes/mcp/info/mcp_reports.php new file mode 100644 index 0000000000..3893ba5abb --- /dev/null +++ b/phpBB/includes/mcp/info/mcp_reports.php @@ -0,0 +1,39 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class mcp_reports_info +{ + function module() + { + return array( + 'filename' => 'mcp_reports', + 'title' => 'MCP_REPORTS', + 'version' => '1.0.0', + 'modes' => array( + 'reports' => array('title' => 'MCP_REPORTS_OPEN', 'auth' => 'aclf_m_report', 'cat' => array('MCP_REPORTS')), + 'reports_closed' => array('title' => 'MCP_REPORTS_CLOSED', 'auth' => 'aclf_m_report', 'cat' => array('MCP_REPORTS')), + 'report_details' => array('title' => 'MCP_REPORT_DETAILS', 'auth' => 'acl_m_report,$id || (!$id && aclf_m_report)', 'cat' => array('MCP_REPORTS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/mcp/info/mcp_warn.php b/phpBB/includes/mcp/info/mcp_warn.php new file mode 100644 index 0000000000..2b0b09f75a --- /dev/null +++ b/phpBB/includes/mcp/info/mcp_warn.php @@ -0,0 +1,40 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class mcp_warn_info +{ + function module() + { + return array( + 'filename' => 'mcp_warn', + 'title' => 'MCP_WARN', + 'version' => '1.0.0', + 'modes' => array( + 'front' => array('title' => 'MCP_WARN_FRONT', 'auth' => 'aclf_m_warn', 'cat' => array('MCP_WARN')), + 'list' => array('title' => 'MCP_WARN_LIST', 'auth' => 'aclf_m_warn', 'cat' => array('MCP_WARN')), + 'warn_user' => array('title' => 'MCP_WARN_USER', 'auth' => 'aclf_m_warn', 'cat' => array('MCP_WARN')), + 'warn_post' => array('title' => 'MCP_WARN_POST', 'auth' => 'acl_m_warn && acl_f_read,$id', 'cat' => array('MCP_WARN')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/mcp/mcp_ban.php b/phpBB/includes/mcp/mcp_ban.php new file mode 100644 index 0000000000..d9f5eb8f22 --- /dev/null +++ b/phpBB/includes/mcp/mcp_ban.php @@ -0,0 +1,219 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package mcp +*/ +class mcp_ban +{ + var $u_action; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $cache; + global $phpbb_root_path, $phpEx; + + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + + // Include the admin banning interface... + include($phpbb_root_path . 'includes/acp/acp_ban.' . $phpEx); + + $bansubmit = (isset($_POST['bansubmit'])) ? true : false; + $unbansubmit = (isset($_POST['unbansubmit'])) ? true : false; + $current_time = time(); + + $user->add_lang(array('acp/ban', 'acp/users')); + $this->tpl_name = 'mcp_ban'; + + // Ban submitted? + if ($bansubmit) + { + // Grab the list of entries + $ban = request_var('ban', '', ($mode === 'user') ? true : false); + + if ($mode === 'user') + { + $ban = utf8_normalize_nfc($ban); + } + + $ban_len = request_var('banlength', 0); + $ban_len_other = request_var('banlengthother', ''); + $ban_exclude = request_var('banexclude', 0); + $ban_reason = utf8_normalize_nfc(request_var('banreason', '', true)); + $ban_give_reason = utf8_normalize_nfc(request_var('bangivereason', '', true)); + + if ($ban) + { + if (confirm_box(true)) + { + user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reason, $ban_give_reason); + + trigger_error($user->lang['BAN_UPDATE_SUCCESSFUL'] . '<br /><br /><a href="' . $this->u_action . '">« ' . $user->lang['BACK_TO_PREV'] . '</a>'); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'mode' => $mode, + 'ban' => $ban, + 'bansubmit' => true, + 'banlength' => $ban_len, + 'banlengthother' => $ban_len_other, + 'banexclude' => $ban_exclude, + 'banreason' => $ban_reason, + 'bangivereason' => $ban_give_reason))); + } + } + } + else if ($unbansubmit) + { + $ban = request_var('unban', array('')); + + if ($ban) + { + if (confirm_box(true)) + { + user_unban($mode, $ban); + + trigger_error($user->lang['BAN_UPDATE_SUCCESSFUL'] . '<br /><br /><a href="' . $this->u_action . '">« ' . $user->lang['BACK_TO_PREV'] . '</a>'); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'mode' => $mode, + 'unbansubmit' => true, + 'unban' => $ban))); + } + } + } + + // Ban length options + $ban_end_text = array(0 => $user->lang['PERMANENT'], 30 => $user->lang['30_MINS'], 60 => $user->lang['1_HOUR'], 360 => $user->lang['6_HOURS'], 1440 => $user->lang['1_DAY'], 10080 => $user->lang['7_DAYS'], 20160 => $user->lang['2_WEEKS'], 40320 => $user->lang['1_MONTH'], -1 => $user->lang['UNTIL'] . ' -> '); + + $ban_end_options = ''; + foreach ($ban_end_text as $length => $text) + { + $ban_end_options .= '<option value="' . $length . '">' . $text . '</option>'; + } + + // Define language vars + $this->page_title = $user->lang[strtoupper($mode) . '_BAN']; + + $l_ban_explain = $user->lang[strtoupper($mode) . '_BAN_EXPLAIN']; + $l_ban_exclude_explain = $user->lang[strtoupper($mode) . '_BAN_EXCLUDE_EXPLAIN']; + $l_unban_title = $user->lang[strtoupper($mode) . '_UNBAN']; + $l_unban_explain = $user->lang[strtoupper($mode) . '_UNBAN_EXPLAIN']; + $l_no_ban_cell = $user->lang[strtoupper($mode) . '_NO_BANNED']; + + switch ($mode) + { + case 'user': + $l_ban_cell = $user->lang['USERNAME']; + break; + + case 'ip': + $l_ban_cell = $user->lang['IP_HOSTNAME']; + break; + + case 'email': + $l_ban_cell = $user->lang['EMAIL_ADDRESS']; + break; + } + + acp_ban::display_ban_options($mode); + + $template->assign_vars(array( + 'L_TITLE' => $this->page_title, + 'L_EXPLAIN' => $l_ban_explain, + 'L_UNBAN_TITLE' => $l_unban_title, + 'L_UNBAN_EXPLAIN' => $l_unban_explain, + 'L_BAN_CELL' => $l_ban_cell, + 'L_BAN_EXCLUDE_EXPLAIN' => $l_ban_exclude_explain, + 'L_NO_BAN_CELL' => $l_no_ban_cell, + + 'S_USERNAME_BAN' => ($mode == 'user') ? true : false, + + 'U_ACTION' => $this->u_action, + 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=mcp_ban&field=ban'), + )); + + if ($mode === 'email' && !$auth->acl_get('a_user')) + { + return; + } + + // As a "service" we will check if any post id is specified and populate the username of the poster id if given + $post_id = request_var('p', 0); + $user_id = request_var('u', 0); + $username = $pre_fill = false; + + if ($user_id && $user_id <> ANONYMOUS) + { + $sql = 'SELECT username, user_email, user_ip + FROM ' . USERS_TABLE . ' + WHERE user_id = ' . $user_id; + $result = $db->sql_query($sql); + switch ($mode) + { + case 'user': + $pre_fill = (string) $db->sql_fetchfield('username'); + break; + + case 'ip': + $pre_fill = (string) $db->sql_fetchfield('user_ip'); + break; + + case 'email': + $pre_fill = (string) $db->sql_fetchfield('user_email'); + break; + } + $db->sql_freeresult($result); + } + else if ($post_id) + { + $post_info = get_post_data($post_id, 'm_ban'); + + if (sizeof($post_info) && !empty($post_info[$post_id])) + { + switch ($mode) + { + case 'user': + $pre_fill = $post_info[$post_id]['username']; + break; + + case 'ip': + $pre_fill = $post_info[$post_id]['poster_ip']; + break; + + case 'email': + $pre_fill = $post_info[$post_id]['user_email']; + break; + } + + } + } + + if ($pre_fill) + { + // left for legacy template compatibility + $template->assign_var('USERNAMES', $pre_fill); + $template->assign_var('BAN_QUANTIFIER', $pre_fill); + } + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/mcp/mcp_forum.php b/phpBB/includes/mcp/mcp_forum.php new file mode 100644 index 0000000000..b70601b479 --- /dev/null +++ b/phpBB/includes/mcp/mcp_forum.php @@ -0,0 +1,447 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* MCP Forum View +*/ +function mcp_forum_view($id, $mode, $action, $forum_info) +{ + global $template, $db, $user, $auth, $cache, $module; + global $phpEx, $phpbb_root_path, $config; + + $user->add_lang(array('viewtopic', 'viewforum')); + + include_once($phpbb_root_path . 'includes/functions_display.' . $phpEx); + + // merge_topic is the quickmod action, merge_topics is the mcp_forum action, and merge_select is the mcp_topic action + $merge_select = ($action == 'merge_select' || $action == 'merge_topic' || $action == 'merge_topics') ? true : false; + + if ($merge_select) + { + // Fixes a "bug" that makes forum_view use the same ordering as topic_view + unset($_POST['sk'], $_POST['sd'], $_REQUEST['sk'], $_REQUEST['sd']); + } + + $forum_id = $forum_info['forum_id']; + $start = request_var('start', 0); + $topic_id_list = request_var('topic_id_list', array(0)); + $post_id_list = request_var('post_id_list', array(0)); + $source_topic_ids = array(request_var('t', 0)); + $to_topic_id = request_var('to_topic_id', 0); + + $url_extra = ''; + $url_extra .= ($forum_id) ? "&f=$forum_id" : ''; + $url_extra .= ($GLOBALS['topic_id']) ? '&t=' . $GLOBALS['topic_id'] : ''; + $url_extra .= ($GLOBALS['post_id']) ? '&p=' . $GLOBALS['post_id'] : ''; + $url_extra .= ($GLOBALS['user_id']) ? '&u=' . $GLOBALS['user_id'] : ''; + + $url = append_sid("{$phpbb_root_path}mcp.$phpEx?$url_extra"); + + // Resync Topics + switch ($action) + { + case 'resync': + $topic_ids = request_var('topic_id_list', array(0)); + mcp_resync_topics($topic_ids); + break; + + case 'merge_topics': + $source_topic_ids = $topic_id_list; + case 'merge_topic': + if ($to_topic_id) + { + merge_topics($forum_id, $source_topic_ids, $to_topic_id); + } + break; + } + + $selected_ids = ''; + if (sizeof($post_id_list) && $action != 'merge_topics') + { + foreach ($post_id_list as $num => $post_id) + { + $selected_ids .= '&post_id_list[' . $num . ']=' . $post_id; + } + } + else if (sizeof($topic_id_list) && $action == 'merge_topics') + { + foreach ($topic_id_list as $num => $topic_id) + { + $selected_ids .= '&topic_id_list[' . $num . ']=' . $topic_id; + } + } + + make_jumpbox($url . "&i=$id&action=$action&mode=$mode" . (($merge_select) ? $selected_ids : ''), $forum_id, false, 'm_', true); + + $topics_per_page = ($forum_info['forum_topics_per_page']) ? $forum_info['forum_topics_per_page'] : $config['topics_per_page']; + + $sort_days = $total = 0; + $sort_key = $sort_dir = ''; + $sort_by_sql = $sort_order_sql = array(); + mcp_sorting('viewforum', $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id); + + $forum_topics = ($total == -1) ? $forum_info['forum_topics'] : $total; + $limit_time_sql = ($sort_days) ? 'AND t.topic_last_post_time >= ' . (time() - ($sort_days * 86400)) : ''; + + $template->assign_vars(array( + 'ACTION' => $action, + 'FORUM_NAME' => $forum_info['forum_name'], + 'FORUM_DESCRIPTION' => generate_text_for_display($forum_info['forum_desc'], $forum_info['forum_desc_uid'], $forum_info['forum_desc_bitfield'], $forum_info['forum_desc_options']), + + 'REPORTED_IMG' => $user->img('icon_topic_reported', 'TOPIC_REPORTED'), + 'UNAPPROVED_IMG' => $user->img('icon_topic_unapproved', 'TOPIC_UNAPPROVED'), + 'LAST_POST_IMG' => $user->img('icon_topic_latest', 'VIEW_LATEST_POST'), + 'NEWEST_POST_IMG' => $user->img('icon_topic_newest', 'VIEW_NEWEST_POST'), + + 'S_CAN_REPORT' => $auth->acl_get('m_report', $forum_id), + 'S_CAN_DELETE' => $auth->acl_get('m_delete', $forum_id), + 'S_CAN_MERGE' => $auth->acl_get('m_merge', $forum_id), + 'S_CAN_MOVE' => $auth->acl_get('m_move', $forum_id), + 'S_CAN_FORK' => $auth->acl_get('m_', $forum_id), + 'S_CAN_LOCK' => $auth->acl_get('m_lock', $forum_id), + 'S_CAN_SYNC' => $auth->acl_get('m_', $forum_id), + 'S_CAN_APPROVE' => $auth->acl_get('m_approve', $forum_id), + 'S_MERGE_SELECT' => ($merge_select) ? true : false, + 'S_CAN_MAKE_NORMAL' => $auth->acl_gets('f_sticky', 'f_announce', $forum_id), + 'S_CAN_MAKE_STICKY' => $auth->acl_get('f_sticky', $forum_id), + 'S_CAN_MAKE_ANNOUNCE' => $auth->acl_get('f_announce', $forum_id), + + 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id), + 'U_VIEW_FORUM_LOGS' => ($auth->acl_gets('a_', 'm_', $forum_id) && $module->loaded('logs')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=logs&mode=forum_logs&f=' . $forum_id) : '', + + 'S_MCP_ACTION' => $url . "&i=$id&forum_action=$action&mode=$mode&start=$start" . (($merge_select) ? $selected_ids : ''), + + 'PAGINATION' => generate_pagination($url . "&i=$id&action=$action&mode=$mode&sd=$sort_dir&sk=$sort_key&st=$sort_days" . (($merge_select) ? $selected_ids : ''), $forum_topics, $topics_per_page, $start), + 'PAGE_NUMBER' => on_page($forum_topics, $topics_per_page, $start), + 'TOTAL_TOPICS' => ($forum_topics == 1) ? $user->lang['VIEW_FORUM_TOPIC'] : sprintf($user->lang['VIEW_FORUM_TOPICS'], $forum_topics), + )); + + // Grab icons + $icons = $cache->obtain_icons(); + + $topic_rows = array(); + + if ($config['load_db_lastread']) + { + $read_tracking_join = ' LEFT JOIN ' . TOPICS_TRACK_TABLE . ' tt ON (tt.topic_id = t.topic_id AND tt.user_id = ' . $user->data['user_id'] . ')'; + $read_tracking_select = ', tt.mark_time'; + } + else + { + $read_tracking_join = $read_tracking_select = ''; + } + + $sql = "SELECT t.topic_id + FROM " . TOPICS_TABLE . " t + WHERE t.forum_id IN($forum_id, 0) + " . (($auth->acl_get('m_approve', $forum_id)) ? '' : 'AND t.topic_approved = 1') . " + $limit_time_sql + ORDER BY t.topic_type DESC, $sort_order_sql"; + $result = $db->sql_query_limit($sql, $topics_per_page, $start); + + $topic_list = $topic_tracking_info = array(); + + while ($row = $db->sql_fetchrow($result)) + { + $topic_list[] = $row['topic_id']; + } + $db->sql_freeresult($result); + + $sql = "SELECT t.*$read_tracking_select + FROM " . TOPICS_TABLE . " t $read_tracking_join + WHERE " . $db->sql_in_set('t.topic_id', $topic_list, false, true); + + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + $topic_rows[$row['topic_id']] = $row; + } + $db->sql_freeresult($result); + + // If there is more than one page, but we have no topic list, then the start parameter is... erm... out of sync + if (!sizeof($topic_list) && $forum_topics && $start > 0) + { + redirect($url . "&i=$id&action=$action&mode=$mode"); + } + + // Get topic tracking info + if (sizeof($topic_list)) + { + if ($config['load_db_lastread']) + { + $topic_tracking_info = get_topic_tracking($forum_id, $topic_list, $topic_rows, array($forum_id => $forum_info['mark_time']), array()); + } + else + { + $topic_tracking_info = get_complete_topic_tracking($forum_id, $topic_list, array()); + } + } + + foreach ($topic_list as $topic_id) + { + $topic_title = ''; + + $row = &$topic_rows[$topic_id]; + + $replies = ($auth->acl_get('m_approve', $forum_id)) ? $row['topic_replies_real'] : $row['topic_replies']; + + if ($row['topic_status'] == ITEM_MOVED) + { + $unread_topic = false; + } + else + { + $unread_topic = (isset($topic_tracking_info[$topic_id]) && $row['topic_last_post_time'] > $topic_tracking_info[$topic_id]) ? true : false; + } + + // Get folder img, topic status/type related information + $folder_img = $folder_alt = $topic_type = ''; + topic_status($row, $replies, $unread_topic, $folder_img, $folder_alt, $topic_type); + + $topic_title = censor_text($row['topic_title']); + + $topic_unapproved = (!$row['topic_approved'] && $auth->acl_get('m_approve', $row['forum_id'])) ? true : false; + $posts_unapproved = ($row['topic_approved'] && $row['topic_replies'] < $row['topic_replies_real'] && $auth->acl_get('m_approve', $row['forum_id'])) ? true : false; + $u_mcp_queue = ($topic_unapproved || $posts_unapproved) ? $url . '&i=queue&mode=' . (($topic_unapproved) ? 'approve_details' : 'unapproved_posts') . '&t=' . $row['topic_id'] : ''; + + $topic_row = array( + 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']) && $row['topic_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', + 'TOPIC_FOLDER_IMG' => $user->img($folder_img, $folder_alt), + 'TOPIC_FOLDER_IMG_SRC' => $user->img($folder_img, $folder_alt, false, '', 'src'), + 'TOPIC_ICON_IMG' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['img'] : '', + 'TOPIC_ICON_IMG_WIDTH' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['width'] : '', + 'TOPIC_ICON_IMG_HEIGHT' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['height'] : '', + 'UNAPPROVED_IMG' => ($topic_unapproved || $posts_unapproved) ? $user->img('icon_topic_unapproved', ($topic_unapproved) ? 'TOPIC_UNAPPROVED' : 'POSTS_UNAPPROVED') : '', + + 'TOPIC_AUTHOR' => get_username_string('username', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + 'TOPIC_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + 'TOPIC_AUTHOR_FULL' => get_username_string('full', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + 'U_TOPIC_AUTHOR' => get_username_string('profile', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + + 'LAST_POST_AUTHOR' => get_username_string('username', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + 'LAST_POST_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + 'LAST_POST_AUTHOR_FULL' => get_username_string('full', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + 'U_LAST_POST_AUTHOR' => get_username_string('profile', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + + 'TOPIC_TYPE' => $topic_type, + 'TOPIC_TITLE' => $topic_title, + 'REPLIES' => ($auth->acl_get('m_approve', $row['forum_id'])) ? $row['topic_replies_real'] : $row['topic_replies'], + 'LAST_POST_TIME' => $user->format_date($row['topic_last_post_time']), + 'FIRST_POST_TIME' => $user->format_date($row['topic_time']), + 'LAST_POST_SUBJECT' => $row['topic_last_post_subject'], + 'LAST_VIEW_TIME' => $user->format_date($row['topic_last_view_time']), + + 'S_TOPIC_REPORTED' => (!empty($row['topic_reported']) && empty($row['topic_moved_id']) && $auth->acl_get('m_report', $row['forum_id'])) ? true : false, + 'S_TOPIC_UNAPPROVED' => $topic_unapproved, + 'S_POSTS_UNAPPROVED' => $posts_unapproved, + 'S_UNREAD_TOPIC' => $unread_topic, + ); + + if ($row['topic_status'] == ITEM_MOVED) + { + $topic_row = array_merge($topic_row, array( + 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "t={$row['topic_moved_id']}"), + 'U_DELETE_TOPIC' => ($auth->acl_get('m_delete', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&f=$forum_id&topic_id_list[]={$row['topic_id']}&mode=forum_view&action=delete_topic") : '', + 'S_MOVED_TOPIC' => true, + 'TOPIC_ID' => $row['topic_moved_id'], + )); + } + else + { + if ($action == 'merge_topic' || $action == 'merge_topics') + { + $u_select_topic = $url . "&i=$id&mode=forum_view&action=$action&to_topic_id=" . $row['topic_id'] . $selected_ids; + } + else + { + $u_select_topic = $url . "&i=$id&mode=topic_view&action=merge&to_topic_id=" . $row['topic_id'] . $selected_ids; + } + $topic_row = array_merge($topic_row, array( + 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&f=$forum_id&t={$row['topic_id']}&mode=topic_view"), + + 'S_SELECT_TOPIC' => ($merge_select && !in_array($row['topic_id'], $source_topic_ids)) ? true : false, + 'U_SELECT_TOPIC' => $u_select_topic, + 'U_MCP_QUEUE' => $u_mcp_queue, + 'U_MCP_REPORT' => ($auth->acl_get('m_report', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&mode=topic_view&t=' . $row['topic_id'] . '&action=reports') : '', + 'TOPIC_ID' => $row['topic_id'], + 'S_TOPIC_CHECKED' => ($topic_id_list && in_array($row['topic_id'], $topic_id_list)) ? true : false, + )); + } + + $template->assign_block_vars('topicrow', $topic_row); + } + unset($topic_rows); +} + +/** +* Resync topics +*/ +function mcp_resync_topics($topic_ids) +{ + global $auth, $db, $template, $phpEx, $user, $phpbb_root_path; + + if (!sizeof($topic_ids)) + { + trigger_error('NO_TOPIC_SELECTED'); + } + + if (!check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_'))) + { + return; + } + + // Sync everything and perform extra checks separately + sync('topic_reported', 'topic_id', $topic_ids, false, true); + sync('topic_attachment', 'topic_id', $topic_ids, false, true); + sync('topic', 'topic_id', $topic_ids, true, false); + + $sql = 'SELECT topic_id, forum_id, topic_title + FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', $topic_ids); + $result = $db->sql_query($sql); + + // Log this action + while ($row = $db->sql_fetchrow($result)) + { + add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_TOPIC_RESYNC', $row['topic_title']); + } + $db->sql_freeresult($result); + + $msg = (sizeof($topic_ids) == 1) ? $user->lang['TOPIC_RESYNC_SUCCESS'] : $user->lang['TOPICS_RESYNC_SUCCESS']; + + $redirect = request_var('redirect', $user->data['session_page']); + + meta_refresh(3, $redirect); + trigger_error($msg . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>')); + + return; +} + +/** +* Merge selected topics into selected topic +*/ +function merge_topics($forum_id, $topic_ids, $to_topic_id) +{ + global $db, $template, $user, $phpEx, $phpbb_root_path, $auth; + + if (!sizeof($topic_ids)) + { + $template->assign_var('MESSAGE', $user->lang['NO_TOPIC_SELECTED']); + return; + } + if (!$to_topic_id) + { + $template->assign_var('MESSAGE', $user->lang['NO_FINAL_TOPIC_SELECTED']); + return; + } + + $topic_data = get_topic_data(array($to_topic_id), 'm_merge'); + + if (!sizeof($topic_data)) + { + $template->assign_var('MESSAGE', $user->lang['NO_FINAL_TOPIC_SELECTED']); + return; + } + + $topic_data = $topic_data[$to_topic_id]; + + $post_id_list = request_var('post_id_list', array(0)); + $start = request_var('start', 0); + + if (!sizeof($post_id_list) && sizeof($topic_ids)) + { + $sql = 'SELECT post_id + FROM ' . POSTS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', $topic_ids); + $result = $db->sql_query($sql); + + $post_id_list = array(); + while ($row = $db->sql_fetchrow($result)) + { + $post_id_list[] = $row['post_id']; + } + $db->sql_freeresult($result); + } + + if (!sizeof($post_id_list)) + { + $template->assign_var('MESSAGE', $user->lang['NO_POST_SELECTED']); + return; + } + + if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_merge'))) + { + return; + } + + $redirect = request_var('redirect', build_url(array('quickmod'))); + + $s_hidden_fields = build_hidden_fields(array( + 'i' => 'main', + 'f' => $forum_id, + 'post_id_list' => $post_id_list, + 'to_topic_id' => $to_topic_id, + 'mode' => 'forum_view', + 'action' => 'merge_topics', + 'start' => $start, + 'redirect' => $redirect, + 'topic_id_list' => $topic_ids) + ); + $success_msg = $return_link = ''; + + if (confirm_box(true)) + { + $to_forum_id = $topic_data['forum_id']; + + move_posts($post_id_list, $to_topic_id); + add_log('mod', $to_forum_id, $to_topic_id, 'LOG_MERGE', $topic_data['topic_title']); + + // Message and return links + $success_msg = 'POSTS_MERGED_SUCCESS'; + + // If the topic no longer exist, we will update the topic watch table. + // To not let it error out on users watching both topics, we just return on an error... + $db->sql_return_on_error(true); + $db->sql_query('UPDATE ' . TOPICS_WATCH_TABLE . ' SET topic_id = ' . (int) $to_topic_id . ' WHERE ' . $db->sql_in_set('topic_id', $topic_ids)); + $db->sql_return_on_error(false); + + $db->sql_query('DELETE FROM ' . TOPICS_WATCH_TABLE . ' WHERE ' . $db->sql_in_set('topic_id', $topic_ids)); + + // Link to the new topic + $return_link .= (($return_link) ? '<br /><br />' : '') . sprintf($user->lang['RETURN_NEW_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $to_forum_id . '&t=' . $to_topic_id) . '">', '</a>'); + } + else + { + confirm_box(false, 'MERGE_TOPICS', $s_hidden_fields); + } + + $redirect = request_var('redirect', "index.$phpEx"); + $redirect = reapply_sid($redirect); + + if (!$success_msg) + { + return; + } + else + { + meta_refresh(3, append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$to_forum_id&t=$to_topic_id")); + trigger_error($user->lang[$success_msg] . '<br /><br />' . $return_link); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/mcp/mcp_front.php b/phpBB/includes/mcp/mcp_front.php new file mode 100644 index 0000000000..50e14b9336 --- /dev/null +++ b/phpBB/includes/mcp/mcp_front.php @@ -0,0 +1,380 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* MCP Front Panel +*/ +function mcp_front_view($id, $mode, $action) +{ + global $phpEx, $phpbb_root_path, $config; + global $template, $db, $user, $auth, $module; + + // Latest 5 unapproved + if ($module->loaded('queue')) + { + $forum_list = array_values(array_intersect(get_forum_list('f_read'), get_forum_list('m_approve'))); + $post_list = array(); + $forum_names = array(); + + $forum_id = request_var('f', 0); + + $template->assign_var('S_SHOW_UNAPPROVED', (!empty($forum_list)) ? true : false); + + if (!empty($forum_list)) + { + $sql = 'SELECT COUNT(post_id) AS total + FROM ' . POSTS_TABLE . ' + WHERE forum_id IN (0, ' . implode(', ', $forum_list) . ') + AND post_approved = 0'; + $result = $db->sql_query($sql); + $total = (int) $db->sql_fetchfield('total'); + $db->sql_freeresult($result); + + if ($total) + { + $global_id = $forum_list[0]; + + $sql = 'SELECT forum_id, forum_name + FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_list); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $forum_names[$row['forum_id']] = $row['forum_name']; + } + $db->sql_freeresult($result); + + $sql = 'SELECT post_id + FROM ' . POSTS_TABLE . ' + WHERE forum_id IN (0, ' . implode(', ', $forum_list) . ') + AND post_approved = 0 + ORDER BY post_time DESC'; + $result = $db->sql_query_limit($sql, 5); + + while ($row = $db->sql_fetchrow($result)) + { + $post_list[] = $row['post_id']; + } + $db->sql_freeresult($result); + + if (empty($post_list)) + { + $total = 0; + } + } + + if ($total) + { + $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.username, u.username_clean, u.user_colour, t.topic_id, t.topic_title, t.topic_first_post_id, p.forum_id + FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t, ' . USERS_TABLE . ' u + WHERE ' . $db->sql_in_set('p.post_id', $post_list) . ' + AND t.topic_id = p.topic_id + AND p.poster_id = u.user_id + ORDER BY p.post_time DESC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $global_topic = ($row['forum_id']) ? false : true; + if ($global_topic) + { + $row['forum_id'] = $global_id; + } + + $template->assign_block_vars('unapproved', array( + 'U_POST_DETAILS' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&mode=approve_details&f=' . $row['forum_id'] . '&p=' . $row['post_id']), + 'U_MCP_FORUM' => (!$global_topic) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&mode=forum_view&f=' . $row['forum_id']) : '', + 'U_MCP_TOPIC' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&mode=topic_view&f=' . $row['forum_id'] . '&t=' . $row['topic_id']), + 'U_FORUM' => (!$global_topic) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id']) : '', + 'U_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $row['forum_id'] . '&t=' . $row['topic_id']), + + 'AUTHOR_FULL' => get_username_string('full', $row['poster_id'], $row['username'], $row['user_colour']), + 'AUTHOR' => get_username_string('username', $row['poster_id'], $row['username'], $row['user_colour']), + 'AUTHOR_COLOUR' => get_username_string('colour', $row['poster_id'], $row['username'], $row['user_colour']), + 'U_AUTHOR' => get_username_string('profile', $row['poster_id'], $row['username'], $row['user_colour']), + + 'FORUM_NAME' => (!$global_topic) ? $forum_names[$row['forum_id']] : $user->lang['GLOBAL_ANNOUNCEMENT'], + 'POST_ID' => $row['post_id'], + 'TOPIC_TITLE' => $row['topic_title'], + 'SUBJECT' => ($row['post_subject']) ? $row['post_subject'] : $user->lang['NO_SUBJECT'], + 'POST_TIME' => $user->format_date($row['post_time'])) + ); + } + $db->sql_freeresult($result); + } + + $s_hidden_fields = build_hidden_fields(array( + 'redirect' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main' . (($forum_id) ? '&f=' . $forum_id : '')) + )); + + $template->assign_vars(array( + 'S_HIDDEN_FIELDS' => $s_hidden_fields, + 'S_MCP_QUEUE_ACTION' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=queue"), + )); + + if ($total == 0) + { + $template->assign_vars(array( + 'L_UNAPPROVED_TOTAL' => $user->lang['UNAPPROVED_POSTS_ZERO_TOTAL'], + 'S_HAS_UNAPPROVED_POSTS' => false) + ); + } + else + { + $template->assign_vars(array( + 'L_UNAPPROVED_TOTAL' => ($total == 1) ? $user->lang['UNAPPROVED_POST_TOTAL'] : sprintf($user->lang['UNAPPROVED_POSTS_TOTAL'], $total), + 'S_HAS_UNAPPROVED_POSTS' => true) + ); + } + } + } + + // Latest 5 reported + if ($module->loaded('reports')) + { + $forum_list = array_values(array_intersect(get_forum_list('f_read'), get_forum_list('m_report'))); + + $template->assign_var('S_SHOW_REPORTS', (!empty($forum_list)) ? true : false); + + if (!empty($forum_list)) + { + $sql = 'SELECT COUNT(r.report_id) AS total + FROM ' . REPORTS_TABLE . ' r, ' . POSTS_TABLE . ' p + WHERE r.post_id = p.post_id + AND r.pm_id = 0 + AND r.report_closed = 0 + AND p.forum_id IN (0, ' . implode(', ', $forum_list) . ')'; + $result = $db->sql_query($sql); + $total = (int) $db->sql_fetchfield('total'); + $db->sql_freeresult($result); + + if ($total) + { + $global_id = $forum_list[0]; + + $sql = $db->sql_build_query('SELECT', array( + 'SELECT' => 'r.report_time, p.post_id, p.post_subject, p.post_time, u.username, u.username_clean, u.user_colour, u.user_id, u2.username as author_name, u2.username_clean as author_name_clean, u2.user_colour as author_colour, u2.user_id as author_id, t.topic_id, t.topic_title, f.forum_id, f.forum_name', + + 'FROM' => array( + REPORTS_TABLE => 'r', + REPORTS_REASONS_TABLE => 'rr', + TOPICS_TABLE => 't', + USERS_TABLE => array('u', 'u2'), + POSTS_TABLE => 'p' + ), + + 'LEFT_JOIN' => array( + array( + 'FROM' => array(FORUMS_TABLE => 'f'), + 'ON' => 'f.forum_id = p.forum_id' + ) + ), + + 'WHERE' => 'r.post_id = p.post_id + AND r.pm_id = 0 + AND r.report_closed = 0 + AND r.reason_id = rr.reason_id + AND p.topic_id = t.topic_id + AND r.user_id = u.user_id + AND p.poster_id = u2.user_id + AND p.forum_id IN (0, ' . implode(', ', $forum_list) . ')', + + 'ORDER_BY' => 'p.post_time DESC' + )); + $result = $db->sql_query_limit($sql, 5); + + while ($row = $db->sql_fetchrow($result)) + { + $global_topic = ($row['forum_id']) ? false : true; + if ($global_topic) + { + $row['forum_id'] = $global_id; + } + + $template->assign_block_vars('report', array( + 'U_POST_DETAILS' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'f=' . $row['forum_id'] . '&p=' . $row['post_id'] . "&i=reports&mode=report_details"), + 'U_MCP_FORUM' => (!$global_topic) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'f=' . $row['forum_id'] . "&i=$id&mode=forum_view") : '', + 'U_MCP_TOPIC' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'f=' . $row['forum_id'] . '&t=' . $row['topic_id'] . "&i=$id&mode=topic_view"), + 'U_FORUM' => (!$global_topic) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id']) : '', + 'U_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $row['forum_id'] . '&t=' . $row['topic_id']), + + 'REPORTER_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']), + 'REPORTER' => get_username_string('username', $row['user_id'], $row['username'], $row['user_colour']), + 'REPORTER_COLOUR' => get_username_string('colour', $row['user_id'], $row['username'], $row['user_colour']), + 'U_REPORTER' => get_username_string('profile', $row['user_id'], $row['username'], $row['user_colour']), + + 'AUTHOR_FULL' => get_username_string('full', $row['author_id'], $row['author_name'], $row['author_colour']), + 'AUTHOR' => get_username_string('username', $row['author_id'], $row['author_name'], $row['author_colour']), + 'AUTHOR_COLOUR' => get_username_string('colour', $row['author_id'], $row['author_name'], $row['author_colour']), + 'U_AUTHOR' => get_username_string('profile', $row['author_id'], $row['author_name'], $row['author_colour']), + + 'FORUM_NAME' => (!$global_topic) ? $row['forum_name'] : $user->lang['GLOBAL_ANNOUNCEMENT'], + 'TOPIC_TITLE' => $row['topic_title'], + 'SUBJECT' => ($row['post_subject']) ? $row['post_subject'] : $user->lang['NO_SUBJECT'], + 'REPORT_TIME' => $user->format_date($row['report_time']), + 'POST_TIME' => $user->format_date($row['post_time']), + )); + } + } + + if ($total == 0) + { + $template->assign_vars(array( + 'L_REPORTS_TOTAL' => $user->lang['REPORTS_ZERO_TOTAL'], + 'S_HAS_REPORTS' => false) + ); + } + else + { + $template->assign_vars(array( + 'L_REPORTS_TOTAL' => ($total == 1) ? $user->lang['REPORT_TOTAL'] : sprintf($user->lang['REPORTS_TOTAL'], $total), + 'S_HAS_REPORTS' => true) + ); + } + } + } + + // Latest 5 reported PMs + if ($module->loaded('pm_reports') && $auth->acl_getf_global('m_report')) + { + $template->assign_var('S_SHOW_PM_REPORTS', true); + $user->add_lang(array('ucp')); + + $sql = 'SELECT COUNT(r.report_id) AS total + FROM ' . REPORTS_TABLE . ' r, ' . PRIVMSGS_TABLE . ' p + WHERE r.post_id = 0 + AND r.pm_id = p.msg_id + AND r.report_closed = 0'; + $result = $db->sql_query($sql); + $total = (int) $db->sql_fetchfield('total'); + $db->sql_freeresult($result); + + if ($total) + { + include($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx); + + $sql = $db->sql_build_query('SELECT', array( + 'SELECT' => 'r.report_id, r.report_time, p.msg_id, p.message_subject, p.message_time, p.to_address, p.bcc_address, u.username, u.username_clean, u.user_colour, u.user_id, u2.username as author_name, u2.username_clean as author_name_clean, u2.user_colour as author_colour, u2.user_id as author_id', + + 'FROM' => array( + REPORTS_TABLE => 'r', + REPORTS_REASONS_TABLE => 'rr', + USERS_TABLE => array('u', 'u2'), + PRIVMSGS_TABLE => 'p' + ), + + 'WHERE' => 'r.pm_id = p.msg_id + AND r.post_id = 0 + AND r.report_closed = 0 + AND r.reason_id = rr.reason_id + AND r.user_id = u.user_id + AND p.author_id = u2.user_id', + + 'ORDER_BY' => 'p.message_time DESC' + )); + $result = $db->sql_query_limit($sql, 5); + + $pm_by_id = $pm_list = array(); + while ($row = $db->sql_fetchrow($result)) + { + $pm_by_id[(int) $row['msg_id']] = $row; + $pm_list[] = (int) $row['msg_id']; + } + + $address_list = get_recipient_strings($pm_by_id); + + foreach ($pm_list as $message_id) + { + $row = $pm_by_id[$message_id]; + + $template->assign_block_vars('pm_report', array( + 'U_PM_DETAILS' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'r=' . $row['report_id'] . "&i=pm_reports&mode=pm_report_details"), + + 'REPORTER_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']), + 'REPORTER' => get_username_string('username', $row['user_id'], $row['username'], $row['user_colour']), + 'REPORTER_COLOUR' => get_username_string('colour', $row['user_id'], $row['username'], $row['user_colour']), + 'U_REPORTER' => get_username_string('profile', $row['user_id'], $row['username'], $row['user_colour']), + + 'PM_AUTHOR_FULL' => get_username_string('full', $row['author_id'], $row['author_name'], $row['author_colour']), + 'PM_AUTHOR' => get_username_string('username', $row['author_id'], $row['author_name'], $row['author_colour']), + 'PM_AUTHOR_COLOUR' => get_username_string('colour', $row['author_id'], $row['author_name'], $row['author_colour']), + 'U_PM_AUTHOR' => get_username_string('profile', $row['author_id'], $row['author_name'], $row['author_colour']), + + 'PM_SUBJECT' => $row['message_subject'], + 'REPORT_TIME' => $user->format_date($row['report_time']), + 'PM_TIME' => $user->format_date($row['message_time']), + 'RECIPIENTS' => implode(', ', $address_list[$row['msg_id']]), + )); + } + } + + if ($total == 0) + { + $template->assign_vars(array( + 'L_PM_REPORTS_TOTAL' => $user->lang['PM_REPORTS_ZERO_TOTAL'], + 'S_HAS_PM_REPORTS' => false) + ); + } + else + { + $template->assign_vars(array( + 'L_PM_REPORTS_TOTAL' => ($total == 1) ? $user->lang['PM_REPORT_TOTAL'] : sprintf($user->lang['PM_REPORTS_TOTAL'], $total), + 'S_HAS_PM_REPORTS' => true) + ); + } + } + + // Latest 5 logs + if ($module->loaded('logs')) + { + $forum_list = array_values(array_intersect(get_forum_list('f_read'), get_forum_list('m_'))); + + if (!empty($forum_list)) + { + // Add forum_id 0 for global announcements + $forum_list[] = 0; + + $log_count = 0; + $log = array(); + view_log('mod', $log, $log_count, 5, 0, $forum_list); + + foreach ($log as $row) + { + $template->assign_block_vars('log', array( + 'USERNAME' => $row['username_full'], + 'IP' => $row['ip'], + 'TIME' => $user->format_date($row['time']), + 'ACTION' => $row['action'], + 'U_VIEW_TOPIC' => (!empty($row['viewtopic'])) ? $row['viewtopic'] : '', + 'U_VIEWLOGS' => (!empty($row['viewlogs'])) ? $row['viewlogs'] : '') + ); + } + } + + $template->assign_vars(array( + 'S_SHOW_LOGS' => (!empty($forum_list)) ? true : false, + 'S_HAS_LOGS' => (!empty($log)) ? true : false) + ); + } + + $template->assign_var('S_MCP_ACTION', append_sid("{$phpbb_root_path}mcp.$phpEx")); + make_jumpbox(append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&mode=forum_view'), 0, false, 'm_', true); +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/mcp/mcp_logs.php b/phpBB/includes/mcp/mcp_logs.php new file mode 100644 index 0000000000..429e19b668 --- /dev/null +++ b/phpBB/includes/mcp/mcp_logs.php @@ -0,0 +1,218 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* mcp_logs +* Handling warning the users +* @package mcp +*/ +class mcp_logs +{ + var $u_action; + var $p_master; + + function mcp_logs(&$p_master) + { + $this->p_master = &$p_master; + } + + function main($id, $mode) + { + global $auth, $db, $user, $template; + global $config, $phpbb_root_path, $phpEx; + + $user->add_lang('acp/common'); + + $action = request_var('action', array('' => '')); + + if (is_array($action)) + { + list($action, ) = each($action); + } + else + { + $action = request_var('action', ''); + } + + // Set up general vars + $start = request_var('start', 0); + $deletemark = ($action == 'del_marked') ? true : false; + $deleteall = ($action == 'del_all') ? true : false; + $marked = request_var('mark', array(0)); + + // Sort keys + $sort_days = request_var('st', 0); + $sort_key = request_var('sk', 't'); + $sort_dir = request_var('sd', 'd'); + + $this->tpl_name = 'mcp_logs'; + $this->page_title = 'MCP_LOGS'; + + $forum_list = array_values(array_intersect(get_forum_list('f_read'), get_forum_list('m_'))); + $forum_list[] = 0; + + $forum_id = $topic_id = 0; + + switch ($mode) + { + case 'front': + break; + + case 'forum_logs': + $forum_id = request_var('f', 0); + + if (!in_array($forum_id, $forum_list)) + { + trigger_error('NOT_AUTHORISED'); + } + + $forum_list = array($forum_id); + break; + + case 'topic_logs': + $topic_id = request_var('t', 0); + + $sql = 'SELECT forum_id + FROM ' . TOPICS_TABLE . ' + WHERE topic_id = ' . $topic_id; + $result = $db->sql_query($sql); + $forum_id = (int) $db->sql_fetchfield('forum_id'); + $db->sql_freeresult($result); + + if (!in_array($forum_id, $forum_list)) + { + trigger_error('NOT_AUTHORISED'); + } + + $forum_list = array($forum_id); + break; + } + + // Delete entries if requested and able + if (($deletemark || $deleteall) && $auth->acl_get('a_clearlogs')) + { + if (confirm_box(true)) + { + if ($deletemark && sizeof($marked)) + { + $sql = 'DELETE FROM ' . LOG_TABLE . ' + WHERE log_type = ' . LOG_MOD . ' + AND ' . $db->sql_in_set('forum_id', $forum_list) . ' + AND ' . $db->sql_in_set('log_id', $marked); + $db->sql_query($sql); + + add_log('admin', 'LOG_CLEAR_MOD'); + } + else if ($deleteall) + { + $sql = 'DELETE FROM ' . LOG_TABLE . ' + WHERE log_type = ' . LOG_MOD . ' + AND ' . $db->sql_in_set('forum_id', $forum_list); + + if ($mode == 'topic_logs') + { + $sql .= ' AND topic_id = ' . $topic_id; + } + $db->sql_query($sql); + + add_log('admin', 'LOG_CLEAR_MOD'); + } + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'f' => $forum_id, + 't' => $topic_id, + 'start' => $start, + 'delmarked' => $deletemark, + 'delall' => $deleteall, + 'mark' => $marked, + 'st' => $sort_days, + 'sk' => $sort_key, + 'sd' => $sort_dir, + 'i' => $id, + 'mode' => $mode, + 'action' => request_var('action', array('' => '')))) + ); + } + } + + // Sorting + $limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + $sort_by_text = array('u' => $user->lang['SORT_USERNAME'], 't' => $user->lang['SORT_DATE'], 'i' => $user->lang['SORT_IP'], 'o' => $user->lang['SORT_ACTION']); + $sort_by_sql = array('u' => 'u.username_clean', 't' => 'l.log_time', 'i' => 'l.log_ip', 'o' => 'l.log_operation'); + + $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = ''; + 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); + + // Define where and sort sql for use in displaying logs + $sql_where = ($sort_days) ? (time() - ($sort_days * 86400)) : 0; + $sql_sort = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC'); + + $keywords = utf8_normalize_nfc(request_var('keywords', '', true)); + $keywords_param = !empty($keywords) ? '&keywords=' . urlencode(htmlspecialchars_decode($keywords)) : ''; + + // Grab log data + $log_data = array(); + $log_count = 0; + view_log('mod', $log_data, $log_count, $config['topics_per_page'], $start, $forum_list, $topic_id, 0, $sql_where, $sql_sort, $keywords); + + $template->assign_vars(array( + 'PAGE_NUMBER' => on_page($log_count, $config['topics_per_page'], $start), + 'TOTAL' => ($log_count == 1) ? $user->lang['TOTAL_LOG'] : sprintf($user->lang['TOTAL_LOGS'], $log_count), + 'PAGINATION' => generate_pagination($this->u_action . "&$u_sort_param$keywords_param", $log_count, $config['topics_per_page'], $start, true), + + 'L_TITLE' => $user->lang['MCP_LOGS'], + + 'U_POST_ACTION' => $this->u_action, + 'S_CLEAR_ALLOWED' => ($auth->acl_get('a_clearlogs')) ? true : false, + 'S_SELECT_SORT_DIR' => $s_sort_dir, + 'S_SELECT_SORT_KEY' => $s_sort_key, + 'S_SELECT_SORT_DAYS' => $s_limit_days, + 'S_LOGS' => ($log_count > 0), + 'S_KEYWORDS' => $keywords, + ) + ); + + foreach ($log_data as $row) + { + $data = array(); + + $checks = array('viewtopic', 'viewforum'); + foreach ($checks as $check) + { + if (isset($row[$check]) && $row[$check]) + { + $data[] = '<a href="' . $row[$check] . '">' . $user->lang['LOGVIEW_' . strtoupper($check)] . '</a>'; + } + } + + $template->assign_block_vars('log', array( + 'USERNAME' => $row['username_full'], + 'IP' => $row['ip'], + 'DATE' => $user->format_date($row['time']), + 'ACTION' => $row['action'], + 'DATA' => (sizeof($data)) ? implode(' | ', $data) : '', + 'ID' => $row['id'], + ) + ); + } + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php new file mode 100644 index 0000000000..50b05e989f --- /dev/null +++ b/phpBB/includes/mcp/mcp_main.php @@ -0,0 +1,1282 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* mcp_main +* Handling mcp actions +* @package mcp +*/ +class mcp_main +{ + var $p_master; + var $u_action; + + function mcp_main(&$p_master) + { + $this->p_master = &$p_master; + } + + function main($id, $mode) + { + global $auth, $db, $user, $template, $action; + global $config, $phpbb_root_path, $phpEx; + + $quickmod = ($mode == 'quickmod') ? true : false; + + switch ($action) + { + case 'lock': + case 'unlock': + $topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0)); + + if (!sizeof($topic_ids)) + { + trigger_error('NO_TOPIC_SELECTED'); + } + + lock_unlock($action, $topic_ids); + break; + + case 'lock_post': + case 'unlock_post': + + $post_ids = (!$quickmod) ? request_var('post_id_list', array(0)) : array(request_var('p', 0)); + + if (!sizeof($post_ids)) + { + trigger_error('NO_POST_SELECTED'); + } + + lock_unlock($action, $post_ids); + break; + + case 'make_announce': + case 'make_sticky': + case 'make_global': + case 'make_normal': + + $topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0)); + + if (!sizeof($topic_ids)) + { + trigger_error('NO_TOPIC_SELECTED'); + } + + change_topic_type($action, $topic_ids); + break; + + case 'move': + $user->add_lang('viewtopic'); + + $topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0)); + + if (!sizeof($topic_ids)) + { + trigger_error('NO_TOPIC_SELECTED'); + } + + mcp_move_topic($topic_ids); + break; + + case 'fork': + $user->add_lang('viewtopic'); + + $topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0)); + + if (!sizeof($topic_ids)) + { + trigger_error('NO_TOPIC_SELECTED'); + } + + mcp_fork_topic($topic_ids); + break; + + case 'delete_topic': + $user->add_lang('viewtopic'); + + $topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0)); + + if (!sizeof($topic_ids)) + { + trigger_error('NO_TOPIC_SELECTED'); + } + + mcp_delete_topic($topic_ids); + break; + + case 'delete_post': + $user->add_lang('posting'); + + $post_ids = (!$quickmod) ? request_var('post_id_list', array(0)) : array(request_var('p', 0)); + + if (!sizeof($post_ids)) + { + trigger_error('NO_POST_SELECTED'); + } + + mcp_delete_post($post_ids); + break; + } + + switch ($mode) + { + case 'front': + include($phpbb_root_path . 'includes/mcp/mcp_front.' . $phpEx); + + $user->add_lang('acp/common'); + + mcp_front_view($id, $mode, $action); + + $this->tpl_name = 'mcp_front'; + $this->page_title = 'MCP_MAIN'; + break; + + case 'forum_view': + include($phpbb_root_path . 'includes/mcp/mcp_forum.' . $phpEx); + + $user->add_lang('viewforum'); + + $forum_id = request_var('f', 0); + + $forum_info = get_forum_data($forum_id, 'm_', true); + + if (!sizeof($forum_info)) + { + $this->main('main', 'front'); + return; + } + + $forum_info = $forum_info[$forum_id]; + + mcp_forum_view($id, $mode, $action, $forum_info); + + $this->tpl_name = 'mcp_forum'; + $this->page_title = 'MCP_MAIN_FORUM_VIEW'; + break; + + case 'topic_view': + include($phpbb_root_path . 'includes/mcp/mcp_topic.' . $phpEx); + + mcp_topic_view($id, $mode, $action); + + $this->tpl_name = 'mcp_topic'; + $this->page_title = 'MCP_MAIN_TOPIC_VIEW'; + break; + + case 'post_details': + include($phpbb_root_path . 'includes/mcp/mcp_post.' . $phpEx); + + mcp_post_details($id, $mode, $action); + + $this->tpl_name = ($action == 'whois') ? 'mcp_whois' : 'mcp_post'; + $this->page_title = 'MCP_MAIN_POST_DETAILS'; + break; + + default: + trigger_error('NO_MODE', E_USER_ERROR); + break; + } + } +} + +/** +* Lock/Unlock Topic/Post +*/ +function lock_unlock($action, $ids) +{ + global $auth, $user, $db, $phpEx, $phpbb_root_path; + + if ($action == 'lock' || $action == 'unlock') + { + $table = TOPICS_TABLE; + $sql_id = 'topic_id'; + $set_id = 'topic_status'; + $l_prefix = 'TOPIC'; + } + else + { + $table = POSTS_TABLE; + $sql_id = 'post_id'; + $set_id = 'post_edit_locked'; + $l_prefix = 'POST'; + } + + $orig_ids = $ids; + + if (!check_ids($ids, $table, $sql_id, array('m_lock'))) + { + // Make sure that for f_user_lock only the lock action is triggered. + if ($action != 'lock') + { + return; + } + + $ids = $orig_ids; + + if (!check_ids($ids, $table, $sql_id, array('f_user_lock'))) + { + return; + } + } + unset($orig_ids); + + $redirect = request_var('redirect', build_url(array('action', 'quickmod'))); + + $s_hidden_fields = build_hidden_fields(array( + $sql_id . '_list' => $ids, + 'action' => $action, + 'redirect' => $redirect) + ); + $success_msg = ''; + + if (confirm_box(true)) + { + $sql = "UPDATE $table + SET $set_id = " . (($action == 'lock' || $action == 'lock_post') ? ITEM_LOCKED : ITEM_UNLOCKED) . ' + WHERE ' . $db->sql_in_set($sql_id, $ids); + $db->sql_query($sql); + + $data = ($action == 'lock' || $action == 'unlock') ? get_topic_data($ids) : get_post_data($ids); + + foreach ($data as $id => $row) + { + add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_' . strtoupper($action), $row['topic_title']); + } + + $success_msg = $l_prefix . ((sizeof($ids) == 1) ? '' : 'S') . '_' . (($action == 'lock' || $action == 'lock_post') ? 'LOCKED' : 'UNLOCKED') . '_SUCCESS'; + } + else + { + confirm_box(false, strtoupper($action) . '_' . $l_prefix . ((sizeof($ids) == 1) ? '' : 'S'), $s_hidden_fields); + } + + $redirect = request_var('redirect', "index.$phpEx"); + $redirect = reapply_sid($redirect); + + if (!$success_msg) + { + redirect($redirect); + } + else + { + meta_refresh(2, $redirect); + trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>')); + } +} + +/** +* Change Topic Type +*/ +function change_topic_type($action, $topic_ids) +{ + global $auth, $user, $db, $phpEx, $phpbb_root_path; + + // For changing topic types, we only allow operations in one forum. + $forum_id = check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('f_announce', 'f_sticky', 'm_'), true); + + if ($forum_id === false) + { + return; + } + + switch ($action) + { + case 'make_announce': + $new_topic_type = POST_ANNOUNCE; + $check_acl = 'f_announce'; + $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_ANNOUNCEMENT' : 'MCP_MAKE_ANNOUNCEMENTS'; + break; + + case 'make_global': + $new_topic_type = POST_GLOBAL; + $check_acl = 'f_announce'; + $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_GLOBAL' : 'MCP_MAKE_GLOBALS'; + break; + + case 'make_sticky': + $new_topic_type = POST_STICKY; + $check_acl = 'f_sticky'; + $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_STICKY' : 'MCP_MAKE_STICKIES'; + break; + + default: + $new_topic_type = POST_NORMAL; + $check_acl = ''; + $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_NORMAL' : 'MCP_MAKE_NORMALS'; + break; + } + + $redirect = request_var('redirect', build_url(array('action', 'quickmod'))); + + $s_hidden_fields = array( + 'topic_id_list' => $topic_ids, + 'f' => $forum_id, + 'action' => $action, + 'redirect' => $redirect, + ); + $success_msg = ''; + + if (confirm_box(true)) + { + if ($new_topic_type != POST_GLOBAL) + { + $sql = 'UPDATE ' . TOPICS_TABLE . " + SET topic_type = $new_topic_type + WHERE " . $db->sql_in_set('topic_id', $topic_ids) . ' + AND forum_id <> 0'; + $db->sql_query($sql); + + // Reset forum id if a global topic is within the array + $to_forum_id = request_var('to_forum_id', 0); + + if ($to_forum_id) + { + $sql = 'UPDATE ' . TOPICS_TABLE . " + SET topic_type = $new_topic_type, forum_id = $to_forum_id + WHERE " . $db->sql_in_set('topic_id', $topic_ids) . ' + AND forum_id = 0'; + $db->sql_query($sql); + + // Update forum_ids for all posts + $sql = 'UPDATE ' . POSTS_TABLE . " + SET forum_id = $to_forum_id + WHERE " . $db->sql_in_set('topic_id', $topic_ids) . ' + AND forum_id = 0'; + $db->sql_query($sql); + + // Do a little forum sync stuff + $sql = 'SELECT SUM(t.topic_replies + t.topic_approved) as topic_posts, COUNT(t.topic_approved) as topics_authed + FROM ' . TOPICS_TABLE . ' t + WHERE ' . $db->sql_in_set('t.topic_id', $topic_ids); + $result = $db->sql_query($sql); + $row_data = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $sync_sql = array(); + + if ($row_data['topic_posts']) + { + $sync_sql[$to_forum_id][] = 'forum_posts = forum_posts + ' . (int) $row_data['topic_posts']; + } + + if ($row_data['topics_authed']) + { + $sync_sql[$to_forum_id][] = 'forum_topics = forum_topics + ' . (int) $row_data['topics_authed']; + } + + $sync_sql[$to_forum_id][] = 'forum_topics_real = forum_topics_real + ' . (int) sizeof($topic_ids); + + foreach ($sync_sql as $forum_id_key => $array) + { + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET ' . implode(', ', $array) . ' + WHERE forum_id = ' . $forum_id_key; + $db->sql_query($sql); + } + + sync('forum', 'forum_id', $to_forum_id); + } + } + else + { + // Get away with those topics already being a global announcement by re-calculating $topic_ids + $sql = 'SELECT topic_id + FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . ' + AND forum_id <> 0'; + $result = $db->sql_query($sql); + + $topic_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $topic_ids[] = $row['topic_id']; + } + $db->sql_freeresult($result); + + if (sizeof($topic_ids)) + { + // Delete topic shadows for global announcements + $sql = 'DELETE FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_moved_id', $topic_ids); + $db->sql_query($sql); + + $sql = 'UPDATE ' . TOPICS_TABLE . " + SET topic_type = $new_topic_type, forum_id = 0 + WHERE " . $db->sql_in_set('topic_id', $topic_ids); + $db->sql_query($sql); + + // Update forum_ids for all posts + $sql = 'UPDATE ' . POSTS_TABLE . ' + SET forum_id = 0 + WHERE ' . $db->sql_in_set('topic_id', $topic_ids); + $db->sql_query($sql); + + // Do a little forum sync stuff + $sql = 'SELECT SUM(t.topic_replies + t.topic_approved) as topic_posts, COUNT(t.topic_approved) as topics_authed + FROM ' . TOPICS_TABLE . ' t + WHERE ' . $db->sql_in_set('t.topic_id', $topic_ids); + $result = $db->sql_query($sql); + $row_data = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $sync_sql = array(); + + if ($row_data['topic_posts']) + { + $sync_sql[$forum_id][] = 'forum_posts = forum_posts - ' . (int) $row_data['topic_posts']; + } + + if ($row_data['topics_authed']) + { + $sync_sql[$forum_id][] = 'forum_topics = forum_topics - ' . (int) $row_data['topics_authed']; + } + + $sync_sql[$forum_id][] = 'forum_topics_real = forum_topics_real - ' . (int) sizeof($topic_ids); + + foreach ($sync_sql as $forum_id_key => $array) + { + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET ' . implode(', ', $array) . ' + WHERE forum_id = ' . $forum_id_key; + $db->sql_query($sql); + } + + sync('forum', 'forum_id', $forum_id); + } + } + + $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_TYPE_CHANGED' : 'TOPICS_TYPE_CHANGED'; + + if (sizeof($topic_ids)) + { + $data = get_topic_data($topic_ids); + + foreach ($data as $topic_id => $row) + { + add_log('mod', $forum_id, $topic_id, 'LOG_TOPIC_TYPE_CHANGED', $row['topic_title']); + } + } + } + else + { + // Global topic involved? + $global_involved = false; + + if ($new_topic_type != POST_GLOBAL) + { + $sql = 'SELECT forum_id + FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . ' + AND forum_id = 0'; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + $global_involved = true; + } + } + + if ($global_involved) + { + global $template; + + $template->assign_vars(array( + 'S_FORUM_SELECT' => make_forum_select(request_var('f', $forum_id), false, false, true, true), + 'S_CAN_LEAVE_SHADOW' => false, + 'ADDITIONAL_MSG' => (sizeof($topic_ids) == 1) ? $user->lang['SELECT_FORUM_GLOBAL_ANNOUNCEMENT'] : $user->lang['SELECT_FORUM_GLOBAL_ANNOUNCEMENTS']) + ); + + confirm_box(false, $l_new_type, build_hidden_fields($s_hidden_fields), 'mcp_move.html'); + } + else + { + confirm_box(false, $l_new_type, build_hidden_fields($s_hidden_fields)); + } + } + + $redirect = request_var('redirect', "index.$phpEx"); + $redirect = reapply_sid($redirect); + + if (!$success_msg) + { + redirect($redirect); + } + else + { + meta_refresh(2, $redirect); + trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>')); + } +} + +/** +* Move Topic +*/ +function mcp_move_topic($topic_ids) +{ + global $auth, $user, $db, $template; + global $phpEx, $phpbb_root_path; + + // Here we limit the operation to one forum only + $forum_id = check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_move'), true); + + if ($forum_id === false) + { + return; + } + + $to_forum_id = request_var('to_forum_id', 0); + $redirect = request_var('redirect', build_url(array('action', 'quickmod'))); + $additional_msg = $success_msg = ''; + + $s_hidden_fields = build_hidden_fields(array( + 'topic_id_list' => $topic_ids, + 'f' => $forum_id, + 'action' => 'move', + 'redirect' => $redirect) + ); + + if ($to_forum_id) + { + $forum_data = get_forum_data($to_forum_id, 'f_post'); + + if (!sizeof($forum_data)) + { + $additional_msg = $user->lang['FORUM_NOT_EXIST']; + } + else + { + $forum_data = $forum_data[$to_forum_id]; + + if ($forum_data['forum_type'] != FORUM_POST) + { + $additional_msg = $user->lang['FORUM_NOT_POSTABLE']; + } + else if (!$auth->acl_get('f_post', $to_forum_id)) + { + $additional_msg = $user->lang['USER_CANNOT_POST']; + } + else if ($forum_id == $to_forum_id) + { + $additional_msg = $user->lang['CANNOT_MOVE_SAME_FORUM']; + } + } + } + else if (isset($_POST['confirm'])) + { + $additional_msg = $user->lang['FORUM_NOT_EXIST']; + } + + if (!$to_forum_id || $additional_msg) + { + unset($_POST['confirm']); + unset($_REQUEST['confirm_key']); + } + + if (confirm_box(true)) + { + $topic_data = get_topic_data($topic_ids); + $leave_shadow = (isset($_POST['move_leave_shadow'])) ? true : false; + + $forum_sync_data = array(); + + $forum_sync_data[$forum_id] = current($topic_data); + $forum_sync_data[$to_forum_id] = $forum_data; + + // Real topics added to target forum + $topics_moved = sizeof($topic_data); + + // Approved topics added to target forum + $topics_authed_moved = 0; + + // Posts (topic replies + topic post if approved) added to target forum + $topic_posts_added = 0; + + // Posts (topic replies + topic post if approved and not global announcement) removed from source forum + $topic_posts_removed = 0; + + // Real topics removed from source forum (all topics without global announcements) + $topics_removed = 0; + + // Approved topics removed from source forum (except global announcements) + $topics_authed_removed = 0; + + foreach ($topic_data as $topic_id => $topic_info) + { + if ($topic_info['topic_approved']) + { + $topics_authed_moved++; + $topic_posts_added++; + } + + $topic_posts_added += $topic_info['topic_replies']; + + if ($topic_info['topic_type'] != POST_GLOBAL) + { + $topics_removed++; + $topic_posts_removed += $topic_info['topic_replies']; + + if ($topic_info['topic_approved']) + { + $topics_authed_removed++; + $topic_posts_removed++; + } + } + } + + $db->sql_transaction('begin'); + + $sync_sql = array(); + + if ($topic_posts_added) + { + $sync_sql[$to_forum_id][] = 'forum_posts = forum_posts + ' . $topic_posts_added; + } + + if ($topics_authed_moved) + { + $sync_sql[$to_forum_id][] = 'forum_topics = forum_topics + ' . (int) $topics_authed_moved; + } + + $sync_sql[$to_forum_id][] = 'forum_topics_real = forum_topics_real + ' . (int) $topics_moved; + + // Move topics, but do not resync yet + move_topics($topic_ids, $to_forum_id, false); + + $forum_ids = array($to_forum_id); + foreach ($topic_data as $topic_id => $row) + { + // Get the list of forums to resync, add a log entry + $forum_ids[] = $row['forum_id']; + add_log('mod', $to_forum_id, $topic_id, 'LOG_MOVE', $row['forum_name'], $forum_data['forum_name']); + + // If we have moved a global announcement, we need to correct the topic type + if ($row['topic_type'] == POST_GLOBAL) + { + $sql = 'UPDATE ' . TOPICS_TABLE . ' + SET topic_type = ' . POST_ANNOUNCE . ' + WHERE topic_id = ' . (int) $row['topic_id']; + $db->sql_query($sql); + } + + // Leave a redirection if required and only if the topic is visible to users + if ($leave_shadow && $row['topic_approved'] && $row['topic_type'] != POST_GLOBAL) + { + $shadow = array( + 'forum_id' => (int) $row['forum_id'], + 'icon_id' => (int) $row['icon_id'], + 'topic_attachment' => (int) $row['topic_attachment'], + 'topic_approved' => 1, // a shadow topic is always approved + 'topic_reported' => 0, // a shadow topic is never reported + 'topic_title' => (string) $row['topic_title'], + 'topic_poster' => (int) $row['topic_poster'], + 'topic_time' => (int) $row['topic_time'], + 'topic_time_limit' => (int) $row['topic_time_limit'], + 'topic_views' => (int) $row['topic_views'], + 'topic_replies' => (int) $row['topic_replies'], + 'topic_replies_real' => (int) $row['topic_replies_real'], + 'topic_status' => ITEM_MOVED, + 'topic_type' => POST_NORMAL, + 'topic_first_post_id' => (int) $row['topic_first_post_id'], + 'topic_first_poster_colour'=>(string) $row['topic_first_poster_colour'], + 'topic_first_poster_name'=> (string) $row['topic_first_poster_name'], + 'topic_last_post_id' => (int) $row['topic_last_post_id'], + 'topic_last_poster_id' => (int) $row['topic_last_poster_id'], + 'topic_last_poster_colour'=>(string) $row['topic_last_poster_colour'], + 'topic_last_poster_name'=> (string) $row['topic_last_poster_name'], + 'topic_last_post_subject'=> (string) $row['topic_last_post_subject'], + 'topic_last_post_time' => (int) $row['topic_last_post_time'], + 'topic_last_view_time' => (int) $row['topic_last_view_time'], + 'topic_moved_id' => (int) $row['topic_id'], + 'topic_bumped' => (int) $row['topic_bumped'], + 'topic_bumper' => (int) $row['topic_bumper'], + 'poll_title' => (string) $row['poll_title'], + 'poll_start' => (int) $row['poll_start'], + 'poll_length' => (int) $row['poll_length'], + 'poll_max_options' => (int) $row['poll_max_options'], + 'poll_last_vote' => (int) $row['poll_last_vote'] + ); + + $db->sql_query('INSERT INTO ' . TOPICS_TABLE . $db->sql_build_array('INSERT', $shadow)); + + // Shadow topics only count on new "topics" and not posts... a shadow topic alone has 0 posts + $topics_removed--; + $topics_authed_removed--; + } + } + unset($topic_data); + + if ($topic_posts_removed) + { + $sync_sql[$forum_id][] = 'forum_posts = forum_posts - ' . $topic_posts_removed; + } + + if ($topics_removed) + { + $sync_sql[$forum_id][] = 'forum_topics_real = forum_topics_real - ' . (int) $topics_removed; + } + + if ($topics_authed_removed) + { + $sync_sql[$forum_id][] = 'forum_topics = forum_topics - ' . (int) $topics_authed_removed; + } + + $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_MOVED_SUCCESS' : 'TOPICS_MOVED_SUCCESS'; + + foreach ($sync_sql as $forum_id_key => $array) + { + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET ' . implode(', ', $array) . ' + WHERE forum_id = ' . $forum_id_key; + $db->sql_query($sql); + } + + $db->sql_transaction('commit'); + + sync('forum', 'forum_id', array($forum_id, $to_forum_id)); + } + else + { + $template->assign_vars(array( + 'S_FORUM_SELECT' => make_forum_select($to_forum_id, $forum_id, false, true, true, true), + 'S_CAN_LEAVE_SHADOW' => true, + 'ADDITIONAL_MSG' => $additional_msg) + ); + + confirm_box(false, 'MOVE_TOPIC' . ((sizeof($topic_ids) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_move.html'); + } + + $redirect = request_var('redirect', "index.$phpEx"); + $redirect = reapply_sid($redirect); + + if (!$success_msg) + { + redirect($redirect); + } + else + { + meta_refresh(3, $redirect); + + $message = $user->lang[$success_msg]; + $message .= '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>'); + $message .= '<br /><br />' . sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id") . '">', '</a>'); + $message .= '<br /><br />' . sprintf($user->lang['RETURN_NEW_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$to_forum_id") . '">', '</a>'); + + trigger_error($message); + } +} + +/** +* Delete Topics +*/ +function mcp_delete_topic($topic_ids) +{ + global $auth, $user, $db, $phpEx, $phpbb_root_path; + + if (!check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_delete'))) + { + return; + } + + $redirect = request_var('redirect', build_url(array('action', 'quickmod'))); + $forum_id = request_var('f', 0); + + $s_hidden_fields = build_hidden_fields(array( + 'topic_id_list' => $topic_ids, + 'f' => $forum_id, + 'action' => 'delete_topic', + 'redirect' => $redirect) + ); + $success_msg = ''; + + if (confirm_box(true)) + { + $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_DELETED_SUCCESS' : 'TOPICS_DELETED_SUCCESS'; + + $data = get_topic_data($topic_ids); + + foreach ($data as $topic_id => $row) + { + if ($row['topic_moved_id']) + { + add_log('mod', $row['forum_id'], $topic_id, 'LOG_DELETE_SHADOW_TOPIC', $row['topic_title']); + } + else + { + add_log('mod', $row['forum_id'], $topic_id, 'LOG_DELETE_TOPIC', $row['topic_title'], $row['topic_first_poster_name']); + } + } + + $return = delete_topics('topic_id', $topic_ids); + } + else + { + confirm_box(false, (sizeof($topic_ids) == 1) ? 'DELETE_TOPIC' : 'DELETE_TOPICS', $s_hidden_fields); + } + + if (!isset($_REQUEST['quickmod'])) + { + $redirect = request_var('redirect', "index.$phpEx"); + $redirect = reapply_sid($redirect); + $redirect_message = 'PAGE'; + } + else + { + $redirect = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id); + $redirect_message = 'FORUM'; + } + + if (!$success_msg) + { + redirect($redirect); + } + else + { + meta_refresh(3, $redirect); + trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_' . $redirect_message], '<a href="' . $redirect . '">', '</a>')); + } +} + +/** +* Delete Posts +*/ +function mcp_delete_post($post_ids) +{ + global $auth, $user, $db, $phpEx, $phpbb_root_path; + + if (!check_ids($post_ids, POSTS_TABLE, 'post_id', array('m_delete'))) + { + return; + } + + $redirect = request_var('redirect', build_url(array('action', 'quickmod'))); + $forum_id = request_var('f', 0); + + $s_hidden_fields = build_hidden_fields(array( + 'post_id_list' => $post_ids, + 'f' => $forum_id, + 'action' => 'delete_post', + 'redirect' => $redirect) + ); + $success_msg = ''; + + if (confirm_box(true)) + { + if (!function_exists('delete_posts')) + { + include($phpbb_root_path . 'includes/functions_admin.' . $phpEx); + } + + // Count the number of topics that are affected + // I did not use COUNT(DISTINCT ...) because I remember having problems + // with it on older versions of MySQL -- Ashe + + $sql = 'SELECT DISTINCT topic_id + FROM ' . POSTS_TABLE . ' + WHERE ' . $db->sql_in_set('post_id', $post_ids); + $result = $db->sql_query($sql); + + $topic_id_list = array(); + while ($row = $db->sql_fetchrow($result)) + { + $topic_id_list[] = $row['topic_id']; + } + $affected_topics = sizeof($topic_id_list); + $db->sql_freeresult($result); + + $post_data = get_post_data($post_ids); + + foreach ($post_data as $id => $row) + { + $post_username = ($row['poster_id'] == ANONYMOUS && !empty($row['post_username'])) ? $row['post_username'] : $row['username']; + add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_DELETE_POST', $row['post_subject'], $post_username); + } + + // Now delete the posts, topics and forums are automatically resync'ed + delete_posts('post_id', $post_ids); + + $sql = 'SELECT COUNT(topic_id) AS topics_left + FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', $topic_id_list); + $result = $db->sql_query_limit($sql, 1); + + $deleted_topics = ($row = $db->sql_fetchrow($result)) ? ($affected_topics - $row['topics_left']) : $affected_topics; + $db->sql_freeresult($result); + + $topic_id = request_var('t', 0); + + // Return links + $return_link = array(); + if ($affected_topics == 1 && !$deleted_topics && $topic_id) + { + $return_link[] = sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&t=$topic_id") . '">', '</a>'); + } + $return_link[] = sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id) . '">', '</a>'); + + if (sizeof($post_ids) == 1) + { + if ($deleted_topics) + { + // We deleted the only post of a topic, which in turn has + // been removed from the database + $success_msg = $user->lang['TOPIC_DELETED_SUCCESS']; + } + else + { + $success_msg = $user->lang['POST_DELETED_SUCCESS']; + } + } + else + { + if ($deleted_topics) + { + // Some of topics disappeared + $success_msg = $user->lang['POSTS_DELETED_SUCCESS'] . '<br /><br />' . $user->lang['EMPTY_TOPICS_REMOVED_WARNING']; + } + else + { + $success_msg = $user->lang['POSTS_DELETED_SUCCESS']; + } + } + } + else + { + confirm_box(false, (sizeof($post_ids) == 1) ? 'DELETE_POST' : 'DELETE_POSTS', $s_hidden_fields); + } + + $redirect = request_var('redirect', "index.$phpEx"); + $redirect = reapply_sid($redirect); + + if (!$success_msg) + { + redirect($redirect); + } + else + { + if ($affected_topics != 1 || $deleted_topics || !$topic_id) + { + $redirect = append_sid("{$phpbb_root_path}mcp.$phpEx", "f=$forum_id&i=main&mode=forum_view", false); + } + + meta_refresh(3, $redirect); + trigger_error($success_msg . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>') . '<br /><br />' . implode('<br /><br />', $return_link)); + } +} + +/** +* Fork Topic +*/ +function mcp_fork_topic($topic_ids) +{ + global $auth, $user, $db, $template, $config; + global $phpEx, $phpbb_root_path; + + if (!check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_'))) + { + return; + } + + $to_forum_id = request_var('to_forum_id', 0); + $forum_id = request_var('f', 0); + $redirect = request_var('redirect', build_url(array('action', 'quickmod'))); + $additional_msg = $success_msg = ''; + + $s_hidden_fields = build_hidden_fields(array( + 'topic_id_list' => $topic_ids, + 'f' => $forum_id, + 'action' => 'fork', + 'redirect' => $redirect) + ); + + if ($to_forum_id) + { + $forum_data = get_forum_data($to_forum_id, 'f_post'); + + if (!sizeof($topic_ids)) + { + $additional_msg = $user->lang['NO_TOPIC_SELECTED']; + } + else if (!sizeof($forum_data)) + { + $additional_msg = $user->lang['FORUM_NOT_EXIST']; + } + else + { + $forum_data = $forum_data[$to_forum_id]; + + if ($forum_data['forum_type'] != FORUM_POST) + { + $additional_msg = $user->lang['FORUM_NOT_POSTABLE']; + } + else if (!$auth->acl_get('f_post', $to_forum_id)) + { + $additional_msg = $user->lang['USER_CANNOT_POST']; + } + } + } + else if (isset($_POST['confirm'])) + { + $additional_msg = $user->lang['FORUM_NOT_EXIST']; + } + + if ($additional_msg) + { + unset($_POST['confirm']); + unset($_REQUEST['confirm_key']); + } + + if (confirm_box(true)) + { + $topic_data = get_topic_data($topic_ids, 'f_post'); + + $total_posts = 0; + $new_topic_id_list = array(); + + foreach ($topic_data as $topic_id => $topic_row) + { + $sql_ary = array( + 'forum_id' => (int) $to_forum_id, + 'icon_id' => (int) $topic_row['icon_id'], + 'topic_attachment' => (int) $topic_row['topic_attachment'], + 'topic_approved' => 1, + 'topic_reported' => 0, + 'topic_title' => (string) $topic_row['topic_title'], + 'topic_poster' => (int) $topic_row['topic_poster'], + 'topic_time' => (int) $topic_row['topic_time'], + 'topic_replies' => (int) $topic_row['topic_replies_real'], + 'topic_replies_real' => (int) $topic_row['topic_replies_real'], + 'topic_status' => (int) $topic_row['topic_status'], + 'topic_type' => (int) $topic_row['topic_type'], + 'topic_first_poster_name' => (string) $topic_row['topic_first_poster_name'], + 'topic_last_poster_id' => (int) $topic_row['topic_last_poster_id'], + 'topic_last_poster_name' => (string) $topic_row['topic_last_poster_name'], + 'topic_last_post_time' => (int) $topic_row['topic_last_post_time'], + 'topic_last_view_time' => (int) $topic_row['topic_last_view_time'], + 'topic_bumped' => (int) $topic_row['topic_bumped'], + 'topic_bumper' => (int) $topic_row['topic_bumper'], + 'poll_title' => (string) $topic_row['poll_title'], + 'poll_start' => (int) $topic_row['poll_start'], + 'poll_length' => (int) $topic_row['poll_length'], + 'poll_max_options' => (int) $topic_row['poll_max_options'], + 'poll_vote_change' => (int) $topic_row['poll_vote_change'], + ); + + $db->sql_query('INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + $new_topic_id = $db->sql_nextid(); + $new_topic_id_list[$topic_id] = $new_topic_id; + + if ($topic_row['poll_start']) + { + $poll_rows = array(); + + $sql = 'SELECT * + FROM ' . POLL_OPTIONS_TABLE . " + WHERE topic_id = $topic_id"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $sql_ary = array( + 'poll_option_id' => (int) $row['poll_option_id'], + 'topic_id' => (int) $new_topic_id, + 'poll_option_text' => (string) $row['poll_option_text'], + 'poll_option_total' => 0 + ); + + $db->sql_query('INSERT INTO ' . POLL_OPTIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + } + } + + $sql = 'SELECT * + FROM ' . POSTS_TABLE . " + WHERE topic_id = $topic_id + ORDER BY post_time ASC"; + $result = $db->sql_query($sql); + + $post_rows = array(); + while ($row = $db->sql_fetchrow($result)) + { + $post_rows[] = $row; + } + $db->sql_freeresult($result); + + if (!sizeof($post_rows)) + { + continue; + } + + $total_posts += sizeof($post_rows); + foreach ($post_rows as $row) + { + $sql_ary = array( + 'topic_id' => (int) $new_topic_id, + 'forum_id' => (int) $to_forum_id, + 'poster_id' => (int) $row['poster_id'], + 'icon_id' => (int) $row['icon_id'], + 'poster_ip' => (string) $row['poster_ip'], + 'post_time' => (int) $row['post_time'], + 'post_approved' => 1, + 'post_reported' => 0, + 'enable_bbcode' => (int) $row['enable_bbcode'], + 'enable_smilies' => (int) $row['enable_smilies'], + 'enable_magic_url' => (int) $row['enable_magic_url'], + 'enable_sig' => (int) $row['enable_sig'], + 'post_username' => (string) $row['post_username'], + 'post_subject' => (string) $row['post_subject'], + 'post_text' => (string) $row['post_text'], + 'post_edit_reason' => (string) $row['post_edit_reason'], + 'post_edit_user' => (int) $row['post_edit_user'], + 'post_checksum' => (string) $row['post_checksum'], + 'post_attachment' => (int) $row['post_attachment'], + 'bbcode_bitfield' => $row['bbcode_bitfield'], + 'bbcode_uid' => (string) $row['bbcode_uid'], + 'post_edit_time' => (int) $row['post_edit_time'], + 'post_edit_count' => (int) $row['post_edit_count'], + 'post_edit_locked' => (int) $row['post_edit_locked'], + 'post_postcount' => 0, + ); + + $db->sql_query('INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + $new_post_id = $db->sql_nextid(); + + // Copy whether the topic is dotted + markread('post', $to_forum_id, $new_topic_id, 0, $row['poster_id']); + + // Copy Attachments + if ($row['post_attachment']) + { + $sql = 'SELECT * FROM ' . ATTACHMENTS_TABLE . " + WHERE post_msg_id = {$row['post_id']} + AND topic_id = $topic_id + AND in_message = 0"; + $result = $db->sql_query($sql); + + $sql_ary = array(); + while ($attach_row = $db->sql_fetchrow($result)) + { + $sql_ary[] = array( + 'post_msg_id' => (int) $new_post_id, + 'topic_id' => (int) $new_topic_id, + 'in_message' => 0, + 'is_orphan' => (int) $attach_row['is_orphan'], + 'poster_id' => (int) $attach_row['poster_id'], + 'physical_filename' => (string) utf8_basename($attach_row['physical_filename']), + 'real_filename' => (string) utf8_basename($attach_row['real_filename']), + 'download_count' => (int) $attach_row['download_count'], + 'attach_comment' => (string) $attach_row['attach_comment'], + 'extension' => (string) $attach_row['extension'], + 'mimetype' => (string) $attach_row['mimetype'], + 'filesize' => (int) $attach_row['filesize'], + 'filetime' => (int) $attach_row['filetime'], + 'thumbnail' => (int) $attach_row['thumbnail'] + ); + } + $db->sql_freeresult($result); + + if (sizeof($sql_ary)) + { + $db->sql_multi_insert(ATTACHMENTS_TABLE, $sql_ary); + } + } + } + + $sql = 'SELECT user_id, notify_status + FROM ' . TOPICS_WATCH_TABLE . ' + WHERE topic_id = ' . $topic_id; + $result = $db->sql_query($sql); + + $sql_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $sql_ary[] = array( + 'topic_id' => (int) $new_topic_id, + 'user_id' => (int) $row['user_id'], + 'notify_status' => (int) $row['notify_status'], + ); + } + $db->sql_freeresult($result); + + if (sizeof($sql_ary)) + { + $db->sql_multi_insert(TOPICS_WATCH_TABLE, $sql_ary); + } + } + + // Sync new topics, parent forums and board stats + sync('topic', 'topic_id', $new_topic_id_list); + + $sync_sql = array(); + + $sync_sql[$to_forum_id][] = 'forum_posts = forum_posts + ' . $total_posts; + $sync_sql[$to_forum_id][] = 'forum_topics = forum_topics + ' . sizeof($new_topic_id_list); + $sync_sql[$to_forum_id][] = 'forum_topics_real = forum_topics_real + ' . sizeof($new_topic_id_list); + + foreach ($sync_sql as $forum_id_key => $array) + { + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET ' . implode(', ', $array) . ' + WHERE forum_id = ' . $forum_id_key; + $db->sql_query($sql); + } + + sync('forum', 'forum_id', $to_forum_id); + set_config_count('num_topics', sizeof($new_topic_id_list), true); + set_config_count('num_posts', $total_posts, true); + + foreach ($new_topic_id_list as $topic_id => $new_topic_id) + { + add_log('mod', $to_forum_id, $new_topic_id, 'LOG_FORK', $topic_row['forum_name']); + } + + $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_FORKED_SUCCESS' : 'TOPICS_FORKED_SUCCESS'; + } + else + { + $template->assign_vars(array( + 'S_FORUM_SELECT' => make_forum_select($to_forum_id, false, false, true, true, true), + 'S_CAN_LEAVE_SHADOW' => false, + 'ADDITIONAL_MSG' => $additional_msg) + ); + + confirm_box(false, 'FORK_TOPIC' . ((sizeof($topic_ids) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_move.html'); + } + + $redirect = request_var('redirect', "index.$phpEx"); + $redirect = reapply_sid($redirect); + + if (!$success_msg) + { + redirect($redirect); + } + else + { + $redirect_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id); + meta_refresh(3, $redirect_url); + $return_link = sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect_url . '">', '</a>'); + + if ($forum_id != $to_forum_id) + { + $return_link .= '<br /><br />' . sprintf($user->lang['RETURN_NEW_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $to_forum_id) . '">', '</a>'); + } + + trigger_error($user->lang[$success_msg] . '<br /><br />' . $return_link); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/mcp/mcp_notes.php b/phpBB/includes/mcp/mcp_notes.php new file mode 100644 index 0000000000..757860e1af --- /dev/null +++ b/phpBB/includes/mcp/mcp_notes.php @@ -0,0 +1,251 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* mcp_notes +* Displays notes about a user +* @package mcp +*/ +class mcp_notes +{ + var $p_master; + var $u_action; + + function mcp_notes(&$p_master) + { + $this->p_master = &$p_master; + } + + function main($id, $mode) + { + global $auth, $db, $user, $template; + global $config, $phpbb_root_path, $phpEx; + + $action = request_var('action', array('' => '')); + + if (is_array($action)) + { + list($action, ) = each($action); + } + + $this->page_title = 'MCP_NOTES'; + + switch ($mode) + { + case 'front': + $template->assign_vars(array( + 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=mcp&field=username&select_single=true'), + 'U_POST_ACTION' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&mode=user_notes'), + + 'L_TITLE' => $user->lang['MCP_NOTES'], + )); + + $this->tpl_name = 'mcp_notes_front'; + break; + + case 'user_notes': + $user->add_lang('acp/common'); + + $this->mcp_notes_user_view($action); + $this->tpl_name = 'mcp_notes_user'; + break; + } + } + + /** + * Display user notes + */ + function mcp_notes_user_view($action) + { + global $phpEx, $phpbb_root_path, $config; + global $template, $db, $user, $auth; + + $user_id = request_var('u', 0); + $username = request_var('username', '', true); + $start = request_var('start', 0); + $st = request_var('st', 0); + $sk = request_var('sk', 'b'); + $sd = request_var('sd', 'd'); + + add_form_key('mcp_notes'); + + $sql_where = ($user_id) ? "user_id = $user_id" : "username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'"; + + $sql = 'SELECT * + FROM ' . USERS_TABLE . " + WHERE $sql_where"; + $result = $db->sql_query($sql); + $userrow = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$userrow) + { + trigger_error('NO_USER'); + } + + $user_id = $userrow['user_id']; + + // Populate user id to the currently active module (this module) + // The following method is another way of adjusting module urls. It is the easy variant if we want + // to directly adjust the current module url based on data retrieved within the same module. + if (strpos($this->u_action, "&u=$user_id") === false) + { + $this->p_master->adjust_url('&u=' . $user_id); + $this->u_action .= "&u=$user_id"; + } + + $deletemark = ($action == 'del_marked') ? true : false; + $deleteall = ($action == 'del_all') ? true : false; + $marked = request_var('marknote', array(0)); + $usernote = utf8_normalize_nfc(request_var('usernote', '', true)); + + // Handle any actions + if (($deletemark || $deleteall) && $auth->acl_get('a_clearlogs')) + { + $where_sql = ''; + if ($deletemark && $marked) + { + $sql_in = array(); + foreach ($marked as $mark) + { + $sql_in[] = $mark; + } + $where_sql = ' AND ' . $db->sql_in_set('log_id', $sql_in); + unset($sql_in); + } + + if ($where_sql || $deleteall) + { + if (check_form_key('mcp_notes')) + { + $sql = 'DELETE FROM ' . LOG_TABLE . ' + WHERE log_type = ' . LOG_USERS . " + AND reportee_id = $user_id + $where_sql"; + $db->sql_query($sql); + + add_log('admin', 'LOG_CLEAR_USER', $userrow['username']); + + $msg = ($deletemark) ? 'MARKED_NOTES_DELETED' : 'ALL_NOTES_DELETED'; + } + else + { + $msg = 'FORM_INVALID'; + } + $redirect = $this->u_action . '&u=' . $user_id; + meta_refresh(3, $redirect); + trigger_error($user->lang[$msg] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>')); + } + } + + if ($usernote && $action == 'add_feedback') + { + if (check_form_key('mcp_notes')) + { + add_log('admin', 'LOG_USER_FEEDBACK', $userrow['username']); + add_log('mod', 0, 0, 'LOG_USER_FEEDBACK', $userrow['username']); + + add_log('user', $user_id, 'LOG_USER_GENERAL', $usernote); + $msg = $user->lang['USER_FEEDBACK_ADDED']; + } + else + { + $msg = $user->lang['FORM_INVALID']; + } + $redirect = $this->u_action; + meta_refresh(3, $redirect); + + trigger_error($msg . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>')); + } + + // Generate the appropriate user information for the user we are looking at + if (!function_exists('get_user_avatar')) + { + include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + } + + $rank_title = $rank_img = ''; + $avatar_img = get_user_avatar($userrow['user_avatar'], $userrow['user_avatar_type'], $userrow['user_avatar_width'], $userrow['user_avatar_height']); + + $limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + $sort_by_text = array('a' => $user->lang['SORT_USERNAME'], 'b' => $user->lang['SORT_DATE'], 'c' => $user->lang['SORT_IP'], 'd' => $user->lang['SORT_ACTION']); + $sort_by_sql = array('a' => 'u.username_clean', 'b' => 'l.log_time', 'c' => 'l.log_ip', 'd' => 'l.log_operation'); + + $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = ''; + gen_sort_selects($limit_days, $sort_by_text, $st, $sk, $sd, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param); + + // Define where and sort sql for use in displaying logs + $sql_where = ($st) ? (time() - ($st * 86400)) : 0; + $sql_sort = $sort_by_sql[$sk] . ' ' . (($sd == 'd') ? 'DESC' : 'ASC'); + + $keywords = utf8_normalize_nfc(request_var('keywords', '', true)); + $keywords_param = !empty($keywords) ? '&keywords=' . urlencode(htmlspecialchars_decode($keywords)) : ''; + + $log_data = array(); + $log_count = 0; + view_log('user', $log_data, $log_count, $config['posts_per_page'], $start, 0, 0, $user_id, $sql_where, $sql_sort, $keywords); + + if ($log_count) + { + $template->assign_var('S_USER_NOTES', true); + + foreach ($log_data as $row) + { + $template->assign_block_vars('usernotes', array( + 'REPORT_BY' => $row['username_full'], + 'REPORT_AT' => $user->format_date($row['time']), + 'ACTION' => $row['action'], + 'IP' => $row['ip'], + 'ID' => $row['id']) + ); + } + } + + $template->assign_vars(array( + 'U_POST_ACTION' => $this->u_action, + 'S_CLEAR_ALLOWED' => ($auth->acl_get('a_clearlogs')) ? true : false, + 'S_SELECT_SORT_DIR' => $s_sort_dir, + 'S_SELECT_SORT_KEY' => $s_sort_key, + 'S_SELECT_SORT_DAYS' => $s_limit_days, + 'S_KEYWORDS' => $keywords, + + 'L_TITLE' => $user->lang['MCP_NOTES_USER'], + + 'PAGE_NUMBER' => on_page($log_count, $config['posts_per_page'], $start), + 'PAGINATION' => generate_pagination($this->u_action . "&$u_sort_param$keywords_param", $log_count, $config['topics_per_page'], $start, true), + 'TOTAL_REPORTS' => ($log_count == 1) ? $user->lang['LIST_REPORT'] : sprintf($user->lang['LIST_REPORTS'], $log_count), + + 'RANK_TITLE' => $rank_title, + 'JOINED' => $user->format_date($userrow['user_regdate']), + 'POSTS' => ($userrow['user_posts']) ? $userrow['user_posts'] : 0, + 'WARNINGS' => ($userrow['user_warnings']) ? $userrow['user_warnings'] : 0, + + 'USERNAME_FULL' => get_username_string('full', $userrow['user_id'], $userrow['username'], $userrow['user_colour']), + 'USERNAME_COLOUR' => get_username_string('colour', $userrow['user_id'], $userrow['username'], $userrow['user_colour']), + 'USERNAME' => get_username_string('username', $userrow['user_id'], $userrow['username'], $userrow['user_colour']), + 'U_PROFILE' => get_username_string('profile', $userrow['user_id'], $userrow['username'], $userrow['user_colour']), + + 'AVATAR_IMG' => $avatar_img, + 'RANK_IMG' => $rank_img, + ) + ); + } + +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/mcp/mcp_pm_reports.php b/phpBB/includes/mcp/mcp_pm_reports.php new file mode 100644 index 0000000000..72f77fae7c --- /dev/null +++ b/phpBB/includes/mcp/mcp_pm_reports.php @@ -0,0 +1,323 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* mcp_reports +* Handling the reports queue +* @package mcp +*/ +class mcp_pm_reports +{ + var $p_master; + var $u_action; + + function mcp_pm_reports(&$p_master) + { + $this->p_master = &$p_master; + } + + function main($id, $mode) + { + global $auth, $db, $user, $template, $cache; + global $config, $phpbb_root_path, $phpEx, $action; + + include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); + include_once($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx); + + $start = request_var('start', 0); + + $this->page_title = 'MCP_PM_REPORTS'; + + switch ($action) + { + case 'close': + case 'delete': + include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + + $report_id_list = request_var('report_id_list', array(0)); + + if (!sizeof($report_id_list)) + { + trigger_error('NO_REPORT_SELECTED'); + } + + if (!function_exists('close_report')) + { + include($phpbb_root_path . 'includes/mcp/mcp_reports.' . $phpEx); + } + + close_report($report_id_list, $mode, $action, true); + + break; + } + + switch ($mode) + { + case 'pm_report_details': + + $user->add_lang(array('posting', 'viewforum', 'viewtopic', 'ucp')); + + $report_id = request_var('r', 0); + + $sql = 'SELECT r.pm_id, r.user_id, r.report_id, r.report_closed, report_time, r.report_text, rr.reason_title, rr.reason_description, u.username, u.username_clean, u.user_colour + FROM ' . REPORTS_TABLE . ' r, ' . REPORTS_REASONS_TABLE . ' rr, ' . USERS_TABLE . ' u + WHERE r.report_id = ' . $report_id . ' + AND rr.reason_id = r.reason_id + AND r.user_id = u.user_id + AND r.post_id = 0 + ORDER BY report_closed ASC'; + $result = $db->sql_query_limit($sql, 1); + $report = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$report_id || !$report) + { + trigger_error('NO_REPORT'); + } + + $pm_id = $report['pm_id']; + $report_id = $report['report_id']; + + $pm_info = get_pm_data(array($pm_id)); + + if (!sizeof($pm_info)) + { + trigger_error('NO_REPORT_SELECTED'); + } + + $pm_info = $pm_info[$pm_id]; + + write_pm_addresses(array('to' => $pm_info['to_address'], 'bcc' => $pm_info['bcc_address']), (int) $pm_info['author_id']); + + $reason = array('title' => $report['reason_title'], 'description' => $report['reason_description']); + if (isset($user->lang['report_reasons']['TITLE'][strtoupper($reason['title'])]) && isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($reason['title'])])) + { + $reason['description'] = $user->lang['report_reasons']['DESCRIPTION'][strtoupper($reason['title'])]; + $reason['title'] = $user->lang['report_reasons']['TITLE'][strtoupper($reason['title'])]; + } + + // Process message, leave it uncensored + $message = $pm_info['message_text']; + + if ($pm_info['bbcode_bitfield']) + { + include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx); + $bbcode = new bbcode($pm_info['bbcode_bitfield']); + $bbcode->bbcode_second_pass($message, $pm_info['bbcode_uid'], $pm_info['bbcode_bitfield']); + } + + $message = bbcode_nl2br($message); + $message = smiley_text($message); + + if ($pm_info['message_attachment'] && $auth->acl_get('u_pm_download')) + { + $sql = 'SELECT * + FROM ' . ATTACHMENTS_TABLE . ' + WHERE post_msg_id = ' . $pm_id . ' + AND in_message = 1 + ORDER BY filetime DESC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $attachments[] = $row; + } + $db->sql_freeresult($result); + + if (sizeof($attachments)) + { + $update_count = array(); + parse_attachments(0, $message, $attachments, $update_count); + } + + // Display not already displayed Attachments for this post, we already parsed them. ;) + if (!empty($attachments)) + { + $template->assign_var('S_HAS_ATTACHMENTS', true); + + foreach ($attachments as $attachment) + { + $template->assign_block_vars('attachment', array( + 'DISPLAY_ATTACHMENT' => $attachment) + ); + } + } + } + + $template->assign_vars(array( + 'S_MCP_REPORT' => true, + 'S_PM' => true, + 'S_CLOSE_ACTION' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=pm_reports&mode=pm_report_details&r=' . $report_id), + 'S_CAN_VIEWIP' => $auth->acl_getf_global('m_info'), + 'S_POST_REPORTED' => $pm_info['message_reported'], + 'S_USER_NOTES' => true, + + 'U_MCP_REPORT' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=pm_reports&mode=pm_report_details&r=' . $report_id), + 'U_MCP_REPORTER_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&mode=user_notes&u=' . $report['user_id']), + 'U_MCP_USER_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&mode=user_notes&u=' . $pm_info['author_id']), + 'U_MCP_WARN_REPORTER' => ($auth->acl_get('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&mode=warn_user&u=' . $report['user_id']) : '', + 'U_MCP_WARN_USER' => ($auth->acl_get('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&mode=warn_user&u=' . $pm_info['author_id']) : '', + + 'EDIT_IMG' => $user->img('icon_post_edit', $user->lang['EDIT_POST']), + 'MINI_POST_IMG' => $user->img('icon_post_target', 'POST'), + + 'RETURN_REPORTS' => sprintf($user->lang['RETURN_REPORTS'], '<a href="' . append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=pm_reports' . (($pm_info['message_reported']) ? '&mode=pm_reports' : '&mode=pm_reports_closed') . '&start=' . $start) . '">', '</a>'), + 'REPORTED_IMG' => $user->img('icon_topic_reported', $user->lang['POST_REPORTED']), + 'REPORT_DATE' => $user->format_date($report['report_time']), + 'REPORT_ID' => $report_id, + 'REPORT_REASON_TITLE' => $reason['title'], + 'REPORT_REASON_DESCRIPTION' => $reason['description'], + 'REPORT_TEXT' => $report['report_text'], + + 'POST_AUTHOR_FULL' => get_username_string('full', $pm_info['author_id'], $pm_info['username'], $pm_info['user_colour']), + 'POST_AUTHOR_COLOUR' => get_username_string('colour', $pm_info['author_id'], $pm_info['username'], $pm_info['user_colour']), + 'POST_AUTHOR' => get_username_string('username', $pm_info['author_id'], $pm_info['username'], $pm_info['user_colour']), + 'U_POST_AUTHOR' => get_username_string('profile', $pm_info['author_id'], $pm_info['username'], $pm_info['user_colour']), + + 'REPORTER_FULL' => get_username_string('full', $report['user_id'], $report['username'], $report['user_colour']), + 'REPORTER_COLOUR' => get_username_string('colour', $report['user_id'], $report['username'], $report['user_colour']), + 'REPORTER_NAME' => get_username_string('username', $report['user_id'], $report['username'], $report['user_colour']), + 'U_VIEW_REPORTER_PROFILE' => get_username_string('profile', $report['user_id'], $report['username'], $report['user_colour']), + + 'POST_PREVIEW' => $message, + 'POST_SUBJECT' => ($pm_info['message_subject']) ? $pm_info['message_subject'] : $user->lang['NO_SUBJECT'], + 'POST_DATE' => $user->format_date($pm_info['message_time']), + 'POST_IP' => $pm_info['author_ip'], + 'POST_IPADDR' => ($auth->acl_getf_global('m_info') && request_var('lookup', '')) ? @gethostbyaddr($pm_info['author_ip']) : '', + 'POST_ID' => $pm_info['msg_id'], + + 'U_LOOKUP_IP' => ($auth->acl_getf_global('m_info')) ? $this->u_action . '&r=' . $report_id . '&pm=' . $pm_id . '&lookup=' . $pm_info['author_ip'] . '#ip' : '', + )); + + $this->tpl_name = 'mcp_post'; + + break; + + case 'pm_reports': + case 'pm_reports_closed': + $user->add_lang(array('ucp')); + + $sort_days = $total = 0; + $sort_key = $sort_dir = ''; + $sort_by_sql = $sort_order_sql = array(); + mcp_sorting($mode, $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total); + + $limit_time_sql = ($sort_days) ? 'AND r.report_time >= ' . (time() - ($sort_days * 86400)) : ''; + + if ($mode == 'pm_reports') + { + $report_state = 'p.message_reported = 1 AND r.report_closed = 0'; + } + else + { + $report_state = 'r.report_closed = 1'; + } + + $sql = 'SELECT r.report_id + FROM ' . PRIVMSGS_TABLE . ' p, ' . REPORTS_TABLE . ' r ' . (($sort_order_sql[0] == 'u') ? ', ' . USERS_TABLE . ' u' : '') . (($sort_order_sql[0] == 'r') ? ', ' . USERS_TABLE . ' ru' : '') . " + WHERE $report_state + AND r.pm_id = p.msg_id + " . (($sort_order_sql[0] == 'u') ? 'AND u.user_id = p.author_id' : '') . ' + ' . (($sort_order_sql[0] == 'r') ? 'AND ru.user_id = r.user_id' : '') . " + AND r.post_id = 0 + $limit_time_sql + ORDER BY $sort_order_sql"; + $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); + + $i = 0; + $report_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $report_ids[] = $row['report_id']; + $row_num[$row['report_id']] = $i++; + } + $db->sql_freeresult($result); + + if (sizeof($report_ids)) + { + $sql = 'SELECT p.*, u.username, u.username_clean, u.user_colour, r.user_id as reporter_id, ru.username as reporter_name, ru.user_colour as reporter_colour, r.report_time, r.report_id + FROM ' . REPORTS_TABLE . ' r, ' . PRIVMSGS_TABLE . ' p, ' . USERS_TABLE . ' u, ' . USERS_TABLE . ' ru + WHERE ' . $db->sql_in_set('r.report_id', $report_ids) . " + AND r.pm_id = p.msg_id + AND p.author_id = u.user_id + AND ru.user_id = r.user_id + ORDER BY $sort_order_sql"; + $result = $db->sql_query($sql); + + $pm_list = $pm_by_id = array(); + while ($row = $db->sql_fetchrow($result)) + { + $pm_by_id[(int) $row['msg_id']] = $row; + $pm_list[] = (int) $row['msg_id']; + } + $db->sql_freeresult($result); + + if (sizeof($pm_list)) + { + $address_list = get_recipient_strings($pm_by_id); + + foreach ($pm_list as $message_id) + { + $row = $pm_by_id[$message_id]; + $template->assign_block_vars('postrow', array( + 'U_VIEW_DETAILS' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=pm_reports&mode=pm_report_details&r={$row['report_id']}"), + + 'PM_AUTHOR_FULL' => get_username_string('full', $row['author_id'], $row['username'], $row['user_colour']), + 'PM_AUTHOR_COLOUR' => get_username_string('colour', $row['author_id'], $row['username'], $row['user_colour']), + 'PM_AUTHOR' => get_username_string('username', $row['author_id'], $row['username'], $row['user_colour']), + 'U_PM_AUTHOR' => get_username_string('profile', $row['author_id'], $row['username'], $row['user_colour']), + + 'REPORTER_FULL' => get_username_string('full', $row['reporter_id'], $row['reporter_name'], $row['reporter_colour']), + 'REPORTER_COLOUR' => get_username_string('colour', $row['reporter_id'], $row['reporter_name'], $row['reporter_colour']), + 'REPORTER' => get_username_string('username', $row['reporter_id'], $row['reporter_name'], $row['reporter_colour']), + 'U_REPORTER' => get_username_string('profile', $row['reporter_id'], $row['reporter_name'], $row['reporter_colour']), + + 'PM_SUBJECT' => ($row['message_subject']) ? $row['message_subject'] : $user->lang['NO_SUBJECT'], + 'PM_TIME' => $user->format_date($row['message_time']), + 'REPORT_ID' => $row['report_id'], + 'REPORT_TIME' => $user->format_date($row['report_time']), + + 'RECIPIENTS' => implode(', ', $address_list[$row['msg_id']]), + )); + } + } + } + + // Now display the page + $template->assign_vars(array( + 'L_EXPLAIN' => ($mode == 'pm_reports') ? $user->lang['MCP_PM_REPORTS_OPEN_EXPLAIN'] : $user->lang['MCP_PM_REPORTS_CLOSED_EXPLAIN'], + 'L_TITLE' => ($mode == 'pm_reports') ? $user->lang['MCP_PM_REPORTS_OPEN'] : $user->lang['MCP_PM_REPORTS_CLOSED'], + + 'S_PM' => true, + 'S_MCP_ACTION' => $this->u_action, + 'S_CLOSED' => ($mode == 'pm_reports_closed') ? true : false, + + 'PAGINATION' => generate_pagination($this->u_action . "&st=$sort_days&sk=$sort_key&sd=$sort_dir", $total, $config['topics_per_page'], $start), + 'PAGE_NUMBER' => on_page($total, $config['topics_per_page'], $start), + 'TOTAL' => $total, + 'TOTAL_REPORTS' => ($total == 1) ? $user->lang['LIST_REPORT'] : sprintf($user->lang['LIST_REPORTS'], $total), + ) + ); + + $this->tpl_name = 'mcp_reports'; + break; + } + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/mcp/mcp_post.php b/phpBB/includes/mcp/mcp_post.php new file mode 100644 index 0000000000..fa44e006dd --- /dev/null +++ b/phpBB/includes/mcp/mcp_post.php @@ -0,0 +1,501 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Handling actions in post details screen +*/ +function mcp_post_details($id, $mode, $action) +{ + global $phpEx, $phpbb_root_path, $config; + global $template, $db, $user, $auth, $cache; + + $user->add_lang('posting'); + + $post_id = request_var('p', 0); + $start = request_var('start', 0); + + // Get post data + $post_info = get_post_data(array($post_id), false, true); + + add_form_key('mcp_post_details'); + + if (!sizeof($post_info)) + { + trigger_error('POST_NOT_EXIST'); + } + + $post_info = $post_info[$post_id]; + $url = append_sid("{$phpbb_root_path}mcp.$phpEx?" . extra_url()); + + switch ($action) + { + case 'whois': + + if ($auth->acl_get('m_info', $post_info['forum_id'])) + { + $ip = request_var('ip', ''); + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + + $template->assign_vars(array( + 'RETURN_POST' => sprintf($user->lang['RETURN_POST'], '<a href="' . append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&mode=$mode&p=$post_id") . '">', '</a>'), + 'U_RETURN_POST' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&mode=$mode&p=$post_id"), + 'L_RETURN_POST' => sprintf($user->lang['RETURN_POST'], '', ''), + 'WHOIS' => user_ipwhois($ip), + )); + } + + // We're done with the whois page so return + return; + + break; + + case 'chgposter': + case 'chgposter_ip': + + if ($action == 'chgposter') + { + $username = request_var('username', '', true); + $sql_where = "username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'"; + } + else + { + $new_user_id = request_var('u', 0); + $sql_where = 'user_id = ' . $new_user_id; + } + + $sql = 'SELECT * + FROM ' . USERS_TABLE . ' + WHERE ' . $sql_where; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error('NO_USER'); + } + + if ($auth->acl_get('m_chgposter', $post_info['forum_id'])) + { + if (check_form_key('mcp_post_details')) + { + change_poster($post_info, $row); + } + else + { + trigger_error('FORM_INVALID'); + } + } + + break; + } + + // Set some vars + $users_ary = $usernames_ary = array(); + $attachments = $extensions = array(); + $post_id = $post_info['post_id']; + $topic_tracking_info = array(); + + // Get topic tracking info + if ($config['load_db_lastread']) + { + $tmp_topic_data = array($post_info['topic_id'] => $post_info); + $topic_tracking_info = get_topic_tracking($post_info['forum_id'], $post_info['topic_id'], $tmp_topic_data, array($post_info['forum_id'] => $post_info['forum_mark_time'])); + unset($tmp_topic_data); + } + else + { + $topic_tracking_info = get_complete_topic_tracking($post_info['forum_id'], $post_info['topic_id']); + } + + $post_unread = (isset($topic_tracking_info[$post_info['topic_id']]) && $post_info['post_time'] > $topic_tracking_info[$post_info['topic_id']]) ? true : false; + + // Process message, leave it uncensored + $message = $post_info['post_text']; + + if ($post_info['bbcode_bitfield']) + { + include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx); + $bbcode = new bbcode($post_info['bbcode_bitfield']); + $bbcode->bbcode_second_pass($message, $post_info['bbcode_uid'], $post_info['bbcode_bitfield']); + } + + $message = bbcode_nl2br($message); + $message = smiley_text($message); + + if ($post_info['post_attachment'] && $auth->acl_get('u_download') && $auth->acl_get('f_download', $post_info['forum_id'])) + { + $extensions = $cache->obtain_attach_extensions($post_info['forum_id']); + + $sql = 'SELECT * + FROM ' . ATTACHMENTS_TABLE . ' + WHERE post_msg_id = ' . $post_id . ' + AND in_message = 0 + ORDER BY filetime DESC, post_msg_id ASC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $attachments[] = $row; + } + $db->sql_freeresult($result); + + if (sizeof($attachments)) + { + $update_count = array(); + parse_attachments($post_info['forum_id'], $message, $attachments, $update_count); + } + + // Display not already displayed Attachments for this post, we already parsed them. ;) + if (!empty($attachments)) + { + $template->assign_var('S_HAS_ATTACHMENTS', true); + + foreach ($attachments as $attachment) + { + $template->assign_block_vars('attachment', array( + 'DISPLAY_ATTACHMENT' => $attachment) + ); + } + } + } + + $template->assign_vars(array( + 'U_MCP_ACTION' => "$url&i=main&quickmod=1", // Use this for mode paramaters + 'U_POST_ACTION' => "$url&i=$id&mode=post_details", // Use this for action parameters + 'U_APPROVE_ACTION' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=queue&p=$post_id&f={$post_info['forum_id']}"), + + 'S_CAN_VIEWIP' => $auth->acl_get('m_info', $post_info['forum_id']), + 'S_CAN_CHGPOSTER' => $auth->acl_get('m_chgposter', $post_info['forum_id']), + 'S_CAN_LOCK_POST' => $auth->acl_get('m_lock', $post_info['forum_id']), + 'S_CAN_DELETE_POST' => $auth->acl_get('m_delete', $post_info['forum_id']), + + 'S_POST_REPORTED' => ($post_info['post_reported']) ? true : false, + 'S_POST_UNAPPROVED' => (!$post_info['post_approved']) ? true : false, + 'S_POST_LOCKED' => ($post_info['post_edit_locked']) ? true : false, + 'S_USER_NOTES' => true, + 'S_CLEAR_ALLOWED' => ($auth->acl_get('a_clearlogs')) ? true : false, + + 'U_EDIT' => ($auth->acl_get('m_edit', $post_info['forum_id'])) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=edit&f={$post_info['forum_id']}&p={$post_info['post_id']}") : '', + 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=mcp_chgposter&field=username&select_single=true'), + 'U_MCP_APPROVE' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&mode=approve_details&f=' . $post_info['forum_id'] . '&p=' . $post_id), + 'U_MCP_REPORT' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&mode=report_details&f=' . $post_info['forum_id'] . '&p=' . $post_id), + 'U_MCP_USER_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&mode=user_notes&u=' . $post_info['user_id']), + 'U_MCP_WARN_USER' => ($auth->acl_get('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&mode=warn_user&u=' . $post_info['user_id']) : '', + 'U_VIEW_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&p=' . $post_info['post_id'] . '#p' . $post_info['post_id']), + 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&t=' . $post_info['topic_id']), + + 'MINI_POST_IMG' => ($post_unread) ? $user->img('icon_post_target_unread', 'NEW_POST') : $user->img('icon_post_target', 'POST'), + + 'RETURN_TOPIC' => sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f={$post_info['forum_id']}&p=$post_id") . "#p$post_id\">", '</a>'), + 'RETURN_FORUM' => sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", "f={$post_info['forum_id']}&start={$start}") . '">', '</a>'), + 'REPORTED_IMG' => $user->img('icon_topic_reported', $user->lang['POST_REPORTED']), + 'UNAPPROVED_IMG' => $user->img('icon_topic_unapproved', $user->lang['POST_UNAPPROVED']), + 'EDIT_IMG' => $user->img('icon_post_edit', $user->lang['EDIT_POST']), + 'SEARCH_IMG' => $user->img('icon_user_search', $user->lang['SEARCH']), + + 'POST_AUTHOR_FULL' => get_username_string('full', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + 'POST_AUTHOR_COLOUR' => get_username_string('colour', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + 'POST_AUTHOR' => get_username_string('username', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + 'U_POST_AUTHOR' => get_username_string('profile', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + + 'POST_PREVIEW' => $message, + 'POST_SUBJECT' => $post_info['post_subject'], + 'POST_DATE' => $user->format_date($post_info['post_time']), + 'POST_IP' => $post_info['poster_ip'], + 'POST_IPADDR' => ($auth->acl_get('m_info', $post_info['forum_id']) && request_var('lookup', '')) ? @gethostbyaddr($post_info['poster_ip']) : '', + 'POST_ID' => $post_info['post_id'], + + 'U_LOOKUP_IP' => ($auth->acl_get('m_info', $post_info['forum_id'])) ? "$url&i=$id&mode=$mode&lookup={$post_info['poster_ip']}#ip" : '', + 'U_WHOIS' => ($auth->acl_get('m_info', $post_info['forum_id'])) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&mode=$mode&action=whois&p=$post_id&ip={$post_info['poster_ip']}") : '', + )); + + // Get User Notes + $log_data = array(); + $log_count = 0; + view_log('user', $log_data, $log_count, $config['posts_per_page'], 0, 0, 0, $post_info['user_id']); + + if ($log_count) + { + $template->assign_var('S_USER_NOTES', true); + + foreach ($log_data as $row) + { + $template->assign_block_vars('usernotes', array( + 'REPORT_BY' => $row['username_full'], + 'REPORT_AT' => $user->format_date($row['time']), + 'ACTION' => $row['action'], + 'ID' => $row['id']) + ); + } + } + + // Get Reports + if ($auth->acl_get('m_', $post_info['forum_id'])) + { + $sql = 'SELECT r.*, re.*, u.user_id, u.username + FROM ' . REPORTS_TABLE . ' r, ' . USERS_TABLE . ' u, ' . REPORTS_REASONS_TABLE . " re + WHERE r.post_id = $post_id + AND r.reason_id = re.reason_id + AND u.user_id = r.user_id + ORDER BY r.report_time DESC"; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + $template->assign_var('S_SHOW_REPORTS', true); + + do + { + // If the reason is defined within the language file, we will use the localized version, else just use the database entry... + if (isset($user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]) && isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])])) + { + $row['reson_description'] = $user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])]; + $row['reason_title'] = $user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]; + } + + $template->assign_block_vars('reports', array( + 'REPORT_ID' => $row['report_id'], + 'REASON_TITLE' => $row['reason_title'], + 'REASON_DESC' => $row['reason_description'], + 'REPORTER' => ($row['user_id'] != ANONYMOUS) ? $row['username'] : $user->lang['GUEST'], + 'U_REPORTER' => ($row['user_id'] != ANONYMOUS) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $row['user_id']) : '', + 'USER_NOTIFY' => ($row['user_notify']) ? true : false, + 'REPORT_TIME' => $user->format_date($row['report_time']), + 'REPORT_TEXT' => bbcode_nl2br(trim($row['report_text'])), + )); + } + while ($row = $db->sql_fetchrow($result)); + } + $db->sql_freeresult($result); + } + + // Get IP + if ($auth->acl_get('m_info', $post_info['forum_id'])) + { + $rdns_ip_num = request_var('rdns', ''); + + if ($rdns_ip_num != 'all') + { + $template->assign_vars(array( + 'U_LOOKUP_ALL' => "$url&i=main&mode=post_details&rdns=all") + ); + } + + // Get other users who've posted under this IP + $sql = 'SELECT poster_id, COUNT(poster_id) as postings + FROM ' . POSTS_TABLE . " + WHERE poster_ip = '" . $db->sql_escape($post_info['poster_ip']) . "' + GROUP BY poster_id + ORDER BY postings DESC"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + // Fill the user select list with users who have posted under this IP + if ($row['poster_id'] != $post_info['poster_id']) + { + $users_ary[$row['poster_id']] = $row; + } + } + $db->sql_freeresult($result); + + if (sizeof($users_ary)) + { + // Get the usernames + $sql = 'SELECT user_id, username + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', array_keys($users_ary)); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $users_ary[$row['user_id']]['username'] = $row['username']; + $usernames_ary[utf8_clean_string($row['username'])] = $users_ary[$row['user_id']]; + } + $db->sql_freeresult($result); + + foreach ($users_ary as $user_id => $user_row) + { + $template->assign_block_vars('userrow', array( + 'USERNAME' => ($user_id == ANONYMOUS) ? $user->lang['GUEST'] : $user_row['username'], + 'NUM_POSTS' => $user_row['postings'], + 'L_POST_S' => ($user_row['postings'] == 1) ? $user->lang['POST'] : $user->lang['POSTS'], + + 'U_PROFILE' => ($user_id == ANONYMOUS) ? '' : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $user_id), + 'U_SEARCHPOSTS' => append_sid("{$phpbb_root_path}search.$phpEx", 'author_id=' . $user_id . '&sr=topics')) + ); + } + } + + // Get other IP's this user has posted under + + // A compound index on poster_id, poster_ip (posts table) would help speed up this query a lot, + // but the extra size is only valuable if there are persons having more than a thousands posts. + // This is better left to the really really big forums. + + $sql = 'SELECT poster_ip, COUNT(poster_ip) AS postings + FROM ' . POSTS_TABLE . ' + WHERE poster_id = ' . $post_info['poster_id'] . " + GROUP BY poster_ip + ORDER BY postings DESC"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $hostname = (($rdns_ip_num == $row['poster_ip'] || $rdns_ip_num == 'all') && $row['poster_ip']) ? @gethostbyaddr($row['poster_ip']) : ''; + + $template->assign_block_vars('iprow', array( + 'IP' => $row['poster_ip'], + 'HOSTNAME' => $hostname, + 'NUM_POSTS' => $row['postings'], + 'L_POST_S' => ($row['postings'] == 1) ? $user->lang['POST'] : $user->lang['POSTS'], + + 'U_LOOKUP_IP' => ($rdns_ip_num == $row['poster_ip'] || $rdns_ip_num == 'all') ? '' : "$url&i=$id&mode=post_details&rdns={$row['poster_ip']}#ip", + 'U_WHOIS' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&mode=$mode&action=whois&p=$post_id&ip={$row['poster_ip']}")) + ); + } + $db->sql_freeresult($result); + + $user_select = ''; + + if (sizeof($usernames_ary)) + { + ksort($usernames_ary); + + foreach ($usernames_ary as $row) + { + $user_select .= '<option value="' . $row['poster_id'] . '">' . $row['username'] . "</option>\n"; + } + } + + $template->assign_var('S_USER_SELECT', $user_select); + } + +} + +/** +* Change a post's poster +*/ +function change_poster(&$post_info, $userdata) +{ + global $auth, $db, $config, $phpbb_root_path, $phpEx; + + if (empty($userdata) || $userdata['user_id'] == $post_info['user_id']) + { + return; + } + + $post_id = $post_info['post_id']; + + $sql = 'UPDATE ' . POSTS_TABLE . " + SET poster_id = {$userdata['user_id']} + WHERE post_id = $post_id"; + $db->sql_query($sql); + + // Resync topic/forum if needed + if ($post_info['topic_last_post_id'] == $post_id || $post_info['forum_last_post_id'] == $post_id || $post_info['topic_first_post_id'] == $post_id) + { + sync('topic', 'topic_id', $post_info['topic_id'], false, false); + sync('forum', 'forum_id', $post_info['forum_id'], false, false); + } + + // Adjust post counts... only if the post is approved (else, it was not added the users post count anyway) + if ($post_info['post_postcount'] && $post_info['post_approved']) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_posts = user_posts - 1 + WHERE user_id = ' . $post_info['user_id'] .' + AND user_posts > 0'; + $db->sql_query($sql); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_posts = user_posts + 1 + WHERE user_id = ' . $userdata['user_id']; + $db->sql_query($sql); + } + + // Add posted to information for this topic for the new user + markread('post', $post_info['forum_id'], $post_info['topic_id'], time(), $userdata['user_id']); + + // Remove the dotted topic option if the old user has no more posts within this topic + if ($config['load_db_track'] && $post_info['user_id'] != ANONYMOUS) + { + $sql = 'SELECT topic_id + FROM ' . POSTS_TABLE . ' + WHERE topic_id = ' . $post_info['topic_id'] . ' + AND poster_id = ' . $post_info['user_id']; + $result = $db->sql_query_limit($sql, 1); + $topic_id = (int) $db->sql_fetchfield('topic_id'); + $db->sql_freeresult($result); + + if (!$topic_id) + { + $sql = 'DELETE FROM ' . TOPICS_POSTED_TABLE . ' + WHERE user_id = ' . $post_info['user_id'] . ' + AND topic_id = ' . $post_info['topic_id']; + $db->sql_query($sql); + } + } + + // change the poster_id within the attachments table, else the data becomes out of sync and errors displayed because of wrong ownership + if ($post_info['post_attachment']) + { + $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' + SET poster_id = ' . $userdata['user_id'] . ' + WHERE poster_id = ' . $post_info['user_id'] . ' + AND post_msg_id = ' . $post_info['post_id'] . ' + AND topic_id = ' . $post_info['topic_id']; + $db->sql_query($sql); + } + + // refresh search cache of this post + $search_type = basename($config['search_type']); + + if (file_exists($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx)) + { + require("{$phpbb_root_path}includes/search/$search_type.$phpEx"); + + // We do some additional checks in the module to ensure it can actually be utilised + $error = false; + $search = new $search_type($error); + + if (!$error && method_exists($search, 'destroy_cache')) + { + $search->destroy_cache(array(), array($post_info['user_id'], $userdata['user_id'])); + } + } + + $from_username = $post_info['username']; + $to_username = $userdata['username']; + + // Renew post info + $post_info = get_post_data(array($post_id), false, true); + + if (!sizeof($post_info)) + { + trigger_error('POST_NOT_EXIST'); + } + + $post_info = $post_info[$post_id]; + + // Now add log entry + add_log('mod', $post_info['forum_id'], $post_info['topic_id'], 'LOG_MCP_CHANGE_POSTER', $post_info['topic_title'], $from_username, $to_username); +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php new file mode 100644 index 0000000000..3783aadab5 --- /dev/null +++ b/phpBB/includes/mcp/mcp_queue.php @@ -0,0 +1,992 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* mcp_queue +* Handling the moderation queue +* @package mcp +*/ +class mcp_queue +{ + var $p_master; + var $u_action; + + function mcp_queue(&$p_master) + { + $this->p_master = &$p_master; + } + + function main($id, $mode) + { + global $auth, $db, $user, $template, $cache; + global $config, $phpbb_root_path, $phpEx, $action; + + include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); + + $forum_id = request_var('f', 0); + $start = request_var('start', 0); + + $this->page_title = 'MCP_QUEUE'; + + switch ($action) + { + case 'approve': + case 'disapprove': + include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + + $post_id_list = request_var('post_id_list', array(0)); + + if (!sizeof($post_id_list)) + { + trigger_error('NO_POST_SELECTED'); + } + + if ($action == 'approve') + { + approve_post($post_id_list, 'queue', $mode); + } + else + { + disapprove_post($post_id_list, 'queue', $mode); + } + + break; + } + + switch ($mode) + { + case 'approve_details': + + $this->tpl_name = 'mcp_post'; + + $user->add_lang(array('posting', 'viewtopic')); + + $post_id = request_var('p', 0); + $topic_id = request_var('t', 0); + + if ($topic_id) + { + $topic_info = get_topic_data(array($topic_id), 'm_approve'); + if (isset($topic_info[$topic_id]['topic_first_post_id'])) + { + $post_id = (int) $topic_info[$topic_id]['topic_first_post_id']; + } + else + { + $topic_id = 0; + } + } + + $post_info = get_post_data(array($post_id), 'm_approve', true); + + if (!sizeof($post_info)) + { + trigger_error('NO_POST_SELECTED'); + } + + $post_info = $post_info[$post_id]; + + if ($post_info['topic_first_post_id'] != $post_id && topic_review($post_info['topic_id'], $post_info['forum_id'], 'topic_review', 0, false)) + { + $template->assign_vars(array( + 'S_TOPIC_REVIEW' => true, + 'TOPIC_TITLE' => $post_info['topic_title']) + ); + } + + $extensions = $attachments = $topic_tracking_info = array(); + + // Get topic tracking info + if ($config['load_db_lastread']) + { + $tmp_topic_data = array($post_info['topic_id'] => $post_info); + $topic_tracking_info = get_topic_tracking($post_info['forum_id'], $post_info['topic_id'], $tmp_topic_data, array($post_info['forum_id'] => $post_info['forum_mark_time'])); + unset($tmp_topic_data); + } + else + { + $topic_tracking_info = get_complete_topic_tracking($post_info['forum_id'], $post_info['topic_id']); + } + + $post_unread = (isset($topic_tracking_info[$post_info['topic_id']]) && $post_info['post_time'] > $topic_tracking_info[$post_info['topic_id']]) ? true : false; + + // Process message, leave it uncensored + $message = $post_info['post_text']; + + if ($post_info['bbcode_bitfield']) + { + include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx); + $bbcode = new bbcode($post_info['bbcode_bitfield']); + $bbcode->bbcode_second_pass($message, $post_info['bbcode_uid'], $post_info['bbcode_bitfield']); + } + + $message = bbcode_nl2br($message); + $message = smiley_text($message); + + if ($post_info['post_attachment'] && $auth->acl_get('u_download') && $auth->acl_get('f_download', $post_info['forum_id'])) + { + $extensions = $cache->obtain_attach_extensions($post_info['forum_id']); + + $sql = 'SELECT * + FROM ' . ATTACHMENTS_TABLE . ' + WHERE post_msg_id = ' . $post_id . ' + AND in_message = 0 + ORDER BY filetime DESC, post_msg_id ASC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $attachments[] = $row; + } + $db->sql_freeresult($result); + + if (sizeof($attachments)) + { + $update_count = array(); + parse_attachments($post_info['forum_id'], $message, $attachments, $update_count); + } + + // Display not already displayed Attachments for this post, we already parsed them. ;) + if (!empty($attachments)) + { + $template->assign_var('S_HAS_ATTACHMENTS', true); + + foreach ($attachments as $attachment) + { + $template->assign_block_vars('attachment', array( + 'DISPLAY_ATTACHMENT' => $attachment) + ); + } + } + } + + $post_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&p=' . $post_info['post_id'] . '#p' . $post_info['post_id']); + $topic_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&t=' . $post_info['topic_id']); + + $template->assign_vars(array( + 'S_MCP_QUEUE' => true, + 'U_APPROVE_ACTION' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=queue&p=$post_id&f=$forum_id"), + 'S_CAN_VIEWIP' => $auth->acl_get('m_info', $post_info['forum_id']), + 'S_POST_REPORTED' => $post_info['post_reported'], + 'S_POST_UNAPPROVED' => !$post_info['post_approved'], + 'S_POST_LOCKED' => $post_info['post_edit_locked'], + 'S_USER_NOTES' => true, + + 'U_EDIT' => ($auth->acl_get('m_edit', $post_info['forum_id'])) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=edit&f={$post_info['forum_id']}&p={$post_info['post_id']}") : '', + 'U_MCP_APPROVE' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&mode=approve_details&f=' . $post_info['forum_id'] . '&p=' . $post_id), + 'U_MCP_REPORT' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&mode=report_details&f=' . $post_info['forum_id'] . '&p=' . $post_id), + 'U_MCP_USER_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&mode=user_notes&u=' . $post_info['user_id']), + 'U_MCP_WARN_USER' => ($auth->acl_get('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&mode=warn_user&u=' . $post_info['user_id']) : '', + 'U_VIEW_POST' => $post_url, + 'U_VIEW_TOPIC' => $topic_url, + + 'MINI_POST_IMG' => ($post_unread) ? $user->img('icon_post_target_unread', 'NEW_POST') : $user->img('icon_post_target', 'POST'), + + 'RETURN_QUEUE' => sprintf($user->lang['RETURN_QUEUE'], '<a href="' . append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue' . (($topic_id) ? '&mode=unapproved_topics' : '&mode=unapproved_posts')) . "&start=$start\">", '</a>'), + 'RETURN_POST' => sprintf($user->lang['RETURN_POST'], '<a href="' . $post_url . '">', '</a>'), + 'RETURN_TOPIC_SIMPLE' => sprintf($user->lang['RETURN_TOPIC_SIMPLE'], '<a href="' . $topic_url . '">', '</a>'), + 'REPORTED_IMG' => $user->img('icon_topic_reported', $user->lang['POST_REPORTED']), + 'UNAPPROVED_IMG' => $user->img('icon_topic_unapproved', $user->lang['POST_UNAPPROVED']), + 'EDIT_IMG' => $user->img('icon_post_edit', $user->lang['EDIT_POST']), + + 'POST_AUTHOR_FULL' => get_username_string('full', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + 'POST_AUTHOR_COLOUR' => get_username_string('colour', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + 'POST_AUTHOR' => get_username_string('username', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + 'U_POST_AUTHOR' => get_username_string('profile', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + + 'POST_PREVIEW' => $message, + 'POST_SUBJECT' => $post_info['post_subject'], + 'POST_DATE' => $user->format_date($post_info['post_time']), + 'POST_IP' => $post_info['poster_ip'], + 'POST_IPADDR' => ($auth->acl_get('m_info', $post_info['forum_id']) && request_var('lookup', '')) ? @gethostbyaddr($post_info['poster_ip']) : '', + 'POST_ID' => $post_info['post_id'], + + 'U_LOOKUP_IP' => ($auth->acl_get('m_info', $post_info['forum_id'])) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&mode=approve_details&f=' . $post_info['forum_id'] . '&p=' . $post_id . '&lookup=' . $post_info['poster_ip']) . '#ip' : '', + )); + + break; + + case 'unapproved_topics': + case 'unapproved_posts': + $user->add_lang(array('viewtopic', 'viewforum')); + + $topic_id = request_var('t', 0); + $forum_info = array(); + + if ($topic_id) + { + $topic_info = get_topic_data(array($topic_id)); + + if (!sizeof($topic_info)) + { + trigger_error('TOPIC_NOT_EXIST'); + } + + $topic_info = $topic_info[$topic_id]; + $forum_id = $topic_info['forum_id']; + } + + $forum_list_approve = get_forum_list('m_approve', false, true); + $forum_list_read = array_flip(get_forum_list('f_read', true, true)); // Flipped so we can isset() the forum IDs + + // Remove forums we cannot read + foreach ($forum_list_approve as $k => $forum_data) + { + if (!isset($forum_list_read[$forum_data['forum_id']])) + { + unset($forum_list_approve[$k]); + } + } + unset($forum_list_read); + + if (!$forum_id) + { + $forum_list = array(); + foreach ($forum_list_approve as $row) + { + $forum_list[] = $row['forum_id']; + } + + if (!sizeof($forum_list)) + { + trigger_error('NOT_MODERATOR'); + } + + $global_id = $forum_list[0]; + + $forum_list = implode(', ', $forum_list); + + $sql = 'SELECT SUM(forum_topics) as sum_forum_topics + FROM ' . FORUMS_TABLE . " + WHERE forum_id IN (0, $forum_list)"; + $result = $db->sql_query($sql); + $forum_info['forum_topics'] = (int) $db->sql_fetchfield('sum_forum_topics'); + $db->sql_freeresult($result); + } + else + { + $forum_info = get_forum_data(array($forum_id), 'm_approve'); + + if (!sizeof($forum_info)) + { + trigger_error('NOT_MODERATOR'); + } + + $forum_info = $forum_info[$forum_id]; + $forum_list = $forum_id; + $global_id = $forum_id; + } + + $forum_options = '<option value="0"' . (($forum_id == 0) ? ' selected="selected"' : '') . '>' . $user->lang['ALL_FORUMS'] . '</option>'; + foreach ($forum_list_approve as $row) + { + $forum_options .= '<option value="' . $row['forum_id'] . '"' . (($forum_id == $row['forum_id']) ? ' selected="selected"' : '') . '>' . str_repeat(' ', $row['padding']) . $row['forum_name'] . '</option>'; + } + + $sort_days = $total = 0; + $sort_key = $sort_dir = ''; + $sort_by_sql = $sort_order_sql = array(); + mcp_sorting($mode, $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id, $topic_id); + + $forum_topics = ($total == -1) ? $forum_info['forum_topics'] : $total; + $limit_time_sql = ($sort_days) ? 'AND t.topic_last_post_time >= ' . (time() - ($sort_days * 86400)) : ''; + + $forum_names = array(); + + if ($mode == 'unapproved_posts') + { + $sql = 'SELECT p.post_id + FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t' . (($sort_order_sql[0] == 'u') ? ', ' . USERS_TABLE . ' u' : '') . " + WHERE p.forum_id IN (0, $forum_list) + AND p.post_approved = 0 + " . (($sort_order_sql[0] == 'u') ? 'AND u.user_id = p.poster_id' : '') . ' + ' . (($topic_id) ? 'AND p.topic_id = ' . $topic_id : '') . " + AND t.topic_id = p.topic_id + AND t.topic_first_post_id <> p.post_id + $limit_time_sql + ORDER BY $sort_order_sql"; + $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); + + $i = 0; + $post_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $post_ids[] = $row['post_id']; + $row_num[$row['post_id']] = $i++; + } + $db->sql_freeresult($result); + + if (sizeof($post_ids)) + { + $sql = 'SELECT t.topic_id, t.topic_title, t.forum_id, p.post_id, p.post_subject, p.post_username, p.poster_id, p.post_time, u.username, u.username_clean, u.user_colour + FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t, ' . USERS_TABLE . ' u + WHERE ' . $db->sql_in_set('p.post_id', $post_ids) . ' + AND t.topic_id = p.topic_id + AND u.user_id = p.poster_id + ORDER BY ' . $sort_order_sql; + $result = $db->sql_query($sql); + + $post_data = $rowset = array(); + while ($row = $db->sql_fetchrow($result)) + { + if ($row['forum_id']) + { + $forum_names[] = $row['forum_id']; + } + $post_data[$row['post_id']] = $row; + } + $db->sql_freeresult($result); + + foreach ($post_ids as $post_id) + { + $rowset[] = $post_data[$post_id]; + } + unset($post_data, $post_ids); + } + else + { + $rowset = array(); + } + } + else + { + $sql = 'SELECT t.forum_id, t.topic_id, t.topic_title, t.topic_title AS post_subject, t.topic_time AS post_time, t.topic_poster AS poster_id, t.topic_first_post_id AS post_id, t.topic_first_poster_name AS username, t.topic_first_poster_colour AS user_colour + FROM ' . TOPICS_TABLE . " t + WHERE forum_id IN (0, $forum_list) + AND topic_approved = 0 + $limit_time_sql + ORDER BY $sort_order_sql"; + $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); + + $rowset = array(); + while ($row = $db->sql_fetchrow($result)) + { + if ($row['forum_id']) + { + $forum_names[] = $row['forum_id']; + } + $rowset[] = $row; + } + $db->sql_freeresult($result); + } + + if (sizeof($forum_names)) + { + // Select the names for the forum_ids + $sql = 'SELECT forum_id, forum_name + FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_names); + $result = $db->sql_query($sql, 3600); + + $forum_names = array(); + while ($row = $db->sql_fetchrow($result)) + { + $forum_names[$row['forum_id']] = $row['forum_name']; + } + $db->sql_freeresult($result); + } + + foreach ($rowset as $row) + { + $global_topic = ($row['forum_id']) ? false : true; + if ($global_topic) + { + $row['forum_id'] = $global_id; + } + + if (empty($row['post_username'])) + { + $row['post_username'] = $user->lang['GUEST']; + } + + $template->assign_block_vars('postrow', array( + 'U_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $row['forum_id'] . '&t=' . $row['topic_id']), + 'U_VIEWFORUM' => (!$global_topic) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id']) : '', + 'U_VIEWPOST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $row['forum_id'] . '&p=' . $row['post_id']) . (($mode == 'unapproved_posts') ? '#p' . $row['post_id'] : ''), + 'U_VIEW_DETAILS' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=queue&start=$start&mode=approve_details&f={$row['forum_id']}&p={$row['post_id']}" . (($mode == 'unapproved_topics') ? "&t={$row['topic_id']}" : '')), + + 'POST_AUTHOR_FULL' => get_username_string('full', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + 'POST_AUTHOR_COLOUR' => get_username_string('colour', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + 'POST_AUTHOR' => get_username_string('username', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + 'U_POST_AUTHOR' => get_username_string('profile', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + + 'POST_ID' => $row['post_id'], + 'FORUM_NAME' => (!$global_topic) ? $forum_names[$row['forum_id']] : $user->lang['GLOBAL_ANNOUNCEMENT'], + 'POST_SUBJECT' => $row['post_subject'], + 'TOPIC_TITLE' => $row['topic_title'], + 'POST_TIME' => $user->format_date($row['post_time'])) + ); + } + unset($rowset, $forum_names); + + // Now display the page + $template->assign_vars(array( + 'L_DISPLAY_ITEMS' => ($mode == 'unapproved_posts') ? $user->lang['DISPLAY_POSTS'] : $user->lang['DISPLAY_TOPICS'], + 'L_EXPLAIN' => ($mode == 'unapproved_posts') ? $user->lang['MCP_QUEUE_UNAPPROVED_POSTS_EXPLAIN'] : $user->lang['MCP_QUEUE_UNAPPROVED_TOPICS_EXPLAIN'], + 'L_TITLE' => ($mode == 'unapproved_posts') ? $user->lang['MCP_QUEUE_UNAPPROVED_POSTS'] : $user->lang['MCP_QUEUE_UNAPPROVED_TOPICS'], + 'L_ONLY_TOPIC' => ($topic_id) ? sprintf($user->lang['ONLY_TOPIC'], $topic_info['topic_title']) : '', + + 'S_FORUM_OPTIONS' => $forum_options, + 'S_MCP_ACTION' => build_url(array('t', 'f', 'sd', 'st', 'sk')), + 'S_TOPICS' => ($mode == 'unapproved_posts') ? false : true, + + 'PAGINATION' => generate_pagination($this->u_action . "&f=$forum_id&st=$sort_days&sk=$sort_key&sd=$sort_dir", $total, $config['topics_per_page'], $start), + 'PAGE_NUMBER' => on_page($total, $config['topics_per_page'], $start), + 'TOPIC_ID' => $topic_id, + 'TOTAL' => ($total == 1) ? (($mode == 'unapproved_posts') ? $user->lang['VIEW_TOPIC_POST'] : $user->lang['VIEW_FORUM_TOPIC']) : sprintf((($mode == 'unapproved_posts') ? $user->lang['VIEW_TOPIC_POSTS'] : $user->lang['VIEW_FORUM_TOPICS']), $total), + )); + + $this->tpl_name = 'mcp_queue'; + break; + } + } +} + +/** +* Approve Post/Topic +*/ +function approve_post($post_id_list, $id, $mode) +{ + global $db, $template, $user, $config; + global $phpEx, $phpbb_root_path; + + if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve'))) + { + trigger_error('NOT_AUTHORISED'); + } + + $redirect = request_var('redirect', build_url(array('quickmod'))); + $success_msg = ''; + + $s_hidden_fields = build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'post_id_list' => $post_id_list, + 'action' => 'approve', + 'redirect' => $redirect) + ); + + $post_info = get_post_data($post_id_list, 'm_approve'); + + if (confirm_box(true)) + { + $notify_poster = (isset($_REQUEST['notify_poster'])) ? true : false; + + // If Topic -> total_topics = total_topics+1, total_posts = total_posts+1, forum_topics = forum_topics+1, forum_posts = forum_posts+1 + // If Post -> total_posts = total_posts+1, forum_posts = forum_posts+1, topic_replies = topic_replies+1 + + $total_topics = $total_posts = 0; + $topic_approve_sql = $post_approve_sql = $topic_id_list = $forum_id_list = $approve_log = array(); + $user_posts_sql = $post_approved_list = array(); + + foreach ($post_info as $post_id => $post_data) + { + if ($post_data['post_approved']) + { + $post_approved_list[] = $post_id; + continue; + } + + $topic_id_list[$post_data['topic_id']] = 1; + + if ($post_data['forum_id']) + { + $forum_id_list[$post_data['forum_id']] = 1; + } + + // User post update (we do not care about topic or post, since user posts are strictly connected to posts) + // But we care about forums where post counts get not increased. ;) + if ($post_data['post_postcount']) + { + $user_posts_sql[$post_data['poster_id']] = (empty($user_posts_sql[$post_data['poster_id']])) ? 1 : $user_posts_sql[$post_data['poster_id']] + 1; + } + + // Topic or Post. ;) + if ($post_data['topic_first_post_id'] == $post_id) + { + if ($post_data['forum_id']) + { + $total_topics++; + } + $topic_approve_sql[] = $post_data['topic_id']; + + $approve_log[] = array( + 'type' => 'topic', + 'post_subject' => $post_data['post_subject'], + 'forum_id' => $post_data['forum_id'], + 'topic_id' => $post_data['topic_id'], + ); + } + else + { + $approve_log[] = array( + 'type' => 'post', + 'post_subject' => $post_data['post_subject'], + 'forum_id' => $post_data['forum_id'], + 'topic_id' => $post_data['topic_id'], + ); + } + + if ($post_data['forum_id']) + { + $total_posts++; + + // Increment by topic_replies if we approve a topic... + // This works because we do not adjust the topic_replies when re-approving a topic after an edit. + if ($post_data['topic_first_post_id'] == $post_id && $post_data['topic_replies']) + { + $total_posts += $post_data['topic_replies']; + } + } + + $post_approve_sql[] = $post_id; + } + + $post_id_list = array_values(array_diff($post_id_list, $post_approved_list)); + for ($i = 0, $size = sizeof($post_approved_list); $i < $size; $i++) + { + unset($post_info[$post_approved_list[$i]]); + } + + if (sizeof($topic_approve_sql)) + { + $sql = 'UPDATE ' . TOPICS_TABLE . ' + SET topic_approved = 1 + WHERE ' . $db->sql_in_set('topic_id', $topic_approve_sql); + $db->sql_query($sql); + } + + if (sizeof($post_approve_sql)) + { + $sql = 'UPDATE ' . POSTS_TABLE . ' + SET post_approved = 1 + WHERE ' . $db->sql_in_set('post_id', $post_approve_sql); + $db->sql_query($sql); + } + + unset($topic_approve_sql, $post_approve_sql); + + foreach ($approve_log as $log_data) + { + add_log('mod', $log_data['forum_id'], $log_data['topic_id'], ($log_data['type'] == 'topic') ? 'LOG_TOPIC_APPROVED' : 'LOG_POST_APPROVED', $log_data['post_subject']); + } + + if (sizeof($user_posts_sql)) + { + // Try to minimize the query count by merging users with the same post count additions + $user_posts_update = array(); + + foreach ($user_posts_sql as $user_id => $user_posts) + { + $user_posts_update[$user_posts][] = $user_id; + } + + foreach ($user_posts_update as $user_posts => $user_id_ary) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_posts = user_posts + ' . $user_posts . ' + WHERE ' . $db->sql_in_set('user_id', $user_id_ary); + $db->sql_query($sql); + } + } + + if ($total_topics) + { + set_config_count('num_topics', $total_topics, true); + } + + if ($total_posts) + { + set_config_count('num_posts', $total_posts, true); + } + + sync('topic', 'topic_id', array_keys($topic_id_list), true); + sync('forum', 'forum_id', array_keys($forum_id_list), true, true); + unset($topic_id_list, $forum_id_list); + + $messenger = new messenger(); + + // Notify Poster? + if ($notify_poster) + { + foreach ($post_info as $post_id => $post_data) + { + if ($post_data['poster_id'] == ANONYMOUS) + { + continue; + } + + $email_template = ($post_data['post_id'] == $post_data['topic_first_post_id'] && $post_data['post_id'] == $post_data['topic_last_post_id']) ? 'topic_approved' : 'post_approved'; + + $messenger->template($email_template, $post_data['user_lang']); + + $messenger->to($post_data['user_email'], $post_data['username']); + $messenger->im($post_data['user_jabber'], $post_data['username']); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($post_data['username']), + 'POST_SUBJECT' => htmlspecialchars_decode(censor_text($post_data['post_subject'])), + 'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($post_data['topic_title'])), + + 'U_VIEW_TOPIC' => generate_board_url() . "/viewtopic.$phpEx?f={$post_data['forum_id']}&t={$post_data['topic_id']}&e=0", + 'U_VIEW_POST' => generate_board_url() . "/viewtopic.$phpEx?f={$post_data['forum_id']}&t={$post_data['topic_id']}&p=$post_id&e=$post_id") + ); + + $messenger->send($post_data['user_notify_type']); + } + } + + $messenger->save_queue(); + + // Send out normal user notifications + $email_sig = str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']); + + foreach ($post_info as $post_id => $post_data) + { + if ($post_id == $post_data['topic_first_post_id'] && $post_id == $post_data['topic_last_post_id']) + { + // Forum Notifications + user_notification('post', $post_data['topic_title'], $post_data['topic_title'], $post_data['forum_name'], $post_data['forum_id'], $post_data['topic_id'], $post_id); + } + else + { + // Topic Notifications + user_notification('reply', $post_data['post_subject'], $post_data['topic_title'], $post_data['forum_name'], $post_data['forum_id'], $post_data['topic_id'], $post_id); + } + } + + if (sizeof($post_id_list) == 1) + { + $post_data = $post_info[$post_id_list[0]]; + $post_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f={$post_data['forum_id']}&t={$post_data['topic_id']}&p={$post_data['post_id']}") . '#p' . $post_data['post_id']; + } + unset($post_info); + + if ($total_topics) + { + $success_msg = ($total_topics == 1) ? 'TOPIC_APPROVED_SUCCESS' : 'TOPICS_APPROVED_SUCCESS'; + } + else + { + $success_msg = (sizeof($post_id_list) + sizeof($post_approved_list) == 1) ? 'POST_APPROVED_SUCCESS' : 'POSTS_APPROVED_SUCCESS'; + } + } + else + { + $show_notify = false; + + foreach ($post_info as $post_data) + { + if ($post_data['poster_id'] == ANONYMOUS) + { + continue; + } + else + { + $show_notify = true; + break; + } + } + + $template->assign_vars(array( + 'S_NOTIFY_POSTER' => $show_notify, + 'S_APPROVE' => true) + ); + + confirm_box(false, 'APPROVE_POST' . ((sizeof($post_id_list) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_approve.html'); + } + + $redirect = request_var('redirect', "index.$phpEx"); + $redirect = reapply_sid($redirect); + + if (!$success_msg) + { + redirect($redirect); + } + else + { + meta_refresh(3, $redirect); + + // If approving one post, also give links back to post... + $add_message = ''; + if (sizeof($post_id_list) == 1 && !empty($post_url)) + { + $add_message = '<br /><br />' . sprintf($user->lang['RETURN_POST'], '<a href="' . $post_url . '">', '</a>'); + } + + trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], "<a href=\"$redirect\">", '</a>') . $add_message); + } +} + +/** +* Disapprove Post/Topic +*/ +function disapprove_post($post_id_list, $id, $mode) +{ + global $db, $template, $user, $config; + global $phpEx, $phpbb_root_path; + + if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve'))) + { + trigger_error('NOT_AUTHORISED'); + } + + $redirect = request_var('redirect', build_url(array('t', 'mode', 'quickmod')) . "&mode=$mode"); + $reason = utf8_normalize_nfc(request_var('reason', '', true)); + $reason_id = request_var('reason_id', 0); + $success_msg = $additional_msg = ''; + + $s_hidden_fields = build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'post_id_list' => $post_id_list, + 'action' => 'disapprove', + 'redirect' => $redirect) + ); + + $notify_poster = (isset($_REQUEST['notify_poster'])) ? true : false; + $disapprove_reason = ''; + + if ($reason_id) + { + $sql = 'SELECT reason_title, reason_description + FROM ' . REPORTS_REASONS_TABLE . " + WHERE reason_id = $reason_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row || (!$reason && strtolower($row['reason_title']) == 'other')) + { + $additional_msg = $user->lang['NO_REASON_DISAPPROVAL']; + unset($_POST['confirm']); + } + else + { + // If the reason is defined within the language file, we will use the localized version, else just use the database entry... + $disapprove_reason = (strtolower($row['reason_title']) != 'other') ? ((isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])])) ? $user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])] : $row['reason_description']) : ''; + $disapprove_reason .= ($reason) ? "\n\n" . $reason : ''; + + if (isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])])) + { + $disapprove_reason_lang = strtoupper($row['reason_title']); + } + + $email_disapprove_reason = $disapprove_reason; + } + } + + $post_info = get_post_data($post_id_list, 'm_approve'); + + if (confirm_box(true)) + { + $disapprove_log = $disapprove_log_topics = $disapprove_log_posts = array(); + $topic_replies_real = $post_disapprove_list = array(); + + // Build a list of posts to be unapproved and get the related topics real replies count + foreach ($post_info as $post_id => $post_data) + { + $post_disapprove_list[$post_id] = $post_data['topic_id']; + if (!isset($topic_replies_real[$post_data['topic_id']])) + { + $topic_replies_real[$post_data['topic_id']] = $post_data['topic_replies_real']; + } + } + + // Now we build the log array + foreach ($post_disapprove_list as $post_id => $topic_id) + { + // If the count of disapproved posts for the topic is greater + // than topic's real replies count, the whole topic is disapproved/deleted + if (sizeof(array_keys($post_disapprove_list, $topic_id)) > $topic_replies_real[$topic_id]) + { + // Don't write the log more than once for every topic + if (!isset($disapprove_log_topics[$topic_id])) + { + // Build disapproved topics log + $disapprove_log_topics[$topic_id] = array( + 'type' => 'topic', + 'post_subject' => $post_info[$post_id]['topic_title'], + 'forum_id' => $post_info[$post_id]['forum_id'], + 'topic_id' => 0, // useless to log a topic id, as it will be deleted + ); + } + } + else + { + // Build disapproved posts log + $disapprove_log_posts[] = array( + 'type' => 'post', + 'post_subject' => $post_info[$post_id]['post_subject'], + 'forum_id' => $post_info[$post_id]['forum_id'], + 'topic_id' => $post_info[$post_id]['topic_id'], + ); + + } + } + + // Get disapproved posts/topics counts separately + $num_disapproved_topics = sizeof($disapprove_log_topics); + $num_disapproved_posts = sizeof($disapprove_log_posts); + + // Build the whole log + $disapprove_log = array_merge($disapprove_log_topics, $disapprove_log_posts); + + // Unset unneeded arrays + unset($post_data, $disapprove_log_topics, $disapprove_log_posts); + + // Let's do the job - delete disapproved posts + if (sizeof($post_disapprove_list)) + { + if (!function_exists('delete_posts')) + { + include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx); + } + + // We do not check for permissions here, because the moderator allowed approval/disapproval should be allowed to delete the disapproved posts + // Note: function delete_posts triggers related forums/topics sync, + // so we don't need to call update_post_information later and to adjust real topic replies or forum topics count manually + delete_posts('post_id', array_keys($post_disapprove_list)); + + foreach ($disapprove_log as $log_data) + { + add_log('mod', $log_data['forum_id'], $log_data['topic_id'], ($log_data['type'] == 'topic') ? 'LOG_TOPIC_DISAPPROVED' : 'LOG_POST_DISAPPROVED', $log_data['post_subject'], $disapprove_reason); + } + } + + $messenger = new messenger(); + + // Notify Poster? + if ($notify_poster) + { + $lang_reasons = array(); + + foreach ($post_info as $post_id => $post_data) + { + if ($post_data['poster_id'] == ANONYMOUS) + { + continue; + } + + if (isset($disapprove_reason_lang)) + { + // Okay we need to get the reason from the posters language + if (!isset($lang_reasons[$post_data['user_lang']])) + { + // Assign the current users translation as the default, this is not ideal but getting the board default adds another layer of complexity. + $lang_reasons[$post_data['user_lang']] = $user->lang['report_reasons']['DESCRIPTION'][$disapprove_reason_lang]; + + // Only load up the language pack if the language is different to the current one + if ($post_data['user_lang'] != $user->lang_name && file_exists($phpbb_root_path . '/language/' . $post_data['user_lang'] . '/mcp.' . $phpEx)) + { + // Load up the language pack + $lang = array(); + @include($phpbb_root_path . '/language/' . basename($post_data['user_lang']) . '/mcp.' . $phpEx); + + // If we find the reason in this language pack use it + if (isset($lang['report_reasons']['DESCRIPTION'][$disapprove_reason_lang])) + { + $lang_reasons[$post_data['user_lang']] = $lang['report_reasons']['DESCRIPTION'][$disapprove_reason_lang]; + } + + unset($lang); // Free memory + } + } + + $email_disapprove_reason = $lang_reasons[$post_data['user_lang']]; + $email_disapprove_reason .= ($reason) ? "\n\n" . $reason : ''; + } + + $email_template = ($post_data['post_id'] == $post_data['topic_first_post_id'] && $post_data['post_id'] == $post_data['topic_last_post_id']) ? 'topic_disapproved' : 'post_disapproved'; + + $messenger->template($email_template, $post_data['user_lang']); + + $messenger->to($post_data['user_email'], $post_data['username']); + $messenger->im($post_data['user_jabber'], $post_data['username']); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($post_data['username']), + 'REASON' => htmlspecialchars_decode($email_disapprove_reason), + 'POST_SUBJECT' => htmlspecialchars_decode(censor_text($post_data['post_subject'])), + 'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($post_data['topic_title']))) + ); + + $messenger->send($post_data['user_notify_type']); + } + + unset($lang_reasons); + } + unset($post_info, $disapprove_reason, $email_disapprove_reason, $disapprove_reason_lang); + + $messenger->save_queue(); + + if ($num_disapproved_topics) + { + $success_msg = ($num_disapproved_topics == 1) ? 'TOPIC_DISAPPROVED_SUCCESS' : 'TOPICS_DISAPPROVED_SUCCESS'; + } + else + { + $success_msg = ($num_disapproved_posts == 1) ? 'POST_DISAPPROVED_SUCCESS' : 'POSTS_DISAPPROVED_SUCCESS'; + } + } + else + { + include_once($phpbb_root_path . 'includes/functions_display.' . $phpEx); + + display_reasons($reason_id); + + $show_notify = false; + + foreach ($post_info as $post_data) + { + if ($post_data['poster_id'] == ANONYMOUS) + { + continue; + } + else + { + $show_notify = true; + break; + } + } + + $template->assign_vars(array( + 'S_NOTIFY_POSTER' => $show_notify, + 'S_APPROVE' => false, + 'REASON' => $reason, + 'ADDITIONAL_MSG' => $additional_msg) + ); + + confirm_box(false, 'DISAPPROVE_POST' . ((sizeof($post_id_list) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_approve.html'); + } + + $redirect = request_var('redirect', "index.$phpEx"); + $redirect = reapply_sid($redirect); + + if (!$success_msg) + { + redirect($redirect); + } + else + { + meta_refresh(3, $redirect); + trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], "<a href=\"$redirect\">", '</a>')); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/mcp/mcp_reports.php b/phpBB/includes/mcp/mcp_reports.php new file mode 100644 index 0000000000..7bed20187a --- /dev/null +++ b/phpBB/includes/mcp/mcp_reports.php @@ -0,0 +1,726 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* mcp_reports +* Handling the reports queue +* @package mcp +*/ +class mcp_reports +{ + var $p_master; + var $u_action; + + function mcp_reports(&$p_master) + { + $this->p_master = &$p_master; + } + + function main($id, $mode) + { + global $auth, $db, $user, $template, $cache; + global $config, $phpbb_root_path, $phpEx, $action; + + include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); + + $forum_id = request_var('f', 0); + $start = request_var('start', 0); + + $this->page_title = 'MCP_REPORTS'; + + switch ($action) + { + case 'close': + case 'delete': + include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + + $report_id_list = request_var('report_id_list', array(0)); + + if (!sizeof($report_id_list)) + { + trigger_error('NO_REPORT_SELECTED'); + } + + close_report($report_id_list, $mode, $action); + + break; + } + + switch ($mode) + { + case 'report_details': + + $user->add_lang(array('posting', 'viewforum', 'viewtopic')); + + $post_id = request_var('p', 0); + + // closed reports are accessed by report id + $report_id = request_var('r', 0); + + $sql = 'SELECT r.post_id, r.user_id, r.report_id, r.report_closed, report_time, r.report_text, rr.reason_title, rr.reason_description, u.username, u.username_clean, u.user_colour + FROM ' . REPORTS_TABLE . ' r, ' . REPORTS_REASONS_TABLE . ' rr, ' . USERS_TABLE . ' u + WHERE ' . (($report_id) ? 'r.report_id = ' . $report_id : "r.post_id = $post_id") . ' + AND rr.reason_id = r.reason_id + AND r.user_id = u.user_id + AND r.pm_id = 0 + ORDER BY report_closed ASC'; + $result = $db->sql_query_limit($sql, 1); + $report = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$report) + { + trigger_error('NO_REPORT'); + } + + if (!$report_id && $report['report_closed']) + { + trigger_error('REPORT_CLOSED'); + } + + $post_id = $report['post_id']; + $report_id = $report['report_id']; + + $post_info = get_post_data(array($post_id), 'm_report', true); + + if (!sizeof($post_info)) + { + trigger_error('NO_REPORT_SELECTED'); + } + + $post_info = $post_info[$post_id]; + + $reason = array('title' => $report['reason_title'], 'description' => $report['reason_description']); + if (isset($user->lang['report_reasons']['TITLE'][strtoupper($reason['title'])]) && isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($reason['title'])])) + { + $reason['description'] = $user->lang['report_reasons']['DESCRIPTION'][strtoupper($reason['title'])]; + $reason['title'] = $user->lang['report_reasons']['TITLE'][strtoupper($reason['title'])]; + } + + if (topic_review($post_info['topic_id'], $post_info['forum_id'], 'topic_review', 0, false)) + { + $template->assign_vars(array( + 'S_TOPIC_REVIEW' => true, + 'TOPIC_TITLE' => $post_info['topic_title']) + ); + } + + $topic_tracking_info = $extensions = $attachments = array(); + // Get topic tracking info + if ($config['load_db_lastread']) + { + $tmp_topic_data = array($post_info['topic_id'] => $post_info); + $topic_tracking_info = get_topic_tracking($post_info['forum_id'], $post_info['topic_id'], $tmp_topic_data, array($post_info['forum_id'] => $post_info['forum_mark_time'])); + unset($tmp_topic_data); + } + else + { + $topic_tracking_info = get_complete_topic_tracking($post_info['forum_id'], $post_info['topic_id']); + } + + $post_unread = (isset($topic_tracking_info[$post_info['topic_id']]) && $post_info['post_time'] > $topic_tracking_info[$post_info['topic_id']]) ? true : false; + + // Process message, leave it uncensored + $message = $post_info['post_text']; + + if ($post_info['bbcode_bitfield']) + { + include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx); + $bbcode = new bbcode($post_info['bbcode_bitfield']); + $bbcode->bbcode_second_pass($message, $post_info['bbcode_uid'], $post_info['bbcode_bitfield']); + } + + $message = bbcode_nl2br($message); + $message = smiley_text($message); + + if ($post_info['post_attachment'] && $auth->acl_get('u_download') && $auth->acl_get('f_download', $post_info['forum_id'])) + { + $sql = 'SELECT * + FROM ' . ATTACHMENTS_TABLE . ' + WHERE post_msg_id = ' . $post_id . ' + AND in_message = 0 + ORDER BY filetime DESC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $attachments[] = $row; + } + $db->sql_freeresult($result); + + if (sizeof($attachments)) + { + $update_count = array(); + parse_attachments($post_info['forum_id'], $message, $attachments, $update_count); + } + + // Display not already displayed Attachments for this post, we already parsed them. ;) + if (!empty($attachments)) + { + $template->assign_var('S_HAS_ATTACHMENTS', true); + + foreach ($attachments as $attachment) + { + $template->assign_block_vars('attachment', array( + 'DISPLAY_ATTACHMENT' => $attachment) + ); + } + } + } + + $template->assign_vars(array( + 'S_MCP_REPORT' => true, + 'S_CLOSE_ACTION' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&mode=report_details&f=' . $post_info['forum_id'] . '&p=' . $post_id), + 'S_CAN_VIEWIP' => $auth->acl_get('m_info', $post_info['forum_id']), + 'S_POST_REPORTED' => $post_info['post_reported'], + 'S_POST_UNAPPROVED' => !$post_info['post_approved'], + 'S_POST_LOCKED' => $post_info['post_edit_locked'], + 'S_USER_NOTES' => true, + + 'U_EDIT' => ($auth->acl_get('m_edit', $post_info['forum_id'])) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=edit&f={$post_info['forum_id']}&p={$post_info['post_id']}") : '', + 'U_MCP_APPROVE' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&mode=approve_details&f=' . $post_info['forum_id'] . '&p=' . $post_id), + 'U_MCP_REPORT' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&mode=report_details&f=' . $post_info['forum_id'] . '&p=' . $post_id), + 'U_MCP_REPORTER_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&mode=user_notes&u=' . $report['user_id']), + 'U_MCP_USER_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&mode=user_notes&u=' . $post_info['user_id']), + 'U_MCP_WARN_REPORTER' => ($auth->acl_get('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&mode=warn_user&u=' . $report['user_id']) : '', + 'U_MCP_WARN_USER' => ($auth->acl_get('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&mode=warn_user&u=' . $post_info['user_id']) : '', + 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $post_info['forum_id']), + 'U_VIEW_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&p=' . $post_info['post_id'] . '#p' . $post_info['post_id']), + 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&t=' . $post_info['topic_id']), + + 'EDIT_IMG' => $user->img('icon_post_edit', $user->lang['EDIT_POST']), + 'MINI_POST_IMG' => ($post_unread) ? $user->img('icon_post_target_unread', 'NEW_POST') : $user->img('icon_post_target', 'POST'), + 'UNAPPROVED_IMG' => $user->img('icon_topic_unapproved', $user->lang['POST_UNAPPROVED']), + + 'RETURN_REPORTS' => sprintf($user->lang['RETURN_REPORTS'], '<a href="' . append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports' . (($post_info['post_reported']) ? '&mode=reports' : '&mode=reports_closed') . '&start=' . $start . '&f=' . $post_info['forum_id']) . '">', '</a>'), + 'REPORTED_IMG' => $user->img('icon_topic_reported', $user->lang['POST_REPORTED']), + 'REPORT_DATE' => $user->format_date($report['report_time']), + 'REPORT_ID' => $report_id, + 'REPORT_REASON_TITLE' => $reason['title'], + 'REPORT_REASON_DESCRIPTION' => $reason['description'], + 'REPORT_TEXT' => $report['report_text'], + + 'POST_AUTHOR_FULL' => get_username_string('full', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + 'POST_AUTHOR_COLOUR' => get_username_string('colour', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + 'POST_AUTHOR' => get_username_string('username', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + 'U_POST_AUTHOR' => get_username_string('profile', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + + 'REPORTER_FULL' => get_username_string('full', $report['user_id'], $report['username'], $report['user_colour']), + 'REPORTER_COLOUR' => get_username_string('colour', $report['user_id'], $report['username'], $report['user_colour']), + 'REPORTER_NAME' => get_username_string('username', $report['user_id'], $report['username'], $report['user_colour']), + 'U_VIEW_REPORTER_PROFILE' => get_username_string('profile', $report['user_id'], $report['username'], $report['user_colour']), + + 'POST_PREVIEW' => $message, + 'POST_SUBJECT' => ($post_info['post_subject']) ? $post_info['post_subject'] : $user->lang['NO_SUBJECT'], + 'POST_DATE' => $user->format_date($post_info['post_time']), + 'POST_IP' => $post_info['poster_ip'], + 'POST_IPADDR' => ($auth->acl_get('m_info', $post_info['forum_id']) && request_var('lookup', '')) ? @gethostbyaddr($post_info['poster_ip']) : '', + 'POST_ID' => $post_info['post_id'], + + 'U_LOOKUP_IP' => ($auth->acl_get('m_info', $post_info['forum_id'])) ? $this->u_action . '&r=' . $report_id . '&p=' . $post_id . '&f=' . $forum_id . '&lookup=' . $post_info['poster_ip'] . '#ip' : '', + )); + + $this->tpl_name = 'mcp_post'; + + break; + + case 'reports': + case 'reports_closed': + $topic_id = request_var('t', 0); + + $forum_info = array(); + $forum_list_reports = get_forum_list('m_report', false, true); + $forum_list_read = array_flip(get_forum_list('f_read', true, true)); // Flipped so we can isset() the forum IDs + + // Remove forums we cannot read + foreach ($forum_list_reports as $k => $forum_data) + { + if (!isset($forum_list_read[$forum_data['forum_id']])) + { + unset($forum_list_reports[$k]); + } + } + unset($forum_list_read); + + if ($topic_id) + { + $topic_info = get_topic_data(array($topic_id)); + + if (!sizeof($topic_info)) + { + trigger_error('TOPIC_NOT_EXIST'); + } + + if ($forum_id != $topic_info[$topic_id]['forum_id']) + { + $topic_id = 0; + } + else + { + $topic_info = $topic_info[$topic_id]; + $forum_id = (int) $topic_info['forum_id']; + } + } + + $forum_list = array(); + + if (!$forum_id) + { + foreach ($forum_list_reports as $row) + { + $forum_list[] = $row['forum_id']; + } + + if (!sizeof($forum_list)) + { + trigger_error('NOT_MODERATOR'); + } + + $global_id = $forum_list[0]; + + $sql = 'SELECT SUM(forum_topics) as sum_forum_topics + FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_list); + $result = $db->sql_query($sql); + $forum_info['forum_topics'] = (int) $db->sql_fetchfield('sum_forum_topics'); + $db->sql_freeresult($result); + } + else + { + $forum_info = get_forum_data(array($forum_id), 'm_report'); + + if (!sizeof($forum_info)) + { + trigger_error('NOT_MODERATOR'); + } + + $forum_info = $forum_info[$forum_id]; + $forum_list = array($forum_id); + $global_id = $forum_id; + } + + $forum_list[] = 0; + $forum_data = array(); + + $forum_options = '<option value="0"' . (($forum_id == 0) ? ' selected="selected"' : '') . '>' . $user->lang['ALL_FORUMS'] . '</option>'; + foreach ($forum_list_reports as $row) + { + $forum_options .= '<option value="' . $row['forum_id'] . '"' . (($forum_id == $row['forum_id']) ? ' selected="selected"' : '') . '>' . str_repeat(' ', $row['padding']) . $row['forum_name'] . '</option>'; + $forum_data[$row['forum_id']] = $row; + } + unset($forum_list_reports); + + $sort_days = $total = 0; + $sort_key = $sort_dir = ''; + $sort_by_sql = $sort_order_sql = array(); + mcp_sorting($mode, $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id, $topic_id); + + $forum_topics = ($total == -1) ? $forum_info['forum_topics'] : $total; + $limit_time_sql = ($sort_days) ? 'AND r.report_time >= ' . (time() - ($sort_days * 86400)) : ''; + + if ($mode == 'reports') + { + $report_state = 'AND p.post_reported = 1 AND r.report_closed = 0'; + } + else + { + $report_state = 'AND r.report_closed = 1'; + } + + $sql = 'SELECT r.report_id + FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t, ' . REPORTS_TABLE . ' r ' . (($sort_order_sql[0] == 'u') ? ', ' . USERS_TABLE . ' u' : '') . (($sort_order_sql[0] == 'r') ? ', ' . USERS_TABLE . ' ru' : '') . ' + WHERE ' . $db->sql_in_set('p.forum_id', $forum_list) . " + $report_state + AND r.post_id = p.post_id + " . (($sort_order_sql[0] == 'u') ? 'AND u.user_id = p.poster_id' : '') . ' + ' . (($sort_order_sql[0] == 'r') ? 'AND ru.user_id = r.user_id' : '') . ' + ' . (($topic_id) ? 'AND p.topic_id = ' . $topic_id : '') . " + AND t.topic_id = p.topic_id + AND r.pm_id = 0 + $limit_time_sql + ORDER BY $sort_order_sql"; + $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); + + $i = 0; + $report_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $report_ids[] = $row['report_id']; + $row_num[$row['report_id']] = $i++; + } + $db->sql_freeresult($result); + + if (sizeof($report_ids)) + { + $sql = 'SELECT t.forum_id, t.topic_id, t.topic_title, p.post_id, p.post_subject, p.post_username, p.poster_id, p.post_time, u.username, u.username_clean, u.user_colour, r.user_id as reporter_id, ru.username as reporter_name, ru.user_colour as reporter_colour, r.report_time, r.report_id + FROM ' . REPORTS_TABLE . ' r, ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t, ' . USERS_TABLE . ' u, ' . USERS_TABLE . ' ru + WHERE ' . $db->sql_in_set('r.report_id', $report_ids) . ' + AND t.topic_id = p.topic_id + AND r.post_id = p.post_id + AND u.user_id = p.poster_id + AND ru.user_id = r.user_id + AND r.pm_id = 0 + ORDER BY ' . $sort_order_sql; + $result = $db->sql_query($sql); + + $report_data = $rowset = array(); + while ($row = $db->sql_fetchrow($result)) + { + $global_topic = ($row['forum_id']) ? false : true; + if ($global_topic) + { + $row['forum_id'] = $global_id; + } + + $template->assign_block_vars('postrow', array( + 'U_VIEWFORUM' => (!$global_topic) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id']) : '', + 'U_VIEWPOST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $row['forum_id'] . '&p=' . $row['post_id']) . '#p' . $row['post_id'], + 'U_VIEW_DETAILS' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=reports&start=$start&mode=report_details&f={$row['forum_id']}&r={$row['report_id']}"), + + 'POST_AUTHOR_FULL' => get_username_string('full', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + 'POST_AUTHOR_COLOUR' => get_username_string('colour', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + 'POST_AUTHOR' => get_username_string('username', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + 'U_POST_AUTHOR' => get_username_string('profile', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + + 'REPORTER_FULL' => get_username_string('full', $row['reporter_id'], $row['reporter_name'], $row['reporter_colour']), + 'REPORTER_COLOUR' => get_username_string('colour', $row['reporter_id'], $row['reporter_name'], $row['reporter_colour']), + 'REPORTER' => get_username_string('username', $row['reporter_id'], $row['reporter_name'], $row['reporter_colour']), + 'U_REPORTER' => get_username_string('profile', $row['reporter_id'], $row['reporter_name'], $row['reporter_colour']), + + 'FORUM_NAME' => (!$global_topic) ? $forum_data[$row['forum_id']]['forum_name'] : $user->lang['GLOBAL_ANNOUNCEMENT'], + 'POST_ID' => $row['post_id'], + 'POST_SUBJECT' => ($row['post_subject']) ? $row['post_subject'] : $user->lang['NO_SUBJECT'], + 'POST_TIME' => $user->format_date($row['post_time']), + 'REPORT_ID' => $row['report_id'], + 'REPORT_TIME' => $user->format_date($row['report_time']), + 'TOPIC_TITLE' => $row['topic_title']) + ); + } + $db->sql_freeresult($result); + unset($report_ids, $row); + } + + // Now display the page + $template->assign_vars(array( + 'L_EXPLAIN' => ($mode == 'reports') ? $user->lang['MCP_REPORTS_OPEN_EXPLAIN'] : $user->lang['MCP_REPORTS_CLOSED_EXPLAIN'], + 'L_TITLE' => ($mode == 'reports') ? $user->lang['MCP_REPORTS_OPEN'] : $user->lang['MCP_REPORTS_CLOSED'], + 'L_ONLY_TOPIC' => ($topic_id) ? sprintf($user->lang['ONLY_TOPIC'], $topic_info['topic_title']) : '', + + 'S_MCP_ACTION' => $this->u_action, + 'S_FORUM_OPTIONS' => $forum_options, + 'S_CLOSED' => ($mode == 'reports_closed') ? true : false, + + 'PAGINATION' => generate_pagination($this->u_action . "&f=$forum_id&t=$topic_id&st=$sort_days&sk=$sort_key&sd=$sort_dir", $total, $config['topics_per_page'], $start), + 'PAGE_NUMBER' => on_page($total, $config['topics_per_page'], $start), + 'TOPIC_ID' => $topic_id, + 'TOTAL' => $total, + 'TOTAL_REPORTS' => ($total == 1) ? $user->lang['LIST_REPORT'] : sprintf($user->lang['LIST_REPORTS'], $total), + ) + ); + + $this->tpl_name = 'mcp_reports'; + break; + } + } +} + +/** +* Closes a report +*/ +function close_report($report_id_list, $mode, $action, $pm = false) +{ + global $db, $template, $user, $config, $auth; + global $phpEx, $phpbb_root_path; + + $pm_where = ($pm) ? ' AND r.post_id = 0 ' : ' AND r.pm_id = 0 '; + $id_column = ($pm) ? 'pm_id' : 'post_id'; + $module = ($pm) ? 'pm_reports' : 'reports'; + $pm_prefix = ($pm) ? 'PM_' : ''; + + $sql = "SELECT r.$id_column + FROM " . REPORTS_TABLE . ' r + WHERE ' . $db->sql_in_set('r.report_id', $report_id_list) . $pm_where; + $result = $db->sql_query($sql); + + $post_id_list = array(); + while ($row = $db->sql_fetchrow($result)) + { + $post_id_list[] = $row[$id_column]; + } + $post_id_list = array_unique($post_id_list); + + if ($pm) + { + if (!$auth->acl_getf_global('m_report')) + { + trigger_error('NOT_AUTHORISED'); + } + } + else + { + if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_report'))) + { + trigger_error('NOT_AUTHORISED'); + } + } + + if ($action == 'delete' && strpos($user->data['session_page'], 'mode=report_details') !== false) + { + $redirect = request_var('redirect', build_url(array('mode', 'r', 'quickmod')) . '&mode=reports'); + } + elseif ($action == 'delete' && strpos($user->data['session_page'], 'mode=pm_report_details') !== false) + { + $redirect = request_var('redirect', build_url(array('mode', 'r', 'quickmod')) . '&mode=pm_reports'); + } + else if ($action == 'close' && !request_var('r', 0)) + { + $redirect = request_var('redirect', build_url(array('mode', 'p', 'quickmod')) . '&mode=' . $module); + } + else + { + $redirect = request_var('redirect', build_url(array('quickmod'))); + } + $success_msg = ''; + $forum_ids = array(); + $topic_ids = array(); + + $s_hidden_fields = build_hidden_fields(array( + 'i' => $module, + 'mode' => $mode, + 'report_id_list' => $report_id_list, + 'action' => $action, + 'redirect' => $redirect) + ); + + if (confirm_box(true)) + { + $post_info = ($pm) ? get_pm_data($post_id_list) : get_post_data($post_id_list, 'm_report'); + + $sql = "SELECT r.report_id, r.$id_column, r.report_closed, r.user_id, r.user_notify, u.username, u.username_clean, u.user_email, u.user_jabber, u.user_lang, u.user_notify_type + FROM " . REPORTS_TABLE . ' r, ' . USERS_TABLE . ' u + WHERE ' . $db->sql_in_set('r.report_id', $report_id_list) . ' + ' . (($action == 'close') ? 'AND r.report_closed = 0' : '') . ' + AND r.user_id = u.user_id' . $pm_where; + $result = $db->sql_query($sql); + + $reports = $close_report_posts = $close_report_topics = $notify_reporters = $report_id_list = array(); + while ($report = $db->sql_fetchrow($result)) + { + $reports[$report['report_id']] = $report; + $report_id_list[] = $report['report_id']; + + if (!$report['report_closed']) + { + $close_report_posts[] = $report[$id_column]; + + if (!$pm) + { + $close_report_topics[] = $post_info[$report['post_id']]['topic_id']; + } + } + + if ($report['user_notify'] && !$report['report_closed']) + { + $notify_reporters[$report['report_id']] = &$reports[$report['report_id']]; + } + } + $db->sql_freeresult($result); + + if (sizeof($reports)) + { + $close_report_posts = array_unique($close_report_posts); + $close_report_topics = array_unique($close_report_topics); + + if (!$pm && sizeof($close_report_posts)) + { + // Get a list of topics that still contain reported posts + $sql = 'SELECT DISTINCT topic_id + FROM ' . POSTS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', $close_report_topics) . ' + AND post_reported = 1 + AND ' . $db->sql_in_set('post_id', $close_report_posts, true); + $result = $db->sql_query($sql); + + $keep_report_topics = array(); + while ($row = $db->sql_fetchrow($result)) + { + $keep_report_topics[] = $row['topic_id']; + } + $db->sql_freeresult($result); + + $close_report_topics = array_diff($close_report_topics, $keep_report_topics); + unset($keep_report_topics); + } + + $db->sql_transaction('begin'); + + if ($action == 'close') + { + $sql = 'UPDATE ' . REPORTS_TABLE . ' + SET report_closed = 1 + WHERE ' . $db->sql_in_set('report_id', $report_id_list); + } + else + { + $sql = 'DELETE FROM ' . REPORTS_TABLE . ' + WHERE ' . $db->sql_in_set('report_id', $report_id_list); + } + $db->sql_query($sql); + + + if (sizeof($close_report_posts)) + { + if ($pm) + { + $sql = 'UPDATE ' . PRIVMSGS_TABLE . ' + SET message_reported = 0 + WHERE ' . $db->sql_in_set('msg_id', $close_report_posts); + $db->sql_query($sql); + + if ($action == 'delete') + { + delete_pm(ANONYMOUS, $close_report_posts, PRIVMSGS_INBOX); + } + } + else + { + $sql = 'UPDATE ' . POSTS_TABLE . ' + SET post_reported = 0 + WHERE ' . $db->sql_in_set('post_id', $close_report_posts); + $db->sql_query($sql); + + if (sizeof($close_report_topics)) + { + $sql = 'UPDATE ' . TOPICS_TABLE . ' + SET topic_reported = 0 + WHERE ' . $db->sql_in_set('topic_id', $close_report_topics) . ' + OR ' . $db->sql_in_set('topic_moved_id', $close_report_topics); + $db->sql_query($sql); + } + } + } + + $db->sql_transaction('commit'); + } + unset($close_report_posts, $close_report_topics); + + foreach ($reports as $report) + { + if ($pm) + { + add_log('mod', 0, 0, 'LOG_PM_REPORT_' . strtoupper($action) . 'D', $post_info[$report['pm_id']]['message_subject']); + } + else + { + add_log('mod', $post_info[$report['post_id']]['forum_id'], $post_info[$report['post_id']]['topic_id'], 'LOG_REPORT_' . strtoupper($action) . 'D', $post_info[$report['post_id']]['post_subject']); + } + } + + $messenger = new messenger(); + + // Notify reporters + if (sizeof($notify_reporters)) + { + foreach ($notify_reporters as $report_id => $reporter) + { + if ($reporter['user_id'] == ANONYMOUS) + { + continue; + } + + $post_id = $reporter[$id_column]; + + $messenger->template((($pm) ? 'pm_report_' : 'report_') . $action . 'd', $reporter['user_lang']); + + $messenger->to($reporter['user_email'], $reporter['username']); + $messenger->im($reporter['user_jabber'], $reporter['username']); + + if ($pm) + { + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($reporter['username']), + 'CLOSER_NAME' => htmlspecialchars_decode($user->data['username']), + 'PM_SUBJECT' => htmlspecialchars_decode(censor_text($post_info[$post_id]['message_subject'])), + )); + } + else + { + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($reporter['username']), + 'CLOSER_NAME' => htmlspecialchars_decode($user->data['username']), + 'POST_SUBJECT' => htmlspecialchars_decode(censor_text($post_info[$post_id]['post_subject'])), + 'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($post_info[$post_id]['topic_title']))) + ); + } + + $messenger->send($reporter['user_notify_type']); + } + } + + if (!$pm) + { + foreach ($post_info as $post) + { + $forum_ids[$post['forum_id']] = $post['forum_id']; + $topic_ids[$post['topic_id']] = $post['topic_id']; + } + } + + unset($notify_reporters, $post_info, $reports); + + $messenger->save_queue(); + + $success_msg = (sizeof($report_id_list) == 1) ? "{$pm_prefix}REPORT_" . strtoupper($action) . 'D_SUCCESS' : "{$pm_prefix}REPORTS_" . strtoupper($action) . 'D_SUCCESS'; + } + else + { + confirm_box(false, $user->lang[strtoupper($action) . "_{$pm_prefix}REPORT" . ((sizeof($report_id_list) == 1) ? '' : 'S') . '_CONFIRM'], $s_hidden_fields); + } + + $redirect = request_var('redirect', "index.$phpEx"); + $redirect = reapply_sid($redirect); + + if (!$success_msg) + { + redirect($redirect); + } + else + { + meta_refresh(3, $redirect); + + $return_forum = ''; + $return_topic = ''; + + if (!$pm) + { + if (sizeof($forum_ids) === 1) + { + $return_forum = sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . current($forum_ids)) . '">', '</a>') . '<br /><br />'; + } + + if (sizeof($topic_ids) === 1) + { + $return_topic = sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=' . current($topic_ids) . '&f=' . current($forum_ids)) . '">', '</a>') . '<br /><br />'; + } + } + + trigger_error($user->lang[$success_msg] . '<br /><br />' . $return_forum . $return_topic . sprintf($user->lang['RETURN_PAGE'], "<a href=\"$redirect\">", '</a>')); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php new file mode 100644 index 0000000000..abdb839e7b --- /dev/null +++ b/phpBB/includes/mcp/mcp_topic.php @@ -0,0 +1,635 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* View topic in MCP +*/ +function mcp_topic_view($id, $mode, $action) +{ + global $phpEx, $phpbb_root_path, $config; + global $template, $db, $user, $auth, $cache; + + $url = append_sid("{$phpbb_root_path}mcp.$phpEx?" . extra_url()); + + $user->add_lang('viewtopic'); + + $topic_id = request_var('t', 0); + $topic_info = get_topic_data(array($topic_id), false, true); + + if (!sizeof($topic_info)) + { + trigger_error('TOPIC_NOT_EXIST'); + } + + $topic_info = $topic_info[$topic_id]; + + // Set up some vars + $icon_id = request_var('icon', 0); + $subject = utf8_normalize_nfc(request_var('subject', '', true)); + $start = request_var('start', 0); + $sort_days_old = request_var('st_old', 0); + $forum_id = request_var('f', 0); + $to_topic_id = request_var('to_topic_id', 0); + $to_forum_id = request_var('to_forum_id', 0); + $sort = isset($_POST['sort']) ? true : false; + $submitted_id_list = request_var('post_ids', array(0)); + $checked_ids = $post_id_list = request_var('post_id_list', array(0)); + + // Split Topic? + if ($action == 'split_all' || $action == 'split_beyond') + { + if (!$sort) + { + split_topic($action, $topic_id, $to_forum_id, $subject); + } + $action = 'split'; + } + + // Merge Posts? + if ($action == 'merge_posts') + { + if (!$sort) + { + merge_posts($topic_id, $to_topic_id); + } + $action = 'merge'; + } + + if ($action == 'split' && !$subject) + { + $subject = $topic_info['topic_title']; + } + + // Approve posts? + if ($action == 'approve' && $auth->acl_get('m_approve', $topic_info['forum_id'])) + { + include($phpbb_root_path . 'includes/mcp/mcp_queue.' . $phpEx); + include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); + include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + + if (!sizeof($post_id_list)) + { + trigger_error('NO_POST_SELECTED'); + } + + if (!$sort) + { + approve_post($post_id_list, $id, $mode); + } + } + + // Jumpbox, sort selects and that kind of things + make_jumpbox($url . "&i=$id&mode=forum_view", $topic_info['forum_id'], false, 'm_', true); + $where_sql = ($action == 'reports') ? 'WHERE post_reported = 1 AND ' : 'WHERE'; + + $sort_days = $total = 0; + $sort_key = $sort_dir = ''; + $sort_by_sql = $sort_order_sql = array(); + mcp_sorting('viewtopic', $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $topic_info['forum_id'], $topic_id, $where_sql); + + $limit_time_sql = ($sort_days) ? 'AND p.post_time >= ' . (time() - ($sort_days * 86400)) : ''; + + if ($total == -1) + { + $total = $topic_info['topic_replies'] + 1; + } + + $posts_per_page = max(0, request_var('posts_per_page', intval($config['posts_per_page']))); + if ($posts_per_page == 0) + { + $posts_per_page = $total; + } + + if ((!empty($sort_days_old) && $sort_days_old != $sort_days) || $total <= $posts_per_page) + { + $start = 0; + } + + // Make sure $start is set to the last page if it exceeds the amount + if ($start < 0 || $start >= $total) + { + $start = ($start < 0) ? 0 : floor(($total - 1) / $posts_per_page) * $posts_per_page; + } + + $sql = 'SELECT u.username, u.username_clean, u.user_colour, p.* + FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u + WHERE ' . (($action == 'reports') ? 'p.post_reported = 1 AND ' : '') . ' + p.topic_id = ' . $topic_id . ' ' . + ((!$auth->acl_get('m_approve', $topic_info['forum_id'])) ? ' AND p.post_approved = 1 ' : '') . ' + AND p.poster_id = u.user_id ' . + $limit_time_sql . ' + ORDER BY ' . $sort_order_sql; + $result = $db->sql_query_limit($sql, $posts_per_page, $start); + + $rowset = $post_id_list = array(); + $bbcode_bitfield = ''; + while ($row = $db->sql_fetchrow($result)) + { + $rowset[] = $row; + $post_id_list[] = $row['post_id']; + $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']); + } + $db->sql_freeresult($result); + + if ($bbcode_bitfield !== '') + { + include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx); + $bbcode = new bbcode(base64_encode($bbcode_bitfield)); + } + + $topic_tracking_info = array(); + + // Get topic tracking info + if ($config['load_db_lastread']) + { + $tmp_topic_data = array($topic_id => $topic_info); + $topic_tracking_info = get_topic_tracking($topic_info['forum_id'], $topic_id, $tmp_topic_data, array($topic_info['forum_id'] => $topic_info['forum_mark_time'])); + unset($tmp_topic_data); + } + else + { + $topic_tracking_info = get_complete_topic_tracking($topic_info['forum_id'], $topic_id); + } + + $has_unapproved_posts = false; + + // Grab extensions + $extensions = $attachments = array(); + if ($topic_info['topic_attachment'] && sizeof($post_id_list)) + { + $extensions = $cache->obtain_attach_extensions($topic_info['forum_id']); + + // Get attachments... + if ($auth->acl_get('u_download') && $auth->acl_get('f_download', $topic_info['forum_id'])) + { + $sql = 'SELECT * + FROM ' . ATTACHMENTS_TABLE . ' + WHERE ' . $db->sql_in_set('post_msg_id', $post_id_list) . ' + AND in_message = 0 + ORDER BY filetime DESC, post_msg_id ASC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $attachments[$row['post_msg_id']][] = $row; + } + $db->sql_freeresult($result); + } + } + + foreach ($rowset as $i => $row) + { + $message = $row['post_text']; + $post_subject = ($row['post_subject'] != '') ? $row['post_subject'] : $topic_info['topic_title']; + + if ($row['bbcode_bitfield']) + { + $bbcode->bbcode_second_pass($message, $row['bbcode_uid'], $row['bbcode_bitfield']); + } + + $message = bbcode_nl2br($message); + $message = smiley_text($message); + + if (!empty($attachments[$row['post_id']])) + { + $update_count = array(); + parse_attachments($topic_info['forum_id'], $message, $attachments[$row['post_id']], $update_count); + } + + if (!$row['post_approved']) + { + $has_unapproved_posts = true; + } + + $post_unread = (isset($topic_tracking_info[$topic_id]) && $row['post_time'] > $topic_tracking_info[$topic_id]) ? true : false; + + $template->assign_block_vars('postrow', array( + 'POST_AUTHOR_FULL' => get_username_string('full', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + 'POST_AUTHOR_COLOUR' => get_username_string('colour', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + 'POST_AUTHOR' => get_username_string('username', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + 'U_POST_AUTHOR' => get_username_string('profile', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + + 'POST_DATE' => $user->format_date($row['post_time']), + 'POST_SUBJECT' => $post_subject, + 'MESSAGE' => $message, + 'POST_ID' => $row['post_id'], + 'RETURN_TOPIC' => sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=' . $topic_id) . '">', '</a>'), + + 'MINI_POST_IMG' => ($post_unread) ? $user->img('icon_post_target_unread', 'NEW_POST') : $user->img('icon_post_target', 'POST'), + + 'S_POST_REPORTED' => ($row['post_reported']) ? true : false, + 'S_POST_UNAPPROVED' => ($row['post_approved']) ? false : true, + 'S_CHECKED' => (($submitted_id_list && !in_array(intval($row['post_id']), $submitted_id_list)) || in_array(intval($row['post_id']), $checked_ids)) ? true : false, + 'S_HAS_ATTACHMENTS' => (!empty($attachments[$row['post_id']])) ? true : false, + + 'U_POST_DETAILS' => "$url&i=$id&p={$row['post_id']}&mode=post_details" . (($forum_id) ? "&f=$forum_id" : ''), + 'U_MCP_APPROVE' => ($auth->acl_get('m_approve', $topic_info['forum_id'])) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&mode=approve_details&f=' . $topic_info['forum_id'] . '&p=' . $row['post_id']) : '', + 'U_MCP_REPORT' => ($auth->acl_get('m_report', $topic_info['forum_id'])) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&mode=report_details&f=' . $topic_info['forum_id'] . '&p=' . $row['post_id']) : '') + ); + + // 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) + { + $template->assign_block_vars('postrow.attachment', array( + 'DISPLAY_ATTACHMENT' => $attachment) + ); + } + } + + unset($rowset[$i]); + } + + // Display topic icons for split topic + $s_topic_icons = false; + + if ($auth->acl_gets('m_split', 'm_merge', (int) $topic_info['forum_id'])) + { + include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); + $s_topic_icons = posting_gen_topic_icons('', $icon_id); + + // Has the user selected a topic for merge? + if ($to_topic_id) + { + $to_topic_info = get_topic_data(array($to_topic_id), 'm_merge'); + + if (!sizeof($to_topic_info)) + { + $to_topic_id = 0; + } + else + { + $to_topic_info = $to_topic_info[$to_topic_id]; + + if (!$to_topic_info['enable_icons'] || $auth->acl_get('!f_icons', $topic_info['forum_id'])) + { + $s_topic_icons = false; + } + } + } + } + + $s_hidden_fields = build_hidden_fields(array( + 'st_old' => $sort_days, + 'post_ids' => $post_id_list, + )); + + $template->assign_vars(array( + 'TOPIC_TITLE' => $topic_info['topic_title'], + 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $topic_info['forum_id'] . '&t=' . $topic_info['topic_id']), + + 'TO_TOPIC_ID' => $to_topic_id, + 'TO_TOPIC_INFO' => ($to_topic_id) ? sprintf($user->lang['YOU_SELECTED_TOPIC'], $to_topic_id, '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $to_topic_info['forum_id'] . '&t=' . $to_topic_id) . '">' . $to_topic_info['topic_title'] . '</a>') : '', + + 'SPLIT_SUBJECT' => $subject, + 'POSTS_PER_PAGE' => $posts_per_page, + 'ACTION' => $action, + + 'REPORTED_IMG' => $user->img('icon_topic_reported', 'POST_REPORTED'), + 'UNAPPROVED_IMG' => $user->img('icon_topic_unapproved', 'POST_UNAPPROVED'), + 'INFO_IMG' => $user->img('icon_post_info', 'VIEW_INFO'), + + 'S_MCP_ACTION' => "$url&i=$id&mode=$mode&action=$action&start=$start", + 'S_FORUM_SELECT' => ($to_forum_id) ? make_forum_select($to_forum_id, false, false, true, true, true) : make_forum_select($topic_info['forum_id'], false, false, true, true, true), + 'S_CAN_SPLIT' => ($auth->acl_get('m_split', $topic_info['forum_id'])) ? true : false, + 'S_CAN_MERGE' => ($auth->acl_get('m_merge', $topic_info['forum_id'])) ? true : false, + 'S_CAN_DELETE' => ($auth->acl_get('m_delete', $topic_info['forum_id'])) ? true : false, + 'S_CAN_APPROVE' => ($has_unapproved_posts && $auth->acl_get('m_approve', $topic_info['forum_id'])) ? true : false, + 'S_CAN_LOCK' => ($auth->acl_get('m_lock', $topic_info['forum_id'])) ? true : false, + 'S_CAN_REPORT' => ($auth->acl_get('m_report', $topic_info['forum_id'])) ? true : false, + 'S_REPORT_VIEW' => ($action == 'reports') ? true : false, + 'S_MERGE_VIEW' => ($action == 'merge') ? true : false, + 'S_SPLIT_VIEW' => ($action == 'split') ? true : false, + + 'S_HIDDEN_FIELDS' => $s_hidden_fields, + + 'S_SHOW_TOPIC_ICONS' => $s_topic_icons, + 'S_TOPIC_ICON' => $icon_id, + + 'U_SELECT_TOPIC' => "$url&i=$id&mode=forum_view&action=merge_select" . (($forum_id) ? "&f=$forum_id" : ''), + + 'RETURN_TOPIC' => sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f={$topic_info['forum_id']}&t={$topic_info['topic_id']}&start=$start") . '">', '</a>'), + 'RETURN_FORUM' => sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", "f={$topic_info['forum_id']}&start=$start") . '">', '</a>'), + + 'PAGE_NUMBER' => on_page($total, $posts_per_page, $start), + 'PAGINATION' => (!$posts_per_page) ? '' : generate_pagination(append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&t={$topic_info['topic_id']}&mode=$mode&action=$action&to_topic_id=$to_topic_id&posts_per_page=$posts_per_page&st=$sort_days&sk=$sort_key&sd=$sort_dir"), $total, $posts_per_page, $start), + 'TOTAL_POSTS' => ($total == 1) ? $user->lang['VIEW_TOPIC_POST'] : sprintf($user->lang['VIEW_TOPIC_POSTS'], $total), + )); +} + +/** +* Split topic +*/ +function split_topic($action, $topic_id, $to_forum_id, $subject) +{ + global $db, $template, $user, $phpEx, $phpbb_root_path, $auth, $config; + + $post_id_list = request_var('post_id_list', array(0)); + $forum_id = request_var('forum_id', 0); + $start = request_var('start', 0); + + if (!sizeof($post_id_list)) + { + $template->assign_var('MESSAGE', $user->lang['NO_POST_SELECTED']); + return; + } + + if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_split'))) + { + return; + } + + $post_id = $post_id_list[0]; + $post_info = get_post_data(array($post_id)); + + if (!sizeof($post_info)) + { + $template->assign_var('MESSAGE', $user->lang['NO_POST_SELECTED']); + return; + } + + $post_info = $post_info[$post_id]; + $subject = trim($subject); + + // Make some tests + if (!$subject) + { + $template->assign_var('MESSAGE', $user->lang['EMPTY_SUBJECT']); + return; + } + + if ($to_forum_id <= 0) + { + $template->assign_var('MESSAGE', $user->lang['NO_DESTINATION_FORUM']); + return; + } + + $forum_info = get_forum_data(array($to_forum_id), 'f_post'); + + if (!sizeof($forum_info)) + { + $template->assign_var('MESSAGE', $user->lang['USER_CANNOT_POST']); + return; + } + + $forum_info = $forum_info[$to_forum_id]; + + if ($forum_info['forum_type'] != FORUM_POST) + { + $template->assign_var('MESSAGE', $user->lang['FORUM_NOT_POSTABLE']); + return; + } + + $redirect = request_var('redirect', build_url(array('quickmod'))); + + $s_hidden_fields = build_hidden_fields(array( + 'i' => 'main', + 'post_id_list' => $post_id_list, + 'f' => $forum_id, + 'mode' => 'topic_view', + 'start' => $start, + 'action' => $action, + 't' => $topic_id, + 'redirect' => $redirect, + 'subject' => $subject, + 'to_forum_id' => $to_forum_id, + 'icon' => request_var('icon', 0)) + ); + $success_msg = $return_link = ''; + + if (confirm_box(true)) + { + if ($action == 'split_beyond') + { + $sort_days = $total = 0; + $sort_key = $sort_dir = ''; + $sort_by_sql = $sort_order_sql = array(); + mcp_sorting('viewtopic', $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id, $topic_id); + + $limit_time_sql = ($sort_days) ? 'AND t.topic_last_post_time >= ' . (time() - ($sort_days * 86400)) : ''; + + if ($sort_order_sql[0] == 'u') + { + $sql = 'SELECT p.post_id, p.forum_id, p.post_approved + FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u + WHERE p.topic_id = $topic_id + AND p.poster_id = u.user_id + $limit_time_sql + ORDER BY $sort_order_sql"; + } + else + { + $sql = 'SELECT p.post_id, p.forum_id, p.post_approved + FROM ' . POSTS_TABLE . " p + WHERE p.topic_id = $topic_id + $limit_time_sql + ORDER BY $sort_order_sql"; + } + $result = $db->sql_query_limit($sql, 0, $start); + + $store = false; + $post_id_list = array(); + while ($row = $db->sql_fetchrow($result)) + { + // If split from selected post (split_beyond), we split the unapproved items too. + if (!$row['post_approved'] && !$auth->acl_get('m_approve', $row['forum_id'])) + { +// continue; + } + + // Start to store post_ids as soon as we see the first post that was selected + if ($row['post_id'] == $post_id) + { + $store = true; + } + + if ($store) + { + $post_id_list[] = $row['post_id']; + } + } + $db->sql_freeresult($result); + } + + if (!sizeof($post_id_list)) + { + trigger_error('NO_POST_SELECTED'); + } + + $icon_id = request_var('icon', 0); + + $sql_ary = array( + 'forum_id' => $to_forum_id, + 'topic_title' => $subject, + 'icon_id' => $icon_id, + 'topic_approved'=> 1 + ); + + $sql = 'INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); + $db->sql_query($sql); + + $to_topic_id = $db->sql_nextid(); + move_posts($post_id_list, $to_topic_id); + + $topic_info = get_topic_data(array($topic_id)); + $topic_info = $topic_info[$topic_id]; + + add_log('mod', $to_forum_id, $to_topic_id, 'LOG_SPLIT_DESTINATION', $subject); + add_log('mod', $forum_id, $topic_id, 'LOG_SPLIT_SOURCE', $topic_info['topic_title']); + + // Change topic title of first post + $sql = 'UPDATE ' . POSTS_TABLE . " + SET post_subject = '" . $db->sql_escape($subject) . "' + WHERE post_id = {$post_id_list[0]}"; + $db->sql_query($sql); + + $success_msg = 'TOPIC_SPLIT_SUCCESS'; + + // Update forum statistics + set_config_count('num_topics', 1, true); + + // Link back to both topics + $return_link = sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&t=' . $post_info['topic_id']) . '">', '</a>') . '<br /><br />' . sprintf($user->lang['RETURN_NEW_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $to_forum_id . '&t=' . $to_topic_id) . '">', '</a>'); + } + else + { + confirm_box(false, ($action == 'split_all') ? 'SPLIT_TOPIC_ALL' : 'SPLIT_TOPIC_BEYOND', $s_hidden_fields); + } + + $redirect = request_var('redirect', "index.$phpEx"); + $redirect = reapply_sid($redirect); + + if (!$success_msg) + { + return; + } + else + { + meta_refresh(3, append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$to_forum_id&t=$to_topic_id")); + trigger_error($user->lang[$success_msg] . '<br /><br />' . $return_link); + } +} + +/** +* Merge selected posts into selected topic +*/ +function merge_posts($topic_id, $to_topic_id) +{ + global $db, $template, $user, $phpEx, $phpbb_root_path, $auth; + + if (!$to_topic_id) + { + $template->assign_var('MESSAGE', $user->lang['NO_FINAL_TOPIC_SELECTED']); + return; + } + + $topic_data = get_topic_data(array($to_topic_id), 'm_merge'); + + if (!sizeof($topic_data)) + { + $template->assign_var('MESSAGE', $user->lang['NO_FINAL_TOPIC_SELECTED']); + return; + } + + $topic_data = $topic_data[$to_topic_id]; + + $post_id_list = request_var('post_id_list', array(0)); + $start = request_var('start', 0); + + if (!sizeof($post_id_list)) + { + $template->assign_var('MESSAGE', $user->lang['NO_POST_SELECTED']); + return; + } + + if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_merge'))) + { + return; + } + + $redirect = request_var('redirect', build_url(array('quickmod'))); + + $s_hidden_fields = build_hidden_fields(array( + 'i' => 'main', + 'post_id_list' => $post_id_list, + 'to_topic_id' => $to_topic_id, + 'mode' => 'topic_view', + 'action' => 'merge_posts', + 'start' => $start, + 'redirect' => $redirect, + 't' => $topic_id) + ); + $success_msg = $return_link = ''; + + if (confirm_box(true)) + { + $to_forum_id = $topic_data['forum_id']; + + move_posts($post_id_list, $to_topic_id); + add_log('mod', $to_forum_id, $to_topic_id, 'LOG_MERGE', $topic_data['topic_title']); + + // Message and return links + $success_msg = 'POSTS_MERGED_SUCCESS'; + + // Does the original topic still exist? If yes, link back to it + $sql = 'SELECT forum_id + FROM ' . TOPICS_TABLE . ' + WHERE topic_id = ' . $topic_id; + $result = $db->sql_query_limit($sql, 1); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + $return_link .= sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $row['forum_id'] . '&t=' . $topic_id) . '">', '</a>'); + } + else + { + // If the topic no longer exist, we will update the topic watch table. + // To not let it error out on users watching both topics, we just return on an error... + $db->sql_return_on_error(true); + $db->sql_query('UPDATE ' . TOPICS_WATCH_TABLE . ' SET topic_id = ' . (int) $to_topic_id . ' WHERE topic_id = ' . (int) $topic_id); + $db->sql_return_on_error(false); + + $db->sql_query('DELETE FROM ' . TOPICS_WATCH_TABLE . ' WHERE topic_id = ' . (int) $topic_id); + } + + // Link to the new topic + $return_link .= (($return_link) ? '<br /><br />' : '') . sprintf($user->lang['RETURN_NEW_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $to_forum_id . '&t=' . $to_topic_id) . '">', '</a>'); + } + else + { + confirm_box(false, 'MERGE_POSTS', $s_hidden_fields); + } + + $redirect = request_var('redirect', "index.$phpEx"); + $redirect = reapply_sid($redirect); + + if (!$success_msg) + { + return; + } + else + { + meta_refresh(3, append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$to_forum_id&t=$to_topic_id")); + trigger_error($user->lang[$success_msg] . '<br /><br />' . $return_link); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/mcp/mcp_warn.php b/phpBB/includes/mcp/mcp_warn.php new file mode 100644 index 0000000000..63e5b19155 --- /dev/null +++ b/phpBB/includes/mcp/mcp_warn.php @@ -0,0 +1,511 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* mcp_warn +* Handling warning the users +* @package mcp +*/ +class mcp_warn +{ + var $p_master; + var $u_action; + + function mcp_warn(&$p_master) + { + $this->p_master = &$p_master; + } + + function main($id, $mode) + { + global $auth, $db, $user, $template; + global $config, $phpbb_root_path, $phpEx; + + $action = request_var('action', array('' => '')); + + if (is_array($action)) + { + list($action, ) = each($action); + } + + $this->page_title = 'MCP_WARN'; + + add_form_key('mcp_warn'); + + switch ($mode) + { + case 'front': + $this->mcp_warn_front_view(); + $this->tpl_name = 'mcp_warn_front'; + break; + + case 'list': + $this->mcp_warn_list_view($action); + $this->tpl_name = 'mcp_warn_list'; + break; + + case 'warn_post': + $this->mcp_warn_post_view($action); + $this->tpl_name = 'mcp_warn_post'; + break; + + case 'warn_user': + $this->mcp_warn_user_view($action); + $this->tpl_name = 'mcp_warn_user'; + break; + } + } + + /** + * Generates the summary on the main page of the warning module + */ + function mcp_warn_front_view() + { + global $phpEx, $phpbb_root_path, $config; + global $template, $db, $user, $auth; + + $template->assign_vars(array( + 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=mcp&field=username&select_single=true'), + 'U_POST_ACTION' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&mode=warn_user'), + )); + + // Obtain a list of the 5 naughtiest users.... + // These are the 5 users with the highest warning count + $highest = array(); + $count = 0; + + view_warned_users($highest, $count, 5); + + foreach ($highest as $row) + { + $template->assign_block_vars('highest', array( + 'U_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&mode=user_notes&u=' . $row['user_id']), + + 'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']), + 'USERNAME' => $row['username'], + 'USERNAME_COLOUR' => ($row['user_colour']) ? '#' . $row['user_colour'] : '', + 'U_USER' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $row['user_id']), + + 'WARNING_TIME' => $user->format_date($row['user_last_warning']), + 'WARNINGS' => $row['user_warnings'], + )); + } + + // And now the 5 most recent users to get in trouble + $sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_colour, u.user_warnings, w.warning_time + FROM ' . USERS_TABLE . ' u, ' . WARNINGS_TABLE . ' w + WHERE u.user_id = w.user_id + ORDER BY w.warning_time DESC'; + $result = $db->sql_query_limit($sql, 5); + + while ($row = $db->sql_fetchrow($result)) + { + $template->assign_block_vars('latest', array( + 'U_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&mode=user_notes&u=' . $row['user_id']), + + 'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']), + 'USERNAME' => $row['username'], + 'USERNAME_COLOUR' => ($row['user_colour']) ? '#' . $row['user_colour'] : '', + 'U_USER' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $row['user_id']), + + 'WARNING_TIME' => $user->format_date($row['warning_time']), + 'WARNINGS' => $row['user_warnings'], + )); + } + $db->sql_freeresult($result); + } + + /** + * Lists all users with warnings + */ + function mcp_warn_list_view($action) + { + global $phpEx, $phpbb_root_path, $config; + global $template, $db, $user, $auth; + + $user->add_lang('memberlist'); + + $start = request_var('start', 0); + $st = request_var('st', 0); + $sk = request_var('sk', 'b'); + $sd = request_var('sd', 'd'); + + $limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + $sort_by_text = array('a' => $user->lang['SORT_USERNAME'], 'b' => $user->lang['SORT_DATE'], 'c' => $user->lang['SORT_WARNINGS']); + $sort_by_sql = array('a' => 'username_clean', 'b' => 'user_last_warning', 'c' => 'user_warnings'); + + $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = ''; + gen_sort_selects($limit_days, $sort_by_text, $st, $sk, $sd, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param); + + // Define where and sort sql for use in displaying logs + $sql_where = ($st) ? (time() - ($st * 86400)) : 0; + $sql_sort = $sort_by_sql[$sk] . ' ' . (($sd == 'd') ? 'DESC' : 'ASC'); + + $users = array(); + $user_count = 0; + + view_warned_users($users, $user_count, $config['topics_per_page'], $start, $sql_where, $sql_sort); + + foreach ($users as $row) + { + $template->assign_block_vars('user', array( + 'U_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&mode=user_notes&u=' . $row['user_id']), + + 'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']), + 'USERNAME' => $row['username'], + 'USERNAME_COLOUR' => ($row['user_colour']) ? '#' . $row['user_colour'] : '', + 'U_USER' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $row['user_id']), + + 'WARNING_TIME' => $user->format_date($row['user_last_warning']), + 'WARNINGS' => $row['user_warnings'], + )); + } + + $template->assign_vars(array( + 'U_POST_ACTION' => $this->u_action, + 'S_CLEAR_ALLOWED' => ($auth->acl_get('a_clearlogs')) ? true : false, + 'S_SELECT_SORT_DIR' => $s_sort_dir, + 'S_SELECT_SORT_KEY' => $s_sort_key, + 'S_SELECT_SORT_DAYS' => $s_limit_days, + + 'PAGE_NUMBER' => on_page($user_count, $config['topics_per_page'], $start), + 'PAGINATION' => generate_pagination(append_sid("{$phpbb_root_path}mcp.$phpEx", "i=warn&mode=list&st=$st&sk=$sk&sd=$sd"), $user_count, $config['topics_per_page'], $start), + 'TOTAL_USERS' => ($user_count == 1) ? $user->lang['LIST_USER'] : sprintf($user->lang['LIST_USERS'], $user_count), + )); + } + + /** + * Handles warning the user when the warning is for a specific post + */ + function mcp_warn_post_view($action) + { + global $phpEx, $phpbb_root_path, $config; + global $template, $db, $user, $auth; + + $post_id = request_var('p', 0); + $forum_id = request_var('f', 0); + $notify = (isset($_REQUEST['notify_user'])) ? true : false; + $warning = utf8_normalize_nfc(request_var('warning', '', true)); + + $sql = 'SELECT u.*, p.* + FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u + WHERE p.post_id = $post_id + AND u.user_id = p.poster_id"; + $result = $db->sql_query($sql); + $user_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$user_row) + { + trigger_error('NO_POST'); + } + + // There is no point issuing a warning to ignored users (ie anonymous and bots) + if ($user_row['user_type'] == USER_IGNORE) + { + trigger_error('CANNOT_WARN_ANONYMOUS'); + } + + // Prevent someone from warning themselves + if ($user_row['user_id'] == $user->data['user_id']) + { + trigger_error('CANNOT_WARN_SELF'); + } + + // Check if there is already a warning for this post to prevent multiple + // warnings for the same offence + $sql = 'SELECT post_id + FROM ' . WARNINGS_TABLE . " + WHERE post_id = $post_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + trigger_error('ALREADY_WARNED'); + } + + $user_id = $user_row['user_id']; + + if (strpos($this->u_action, "&f=$forum_id&p=$post_id") === false) + { + $this->p_master->adjust_url("&f=$forum_id&p=$post_id"); + $this->u_action .= "&f=$forum_id&p=$post_id"; + } + + // Check if can send a notification + if ($config['allow_privmsg']) + { + $auth2 = new auth(); + $auth2->acl($user_row); + $s_can_notify = ($auth2->acl_get('u_readpm')) ? true : false; + unset($auth2); + } + else + { + $s_can_notify = false; + } + + // Prevent against clever people + if ($notify && !$s_can_notify) + { + $notify = false; + } + + if ($warning && $action == 'add_warning') + { + if (check_form_key('mcp_warn')) + { + add_warning($user_row, $warning, $notify, $post_id); + $msg = $user->lang['USER_WARNING_ADDED']; + } + else + { + $msg = $user->lang['FORM_INVALID']; + } + $redirect = append_sid("{$phpbb_root_path}mcp.$phpEx", "i=notes&mode=user_notes&u=$user_id"); + meta_refresh(2, $redirect); + trigger_error($msg . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>')); + } + + // OK, they didn't submit a warning so lets build the page for them to do so + + // We want to make the message available here as a reminder + // Parse the message and subject + $message = censor_text($user_row['post_text']); + + // Second parse bbcode here + if ($user_row['bbcode_bitfield']) + { + include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx); + + $bbcode = new bbcode($user_row['bbcode_bitfield']); + $bbcode->bbcode_second_pass($message, $user_row['bbcode_uid'], $user_row['bbcode_bitfield']); + } + + $message = bbcode_nl2br($message); + $message = smiley_text($message); + + // Generate the appropriate user information for the user we are looking at + if (!function_exists('get_user_avatar')) + { + include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + } + + $rank_title = $rank_img = ''; + $avatar_img = get_user_avatar($user_row['user_avatar'], $user_row['user_avatar_type'], $user_row['user_avatar_width'], $user_row['user_avatar_height']); + + $template->assign_vars(array( + 'U_POST_ACTION' => $this->u_action, + + 'POST' => $message, + 'USERNAME' => $user_row['username'], + 'USER_COLOR' => (!empty($user_row['user_colour'])) ? $user_row['user_colour'] : '', + 'RANK_TITLE' => $rank_title, + 'JOINED' => $user->format_date($user_row['user_regdate']), + 'POSTS' => ($user_row['user_posts']) ? $user_row['user_posts'] : 0, + 'WARNINGS' => ($user_row['user_warnings']) ? $user_row['user_warnings'] : 0, + + 'AVATAR_IMG' => $avatar_img, + 'RANK_IMG' => $rank_img, + + 'L_WARNING_POST_DEFAULT' => sprintf($user->lang['WARNING_POST_DEFAULT'], generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&p=$post_id#p$post_id"), + + 'S_CAN_NOTIFY' => $s_can_notify, + )); + } + + /** + * Handles warning the user + */ + function mcp_warn_user_view($action) + { + global $phpEx, $phpbb_root_path, $config, $module; + global $template, $db, $user, $auth; + + $user_id = request_var('u', 0); + $username = request_var('username', '', true); + $notify = (isset($_REQUEST['notify_user'])) ? true : false; + $warning = utf8_normalize_nfc(request_var('warning', '', true)); + + $sql_where = ($user_id) ? "user_id = $user_id" : "username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'"; + + $sql = 'SELECT * + FROM ' . USERS_TABLE . ' + WHERE ' . $sql_where; + $result = $db->sql_query($sql); + $user_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$user_row) + { + trigger_error('NO_USER'); + } + + // Prevent someone from warning themselves + if ($user_row['user_id'] == $user->data['user_id']) + { + trigger_error('CANNOT_WARN_SELF'); + } + + $user_id = $user_row['user_id']; + + if (strpos($this->u_action, "&u=$user_id") === false) + { + $this->p_master->adjust_url('&u=' . $user_id); + $this->u_action .= "&u=$user_id"; + } + + // Check if can send a notification + if ($config['allow_privmsg']) + { + $auth2 = new auth(); + $auth2->acl($user_row); + $s_can_notify = ($auth2->acl_get('u_readpm')) ? true : false; + unset($auth2); + } + else + { + $s_can_notify = false; + } + + // Prevent against clever people + if ($notify && !$s_can_notify) + { + $notify = false; + } + + if ($warning && $action == 'add_warning') + { + if (check_form_key('mcp_warn')) + { + add_warning($user_row, $warning, $notify); + $msg = $user->lang['USER_WARNING_ADDED']; + } + else + { + $msg = $user->lang['FORM_INVALID']; + } + $redirect = append_sid("{$phpbb_root_path}mcp.$phpEx", "i=notes&mode=user_notes&u=$user_id"); + meta_refresh(2, $redirect); + trigger_error($msg . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>')); + } + + // Generate the appropriate user information for the user we are looking at + if (!function_exists('get_user_avatar')) + { + include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + } + + $rank_title = $rank_img = ''; + $avatar_img = get_user_avatar($user_row['user_avatar'], $user_row['user_avatar_type'], $user_row['user_avatar_width'], $user_row['user_avatar_height']); + + // OK, they didn't submit a warning so lets build the page for them to do so + $template->assign_vars(array( + 'U_POST_ACTION' => $this->u_action, + + 'RANK_TITLE' => $rank_title, + 'JOINED' => $user->format_date($user_row['user_regdate']), + 'POSTS' => ($user_row['user_posts']) ? $user_row['user_posts'] : 0, + 'WARNINGS' => ($user_row['user_warnings']) ? $user_row['user_warnings'] : 0, + + 'USERNAME_FULL' => get_username_string('full', $user_row['user_id'], $user_row['username'], $user_row['user_colour']), + 'USERNAME_COLOUR' => get_username_string('colour', $user_row['user_id'], $user_row['username'], $user_row['user_colour']), + 'USERNAME' => get_username_string('username', $user_row['user_id'], $user_row['username'], $user_row['user_colour']), + 'U_PROFILE' => get_username_string('profile', $user_row['user_id'], $user_row['username'], $user_row['user_colour']), + + 'AVATAR_IMG' => $avatar_img, + 'RANK_IMG' => $rank_img, + + 'S_CAN_NOTIFY' => $s_can_notify, + )); + + return $user_id; + } +} + +/** +* Insert the warning into the database +*/ +function add_warning($user_row, $warning, $send_pm = true, $post_id = 0) +{ + global $phpEx, $phpbb_root_path, $config; + global $template, $db, $user, $auth; + + if ($send_pm) + { + include_once($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx); + include_once($phpbb_root_path . 'includes/message_parser.' . $phpEx); + + $user_row['user_lang'] = (file_exists($phpbb_root_path . 'language/' . $user_row['user_lang'] . "/mcp.$phpEx")) ? $user_row['user_lang'] : $config['default_lang']; + include($phpbb_root_path . 'language/' . basename($user_row['user_lang']) . "/mcp.$phpEx"); + + $message_parser = new parse_message(); + + $message_parser->message = sprintf($lang['WARNING_PM_BODY'], $warning); + $message_parser->parse(true, true, true, false, false, true, true); + + $pm_data = array( + 'from_user_id' => $user->data['user_id'], + 'from_user_ip' => $user->ip, + 'from_username' => $user->data['username'], + 'enable_sig' => false, + 'enable_bbcode' => true, + 'enable_smilies' => true, + 'enable_urls' => false, + 'icon_id' => 0, + 'bbcode_bitfield' => $message_parser->bbcode_bitfield, + 'bbcode_uid' => $message_parser->bbcode_uid, + 'message' => $message_parser->message, + 'address_list' => array('u' => array($user_row['user_id'] => 'to')), + ); + + submit_pm('post', $lang['WARNING_PM_SUBJECT'], $pm_data, false); + } + + add_log('admin', 'LOG_USER_WARNING', $user_row['username']); + $log_id = add_log('user', $user_row['user_id'], 'LOG_USER_WARNING_BODY', $warning); + + $sql_ary = array( + 'user_id' => $user_row['user_id'], + 'post_id' => $post_id, + 'log_id' => $log_id, + 'warning_time' => time(), + ); + + $db->sql_query('INSERT INTO ' . WARNINGS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_warnings = user_warnings + 1, + user_last_warning = ' . time() . ' + WHERE user_id = ' . $user_row['user_id']; + $db->sql_query($sql); + + // We add this to the mod log too for moderators to see that a specific user got warned. + $sql = 'SELECT forum_id, topic_id + FROM ' . POSTS_TABLE . ' + WHERE post_id = ' . $post_id; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_USER_WARNING', $user_row['username']); +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php new file mode 100644 index 0000000000..3df582d640 --- /dev/null +++ b/phpBB/includes/message_parser.php @@ -0,0 +1,1685 @@ +<?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.' . $phpEx); +} + +/** +* 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(); + } + + global $user; + + $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($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(=(.*))?\]((?s).*)\[/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]{3}|#[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)) + { + global $db; + $rowset = array(); + + $sql = 'SELECT * + FROM ' . BBCODES_TABLE; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $rowset[] = $row; + } + $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) + { + global $user, $config; + + if (!$this->check_bbcode('size', $in)) + { + return $in; + } + + if ($config['max_' . $this->mode . '_font_size'] && $config['max_' . $this->mode . '_font_size'] < $stx) + { + $this->warn_msg[] = sprintf($user->lang['MAX_FONT_SIZE_EXCEEDED'], $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) + { + global $user, $config; + + 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 ($config['max_' . $this->mode . '_img_height'] || $config['max_' . $this->mode . '_img_width']) + { + $stats = @getimagesize($in); + + if ($stats === false) + { + $error = true; + $this->warn_msg[] = $user->lang['UNABLE_GET_IMAGE_SIZE']; + } + else + { + if ($config['max_' . $this->mode . '_img_height'] && $config['max_' . $this->mode . '_img_height'] < $stats[1]) + { + $error = true; + $this->warn_msg[] = sprintf($user->lang['MAX_IMG_HEIGHT_EXCEEDED'], $config['max_' . $this->mode . '_img_height']); + } + + if ($config['max_' . $this->mode . '_img_width'] && $config['max_' . $this->mode . '_img_width'] < $stats[0]) + { + $error = true; + $this->warn_msg[] = sprintf($user->lang['MAX_IMG_WIDTH_EXCEEDED'], $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) + { + global $user, $config; + + 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 ($config['max_' . $this->mode . '_img_height'] || $config['max_' . $this->mode . '_img_width']) + { + if ($config['max_' . $this->mode . '_img_height'] && $config['max_' . $this->mode . '_img_height'] < $height) + { + $error = true; + $this->warn_msg[] = sprintf($user->lang['MAX_FLASH_HEIGHT_EXCEEDED'], $config['max_' . $this->mode . '_img_height']); + } + + if ($config['max_' . $this->mode . '_img_width'] && $config['max_' . $this->mode . '_img_width'] < $width) + { + $error = true; + $this->warn_msg[] = sprintf($user->lang['MAX_FLASH_WIDTH_EXCEEDED'], $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) + { + global $config, $user; + + /** + * 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 ($config['max_quote_depth'] && sizeof($close_tags) >= $config['max_quote_depth']) + { + // there are too many nested quotes + $error_ary['quote_depth'] = sprintf($user->lang['QUOTE_DEPTH_EXCEEDED'], $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) + { + global $config; + + $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) + { + global $config, $phpEx, $user; + + if ($config['force_server_vars']) + { + $check_path = $config['script_path']; + } + else + { + $check_path = ($user->page['root_script_path'] != '/') ? substr($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, ".{$phpEx}") !== false && strpos($url, $check_path) !== false) + { + $server_name = $user->host; + + // Forcing server vars is the only way to specify/override the protocol + if ($config['force_server_vars'] || !$server_name) + { + $server_name = $config['server_name']; + } + + // Check again in correct order... + $pos_ext = strpos($url, ".{$phpEx}"); + $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.' . $phpEx) !== 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') + { + global $config, $db, $user; + + $this->mode = $mode; + + if (!isset($config['max_' . $mode . '_chars'])) + { + $config['max_' . $mode . '_chars'] = 0; + } + if (!isset($config['max_' . $mode . '_smilies'])) + { + $config['max_' . $mode . '_smilies'] = 0; + } + if (!isset($config['max_' . $mode . '_urls'])) + { + $config['max_' . $mode . '_urls'] = 0; + } + + $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)); + + // Store message length... + $message_length = ($mode == 'post') ? utf8_strlen($this->message) : utf8_strlen(preg_replace('#\[\/?[a-z\*\+\-]+(=[\S]+)?\]#ius', ' ', $this->message)); + + // Maximum message length check. 0 disables this check completely. + if ((int) $config['max_' . $mode . '_chars'] > 0 && $message_length > (int) $config['max_' . $mode . '_chars']) + { + $this->warn_msg[] = sprintf($user->lang['TOO_MANY_CHARS_' . strtoupper($mode)], $message_length, (int) $config['max_' . $mode . '_chars']); + return (!$update_this_message) ? $return_message : $this->warn_msg; + } + + // Minimum message length check for post only + if ($mode === 'post') + { + if (!$message_length || $message_length < (int) $config['min_post_chars']) + { + $this->warn_msg[] = (!$message_length) ? $user->lang['TOO_FEW_CHARS'] : sprintf($user->lang['TOO_FEW_CHARS_LIMIT'], $message_length, (int) $config['min_post_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($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 ($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 === 'post' && 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 ($config['max_' . $mode . '_urls'] && $num_urls > $config['max_' . $mode . '_urls']) + { + $this->warn_msg[] = sprintf($user->lang['TOO_MANY_URLS'], $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) + { + global $db, $user; + 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 + switch ($db->sql_layer) + { + case 'mssql': + case 'mssql_odbc': + $sql = 'SELECT * + FROM ' . SMILIES_TABLE . ' + ORDER BY LEN(code) DESC'; + break; + + case 'firebird': + $sql = 'SELECT * + FROM ' . SMILIES_TABLE . ' + ORDER BY CHAR_LENGTH(code) DESC'; + break; + + // LENGTH supported by MySQL, IBM DB2, Oracle and Access for sure... + default: + $sql = 'SELECT * + FROM ' . SMILIES_TABLE . ' + ORDER BY LENGTH(code) DESC'; + break; + } + $result = $db->sql_query($sql, 600); + + while ($row = $db->sql_fetchrow($result)) + { + if (empty($row['code'])) + { + continue; + } + + // (assertion) + $match[] = preg_quote($row['code'], '#'); + $replace[] = '<!-- s' . $row['code'] . ' --><img src="{SMILIES_PATH}/' . $row['smiley_url'] . '" alt="' . $row['code'] . '" title="' . $row['emotion'] . '" /><!-- s' . $row['code'] . ' -->'; + } + $db->sql_freeresult($result); + } + + if (sizeof($match)) + { + if ($max_smilies) + { + $num_matches = preg_match_all('#(?<=^|[\n .])(?:' . implode('|', $match) . ')(?![^<>]*>)#', $this->message, $matches); + unset($matches); + + if ($num_matches !== false && $num_matches > $max_smilies) + { + $this->warn_msg[] = sprintf($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), '#(?<=^|[\n .])' . implode('(?![^<>]*>)#' . chr(0) . '#(?<=^|[\n .])', $match) . '(?![^<>]*>)#'), $replace, $this->message)); + } + } + + /** + * Parse Attachments + */ + function parse_attachments($form_name, $mode, $forum_id, $submit, $preview, $refresh, $is_message = false) + { + global $config, $auth, $user, $phpbb_root_path, $phpEx, $db; + + $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 = (isset($_POST['add_file'])) ? true : false; + $delete_file = (isset($_POST['delete_file'])) ? true : false; + + // 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) ? $config['max_attachments_pm'] : $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'] || $auth->acl_get('a_') || $auth->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' => $user->data['user_id'], + ); + + $db->sql_query('INSERT INTO ' . ATTACHMENTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + + $new_entry = array( + 'attach_id' => $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($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.' . $phpEx); + + $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 = ' . $user->data['user_id']; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + phpbb_unlink($row['physical_filename'], 'file'); + + if ($row['thumbnail']) + { + phpbb_unlink($row['physical_filename'], 'thumbnail'); + } + + $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'] || $auth->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' => $user->data['user_id'], + ); + + $db->sql_query('INSERT INTO ' . ATTACHMENTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + + $new_entry = array( + 'attach_id' => $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($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) + { + global $user, $db, $phpbb_root_path, $phpEx, $config; + + $this->filename_data['filecomment'] = utf8_normalize_nfc(request_var('filecomment', '', true)); + $attachment_data = (isset($_POST['attachment_data'])) ? $_POST['attachment_data'] : array(); + $this->attachment_data = array(); + + $check_user_id = ($check_user_id === false) ? $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 ' . $db->sql_in_set('attach_id', array_keys($not_orphan)) . ' + AND poster_id = ' . $check_user_id; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $pos = $not_orphan[$row['attach_id']]; + $this->attachment_data[$pos] = $row; + set_var($this->attachment_data[$pos]['attach_comment'], $_POST['attachment_data'][$pos]['attach_comment'], 'string', true); + + unset($not_orphan[$row['attach_id']]); + } + $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 ' . $db->sql_in_set('attach_id', array_keys($orphan)) . ' + AND poster_id = ' . $user->data['user_id'] . ' + AND is_orphan = 1'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $pos = $orphan[$row['attach_id']]; + $this->attachment_data[$pos] = $row; + set_var($this->attachment_data[$pos]['attach_comment'], $_POST['attachment_data'][$pos]['attach_comment'], 'string', true); + + unset($orphan[$row['attach_id']]); + } + $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) + { + global $auth, $user, $config; + + $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'], ($config['allow_post_links']) ? $poll['enable_urls'] : false, $poll['enable_smilies'], $poll['img_status'], false, false, $config['allow_post_links'], false, 'poll'); + + $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[] = $user->lang['NO_POLL_TITLE']; + } + else + { + if (utf8_strlen(preg_replace('#\[\/?[a-z\*\+\-]+(=[\S]+)?\]#ius', ' ', $this->message)) > 100) + { + $this->warn_msg[] = $user->lang['POLL_TITLE_TOO_LONG']; + } + $poll['poll_title'] = $this->parse($poll['enable_bbcode'], ($config['allow_post_links']) ? $poll['enable_urls'] : false, $poll['enable_smilies'], $poll['img_status'], false, false, $config['allow_post_links'], false, 'poll'); + if (strlen($poll['poll_title']) > 255) + { + $this->warn_msg[] = $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[] = $user->lang['TOO_FEW_POLL_OPTIONS']; + } + else if ($poll['poll_options_size'] > (int) $config['max_poll_options']) + { + $this->warn_msg[] = $user->lang['TOO_MANY_POLL_OPTIONS']; + } + else if ($poll_max_options > $poll['poll_options_size']) + { + $this->warn_msg[] = $user->lang['TOO_MANY_USER_OPTIONS']; + } + + $poll['poll_max_options'] = ($poll['poll_max_options'] < 1) ? 1 : (($poll['poll_max_options'] > $config['max_poll_options']) ? $config['max_poll_options'] : $poll['poll_max_options']); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/questionnaire/questionnaire.php b/phpBB/includes/questionnaire/questionnaire.php new file mode 100644 index 0000000000..1d015576a7 --- /dev/null +++ b/phpBB/includes/questionnaire/questionnaire.php @@ -0,0 +1,471 @@ +<?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; +} + +/** +* This class collects data which is used to create some usage statistics. +* +* The collected data is - after authorization of the administrator - submitted +* to a central server. For privacy reasons we try to collect only data which aren't private +* or don't give any information which might help to identify the user. +* +* @author Johannes Schlueter <johannes@php.net> +* @copyright (c) 2007-2008 Johannes Schlueter +*/ +class phpbb_questionnaire_data_collector +{ + var $providers; + var $data = null; + var $install_id = ''; + + /** + * Constructor. + * + * @param string + */ + function phpbb_questionnaire_data_collector($install_id) + { + $this->install_id = $install_id; + $this->providers = array(); + } + + function add_data_provider(&$provider) + { + $this->providers[] = &$provider; + } + + /** + * Get data as an array. + * + * @return array All Data + */ + function get_data_raw() + { + if (!$this->data) + { + $this->collect(); + } + + return $this->data; + } + + function get_data_for_form() + { + return base64_encode(serialize($this->get_data_raw())); + } + + /** + * Collect info into the data property. + * + * @return void + */ + function collect() + { + foreach (array_keys($this->providers) as $key) + { + $provider = &$this->providers[$key]; + $this->data[$provider->get_identifier()] = $provider->get_data(); + } + $this->data['install_id'] = $this->install_id; + } +} + +/** interface: get_indentifier(), get_data() */ + +/** +* Questionnaire PHP data provider +* @package phpBB3 +*/ +class phpbb_questionnaire_php_data_provider +{ + function get_identifier() + { + return 'PHP'; + } + + /** + * Get data about the PHP runtime setup. + * + * @return array + */ + function get_data() + { + return array( + 'version' => PHP_VERSION, + 'sapi' => PHP_SAPI, + 'int_size' => defined('PHP_INT_SIZE') ? PHP_INT_SIZE : '', + 'safe_mode' => (int) @ini_get('safe_mode'), + 'open_basedir' => (int) @ini_get('open_basedir'), + 'memory_limit' => @ini_get('memory_limit'), + 'allow_url_fopen' => (int) @ini_get('allow_url_fopen'), + 'allow_url_include' => (int) @ini_get('allow_url_include'), + 'file_uploads' => (int) @ini_get('file_uploads'), + 'upload_max_filesize' => @ini_get('upload_max_filesize'), + 'post_max_size' => @ini_get('post_max_size'), + 'disable_functions' => @ini_get('disable_functions'), + 'disable_classes' => @ini_get('disable_classes'), + 'enable_dl' => (int) @ini_get('enable_dl'), + 'magic_quotes_gpc' => (int) @ini_get('magic_quotes_gpc'), + 'register_globals' => (int) @ini_get('register_globals'), + 'filter.default' => @ini_get('filter.default'), + 'zend.ze1_compatibility_mode' => (int) @ini_get('zend.ze1_compatibility_mode'), + 'unicode.semantics' => (int) @ini_get('unicode.semantics'), + 'zend_thread_safty' => (int) function_exists('zend_thread_id'), + 'extensions' => get_loaded_extensions(), + ); + } +} + +/** +* Questionnaire System data provider +* @package phpBB3 +*/ +class phpbb_questionnaire_system_data_provider +{ + function get_identifier() + { + return 'System'; + } + + /** + * Get data about the general system information, like OS or IP (shortened). + * + * @return array + */ + function get_data() + { + // Start discovering the IPV4 server address, if available + $server_address = '0.0.0.0'; + + if (!empty($_SERVER['SERVER_ADDR'])) + { + $server_address = $_SERVER['SERVER_ADDR']; + } + + // Running on IIS? + if (!empty($_SERVER['LOCAL_ADDR'])) + { + $server_address = $_SERVER['LOCAL_ADDR']; + } + + $ip_address_ary = explode('.', $server_address); + + // build ip + if (!isset($ip_address_ary[0]) || !isset($ip_address_ary[1])) + { + $ip_address_ary = explode('.', '0.0.0.0'); + } + + return array( + 'os' => PHP_OS, + 'httpd' => $_SERVER['SERVER_SOFTWARE'], + // we don't want the real IP address (for privacy policy reasons) but only + // a network address to see whether your installation is running on a private or public network. + // IANA reserved addresses for private networks (RFC 1918) are: + // - 10.0.0.0/8 + // - 172.16.0.0/12 + // - 192.168.0.0/16 + 'ip' => $ip_address_ary[0] . '.' . $ip_address_ary[1] . '.XXX.YYY', + ); + } +} + +/** +* Questionnaire phpBB data provider +* @package phpBB3 +*/ +class phpbb_questionnaire_phpbb_data_provider +{ + var $config; + var $unique_id; + + /** + * Constructor. + * + * @param array $config + */ + function phpbb_questionnaire_phpbb_data_provider($config) + { + // generate a unique id if necessary + if (empty($config['questionnaire_unique_id'])) + { + $this->unique_id = unique_id(); + set_config('questionnaire_unique_id', $this->unique_id); + } + else + { + $this->unique_id = $config['questionnaire_unique_id']; + } + + $this->config = $config; + } + + /** + * Returns a string identifier for this data provider + * + * @return string "phpBB" + */ + function get_identifier() + { + return 'phpBB'; + } + + /** + * Get data about this phpBB installation. + * + * @return array Relevant anonymous config options + */ + function get_data() + { + global $phpbb_root_path, $phpEx; + include("{$phpbb_root_path}config.$phpEx"); + + // Only send certain config vars + $config_vars = array( + 'active_sessions' => true, + 'allow_attachments' => true, + 'allow_autologin' => true, + 'allow_avatar' => true, + 'allow_avatar_local' => true, + 'allow_avatar_remote' => true, + 'allow_avatar_upload' => true, + 'allow_bbcode' => true, + 'allow_birthdays' => true, + 'allow_bookmarks' => true, + 'allow_emailreuse' => true, + 'allow_forum_notify' => true, + 'allow_mass_pm' => true, + 'allow_name_chars' => true, + 'allow_namechange' => true, + 'allow_nocensors' => true, + 'allow_pm_attach' => true, + 'allow_pm_report' => true, + 'allow_post_flash' => true, + 'allow_post_links' => true, + 'allow_privmsg' => true, + 'allow_quick_reply' => true, + 'allow_sig' => true, + 'allow_sig_bbcode' => true, + 'allow_sig_flash' => true, + 'allow_sig_img' => true, + 'allow_sig_links' => true, + 'allow_sig_pm' => true, + 'allow_sig_smilies' => true, + 'allow_smilies' => true, + 'allow_topic_notify' => true, + 'attachment_quota' => true, + 'auth_bbcode_pm' => true, + 'auth_flash_pm' => true, + 'auth_img_pm' => true, + 'auth_method' => true, + 'auth_smilies_pm' => true, + 'avatar_filesize' => true, + 'avatar_max_height' => true, + 'avatar_max_width' => true, + 'avatar_min_height' => true, + 'avatar_min_width' => true, + 'board_dst' => true, + 'board_email_form' => true, + 'board_hide_emails' => true, + 'board_timezone' => true, + 'browser_check' => true, + 'bump_interval' => true, + 'bump_type' => true, + 'cache_gc' => true, + 'captcha_plugin' => true, + 'captcha_gd' => true, + 'captcha_gd_foreground_noise' => true, + 'captcha_gd_x_grid' => true, + 'captcha_gd_y_grid' => true, + 'captcha_gd_wave' => true, + 'captcha_gd_3d_noise' => true, + 'captcha_gd_fonts' => true, + 'confirm_refresh' => true, + 'check_attachment_content' => true, + 'check_dnsbl' => true, + 'chg_passforce' => true, + 'cookie_secure' => true, + 'coppa_enable' => true, + 'database_gc' => true, + 'dbms_version' => true, + 'default_dateformat' => true, + 'display_last_edited' => true, + 'display_order' => true, + 'edit_time' => true, + 'email_check_mx' => true, + 'email_enable' => true, + 'email_function_name' => true, + 'email_package_size' => true, + 'enable_confirm' => true, + 'enable_pm_icons' => true, + 'enable_post_confirm' => true, + 'feed_enable' => true, + 'feed_limit' => true, + 'feed_overall_forums' => true, + 'feed_overall_forums_limit' => true, + 'feed_overall_topics' => true, + 'feed_overall_topics_limit' => true, + 'feed_forum' => true, + 'feed_topic' => true, + 'feed_item_statistics' => true, + 'flood_interval' => true, + 'force_server_vars' => true, + 'form_token_lifetime' => true, + 'form_token_mintime' => true, + 'form_token_sid_guests' => true, + 'forward_pm' => true, + 'forwarded_for_check' => true, + 'full_folder_action' => true, + 'fulltext_native_common_thres' => true, + 'fulltext_native_load_upd' => true, + 'fulltext_native_max_chars' => true, + 'fulltext_native_min_chars' => true, + 'gzip_compress' => true, + 'hot_threshold' => true, + 'img_create_thumbnail' => true, + 'img_display_inlined' => true, + 'img_imagick' => true, + 'img_link_height' => true, + 'img_link_width' => true, + 'img_max_height' => true, + 'img_max_thumb_width' => true, + 'img_max_width' => true, + 'img_min_thumb_filesize' => true, + 'ip_check' => true, + 'jab_enable' => true, + 'jab_package_size' => true, + 'jab_use_ssl' => true, + 'limit_load' => true, + 'limit_search_load' => true, + 'load_anon_lastread' => true, + 'load_birthdays' => true, + 'load_cpf_memberlist' => true, + 'load_cpf_viewprofile' => true, + 'load_cpf_viewtopic' => true, + 'load_db_lastread' => true, + 'load_db_track' => true, + 'load_jumpbox' => true, + 'load_moderators' => true, + 'load_online' => true, + 'load_online_guests' => true, + 'load_online_time' => true, + 'load_onlinetrack' => true, + 'load_search' => true, + 'load_tplcompile' => true, + 'load_user_activity' => true, + 'max_attachments' => true, + 'max_attachments_pm' => true, + 'max_autologin_time' => true, + 'max_filesize' => true, + 'max_filesize_pm' => true, + 'max_login_attempts' => true, + 'max_name_chars' => true, + 'max_num_search_keywords' => true, + 'max_pass_chars' => true, + 'max_poll_options' => true, + 'max_post_chars' => true, + 'max_post_font_size' => true, + 'max_post_img_height' => true, + 'max_post_img_width' => true, + 'max_post_smilies' => true, + 'max_post_urls' => true, + 'max_quote_depth' => true, + 'max_reg_attempts' => true, + 'max_sig_chars' => true, + 'max_sig_font_size' => true, + 'max_sig_img_height' => true, + 'max_sig_img_width' => true, + 'max_sig_smilies' => true, + 'max_sig_urls' => true, + 'min_name_chars' => true, + 'min_pass_chars' => true, + 'min_post_chars' => true, + 'min_search_author_chars' => true, + 'mime_triggers' => true, + 'new_member_post_limit' => true, + 'new_member_group_default' => true, + 'override_user_style' => true, + 'pass_complex' => true, + 'pm_edit_time' => true, + 'pm_max_boxes' => true, + 'pm_max_msgs' => true, + 'pm_max_recipients' => true, + 'posts_per_page' => true, + 'print_pm' => true, + 'queue_interval' => true, + 'require_activation' => true, + 'referer_validation' => true, + 'search_block_size' => true, + 'search_gc' => true, + 'search_interval' => true, + 'search_anonymous_interval' => true, + 'search_type' => true, + 'search_store_results' => true, + 'secure_allow_deny' => true, + 'secure_allow_empty_referer' => true, + 'secure_downloads' => true, + 'session_gc' => true, + 'session_length' => true, + 'smtp_auth_method' => true, + 'smtp_delivery' => true, + 'topics_per_page' => true, + 'tpl_allow_php' => true, + 'version' => true, + 'warnings_expire_days' => true, + 'warnings_gc' => true, + + 'num_files' => true, + 'num_posts' => true, + 'num_topics' => true, + 'num_users' => true, + 'record_online_users' => true, + ); + + $result = array(); + foreach ($config_vars as $name => $void) + { + if (isset($this->config[$name])) + { + $result['config_' . $name] = $this->config[$name]; + } + } + + $result['dbms'] = $dbms; + $result['acm_type'] = $acm_type; + $result['load_extensions'] = $load_extensions; + $result['user_agent'] = 'Unknown'; + + // Try to get user agent vendor and version + $match = array(); + $user_agent = (!empty($_SERVER['HTTP_USER_AGENT'])) ? (string) $_SERVER['HTTP_USER_AGENT'] : ''; + $agents = array('firefox', 'msie', 'opera', 'chrome', 'safari', 'mozilla', 'seamonkey', 'konqueror', 'netscape', 'gecko', 'navigator', 'mosaic', 'lynx', 'amaya', 'omniweb', 'avant', 'camino', 'flock', 'aol'); + + // We check here 1 by 1 because some strings occur after others (for example Mozilla [...] Firefox/) + foreach ($agents as $agent) + { + if (preg_match('#(' . $agent . ')[/ ]?([0-9.]*)#i', $user_agent, $match)) + { + $result['user_agent'] = $match[1] . ' ' . $match[2]; + break; + } + } + + return $result; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/search/fulltext_mysql.php b/phpBB/includes/search/fulltext_mysql.php new file mode 100644 index 0000000000..d1c1ff00d1 --- /dev/null +++ b/phpBB/includes/search/fulltext_mysql.php @@ -0,0 +1,932 @@ +<?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.' . $phpEx); + +/** +* fulltext_mysql +* Fulltext search for MySQL +* @package search +*/ +class fulltext_mysql extends search_backend +{ + var $stats = array(); + var $word_length = array(); + var $split_words = array(); + var $search_query; + var $common_words = array(); + var $pcre_properties = false; + var $mbstring_regex = false; + + function fulltext_mysql(&$error) + { + global $config; + + $this->word_length = array('min' => $config['fulltext_mysql_min_word_len'], 'max' => $config['fulltext_mysql_max_word_len']); + + if (version_compare(PHP_VERSION, '5.1.0', '>=') || (version_compare(PHP_VERSION, '5.0.0-dev', '<=') && version_compare(PHP_VERSION, '4.4.0', '>='))) + { + // While this is the proper range of PHP versions, PHP may not be linked with the bundled PCRE lib and instead with an older version + if (@preg_match('/\p{L}/u', 'a') !== false) + { + $this->pcre_properties = true; + } + } + + if (function_exists('mb_ereg')) + { + $this->mbstring_regex = true; + mb_regex_encoding('UTF-8'); + } + + $error = false; + } + + /** + * Checks for correct MySQL version and stores min/max word length in the config + */ + function init() + { + global $db, $user; + + if ($db->sql_layer != 'mysql4' && $db->sql_layer != 'mysqli') + { + return $user->lang['FULLTEXT_MYSQL_INCOMPATIBLE_VERSION']; + } + + $result = $db->sql_query('SHOW TABLE STATUS LIKE \'' . POSTS_TABLE . '\''); + $info = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $engine = ''; + if (isset($info['Engine'])) + { + $engine = $info['Engine']; + } + else if (isset($info['Type'])) + { + $engine = $info['Type']; + } + + if ($engine != 'MyISAM') + { + return $user->lang['FULLTEXT_MYSQL_NOT_MYISAM']; + } + + $sql = 'SHOW VARIABLES + LIKE \'ft\_%\''; + $result = $db->sql_query($sql); + + $mysql_info = array(); + while ($row = $db->sql_fetchrow($result)) + { + $mysql_info[$row['Variable_name']] = $row['Value']; + } + $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 + */ + function split_keywords(&$keywords, $terms) + { + global $config, $user; + + 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 + if ($this->pcre_properties) + { + $split_keywords = preg_replace('#([^\p{L}\p{N}\'*"()])#u', '$1$1', str_replace('\'\'', '\' \'', trim($split_keywords))); + } + else if ($this->mbstring_regex) + { + $split_keywords = mb_ereg_replace('([^\w\'*"()])', '\\1\\1', str_replace('\'\'', '\' \'', trim($split_keywords))); + } + else + { + $split_keywords = preg_replace('#([^\w\'*"()])#u', '$1$1', str_replace('\'\'', '\' \'', trim($split_keywords))); + } + + if ($this->pcre_properties) + { + $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]; + } + else if ($this->mbstring_regex) + { + mb_ereg_search_init($split_keywords, '(?:[^\w*"()]|^)([+\-|]?(?:[\w*"()]+\'?)*[\w*"()])(?:[^\w*"()]|$)'); + + while (($word = mb_ereg_search_regs())) + { + $this->split_words[] = $word[1]; + } + } + else + { + $matches = array(); + preg_match_all('#(?:[^\w*"()]|^)([+\-|]?(?:[\w*"()]+\'?)*[\w*"()])(?:[^\w*"()]|$)#u', $split_keywords, $matches); + $this->split_words = $matches[1]; + } + + // We limit the number of allowed keywords to minimize load on the database + if ($config['max_num_search_keywords'] && sizeof($this->split_words) > $config['max_num_search_keywords']) + { + trigger_error($user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', $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 < $config['fulltext_mysql_min_word_len']) || ($clean_len > $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 + */ + function split_message($text) + { + global $config; + + // Split words + if ($this->pcre_properties) + { + $text = preg_replace('#([^\p{L}\p{N}\'*])#u', '$1$1', str_replace('\'\'', '\' \'', trim($text))); + } + else if ($this->mbstring_regex) + { + $text = mb_ereg_replace('([^\w\'*])', '\\1\\1', str_replace('\'\'', '\' \'', trim($text))); + } + else + { + $text = preg_replace('#([^\w\'*])#u', '$1$1', str_replace('\'\'', '\' \'', trim($text))); + } + + if ($this->pcre_properties) + { + $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]; + } + else if ($this->mbstring_regex) + { + mb_ereg_search_init($text, '(?:[^\w*]|^)([+\-|]?(?:[\w*]+\'?)*[\w*])(?:[^\w*]|$)'); + + $text = array(); + while (($word = mb_ereg_search_regs())) + { + $text[] = $word[1]; + } + } + else + { + $matches = array(); + preg_match_all('#(?:[^\w*]|^)([+\-|]?(?:[\w*]+\'?)*[\w*])(?:[^\w*]|$)#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]) < $config['fulltext_mysql_min_word_len'] || utf8_strlen($text[$i]) > $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 string $author_name specifies the author match, when ANONYMOUS is also a search-match + * @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 + */ + 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, $author_name, &$id_ary, $start, $per_page) + { + global $config, $db; + + // 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) == 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 ' . $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'; + if (sizeof($author_ary) && $author_name) + { + // first one matches post of registered users, second one guests and deleted users + $sql_author = '(' . $db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')'; + } + else if (sizeof($author_ary)) + { + $sql_author = ' AND ' . $db->sql_in_set('p.poster_id', $author_ary); + } + else + { + $sql_author = ''; + } + + $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 ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : ''; + $sql_where_options .= $m_approve_fid_sql; + $sql_where_options .= $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 ('" . $db->sql_escape(htmlspecialchars_decode($this->search_query)) . "' IN BOOLEAN MODE) + $sql_where_options + ORDER BY $sql_sort"; + $result = $db->sql_query_limit($sql, $config['search_block_size'], $start); + + while ($row = $db->sql_fetchrow($result)) + { + $id_ary[] = $row[$field]; + } + $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 = $db->sql_query($sql); + $result_count = (int) $db->sql_fetchfield('result_count'); + $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 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 string $author_name specifies the author match, when ANONYMOUS is also a search-match + * @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 + */ + 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, $author_name, &$id_ary, $start, $per_page) + { + global $config, $db; + + // 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), + $author_name, + ))); + + // try reading the results from cache + $result_count = 0; + if ($this->obtain_ids($search_key, $result_count, $id_ary, $start, $per_page, $sort_dir) == SEARCH_RESULT_IN_CACHE) + { + return $result_count; + } + + $id_ary = array(); + + // Create some display specific sql strings + if ($author_name) + { + // first one matches post of registered users, second one guests and deleted users + $sql_author = '(' . $db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')'; + } + else + { + $sql_author = $db->sql_in_set('p.poster_id', $author_ary); + } + $sql_fora = (sizeof($ex_fid_ary)) ? ' AND ' . $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 ' . $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 = $db->sql_query_limit($sql, $config['search_block_size'], $start); + + while ($row = $db->sql_fetchrow($result)) + { + $id_ary[] = $row[$field]; + } + $db->sql_freeresult($result); + + // retrieve the total result count if needed + if (!$result_count) + { + $sql = 'SELECT FOUND_ROWS() as result_count'; + $result = $db->sql_query($sql); + $result_count = (int) $db->sql_fetchfield('result_count'); + $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 ... + */ + function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id) + { + global $db; + + // 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 + */ + function index_remove($post_ids, $author_ids, $forum_ids) + { + $this->destroy_cache(array(), $author_ids); + } + + /** + * Destroy old cache entries + */ + function tidy() + { + global $db, $config; + + // destroy too old cached search results + $this->destroy_cache(array()); + + set_config('search_last_gc', time(), true); + } + + /** + * Create fulltext index + */ + function create_index($acp_module, $u_action) + { + global $db; + + // 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'])) + { + if ($db->sql_layer == 'mysqli' || version_compare($db->sql_server_info(true), '4.1.3', '>=')) + { + //$alter[] = 'MODIFY post_subject varchar(100) COLLATE utf8_unicode_ci DEFAULT \'\' NOT NULL'; + } + else + { + $alter[] = 'MODIFY post_subject text NOT NULL'; + } + $alter[] = 'ADD FULLTEXT (post_subject)'; + } + + if (!isset($this->stats['post_text'])) + { + if ($db->sql_layer == 'mysqli' || version_compare($db->sql_server_info(true), '4.1.3', '>=')) + { + $alter[] = 'MODIFY post_text mediumtext COLLATE utf8_unicode_ci NOT NULL'; + } + else + { + $alter[] = 'MODIFY post_text mediumtext 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)) + { + $db->sql_query('ALTER TABLE ' . POSTS_TABLE . ' ' . implode(', ', $alter)); + } + + $db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE); + + return false; + } + + /** + * Drop fulltext index + */ + function delete_index($acp_module, $u_action) + { + global $db; + + // 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)) + { + $db->sql_query('ALTER TABLE ' . POSTS_TABLE . ' ' . implode(', ', $alter)); + } + + $db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE); + + return false; + } + + /** + * Returns true if both FULLTEXT indexes exist + */ + 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 + */ + function index_stats() + { + global $user; + + if (empty($this->stats)) + { + $this->get_stats(); + } + + return array( + $user->lang['FULLTEXT_MYSQL_TOTAL_POSTS'] => ($this->index_created()) ? $this->stats['total_posts'] : 0, + ); + } + + function get_stats() + { + global $db; + + if (strpos($db->sql_layer, 'mysql') === false) + { + $this->stats = array(); + return; + } + + $sql = 'SHOW INDEX + FROM ' . POSTS_TABLE; + $result = $db->sql_query($sql); + + while ($row = $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; + } + } + } + $db->sql_freeresult($result); + + $sql = 'SELECT COUNT(post_id) as total_posts + FROM ' . POSTS_TABLE; + $result = $db->sql_query($sql); + $this->stats['total_posts'] = (int) $db->sql_fetchfield('total_posts'); + $db->sql_freeresult($result); + } + + /** + * Display a note, that UTF-8 support is not available with certain versions of PHP + */ + function acp() + { + global $user, $config; + + $tpl = ' + <dl> + <dt><label>' . $user->lang['FULLTEXT_MYSQL_PCRE'] . '</label><br /><span>' . $user->lang['FULLTEXT_MYSQL_PCRE_EXPLAIN'] . '</span></dt> + <dd>' . (($this->pcre_properties) ? $user->lang['YES'] : $user->lang['NO']) . ' (PHP ' . PHP_VERSION . ')</dd> + </dl> + <dl> + <dt><label>' . $user->lang['FULLTEXT_MYSQL_MBSTRING'] . '</label><br /><span>' . $user->lang['FULLTEXT_MYSQL_MBSTRING_EXPLAIN'] . '</span></dt> + <dd>' . (($this->mbstring_regex) ? $user->lang['YES'] : $user->lang['NO']). '</dd> + </dl> + '; + + // 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 new file mode 100644 index 0000000000..5af3929ccd --- /dev/null +++ b/phpBB/includes/search/fulltext_native.php @@ -0,0 +1,1742 @@ +<?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.' . $phpEx); + +/** +* fulltext_native +* phpBB's own db driven fulltext search, version 2 +* @package search +*/ +class fulltext_native extends search_backend +{ + var $stats = array(); + var $word_length = array(); + var $search_query; + var $common_words = array(); + + var $must_contain_ids = array(); + var $must_not_contain_ids = array(); + var $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 fulltext_native(&$error) + { + global $phpbb_root_path, $phpEx, $config; + + $this->word_length = array('min' => $config['fulltext_native_min_chars'], 'max' => $config['fulltext_native_max_chars']); + + /** + * Load the UTF tools + */ + if (!class_exists('utf_normalizer')) + { + include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx); + } + + + $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 + */ + function split_keywords($keywords, $terms) + { + global $db, $user, $config; + + $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 ($config['max_num_search_keywords'] && $num_keywords > $config['max_num_search_keywords']) + { + trigger_error($user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', $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 ' . $db->sql_in_set('word_text', $exact_words); + $result = $db->sql_query($sql); + + // store an array of words and ids, remove common words + while ($row = $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']; + } + $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[] = '\'' . $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(sprintf($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'}[] = '\'' . $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(sprintf($user->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 string $author_name specifies the author match, when ANONYMOUS is also a search-match + * @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 + */ + 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, $author_name, &$id_ary, $start, $per_page) + { + global $config, $db; + + // 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), + $author_name, + ))); + + // try reading the results from cache + $total_results = 0; + if ($this->obtain_ids($search_key, $total_results, $id_ary, $start, $per_page, $sort_dir) == 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 = ''; + $left_join_topics = false; + $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': + $left_join_topics = true; + $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') + { + $left_join_topics = true; + $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[] = $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' => $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 ' . $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)) + { + if ($author_name) + { + // first one matches post of registered users, second one guests and deleted users + $sql_author = '(' . $db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')'; + } + else + { + $sql_author = $db->sql_in_set('p.poster_id', $author_ary); + } + $sql_where[] = $sql_author; + } + + if (sizeof($ex_fid_ary)) + { + $sql_where[] = $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 ($left_join_topics) + { + $sql_array_count['LEFT_JOIN'][] = array( + 'FROM' => array(TOPICS_TABLE => 't'), + 'ON' => 'p.topic_id = t.topic_id' + ); + } + + switch ($db->sql_layer) + { + case 'mysql4': + case 'mysqli': + + // 3.x does not support SQL_CALC_FOUND_ROWS + // $sql_array['SELECT'] = 'SQL_CALC_FOUND_ROWS ' . $sql_array['SELECT']; + $is_mysql = true; + + break; + + case 'sqlite': + $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 (' . $db->sql_build_query('SELECT', $sql_array_count) . ')'; + + // no break + + default: + $sql_array_count['SELECT'] = ($type == 'posts') ? 'COUNT(DISTINCT p.post_id) AS total_results' : 'COUNT(DISTINCT p.topic_id) AS total_results'; + $sql = (!$sql) ? $db->sql_build_query('SELECT', $sql_array_count) : $sql; + + $result = $db->sql_query($sql); + $total_results = (int) $db->sql_fetchfield('total_results'); + $db->sql_freeresult($result); + + if (!$total_results) + { + return false; + } + break; + } + + 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': + $left_join_topics = true; + break; + + case 'f': + $sql_array['FROM'][FORUMS_TABLE] = 'f'; + $sql_where[] = 'f.forum_id = p.forum_id'; + break; + } + + if ($left_join_topics) + { + $sql_array['LEFT_JOIN'][] = array( + 'FROM' => array(TOPICS_TABLE => 't'), + 'ON' => 'p.topic_id = t.topic_id' + ); + } + + $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 = $db->sql_build_query('SELECT', $sql_array); + $result = $db->sql_query_limit($sql, $config['search_block_size'], $start); + + while ($row = $db->sql_fetchrow($result)) + { + $id_ary[] = $row[(($type == 'posts') ? 'post_id' : 'topic_id')]; + } + $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) + { + // Count rows for the executed queries. Replace $select within $sql with SQL_CALC_FOUND_ROWS, and run it. + $sql_array_copy = $sql_array; + $sql_array_copy['SELECT'] = 'SQL_CALC_FOUND_ROWS p.post_id '; + + $sql = $db->sql_build_query('SELECT', $sql_array_copy); + unset($sql_array_copy); + + $db->sql_query($sql); + $db->sql_freeresult($result); + + $sql = 'SELECT FOUND_ROWS() as total_results'; + $result = $db->sql_query($sql); + $total_results = (int) $db->sql_fetchfield('total_results'); + $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 string $author_name specifies the author match, when ANONYMOUS is also a search-match + * @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 + */ + 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, $author_name, &$id_ary, $start, $per_page) + { + global $config, $db; + + // 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), + $author_name, + ))); + + // try reading the results from cache + $total_results = 0; + if ($this->obtain_ids($search_key, $total_results, $id_ary, $start, $per_page, $sort_dir) == SEARCH_RESULT_IN_CACHE) + { + return $total_results; + } + + $id_ary = array(); + + // Create some display specific sql strings + if ($author_name) + { + // first one matches post of registered users, second one guests and deleted users + $sql_author = '(' . $db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')'; + } + else + { + $sql_author = $db->sql_in_set('p.poster_id', $author_ary); + } + $sql_fora = (sizeof($ex_fid_ary)) ? ' AND ' . $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 ' . $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) + { + switch ($db->sql_layer) + { + case 'mysql4': + case 'mysqli': +// $select = 'SQL_CALC_FOUND_ROWS ' . $select; + $is_mysql = true; + break; + + default: + 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 ($db->sql_layer == 'sqlite') + { + $sql = 'SELECT COUNT(topic_id) as total_results + FROM (SELECT DISTINCT t.topic_id'; + } + else + { + $sql = 'SELECT COUNT(DISTINCT t.topic_id) as total_results'; + } + + $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" . (($db->sql_layer == 'sqlite') ? ')' : ''); + } + $result = $db->sql_query($sql); + + $total_results = (int) $db->sql_fetchfield('total_results'); + $db->sql_freeresult($result); + + if (!$total_results) + { + return false; + } + break; + } + } + + // 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 = $db->sql_query_limit($sql, $config['search_block_size'], $start); + + while ($row = $db->sql_fetchrow($result)) + { + $id_ary[] = $row[$field]; + } + $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); + + $db->sql_query($sql); + $db->sql_freeresult($result); + + $sql = 'SELECT FOUND_ROWS() as total_results'; + $result = $db->sql_query($sql); + $total_results = (int) $db->sql_fetchfield('total_results'); + $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 + */ + function split_message($text) + { + global $phpbb_root_path, $phpEx, $user; + + $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, UTF8_HANGUL_FIRST, 3) < 0 || strncmp($word, UTF8_HANGUL_LAST, 3) > 0) + && (strncmp($word, UTF8_CJK_FIRST, 3) < 0 || strncmp($word, UTF8_CJK_LAST, 3) > 0) + && (strncmp($word, UTF8_CJK_B_FIRST, 4) < 0 || strncmp($word, 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 + */ + function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id) + { + global $config, $db, $user; + + if (!$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 = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $which = ($row['title_match']) ? 'title' : 'post'; + $cur_words[$which][$row['word_text']] = $row['word_id']; + } + $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 ' . $db->sql_in_set('word_text', $unique_add_words); + $result = $db->sql_query($sql); + + $word_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $word_ids[$row['word_text']] = $row['word_id']; + } + $db->sql_freeresult($result); + $new_words = array_diff($unique_add_words, array_keys($word_ids)); + + $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); + } + $db->sql_return_on_error(true); + $db->sql_multi_insert(SEARCH_WORDLIST_TABLE, $sql_ary); + $db->sql_return_on_error(false); + } + unset($new_words, $sql_ary); + } + else + { + $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 ' . $db->sql_in_set('word_id', $sql_in) . ' + AND post_id = ' . intval($post_id) . " + AND title_match = $title_match"; + $db->sql_query($sql); + + $sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . ' + SET word_count = word_count - 1 + WHERE ' . $db->sql_in_set('word_id', $sql_in) . ' + AND word_count > 0'; + $db->sql_query($sql); + + unset($sql_in); + } + } + + $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 ' . $db->sql_in_set('word_text', $word_ary); + $db->sql_query($sql); + + $sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . ' + SET word_count = word_count + 1 + WHERE ' . $db->sql_in_set('word_text', $word_ary); + $db->sql_query($sql); + } + } + $db->sql_return_on_error(false); + + $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 + */ + function index_remove($post_ids, $author_ids, $forum_ids) + { + global $db; + + 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 ' . $db->sql_in_set('m.post_id', $post_ids) . ' + AND w.word_id = m.word_id'; + $result = $db->sql_query($sql); + + $message_word_ids = $title_word_ids = $word_texts = array(); + while ($row = $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']; + } + $db->sql_freeresult($result); + + if (sizeof($title_word_ids)) + { + $sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . ' + SET word_count = word_count - 1 + WHERE ' . $db->sql_in_set('word_id', $title_word_ids) . ' + AND word_count > 0'; + $db->sql_query($sql); + } + + if (sizeof($message_word_ids)) + { + $sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . ' + SET word_count = word_count - 1 + WHERE ' . $db->sql_in_set('word_id', $message_word_ids) . ' + AND word_count > 0'; + $db->sql_query($sql); + } + + unset($title_word_ids); + unset($message_word_ids); + + $sql = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE . ' + WHERE ' . $db->sql_in_set('post_id', $post_ids); + $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 + */ + function tidy() + { + global $db, $config; + + // 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 (!$config['fulltext_native_load_upd']) + { + set_config('search_last_gc', time(), true); + return; + } + + $destroy_cache_words = array(); + + // Remove common words + if ($config['num_posts'] >= 100 && $config['fulltext_native_common_thres']) + { + $common_threshold = ((double) $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($config['num_posts'] * $common_threshold) . ' + OR word_common = 1'; + $result = $db->sql_query($sql); + + $sql_in = array(); + while ($row = $db->sql_fetchrow($result)) + { + $sql_in[] = $row['word_id']; + $destroy_cache_words[] = $row['word_text']; + } + $db->sql_freeresult($result); + + if (sizeof($sql_in)) + { + // Flag the words + $sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . ' + SET word_common = 1 + WHERE ' . $db->sql_in_set('word_id', $sql_in); + $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 ' . $db->sql_in_set('word_id', $sql_in); + $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 + */ + function delete_index($acp_module, $u_action) + { + global $db; + + switch ($db->sql_layer) + { + case 'sqlite': + case 'firebird': + $db->sql_query('DELETE FROM ' . SEARCH_WORDLIST_TABLE); + $db->sql_query('DELETE FROM ' . SEARCH_WORDMATCH_TABLE); + $db->sql_query('DELETE FROM ' . SEARCH_RESULTS_TABLE); + break; + + default: + $db->sql_query('TRUNCATE TABLE ' . SEARCH_WORDLIST_TABLE); + $db->sql_query('TRUNCATE TABLE ' . SEARCH_WORDMATCH_TABLE); + $db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE); + break; + } + } + + /** + * Returns true if both FULLTEXT indexes exist + */ + 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 + */ + function index_stats() + { + global $user; + + if (!sizeof($this->stats)) + { + $this->get_stats(); + } + + return array( + $user->lang['TOTAL_WORDS'] => $this->stats['total_words'], + $user->lang['TOTAL_MATCHES'] => $this->stats['total_matches']); + } + + function get_stats() + { + global $db; + + $sql = 'SELECT COUNT(*) as total_words + FROM ' . SEARCH_WORDLIST_TABLE; + $result = $db->sql_query($sql); + $this->stats['total_words'] = (int) $db->sql_fetchfield('total_words'); + $db->sql_freeresult($result); + + $sql = 'SELECT COUNT(*) as total_matches + FROM ' . SEARCH_WORDMATCH_TABLE; + $result = $db->sql_query($sql); + $this->stats['total_matches'] = (int) $db->sql_fetchfield('total_matches'); + $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 + * @param string $encoding Text encoding + * @return string Cleaned up text, only alphanumeric chars are left + * + * @todo normalizer::cleanup being able to be used? + */ + function cleanup($text, $allowed_chars = null, $encoding = 'utf-8') + { + global $phpbb_root_path, $phpEx; + static $conv = array(), $conv_loaded = array(); + $words = $allow = array(); + + // Convert the text to UTF-8 + $encoding = strtolower($encoding); + if ($encoding != 'utf-8') + { + $text = utf8_recode($text, $encoding); + } + + $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 . '.' . $phpEx; + + 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 + */ + function acp() + { + global $user, $config; + + + /** + * 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">' . $user->lang['YES_SEARCH_UPDATE'] . ':</label><br /><span>' . $user->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"' . (($config['fulltext_native_load_upd']) ? ' checked="checked"' : '') . ' class="radio" /> ' . $user->lang['YES'] . '</label><label><input type="radio" name="config[fulltext_native_load_upd]" value="0"' . ((!$config['fulltext_native_load_upd']) ? ' checked="checked"' : '') . ' class="radio" /> ' . $user->lang['NO'] . '</label></dd> + </dl> + <dl> + <dt><label for="fulltext_native_min_chars">' . $user->lang['MIN_SEARCH_CHARS'] . ':</label><br /><span>' . $user->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) $config['fulltext_native_min_chars'] . '" /></dd> + </dl> + <dl> + <dt><label for="fulltext_native_max_chars">' . $user->lang['MAX_SEARCH_CHARS'] . ':</label><br /><span>' . $user->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) $config['fulltext_native_max_chars'] . '" /></dd> + </dl> + <dl> + <dt><label for="fulltext_native_common_thres">' . $user->lang['COMMON_WORD_THRESHOLD'] . ':</label><br /><span>' . $user->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="' . (double) $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/index.htm b/phpBB/includes/search/index.htm new file mode 100644 index 0000000000..ee1f723a7d --- /dev/null +++ b/phpBB/includes/search/index.htm @@ -0,0 +1,10 @@ +<html> +<head> +<title></title> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> +</head> + +<body bgcolor="#FFFFFF" text="#000000"> + +</body> +</html> diff --git a/phpBB/includes/search/search.php b/phpBB/includes/search/search.php new file mode 100644 index 0000000000..2f20d11495 --- /dev/null +++ b/phpBB/includes/search/search.php @@ -0,0 +1,320 @@ +<?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 +*/ +define('SEARCH_RESULT_NOT_IN_CACHE', 0); +define('SEARCH_RESULT_IN_CACHE', 1); +define('SEARCH_RESULT_INCOMPLETE', 2); + +/** +* 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 +{ + var $ignore_words = array(); + var $match_synonym = array(); + var $replace_synonym = array(); + + function search_backend(&$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 + */ + function get_ignore_words() + { + if (!sizeof($this->ignore_words)) + { + global $user, $phpEx; + + $words = array(); + + if (file_exists("{$user->lang_path}{$user->lang_name}/search_ignore_words.$phpEx")) + { + // include the file containing ignore words + include("{$user->lang_path}{$user->lang_name}/search_ignore_words.$phpEx"); + } + + $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 + */ + function get_synonyms() + { + if (!sizeof($this->match_synonym)) + { + global $user, $phpEx; + + $synonyms = array(); + + if (file_exists("{$user->lang_path}{$user->lang_name}/search_synonyms.$phpEx")) + { + // include the file containing synonyms + include("{$user->lang_path}{$user->lang_name}/search_synonyms.$phpEx"); + } + + $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 + */ + function obtain_ids($search_key, &$result_count, &$id_ary, $start, $per_page, $sort_dir) + { + global $cache; + + if (!($stored_ids = $cache->get('_search_results_' . $search_key))) + { + // no search results cached for this search_key + return 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 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 SEARCH_RESULT_INCOMPLETE; + } + return 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. + */ + function save_ids($search_key, $keywords, $author_ary, $result_count, &$id_ary, $start, $sort_dir) + { + global $cache, $config, $db, $user; + + $length = min(sizeof($id_ary), $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 = $cache->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 = \'' . $db->sql_escape($search_key) . '\''; + $result = $db->sql_query($sql); + + if (!$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 . ' ' . $db->sql_build_array('INSERT', $sql_ary); + $db->sql_query($sql); + } + $db->sql_freeresult($result); + } + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_last_search = ' . time() . ' + WHERE user_id = ' . $user->data['user_id']; + $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 * $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 * $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 * $config['search_block_size']; $i > $n; $i--) + { + if (isset($store[$i])) + { + unset($store[$i]); + } + } + } + $cache->put('_search_results_' . $search_key, $store, $config['search_store_results']); + + $sql = 'UPDATE ' . SEARCH_RESULTS_TABLE . ' + SET search_time = ' . time() . ' + WHERE search_key = \'' . $db->sql_escape($search_key) . '\''; + $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. + */ + function destroy_cache($words, $authors = false) + { + global $db, $cache, $config; + + // clear all searches that searched for the specified words + if (sizeof($words)) + { + $sql_where = ''; + foreach ($words as $word) + { + $sql_where .= " OR search_keywords " . $db->sql_like_expression($db->any_char . $word . $db->any_char); + } + + $sql = 'SELECT search_key + FROM ' . SEARCH_RESULTS_TABLE . " + WHERE search_keywords LIKE '%*%' $sql_where"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $cache->destroy('_search_results_' . $row['search_key']); + } + $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 = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $cache->destroy('_search_results_' . $row['search_key']); + } + $db->sql_freeresult($result); + } + + $sql = 'DELETE + FROM ' . SEARCH_RESULTS_TABLE . ' + WHERE search_time < ' . (time() - $config['search_store_results']); + $db->sql_query($sql); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php new file mode 100644 index 0000000000..bf41fea7de --- /dev/null +++ b/phpBB/includes/session.php @@ -0,0 +1,2342 @@ +<?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; +} + +/** +* Session class +* @package phpBB3 +*/ +class session +{ + var $cookie_data = array(); + var $page = array(); + var $data = array(); + var $browser = ''; + var $forwarded_for = ''; + var $host = ''; + var $session_id = ''; + var $ip = ''; + var $load = 0; + var $time_now = 0; + var $update_session_page = true; + + /** + * Extract current session page + * + * @param string $root_path current root path (phpbb_root_path) + */ + function extract_current_page($root_path) + { + $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 $key => $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_realpath($root_path))); + $page_dirs = explode('/', str_replace('\\', '/', phpbb_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' => (isset($_REQUEST['f']) && $_REQUEST['f'] > 0) ? (int) $_REQUEST['f'] : 0, + ); + + return $page_array; + } + + /** + * Get valid hostname/port. HTTP_HOST is used, SERVER_NAME if HTTP_HOST not present. + */ + function extract_current_hostname() + { + global $config; + + // 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($config['cookie_domain']) && $host === $config['cookie_domain']) || (isset($config['server_name']) && $host === $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); + $host = (!empty($host['host'])) ? $host['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($config['server_name'])) + { + $host = $config['server_name']; + } + else if (!empty($config['cookie_domain'])) + { + $host = (strpos($config['cookie_domain'], '.') === 0) ? substr($config['cookie_domain'], 1) : $config['cookie_domain']; + } + else + { + // Set to OS hostname or localhost + $host = (function_exists('php_uname')) ? 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; + } + + /** + * 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 circumvent certain scripts to update the users last visited page. + */ + function session_begin($update_session_page = true) + { + global $phpEx, $SID, $_SID, $_EXTRA_URL, $db, $config, $phpbb_root_path; + + // Give us some basic information + $this->time_now = time(); + $this->cookie_data = array('u' => 0, 'k' => ''); + $this->update_session_page = $update_session_page; + $this->browser = (!empty($_SERVER['HTTP_USER_AGENT'])) ? htmlspecialchars((string) $_SERVER['HTTP_USER_AGENT']) : ''; + $this->referer = (!empty($_SERVER['HTTP_REFERER'])) ? htmlspecialchars((string) $_SERVER['HTTP_REFERER']) : ''; + $this->forwarded_for = (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) ? htmlspecialchars((string) $_SERVER['HTTP_X_FORWARDED_FOR']) : ''; + + $this->host = $this->extract_current_hostname(); + $this->page = $this->extract_current_page($phpbb_root_path); + + // if the forwarded for header shall be checked we have to validate its contents + if ($config['forwarded_for_check']) + { + $this->forwarded_for = preg_replace('#[ ]{2,}#', ' ', str_replace(array(',', ' '), ' ', $this->forwarded_for)); + + // split the list of IPs + $ips = explode(' ', $this->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 + $this->forwarded_for = ''; + break; + } + } + } + else + { + $this->forwarded_for = ''; + } + + if (isset($_COOKIE[$config['cookie_name'] . '_sid']) || isset($_COOKIE[$config['cookie_name'] . '_u'])) + { + $this->cookie_data['u'] = request_var($config['cookie_name'] . '_u', 0, false, true); + $this->cookie_data['k'] = request_var($config['cookie_name'] . '_k', '', false, true); + $this->session_id = request_var($config['cookie_name'] . '_sid', '', false, true); + + $SID = (defined('NEED_SID')) ? '?sid=' . $this->session_id : '?sid='; + $_SID = (defined('NEED_SID')) ? $this->session_id : ''; + + if (empty($this->session_id)) + { + $this->session_id = $_SID = request_var('sid', ''); + $SID = '?sid=' . $this->session_id; + $this->cookie_data = array('u' => 0, 'k' => ''); + } + } + else + { + $this->session_id = $_SID = request_var('sid', ''); + $SID = '?sid=' . $this->session_id; + } + + $_EXTRA_URL = array(); + + // Why no forwarded_for et al? Well, too easily spoofed. With the results of my recent requests + // it's pretty clear that in the majority of cases you'll at least be left with a proxy/cache ip. + $this->ip = (!empty($_SERVER['REMOTE_ADDR'])) ? htmlspecialchars((string) $_SERVER['REMOTE_ADDR']) : ''; + $this->ip = preg_replace('#[ ]{2,}#', ' ', str_replace(array(',', ' '), ' ', $this->ip)); + + // split the list of IPs + $ips = explode(' ', $this->ip); + + // Default IP if REMOTE_ADDR is invalid + $this->ip = '127.0.0.1'; + + 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)) + { + // Just break + break; + } + + // Use the last in chain + $this->ip = $ip; + } + + $this->load = false; + + // Load limit check (if applicable) + if ($config['limit_load'] || $config['limit_search_load']) + { + if ((function_exists('sys_getloadavg') && $load = sys_getloadavg()) || ($load = explode(' ', @file_get_contents('/proc/loadavg')))) + { + $this->load = array_slice($load, 0, 1); + $this->load = floatval($this->load[0]); + } + else + { + set_config('limit_load', '0'); + set_config('limit_search_load', '0'); + } + } + + // Is session_id is set or session_id is set and matches the url param if required + if (!empty($this->session_id) && (!defined('NEED_SID') || (isset($_GET['sid']) && $this->session_id === $_GET['sid']))) + { + $sql = 'SELECT u.*, s.* + FROM ' . SESSIONS_TABLE . ' s, ' . USERS_TABLE . " u + WHERE s.session_id = '" . $db->sql_escape($this->session_id) . "' + AND u.user_id = s.session_user_id"; + $result = $db->sql_query($sql); + $this->data = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + // Did the session exist in the DB? + if (isset($this->data['user_id'])) + { + // Validate IP length according to admin ... enforces an IP + // check on bots if admin requires this +// $quadcheck = ($config['ip_check_bot'] && $this->data['user_type'] & USER_BOT) ? 4 : $config['ip_check']; + + if (strpos($this->ip, ':') !== false && strpos($this->data['session_ip'], ':') !== false) + { + $s_ip = short_ipv6($this->data['session_ip'], $config['ip_check']); + $u_ip = short_ipv6($this->ip, $config['ip_check']); + } + else + { + $s_ip = implode('.', array_slice(explode('.', $this->data['session_ip']), 0, $config['ip_check'])); + $u_ip = implode('.', array_slice(explode('.', $this->ip), 0, $config['ip_check'])); + } + + $s_browser = ($config['browser_check']) ? trim(strtolower(substr($this->data['session_browser'], 0, 149))) : ''; + $u_browser = ($config['browser_check']) ? trim(strtolower(substr($this->browser, 0, 149))) : ''; + + $s_forwarded_for = ($config['forwarded_for_check']) ? substr($this->data['session_forwarded_for'], 0, 254) : ''; + $u_forwarded_for = ($config['forwarded_for_check']) ? substr($this->forwarded_for, 0, 254) : ''; + + // referer checks + // The @ before $config['referer_validation'] suppresses notices present while running the updater + $check_referer_path = (@$config['referer_validation'] == REFERER_VALIDATE_PATH); + $referer_valid = true; + + // we assume HEAD and TRACE to be foul play and thus only whitelist GET + if (@$config['referer_validation'] && isset($_SERVER['REQUEST_METHOD']) && strtolower($_SERVER['REQUEST_METHOD']) !== 'get') + { + $referer_valid = $this->validate_referer($check_referer_path); + } + + if ($u_ip === $s_ip && $s_browser === $u_browser && $s_forwarded_for === $u_forwarded_for && $referer_valid) + { + $session_expired = false; + + // Check whether the session is still valid if we have one + $method = basename(trim($config['auth_method'])); + include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx); + + $method = 'validate_session_' . $method; + if (function_exists($method)) + { + if (!$method($this->data)) + { + $session_expired = true; + } + } + + if (!$session_expired) + { + // 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 - ($config['session_length'] + 60)) + { + $session_expired = true; + } + } + else if (!$config['allow_autologin'] || ($config['max_autologin_time'] && $this->data['session_time'] < $this->time_now - (86400 * (int) $config['max_autologin_time']) + 60)) + { + $session_expired = true; + } + } + + if (!$session_expired) + { + // 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->page['page'])) + { + $sql_ary = array('session_time' => $this->time_now); + + if ($this->update_session_page) + { + $sql_ary['session_page'] = substr($this->page['page'], 0, 199); + $sql_ary['session_forum_id'] = $this->page['forum']; + } + + $db->sql_return_on_error(true); + + $sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE session_id = '" . $db->sql_escape($this->session_id) . "'"; + $result = $db->sql_query($sql); + + $db->sql_return_on_error(false); + + // If the database is not yet updated, there will be an error due to the session_forum_id + // @todo REMOVE for 3.0.2 + if ($result === false) + { + unset($sql_ary['session_forum_id']); + + $sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE session_id = '" . $db->sql_escape($this->session_id) . "'"; + $db->sql_query($sql); + } + + if ($this->data['user_id'] != ANONYMOUS && !empty($config['new_member_post_limit']) && $this->data['user_new'] && $config['new_member_post_limit'] <= $this->data['user_posts']) + { + $this->leave_newly_registered(); + } + } + + $this->data['is_registered'] = ($this->data['user_id'] != ANONYMOUS && ($this->data['user_type'] == USER_NORMAL || $this->data['user_type'] == USER_FOUNDER)) ? true : false; + $this->data['is_bot'] = (!$this->data['is_registered'] && $this->data['user_id'] != ANONYMOUS) ? true : false; + $this->data['user_lang'] = basename($this->data['user_lang']); + + return true; + } + } + else + { + // Added logging temporarly to help debug bugs... + if (defined('DEBUG_EXTRA') && $this->data['user_id'] != ANONYMOUS) + { + if ($referer_valid) + { + add_log('critical', 'LOG_IP_BROWSER_FORWARDED_CHECK', $u_ip, $s_ip, $u_browser, $s_browser, htmlspecialchars($u_forwarded_for), htmlspecialchars($s_forwarded_for)); + } + else + { + add_log('critical', 'LOG_REFERER_INVALID', $this->referer); + } + } + } + } + } + + // 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. + */ + function session_create($user_id = false, $set_admin = false, $persist_login = false, $viewonline = true) + { + global $SID, $_SID, $db, $config, $cache, $phpbb_root_path, $phpEx; + + $this->data = array(); + + /* Garbage collection ... remove old sessions updating user information + // if necessary. It means (potentially) 11 queries but only infrequently + if ($this->time_now > $config['session_last_gc'] + $config['session_gc']) + { + $this->session_gc(); + }*/ + + // Do we allow autologin on this board? No? Then override anything + // that may be requested here + if (!$config['allow_autologin']) + { + $this->cookie_data['k'] = $persist_login = false; + } + + /** + * 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 + */ + $bot = false; + $active_bots = $cache->obtain_bots(); + + foreach ($active_bots as $row) + { + if ($row['bot_agent'] && preg_match('#' . str_replace('\*', '.*?', preg_quote($row['bot_agent'], '#')) . '#i', $this->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) + { + $bot_ip = trim($bot_ip); + + if (!$bot_ip) + { + continue; + } + + if (strpos($this->ip, $bot_ip) === 0) + { + $bot = (int) $row['user_id']; + break; + } + } + } + + if ($bot) + { + break; + } + } + + $method = basename(trim($config['auth_method'])); + include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx); + + $method = 'autologin_' . $method; + if (function_exists($method)) + { + $this->data = $method(); + + if (sizeof($this->data)) + { + $this->cookie_data['k'] = ''; + $this->cookie_data['u'] = $this->data['user_id']; + } + } + + // 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 (' . USER_NORMAL . ', ' . USER_FOUNDER . ") + AND k.user_id = u.user_id + AND k.key_id = '" . $db->sql_escape(md5($this->cookie_data['k'])) . "'"; + $result = $db->sql_query($sql); + $this->data = $db->sql_fetchrow($result); + $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 (' . USER_NORMAL . ', ' . USER_FOUNDER . ')'; + $result = $db->sql_query($sql); + $this->data = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + $bot = false; + } + + // 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 = $db->sql_query($sql); + $this->data = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + } + + if ($this->data['user_id'] != ANONYMOUS && !$bot) + { + $this->data['session_last_visit'] = (isset($this->data['session_time']) && $this->data['session_time']) ? $this->data['session_time'] : (($this->data['user_lastvisit']) ? $this->data['user_lastvisit'] : time()); + } + else + { + $this->data['session_last_visit'] = $this->time_now; + } + + // Force user id to be integer... + $this->data['user_id'] = (int) $this->data['user_id']; + + // 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'] != USER_FOUNDER) + { + if (!$config['forwarded_for_check']) + { + $this->check_ban($this->data['user_id'], $this->ip); + } + else + { + $ips = explode(' ', $this->forwarded_for); + $ips[] = $this->ip; + $this->check_ban($this->data['user_id'], $ips); + } + } + + $this->data['is_registered'] = (!$bot && $this->data['user_id'] != ANONYMOUS && ($this->data['user_type'] == USER_NORMAL || $this->data['user_type'] == USER_FOUNDER)) ? true : false; + $this->data['is_bot'] = ($bot) ? true : false; + + // If our friend is a bot, we re-assign a previously assigned session + if ($this->data['is_bot'] && $bot == $this->data['user_id'] && $this->data['session_id']) + { + // Only assign the current session if the ip, browser and forwarded_for match... + if (strpos($this->ip, ':') !== false && strpos($this->data['session_ip'], ':') !== false) + { + $s_ip = short_ipv6($this->data['session_ip'], $config['ip_check']); + $u_ip = short_ipv6($this->ip, $config['ip_check']); + } + else + { + $s_ip = implode('.', array_slice(explode('.', $this->data['session_ip']), 0, $config['ip_check'])); + $u_ip = implode('.', array_slice(explode('.', $this->ip), 0, $config['ip_check'])); + } + + $s_browser = ($config['browser_check']) ? trim(strtolower(substr($this->data['session_browser'], 0, 149))) : ''; + $u_browser = ($config['browser_check']) ? trim(strtolower(substr($this->browser, 0, 149))) : ''; + + $s_forwarded_for = ($config['forwarded_for_check']) ? substr($this->data['session_forwarded_for'], 0, 254) : ''; + $u_forwarded_for = ($config['forwarded_for_check']) ? substr($this->forwarded_for, 0, 254) : ''; + + if ($u_ip === $s_ip && $s_browser === $u_browser && $s_forwarded_for === $u_forwarded_for) + { + $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->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->page['page'], 0, 199); + $sql_ary['session_forum_id'] = $this->page['forum']; + } + + $sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE session_id = '" . $db->sql_escape($this->session_id) . "'"; + $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']; + $db->sql_query($sql); + } + + $SID = '?sid='; + $_SID = ''; + return true; + } + else + { + // If the ip and browser does not match make sure we only have one bot assigned to one session + $db->sql_query('DELETE FROM ' . SESSIONS_TABLE . ' WHERE session_user_id = ' . $this->data['user_id']); + } + } + + $session_autologin = (($this->cookie_data['k'] || $persist_login) && $this->data['is_registered']) ? true : false; + $set_admin = ($set_admin && $this->data['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->browser, 0, 149)), + 'session_forwarded_for' => (string) $this->forwarded_for, + 'session_ip' => (string) $this->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->page['page'], 0, 199); + $sql_ary['session_forum_id'] = $this->page['forum']; + } + + $db->sql_return_on_error(true); + + $sql = 'DELETE + FROM ' . SESSIONS_TABLE . ' + WHERE session_id = \'' . $db->sql_escape($this->session_id) . '\' + AND session_user_id = ' . ANONYMOUS; + + if (!defined('IN_ERROR_HANDLER') && (!$this->session_id || !$db->sql_query($sql) || !$db->sql_affectedrows())) + { + // Limit new sessions in 1 minute period (if required) + if (empty($this->data['session_time']) && $config['active_sessions']) + { +// $db->sql_return_on_error(false); + + $sql = 'SELECT COUNT(session_id) AS sessions + FROM ' . SESSIONS_TABLE . ' + WHERE session_time >= ' . ($this->time_now - 60); + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ((int) $row['sessions'] > (int) $config['active_sessions']) + { + header('HTTP/1.1 503 Service Unavailable'); + trigger_error('BOARD_UNAVAILABLE'); + } + } + } + + // Since we re-create the session id here, the inserted row must be unique. Therefore, we display potential errors. + // Commented out because it will not allow forums to update correctly +// $db->sql_return_on_error(false); + + // 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(unique_id()); + + $sql_ary['session_id'] = (string) $this->session_id; + $sql_ary['session_page'] = (string) substr($this->page['page'], 0, 199); + $sql_ary['session_forum_id'] = $this->page['forum']; + + $sql = 'INSERT INTO ' . SESSIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); + $db->sql_query($sql); + + $db->sql_return_on_error(false); + + // Regenerate autologin/persistent login key + if ($session_autologin) + { + $this->set_login_key(); + } + + // refresh data + $SID = '?sid=' . $this->session_id; + $_SID = $this->session_id; + $this->data = array_merge($this->data, $sql_ary); + + if (!$bot) + { + $cookie_expire = $this->time_now + (($config['max_autologin_time']) ? 86400 * (int) $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); + + $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($config['session_length'], $config['form_token_lifetime']))); + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ((int) $row['sessions'] <= 1 || empty($this->data['user_form_salt'])) + { + $this->data['user_form_salt'] = unique_id(); + // Update the form key + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_form_salt = \'' . $db->sql_escape($this->data['user_form_salt']) . '\' + WHERE user_id = ' . (int) $this->data['user_id']; + $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']; + $db->sql_query($sql); + + $SID = '?sid='; + $_SID = ''; + } + + 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. + */ + function session_kill($new_session = true) + { + global $SID, $_SID, $db, $config, $phpbb_root_path, $phpEx; + + $sql = 'DELETE FROM ' . SESSIONS_TABLE . " + WHERE session_id = '" . $db->sql_escape($this->session_id) . "' + AND session_user_id = " . (int) $this->data['user_id']; + $db->sql_query($sql); + + // Allow connecting logout with external auth method logout + $method = basename(trim($config['auth_method'])); + include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx); + + $method = 'logout_' . $method; + if (function_exists($method)) + { + $method($this->data, $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']; + $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 = '" . $db->sql_escape(md5($this->cookie_data['k'])) . "'"; + $db->sql_query($sql); + } + + // Reset the data array + $this->data = array(); + + $sql = 'SELECT * + FROM ' . USERS_TABLE . ' + WHERE user_id = ' . ANONYMOUS; + $result = $db->sql_query($sql); + $this->data = $db->sql_fetchrow($result); + $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); + + $SID = '?sid='; + $this->session_id = $_SID = ''; + + // To make sure a valid session is created we create one for the anonymous user + if ($new_session) + { + $this->session_create(ANONYMOUS); + } + + return true; + } + + /** + * 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. + */ + function session_gc() + { + global $db, $config, $phpbb_root_path, $phpEx; + + $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 - $config['session_length']); + $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 - $config['session_length']) . ' + GROUP BY session_user_id, session_page'; + $result = $db->sql_query_limit($sql, $batch_size); + + $del_user_id = array(); + $del_sessions = 0; + + while ($row = $db->sql_fetchrow($result)) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_lastvisit = ' . (int) $row['recent_time'] . ", user_lastpage = '" . $db->sql_escape($row['session_page']) . "' + WHERE user_id = " . (int) $row['session_user_id']; + $db->sql_query($sql); + + $del_user_id[] = (int) $row['session_user_id']; + $del_sessions++; + } + $db->sql_freeresult($result); + + if (sizeof($del_user_id)) + { + // Delete expired sessions + $sql = 'DELETE FROM ' . SESSIONS_TABLE . ' + WHERE ' . $db->sql_in_set('session_user_id', $del_user_id) . ' + AND session_time < ' . ($this->time_now - $config['session_length']); + $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 ($config['max_autologin_time']) + { + $sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . ' + WHERE last_login < ' . (time() - (86400 * (int) $config['max_autologin_time'])); + $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." . $phpEx); + } + phpbb_captcha_factory::garbage_collect($config['captcha_plugin']); + } + + return; + } + + /** + * Sets a cookie + * + * 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. + */ + function set_cookie($name, $cookiedata, $cookietime) + { + global $config; + + $name_data = rawurlencode($config['cookie_name'] . '_' . $name) . '=' . rawurlencode($cookiedata); + $expire = gmdate('D, d-M-Y H:i:s \\G\\M\\T', $cookietime); + $domain = (!$config['cookie_domain'] || $config['cookie_domain'] == 'localhost' || $config['cookie_domain'] == '127.0.0.1') ? '' : '; domain=' . $config['cookie_domain']; + + header('Set-Cookie: ' . $name_data . (($cookietime) ? '; expires=' . $expire : '') . '; path=' . $config['cookie_path'] . $domain . ((!$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 string|array $user_ips Can contain a string with one IP or an array of multiple IPs + */ + function check_ban($user_id = false, $user_ips = false, $user_email = false, $return = false) + { + global $config, $db; + + 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 = $db->sql_query($sql, $cache_ttl); + + $ban_triggered_by = 'user'; + while ($row = $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 + } + } + } + $db->sql_freeresult($result); + + if ($banned && !$return) + { + global $template; + + // 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) + { + global $phpEx; + + $this->setup('ucp'); + $this->data['is_registered'] = $this->data['is_bot'] = false; + + // 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.$phpEx"); + + // 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:' . $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) + * + * @author satmd (from the php manual) + * @param string $mode register/post - spamcop for example is ommitted for posting + * @return false if ip is not blacklisted, else an array([checked server], [lookup]) + */ + function check_dnsbl($mode, $ip = false) + { + if ($ip === false) + { + $ip = $this->ip; + } + + $dnsbl_check = array( + 'sbl.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; + } + + /** + * Check if URI is blacklisted + * This should be called only where absolutly necessary, for example on the submitted website field + * This function is not in use at the moment and is only included for testing purposes, it may not work at all! + * This means it is untested at the moment and therefore commented out + * + * @param string $uri URI to check + * @return true if uri is on blacklist, else false. Only blacklist is checked (~zero FP), no grey lists + function check_uribl($uri) + { + // Normally parse_url() is not intended to parse uris + // We need to get the top-level domain name anyway... change. + $uri = parse_url($uri); + + if ($uri === false || empty($uri['host'])) + { + return false; + } + + $uri = trim($uri['host']); + + if ($uri) + { + // One problem here... the return parameter for the "windows" method is different from what + // we expect... this may render this check useless... + if (phpbb_checkdnsrr($uri . '.multi.uribl.com.', 'A') === true) + { + return true; + } + } + + 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. + */ + function set_login_key($user_id = false, $key = false, $user_ip = false) + { + global $config, $db; + + $user_id = ($user_id === false) ? $this->data['user_id'] : $user_id; + $user_ip = ($user_ip === false) ? $this->ip : $user_ip; + $key = ($key === false) ? (($this->cookie_data['k']) ? $this->cookie_data['k'] : false) : $key; + + $key_id = unique_id(hexdec(substr($this->session_id, 0, 8))); + + $sql_ary = array( + 'key_id' => (string) md5($key_id), + 'last_ip' => (string) $this->ip, + 'last_login' => (int) time() + ); + + if (!$key) + { + $sql_ary += array( + 'user_id' => (int) $user_id + ); + } + + if ($key) + { + $sql = 'UPDATE ' . SESSIONS_KEYS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . (int) $user_id . " + AND key_id = '" . $db->sql_escape(md5($key)) . "'"; + } + else + { + $sql = 'INSERT INTO ' . SESSIONS_KEYS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); + } + $db->sql_query($sql); + + $this->cookie_data['k'] = $key_id; + + return false; + } + + /** + * 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 + */ + function reset_login_keys($user_id = false) + { + global $config, $db; + + $user_id = ($user_id === false) ? $this->data['user_id'] : $user_id; + + $sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . ' + WHERE user_id = ' . (int) $user_id; + $db->sql_query($sql); + + // Update last visit info first before deleting sessions + $sql = 'SELECT session_time, session_page + FROM ' . SESSIONS_TABLE . ' + WHERE session_user_id = ' . (int) $user_id . ' + ORDER BY session_time DESC'; + $result = $db->sql_query_limit($sql, 1); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_lastvisit = ' . (int) $row['session_time'] . ", user_lastpage = '" . $db->sql_escape($row['session_page']) . "' + WHERE user_id = " . (int) $user_id; + $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 <> '" . $db->sql_escape($this->session_id) . "'" : ''; + + $sql = 'DELETE FROM ' . SESSIONS_TABLE . " + WHERE $sql_where"; + $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); + } + } + + + /** + * Check if the request originated from the same page. + * @param bool $check_script_path If true, the path will be checked as well + */ + function validate_referer($check_script_path = false) + { + global $config; + + // 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->referer) || empty($this->host)) + { + return true; + } + + $host = htmlspecialchars($this->host); + $ref = substr($this->referer, strpos($this->referer, '://') + 3); + + if (!(stripos($ref, $host) === 0) && (!$config['force_server_vars'] || !(stripos($ref, $config['server_name']) === 0))) + { + return false; + } + else if ($check_script_path && rtrim($this->page['root_script_path'], '/') !== '') + { + $ref = substr($ref, strlen($host)); + $server_port = (!empty($_SERVER['SERVER_PORT'])) ? (int) $_SERVER['SERVER_PORT'] : (int) getenv('SERVER_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->page['root_script_path'], '/')) === 0)) + { + return false; + } + } + + return true; + } + + + function unset_admin() + { + global $db; + $sql = 'UPDATE ' . SESSIONS_TABLE . ' + SET session_admin = 0 + WHERE session_id = \'' . $db->sql_escape($this->session_id) . '\''; + $db->sql_query($sql); + } +} + + +/** +* 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 user extends session +{ + var $lang = array(); + var $help = array(); + var $theme = array(); + var $date_format; + var $timezone; + var $dst; + + var $lang_name = false; + var $lang_id = false; + var $lang_path; + var $img_lang; + var $img_array = array(); + + // Able to add new options (up to id 31) + var $keyoptions = array('viewimg' => 0, 'viewflash' => 1, 'viewsmilies' => 2, 'viewsigs' => 3, 'viewavatars' => 4, 'viewcensors' => 5, 'attachsig' => 6, 'bbcode' => 8, 'smilies' => 9, 'popuppm' => 10, 'sig_bbcode' => 15, 'sig_smilies' => 16, 'sig_links' => 17); + var $keyvalues = array(); + + /** + * Constructor to set the lang path + */ + function user() + { + global $phpbb_root_path; + + $this->lang_path = $phpbb_root_path . 'language/'; + } + + /** + * Function to set custom language path (able to use directory outside of phpBB) + * + * @param string $lang_path New language path used. + * @access public + */ + function set_custom_lang_path($lang_path) + { + $this->lang_path = $lang_path; + + if (substr($this->lang_path, -1) != '/') + { + $this->lang_path .= '/'; + } + } + + /** + * Setup basic user-specific items (style, language, ...) + */ + function setup($lang_set = false, $style = false) + { + global $db, $template, $config, $auth, $phpEx, $phpbb_root_path, $cache; + + if ($this->data['user_id'] != ANONYMOUS) + { + $this->lang_name = (file_exists($this->lang_path . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($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($config['default_lang']); + $this->date_format = $config['default_dateformat']; + $this->timezone = $config['board_timezone'] * 3600; + $this->dst = $config['board_dst'] * 3600; + + /** + * If a guest user is surfing, we try to guess his/her language first by obtaining the browser language + * If re-enabled we need to make sure only those languages installed are checked + * Commented out so we do not loose the code. + + if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) + { + $accept_lang_ary = explode(',', $_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) . '_' . strtoupper(substr($accept_lang, 3, 2)); + $accept_lang = basename($accept_lang); + + if (file_exists($this->lang_path . $accept_lang . "/common.$phpEx")) + { + $this->lang_name = $config['default_lang'] = $accept_lang; + break; + } + else + { + // No match on xx_YY so try xx + $accept_lang = substr($accept_lang, 0, 2); + $accept_lang = basename($accept_lang); + + if (file_exists($this->lang_path . $accept_lang . "/common.$phpEx")) + { + $this->lang_name = $config['default_lang'] = $accept_lang; + break; + } + } + } + } + */ + } + + // We include common language file here to not load it every time a custom language file is included + $lang = &$this->lang; + + // Do not suppress error if in DEBUG_EXTRA mode + $include_result = (defined('DEBUG_EXTRA')) ? (include $this->lang_path . $this->lang_name . "/common.$phpEx") : (@include $this->lang_path . $this->lang_name . "/common.$phpEx"); + + if ($include_result === false) + { + die('Language file ' . $this->lang_path . $this->lang_name . "/common.$phpEx" . " couldn't be opened."); + } + + $this->add_lang($lang_set); + unset($lang_set); + + if (!empty($_GET['style']) && $auth->acl_get('a_styles') && !defined('ADMIN_START')) + { + global $SID, $_EXTRA_URL; + + $style = request_var('style', 0); + $SID .= '&style=' . $style; + $_EXTRA_URL = array('style=' . $style); + } + else + { + // Set up style + $style = ($style) ? $style : ((!$config['override_user_style']) ? $this->data['user_style'] : $config['default_style']); + } + + $sql = 'SELECT s.style_id, t.template_storedb, t.template_path, t.template_id, t.bbcode_bitfield, t.template_inherits_id, t.template_inherit_path, 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 = $db->sql_query($sql, 3600); + $this->theme = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + // User has wrong style + if (!$this->theme && $style == $this->data['user_style']) + { + $style = $this->data['user_style'] = $config['default_style']; + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_style = $style + WHERE user_id = {$this->data['user_id']}"; + $db->sql_query($sql); + + $sql = 'SELECT s.style_id, t.template_storedb, 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 = $db->sql_query($sql, 3600); + $this->theme = $db->sql_fetchrow($result); + $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 + $parsed_items = $cache->obtain_cfg_items($this->theme); + + // We are only interested in the theme configuration for now + $parsed_items = $parsed_items['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 + ); + + $sql = 'UPDATE ' . STYLES_THEME_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE theme_id = ' . $this->theme['theme_id']; + $db->sql_query($sql); + + unset($sql_ary); + } + + $template->set_template(); + + $this->img_lang = (file_exists($phpbb_root_path . 'styles/' . $this->theme['imageset_path'] . '/imageset/' . $this->lang_name)) ? $this->lang_name : $config['default_lang']; + + // Same query in style.php + $sql = 'SELECT * + FROM ' . STYLES_IMAGESET_DATA_TABLE . ' + WHERE imageset_id = ' . $this->theme['imageset_id'] . " + AND image_filename <> '' + AND image_lang IN ('" . $db->sql_escape($this->img_lang) . "', '')"; + $result = $db->sql_query($sql, 3600); + + $localised_images = false; + while ($row = $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; + } + $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(); + + $db->sql_transaction('begin'); + + $sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . ' + WHERE imageset_id = ' . $this->theme['imageset_id'] . ' + AND image_lang = \'' . $db->sql_escape($this->img_lang) . '\''; + $result = $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)) + { + $db->sql_multi_insert(STYLES_IMAGESET_DATA_TABLE, $sql_ary); + $db->sql_transaction('commit'); + $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE); + + add_log('admin', 'LOG_IMAGESET_LANG_REFRESHED', $this->theme['imageset_name'], $this->img_lang); + } + else + { + $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 (!defined('DEBUG_EXTRA') && !defined('ADMIN_START') && !defined('IN_INSTALL') && !defined('IN_LOGIN') && file_exists($phpbb_root_path . 'install') && !is_file($phpbb_root_path . 'install')) + { + // Adjust the message slightly according to the permissions + if ($auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_')) + { + $message = 'REMOVE_INSTALL'; + } + else + { + $message = (!empty($config['board_disable_msg'])) ? $config['board_disable_msg'] : 'BOARD_DISABLE'; + } + trigger_error($message); + } + + // Is board disabled and user not an admin or moderator? + if ($config['board_disable'] && !defined('IN_LOGIN') && !$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_')) + { + if ($this->data['is_bot']) + { + header('HTTP/1.1 503 Service Unavailable'); + } + + $message = (!empty($config['board_disable_msg'])) ? $config['board_disable_msg'] : 'BOARD_DISABLE'; + trigger_error($message); + } + + // Is load exceeded? + if ($config['limit_load'] && $this->load !== false) + { + if ($this->load > floatval($config['limit_load']) && !defined('IN_LOGIN')) + { + // Set board disabled to true to let the admins/mods get the proper notification + $config['board_disable'] = '1'; + + if (!$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_')) + { + if ($this->data['is_bot']) + { + 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 (!$auth->acl_get('u_hideonline')) + { + $sql = 'UPDATE ' . SESSIONS_TABLE . ' + SET session_viewonline = 1 + WHERE session_user_id = ' . $this->data['user_id']; + $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 ($auth->acl_get('u_hideonline')) + { + $sql = 'UPDATE ' . SESSIONS_TABLE . ' + SET session_viewonline = 0 + WHERE session_user_id = ' . $this->data['user_id']; + $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') && $config['chg_passforce'] && !empty($this->data['is_registered']) && $auth->acl_get('u_chgpasswd') && $this->data['user_passchg'] < time() - ($config['chg_passforce'] * 86400)) + { + if (strpos($this->page['query_string'], 'mode=reg_details') === false && $this->page['page_name'] != "ucp.$phpEx") + { + redirect(append_sid("{$phpbb_root_path}ucp.$phpEx", '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 is inspired by SHS` and Ashe. + * + * Example call: <samp>$user->lang('NUM_POSTS_IN_QUEUE', 1);</samp> + */ + 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) + * + * @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 + * + * 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> + */ + function add_lang($lang_set, $use_db = false, $use_help = false) + { + global $phpEx; + + 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 add_lang) + * @access private + */ + function set_lang(&$lang, &$help, $lang_file, $use_db = false, $use_help = false) + { + global $phpEx; + + // Make sure the language name is set (if the user setup did not happen it is not set) + if (!$this->lang_name) + { + global $config; + $this->lang_name = basename($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) . '.' . $phpEx; + } + else + { + $language_filename = $this->lang_path . $this->lang_name . '/' . (($use_help) ? 'help_' : '') . $lang_file . '.' . $phpEx; + } + + if (!file_exists($language_filename)) + { + global $config; + + 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($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 ($this->lang_name == $this->data['user_lang']) + { + // Fall back to the board default language + $this->lang_name = basename($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.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']); + return; + } + + // Do not suppress error if in DEBUG_EXTRA mode + $include_result = (defined('DEBUG_EXTRA')) ? (include $language_filename) : (@include $language_filename); + + if ($include_result === 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 + * @param string $format date format in date() notation. | 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. + * + * @return mixed translated date + */ + 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 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 + */ + function get_iso_lang_id() + { + global $config, $db; + + if (!empty($this->lang_id)) + { + return $this->lang_id; + } + + if (!$this->lang_name) + { + $this->lang_name = $config['default_lang']; + } + + $sql = 'SELECT lang_id + FROM ' . LANG_TABLE . " + WHERE lang_iso = '" . $db->sql_escape($this->lang_name) . "'"; + $result = $db->sql_query($sql); + $this->lang_id = (int) $db->sql_fetchfield('lang_id'); + $db->sql_freeresult($result); + + return $this->lang_id; + } + + /** + * Get users profile fields + */ + function get_profile_fields($user_id) + { + global $db; + + if (isset($this->profile_fields)) + { + return; + } + + $sql = 'SELECT * + FROM ' . PROFILE_FIELDS_DATA_TABLE . " + WHERE user_id = $user_id"; + $result = $db->sql_query_limit($sql, 1); + $this->profile_fields = (!($row = $db->sql_fetchrow($result))) ? array() : $row; + $db->sql_freeresult($result); + } + + /** + * Specify/Get image + * $suffix is no longer used - we know it. ;) It is there for backward compatibility. + */ + function img($img, $alt = '', $width = false, $suffix = '', $type = 'full_tag') + { + static $imgs; + global $phpbb_root_path; + + $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; + } + + // Use URL if told so + $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path; + + $img_data['src'] = $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 + */ + function optionget($key, $data = false) + { + if (!isset($this->keyvalues[$key])) + { + $var = ($data) ? $data : $this->data['user_options']; + $this->keyvalues[$key] = ($var & 1 << $this->keyoptions[$key]) ? true : false; + } + + return $this->keyvalues[$key]; + } + + /** + * Set option bit field for user options + */ + 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'] = $var; + return true; + } + else + { + return $var; + } + } + + /** + * Funtion to make the user leave the NEWLY_REGISTERED system group. + * @access public + */ + function leave_newly_registered() + { + global $db; + + if (empty($this->data['user_new'])) + { + return false; + } + + if (!function_exists('remove_newly_registered')) + { + global $phpbb_root_path, $phpEx; + + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); + } + if ($group = remove_newly_registered($this->data['user_id'], $this->data)) + { + $this->data['group_id'] = $group; + + } + $this->data['user_permissions'] = ''; + $this->data['user_new'] = 0; + + return true; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/template.php b/phpBB/includes/template.php new file mode 100644 index 0000000000..648af61c00 --- /dev/null +++ b/phpBB/includes/template.php @@ -0,0 +1,668 @@ +<?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; +} + +/** +* Base Template class. +* @package phpBB3 +*/ +class template +{ + /** 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 $_tpldata = array('.' => array(0 => array())); + var $_rootref; + + // Root dir and hash of filenames for each template handle. + var $root = ''; + var $cachepath = ''; + var $files = array(); + var $filename = array(); + var $files_inherit = array(); + var $files_template = array(); + var $inherit_root = ''; + var $orig_tpl_storedb; + var $orig_tpl_inherits_id; + + // this will hash handle names to the compiled/uncompiled code for that handle. + var $compiled_code = array(); + + /** + * Set template location + * @access public + */ + function set_template() + { + global $phpbb_root_path, $user; + + if (file_exists($phpbb_root_path . 'styles/' . $user->theme['template_path'] . '/template')) + { + $this->root = $phpbb_root_path . 'styles/' . $user->theme['template_path'] . '/template'; + $this->cachepath = $phpbb_root_path . 'cache/tpl_' . str_replace('_', '-', $user->theme['template_path']) . '_'; + + if ($this->orig_tpl_storedb === null) + { + $this->orig_tpl_storedb = $user->theme['template_storedb']; + } + + if ($this->orig_tpl_inherits_id === null) + { + $this->orig_tpl_inherits_id = $user->theme['template_inherits_id']; + } + + $user->theme['template_storedb'] = $this->orig_tpl_storedb; + $user->theme['template_inherits_id'] = $this->orig_tpl_inherits_id; + + if ($user->theme['template_inherits_id']) + { + $this->inherit_root = $phpbb_root_path . 'styles/' . $user->theme['template_inherit_path'] . '/template'; + } + } + else + { + trigger_error('Template path could not be found: styles/' . $user->theme['template_path'] . '/template', E_USER_ERROR); + } + + $this->_rootref = &$this->_tpldata['.'][0]; + + return true; + } + + /** + * Set custom template location (able to use directory outside of phpBB) + * @access public + */ + function set_custom_template($template_path, $template_name, $template_mode = 'template') + { + global $phpbb_root_path, $user; + + // Make sure $template_path has no ending slash + if (substr($template_path, -1) == '/') + { + $template_path = substr($template_path, 0, -1); + } + + $this->root = $template_path; + $this->cachepath = $phpbb_root_path . 'cache/ctpl_' . str_replace('_', '-', $template_name) . '_'; + + // As the template-engine is used for more than the template (emails, etc.), we should not set $user->theme in all cases, but only on the real template. + if ($template_mode == 'template') + { + $user->theme['template_storedb'] = false; + $user->theme['template_inherits_id'] = false; + } + + $this->_rootref = &$this->_tpldata['.'][0]; + + return true; + } + + /** + * Sets the template filenames for handles. $filename_array + * should be a hash of handle => filename pairs. + * @access public + */ + function set_filenames($filename_array) + { + if (!is_array($filename_array)) + { + return false; + } + 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; + + if ($this->inherit_root) + { + $this->files_inherit[$handle] = $this->inherit_root . '/' . $filename; + } + } + + return true; + } + + /** + * Destroy template data set + * @access public + */ + function destroy() + { + $this->_tpldata = array('.' => array(0 => array())); + } + + /** + * Reset/empty complete block + * @access 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]); + } + + return true; + } + + /** + * Display handle + * @access public + */ + function display($handle, $include_once = true) + { + global $user, $phpbb_hook; + + 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); + } + } + + if ($filename = $this->_tpl_load($handle)) + { + ($include_once) ? include_once($filename) : include($filename); + } + else + { + eval(' ?>' . $this->compiled_code[$handle] . '<?php '); + } + + return true; + } + + /** + * Display the handle and assign the output to a template variable or return the compiled result. + * @access 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 + */ + function _tpl_load(&$handle) + { + global $user, $phpEx, $config; + + $filename = $this->cachepath . str_replace('/', '.', $this->filename[$handle]) . '.' . $phpEx; + $this->files_template[$handle] = $user->theme['template_id']; + + $recompile = false; + if (!file_exists($filename) || @filesize($filename) === 0) + { + $recompile = true; + } + else if ($config['load_tplcompile']) + { + // No way around it: we need to check inheritance here + if ($user->theme['template_inherits_id'] && !file_exists($this->files[$handle])) + { + $this->files[$handle] = $this->files_inherit[$handle]; + $this->files_template[$handle] = $user->theme['template_inherits_id']; + } + $recompile = (@filemtime($filename) < filemtime($this->files[$handle])) ? true : false; + } + + // Recompile page if the original template is newer, otherwise load the compiled version + if (!$recompile) + { + return $filename; + } + + global $db, $phpbb_root_path; + + if (!class_exists('template_compile')) + { + include($phpbb_root_path . 'includes/functions_template.' . $phpEx); + } + + // Inheritance - we point to another template file for this one. Equality is also used for store_db + if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id'] && !file_exists($this->files[$handle])) + { + $this->files[$handle] = $this->files_inherit[$handle]; + $this->files_template[$handle] = $user->theme['template_inherits_id']; + } + + $compile = new 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); + } + + // Just compile if no user object is present (happens within the installer) + if (!$user) + { + $compile->_tpl_load_file($handle); + return false; + } + + if (isset($user->theme['template_storedb']) && $user->theme['template_storedb']) + { + $rows = array(); + $ids = array(); + // Inheritance + if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id']) + { + $ids[] = $user->theme['template_inherits_id']; + } + $ids[] = $user->theme['template_id']; + + foreach ($ids as $id) + { + $sql = 'SELECT * + FROM ' . STYLES_TEMPLATE_DATA_TABLE . ' + WHERE template_id = ' . $id . " + AND (template_filename = '" . $db->sql_escape($this->filename[$handle]) . "' + OR template_included " . $db->sql_like_expression($db->any_char . $this->filename[$handle] . ':' . $db->any_char) . ')'; + + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + $rows[$row['template_filename']] = $row; + } + $db->sql_freeresult($result); + } + + if (sizeof($rows)) + { + foreach ($rows as $row) + { + $file = $this->root . '/' . $row['template_filename']; + $force_reload = false; + if ($row['template_id'] != $user->theme['template_id']) + { + // make sure that we are not overlooking a file not in the db yet + if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id'] && !file_exists($file)) + { + $file = $this->inherit_root . '/' . $row['template_filename']; + $this->files[$row['template_filename']] = $file; + $this->files_inherit[$row['template_filename']] = $file; + $this->files_template[$row['template_filename']] = $user->theme['template_inherits_id']; + } + else if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id']) + { + // Ok, we have a situation. There is a file in the subtemplate, but nothing in the DB. We have to fix that. + $force_reload = true; + $this->files_template[$row['template_filename']] = $user->theme['template_inherits_id']; + } + } + else + { + $this->files_template[$row['template_filename']] = $user->theme['template_id']; + } + + if ($force_reload || $row['template_mtime'] < filemtime($file)) + { + if ($row['template_filename'] == $this->filename[$handle]) + { + $compile->_tpl_load_file($handle, true); + } + else + { + $this->files[$row['template_filename']] = $file; + $this->filename[$row['template_filename']] = $row['template_filename']; + $compile->_tpl_load_file($row['template_filename'], true); + unset($this->compiled_code[$row['template_filename']]); + unset($this->files[$row['template_filename']]); + unset($this->filename[$row['template_filename']]); + } + } + + if ($row['template_filename'] == $this->filename[$handle]) + { + $this->compiled_code[$handle] = $compile->compile(trim($row['template_data'])); + $compile->compile_write($handle, $this->compiled_code[$handle]); + } + else + { + // Only bother compiling if it doesn't already exist + if (!file_exists($this->cachepath . str_replace('/', '.', $row['template_filename']) . '.' . $phpEx)) + { + $this->filename[$row['template_filename']] = $row['template_filename']; + $compile->compile_write($row['template_filename'], $compile->compile(trim($row['template_data']))); + unset($this->filename[$row['template_filename']]); + } + } + } + } + else + { + $file = $this->root . '/' . $row['template_filename']; + + if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id'] && !file_exists($file)) + { + $file = $this->inherit_root . '/' . $row['template_filename']; + $this->files[$row['template_filename']] = $file; + $this->files_inherit[$row['template_filename']] = $file; + $this->files_template[$row['template_filename']] = $user->theme['template_inherits_id']; + } + // Try to load from filesystem and instruct to insert into the styles table... + $compile->_tpl_load_file($handle, true); + return false; + } + + return false; + } + + $compile->_tpl_load_file($handle); + return false; + } + + /** + * Assign key variable pairs from an array + * @access public + */ + function assign_vars($vararray) + { + foreach ($vararray as $key => $val) + { + $this->_rootref[$key] = $val; + } + + return true; + } + + /** + * Assign a single variable to a single key + * @access public + */ + function assign_var($varname, $varval) + { + $this->_rootref[$varname] = $varval; + + return true; + } + + /** + * Assign key variable pairs from an array to a specified block + * @access public + */ + function assign_block_vars($blockname, $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]; + } + + $s_row_count = isset($str[$blocks[$blockcount]]) ? sizeof($str[$blocks[$blockcount]]) : 0; + $vararray['S_ROW_COUNT'] = $s_row_count; + + // Assign S_FIRST_ROW + if (!$s_row_count) + { + $vararray['S_FIRST_ROW'] = true; + } + + // Now the tricky part, we always assign S_LAST_ROW and remove the entry before + // This is much more clever than going through the complete template data on display (phew) + $vararray['S_LAST_ROW'] = true; + if ($s_row_count > 0) + { + unset($str[$blocks[$blockcount]][($s_row_count - 1)]['S_LAST_ROW']); + } + + // 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. + $s_row_count = (isset($this->_tpldata[$blockname])) ? sizeof($this->_tpldata[$blockname]) : 0; + $vararray['S_ROW_COUNT'] = $s_row_count; + + // Assign S_FIRST_ROW + if (!$s_row_count) + { + $vararray['S_FIRST_ROW'] = true; + } + + // We always assign S_LAST_ROW and remove the entry before + $vararray['S_LAST_ROW'] = true; + if ($s_row_count > 0) + { + unset($this->_tpldata[$blockname][($s_row_count - 1)]['S_LAST_ROW']); + } + + // Add a new iteration to this block with the variable assignments we were given. + $this->_tpldata[$blockname][] = $vararray; + } + + return true; + } + + /** + * Change already assigned key variable pair (one-dimensional - single loop entry) + * + * An example of how to use this function: + * {@example alter_block_array.php} + * + * @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 + */ + function alter_block_array($blockname, $vararray, $key = false, $mode = 'insert') + { + if (strpos($blockname, '.') !== false) + { + // Nested blocks are not supported + return false; + } + + // 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($this->_tpldata[$blockname]); + } + + // 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 ($this->_tpldata[$blockname] 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') + { + // Make sure we are not exceeding the last iteration + if ($key >= sizeof($this->_tpldata[$blockname])) + { + $key = sizeof($this->_tpldata[$blockname]); + unset($this->_tpldata[$blockname][($key - 1)]['S_LAST_ROW']); + $vararray['S_LAST_ROW'] = true; + } + else if ($key === 0) + { + unset($this->_tpldata[$blockname][0]['S_FIRST_ROW']); + $vararray['S_FIRST_ROW'] = true; + } + + // Re-position template blocks + for ($i = sizeof($this->_tpldata[$blockname]); $i > $key; $i--) + { + $this->_tpldata[$blockname][$i] = $this->_tpldata[$blockname][$i-1]; + $this->_tpldata[$blockname][$i]['S_ROW_COUNT'] = $i; + } + + // Insert vararray at given position + $vararray['S_ROW_COUNT'] = $key; + $this->_tpldata[$blockname][$key] = $vararray; + + return true; + } + + // Which block to change? + if ($mode == 'change') + { + if ($key == sizeof($this->_tpldata[$blockname])) + { + $key--; + } + + $this->_tpldata[$blockname][$key] = array_merge($this->_tpldata[$blockname][$key], $vararray); + return true; + } + + return false; + } + + /** + * Include a separate template + * @access private + */ + function _tpl_include($filename, $include = true) + { + $handle = $filename; + $this->filename[$handle] = $filename; + $this->files[$handle] = $this->root . '/' . $filename; + if ($this->inherit_root) + { + $this->files_inherit[$handle] = $this->inherit_root . '/' . $filename; + } + + $filename = $this->_tpl_load($handle); + + if ($include) + { + global $user; + + if ($filename) + { + include($filename); + return; + } + eval(' ?>' . $this->compiled_code[$handle] . '<?php '); + } + } + + /** + * Include a php-file + * @access private + */ + function _php_include($filename) + { + global $phpbb_root_path; + + $file = $phpbb_root_path . $filename; + + if (!file_exists($file)) + { + // trigger_error cannot be used here, as the output already started + echo 'template->_php_include(): File ' . htmlspecialchars($file) . ' does not exist or is empty'; + return; + } + include($file); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/info/ucp_attachments.php b/phpBB/includes/ucp/info/ucp_attachments.php new file mode 100644 index 0000000000..84edce446c --- /dev/null +++ b/phpBB/includes/ucp/info/ucp_attachments.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class ucp_attachments_info +{ + function module() + { + return array( + 'filename' => 'ucp_attachments', + 'title' => 'UCP_ATTACHMENTS', + 'version' => '1.0.0', + 'modes' => array( + 'attachments' => array('title' => 'UCP_MAIN_ATTACHMENTS', 'auth' => 'acl_u_attach', 'cat' => array('UCP_MAIN')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/info/ucp_groups.php b/phpBB/includes/ucp/info/ucp_groups.php new file mode 100644 index 0000000000..2002123c50 --- /dev/null +++ b/phpBB/includes/ucp/info/ucp_groups.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class ucp_groups_info +{ + function module() + { + return array( + 'filename' => 'ucp_groups', + 'title' => 'UCP_USERGROUPS', + 'version' => '1.0.0', + 'modes' => array( + 'membership' => array('title' => 'UCP_USERGROUPS_MEMBER', 'auth' => '', 'cat' => array('UCP_USERGROUPS')), + 'manage' => array('title' => 'UCP_USERGROUPS_MANAGE', 'auth' => '', 'cat' => array('UCP_USERGROUPS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/info/ucp_main.php b/phpBB/includes/ucp/info/ucp_main.php new file mode 100644 index 0000000000..722b7865e6 --- /dev/null +++ b/phpBB/includes/ucp/info/ucp_main.php @@ -0,0 +1,40 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class ucp_main_info +{ + function module() + { + return array( + 'filename' => 'ucp_main', + 'title' => 'UCP_MAIN', + 'version' => '1.0.0', + 'modes' => array( + 'front' => array('title' => 'UCP_MAIN_FRONT', 'auth' => '', 'cat' => array('UCP_MAIN')), + 'subscribed' => array('title' => 'UCP_MAIN_SUBSCRIBED', 'auth' => '', 'cat' => array('UCP_MAIN')), + 'bookmarks' => array('title' => 'UCP_MAIN_BOOKMARKS', 'auth' => 'cfg_allow_bookmarks', 'cat' => array('UCP_MAIN')), + 'drafts' => array('title' => 'UCP_MAIN_DRAFTS', 'auth' => '', 'cat' => array('UCP_MAIN')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/info/ucp_pm.php b/phpBB/includes/ucp/info/ucp_pm.php new file mode 100644 index 0000000000..ade12005c0 --- /dev/null +++ b/phpBB/includes/ucp/info/ucp_pm.php @@ -0,0 +1,40 @@ +<?php +/** +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class ucp_pm_info +{ + function module() + { + return array( + 'filename' => 'ucp_pm', + 'title' => 'UCP_PM', + 'version' => '1.0.0', + 'modes' => array( + 'view' => array('title' => 'UCP_PM_VIEW', 'auth' => 'cfg_allow_privmsg', 'display' => false, 'cat' => array('UCP_PM')), + 'compose' => array('title' => 'UCP_PM_COMPOSE', 'auth' => 'cfg_allow_privmsg', 'cat' => array('UCP_PM')), + 'drafts' => array('title' => 'UCP_PM_DRAFTS', 'auth' => 'cfg_allow_privmsg', 'cat' => array('UCP_PM')), + 'options' => array('title' => 'UCP_PM_OPTIONS', 'auth' => 'cfg_allow_privmsg', 'cat' => array('UCP_PM')), + 'popup' => array('title' => 'UCP_PM_POPUP_TITLE', 'auth' => 'cfg_allow_privmsg', 'display' => false, 'cat' => array('UCP_PM')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/info/ucp_prefs.php b/phpBB/includes/ucp/info/ucp_prefs.php new file mode 100644 index 0000000000..58359e8a19 --- /dev/null +++ b/phpBB/includes/ucp/info/ucp_prefs.php @@ -0,0 +1,39 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class ucp_prefs_info +{ + function module() + { + return array( + 'filename' => 'ucp_prefs', + 'title' => 'UCP_PREFS', + 'version' => '1.0.0', + 'modes' => array( + 'personal' => array('title' => 'UCP_PREFS_PERSONAL', 'auth' => '', 'cat' => array('UCP_PREFS')), + 'post' => array('title' => 'UCP_PREFS_POST', 'auth' => '', 'cat' => array('UCP_PREFS')), + 'view' => array('title' => 'UCP_PREFS_VIEW', 'auth' => '', 'cat' => array('UCP_PREFS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/info/ucp_profile.php b/phpBB/includes/ucp/info/ucp_profile.php new file mode 100644 index 0000000000..03a4c81f46 --- /dev/null +++ b/phpBB/includes/ucp/info/ucp_profile.php @@ -0,0 +1,40 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class ucp_profile_info +{ + function module() + { + return array( + 'filename' => 'ucp_profile', + 'title' => 'UCP_PROFILE', + 'version' => '1.0.0', + 'modes' => array( + 'profile_info' => array('title' => 'UCP_PROFILE_PROFILE_INFO', 'auth' => '', 'cat' => array('UCP_PROFILE')), + 'signature' => array('title' => 'UCP_PROFILE_SIGNATURE', 'auth' => '', 'cat' => array('UCP_PROFILE')), + 'avatar' => array('title' => 'UCP_PROFILE_AVATAR', 'auth' => '', 'cat' => array('UCP_PROFILE')), + 'reg_details' => array('title' => 'UCP_PROFILE_REG_DETAILS', 'auth' => '', 'cat' => array('UCP_PROFILE')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/info/ucp_zebra.php b/phpBB/includes/ucp/info/ucp_zebra.php new file mode 100644 index 0000000000..5fc1f8bee7 --- /dev/null +++ b/phpBB/includes/ucp/info/ucp_zebra.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class ucp_zebra_info +{ + function module() + { + return array( + 'filename' => 'ucp_zebra', + 'title' => 'UCP_ZEBRA', + 'version' => '1.0.0', + 'modes' => array( + 'friends' => array('title' => 'UCP_ZEBRA_FRIENDS', 'auth' => '', 'cat' => array('UCP_ZEBRA')), + 'foes' => array('title' => 'UCP_ZEBRA_FOES', 'auth' => '', 'cat' => array('UCP_ZEBRA')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/ucp_activate.php b/phpBB/includes/ucp/ucp_activate.php new file mode 100644 index 0000000000..8debaabf31 --- /dev/null +++ b/phpBB/includes/ucp/ucp_activate.php @@ -0,0 +1,143 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ucp_activate +* User activation +* @package ucp +*/ +class ucp_activate +{ + var $u_action; + + function main($id, $mode) + { + global $config, $phpbb_root_path, $phpEx; + global $db, $user, $auth, $template; + + $user_id = request_var('u', 0); + $key = request_var('k', ''); + + $sql = 'SELECT user_id, username, user_type, user_email, user_newpasswd, user_lang, user_notify_type, user_actkey, user_inactive_reason + FROM ' . USERS_TABLE . " + WHERE user_id = $user_id"; + $result = $db->sql_query($sql); + $user_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$user_row) + { + trigger_error('NO_USER'); + } + + if ($user_row['user_type'] <> USER_INACTIVE && !$user_row['user_newpasswd']) + { + meta_refresh(3, append_sid("{$phpbb_root_path}index.$phpEx")); + trigger_error('ALREADY_ACTIVATED'); + } + + if (($user_row['user_inactive_reason'] == INACTIVE_MANUAL) || $user_row['user_actkey'] != $key) + { + trigger_error('WRONG_ACTIVATION'); + } + + // Do not allow activating by non administrators when admin activation is on + // Only activation type the user should be able to do is INACTIVE_REMIND + // or activate a new password which is not an activation state :@ + if (!$user_row['user_newpasswd'] && $user_row['user_inactive_reason'] != INACTIVE_REMIND && $config['require_activation'] == USER_ACTIVATION_ADMIN && !$auth->acl_get('a_user')) + { + if (!$user->data['is_registered']) + { + login_box('', $user->lang['NO_AUTH_OPERATION']); + } + trigger_error('NO_AUTH_OPERATION'); + } + + $update_password = ($user_row['user_newpasswd']) ? true : false; + + if ($update_password) + { + $sql_ary = array( + 'user_actkey' => '', + 'user_password' => $user_row['user_newpasswd'], + 'user_newpasswd' => '', + 'user_pass_convert' => 0, + 'user_login_attempts' => 0, + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . $user_row['user_id']; + $db->sql_query($sql); + + add_log('user', $user_row['user_id'], 'LOG_USER_NEW_PASSWORD', $user_row['username']); + } + + if (!$update_password) + { + include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); + + user_active_flip('activate', $user_row['user_id']); + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_actkey = '' + WHERE user_id = {$user_row['user_id']}"; + $db->sql_query($sql); + } + + if ($config['require_activation'] == USER_ACTIVATION_ADMIN && !$update_password) + { + include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + + $messenger = new messenger(false); + + $messenger->template('admin_welcome_activated', $user_row['user_lang']); + + $messenger->to($user_row['user_email'], $user_row['username']); + + $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); + $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); + $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); + $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($user_row['username'])) + ); + + $messenger->send($user_row['user_notify_type']); + + $message = 'ACCOUNT_ACTIVE_ADMIN'; + } + else + { + if (!$update_password) + { + $message = ($user_row['user_inactive_reason'] == INACTIVE_PROFILE) ? 'ACCOUNT_ACTIVE_PROFILE' : 'ACCOUNT_ACTIVE'; + } + else + { + $message = 'PASSWORD_ACTIVATED'; + } + } + + meta_refresh(3, append_sid("{$phpbb_root_path}index.$phpEx")); + trigger_error($user->lang[$message]); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/ucp_attachments.php b/phpBB/includes/ucp/ucp_attachments.php new file mode 100644 index 0000000000..b011b4f75d --- /dev/null +++ b/phpBB/includes/ucp/ucp_attachments.php @@ -0,0 +1,201 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ucp_attachments +* User attachments +* @package ucp +*/ +class ucp_attachments +{ + var $u_action; + + function main($id, $mode) + { + global $template, $user, $db, $config, $phpEx, $phpbb_root_path; + + $start = request_var('start', 0); + $sort_key = request_var('sk', 'a'); + $sort_dir = request_var('sd', 'a'); + + $delete = (isset($_POST['delete'])) ? true : false; + $confirm = (isset($_POST['confirm'])) ? true : false; + $delete_ids = array_keys(request_var('attachment', array(0))); + + if ($delete && sizeof($delete_ids)) + { + // Validate $delete_ids... + $sql = 'SELECT attach_id + FROM ' . ATTACHMENTS_TABLE . ' + WHERE poster_id = ' . $user->data['user_id'] . ' + AND is_orphan = 0 + AND ' . $db->sql_in_set('attach_id', $delete_ids); + $result = $db->sql_query($sql); + + $delete_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $delete_ids[] = $row['attach_id']; + } + $db->sql_freeresult($result); + } + + if ($delete && sizeof($delete_ids)) + { + $s_hidden_fields = array( + 'delete' => 1 + ); + + foreach ($delete_ids as $attachment_id) + { + $s_hidden_fields['attachment'][$attachment_id] = 1; + } + + if (confirm_box(true)) + { + if (!function_exists('delete_attachments')) + { + include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx); + } + + delete_attachments('attach', $delete_ids); + + meta_refresh(3, $this->u_action); + $message = ((sizeof($delete_ids) == 1) ? $user->lang['ATTACHMENT_DELETED'] : $user->lang['ATTACHMENTS_DELETED']) . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + trigger_error($message); + } + else + { + confirm_box(false, (sizeof($delete_ids) == 1) ? 'DELETE_ATTACHMENT' : 'DELETE_ATTACHMENTS', build_hidden_fields($s_hidden_fields)); + } + } + + // Select box eventually + $sort_key_text = array('a' => $user->lang['SORT_FILENAME'], 'b' => $user->lang['SORT_COMMENT'], 'c' => $user->lang['SORT_EXTENSION'], 'd' => $user->lang['SORT_SIZE'], 'e' => $user->lang['SORT_DOWNLOADS'], 'f' => $user->lang['SORT_POST_TIME'], 'g' => $user->lang['SORT_TOPIC_TITLE']); + $sort_key_sql = array('a' => 'a.real_filename', 'b' => 'a.attach_comment', 'c' => 'a.extension', 'd' => 'a.filesize', 'e' => 'a.download_count', 'f' => 'a.filetime', 'g' => 't.topic_title'); + + $sort_dir_text = array('a' => $user->lang['ASCENDING'], 'd' => $user->lang['DESCENDING']); + + $s_sort_key = ''; + foreach ($sort_key_text as $key => $value) + { + $selected = ($sort_key == $key) ? ' selected="selected"' : ''; + $s_sort_key .= '<option value="' . $key . '"' . $selected . '>' . $value . '</option>'; + } + + $s_sort_dir = ''; + foreach ($sort_dir_text as $key => $value) + { + $selected = ($sort_dir == $key) ? ' selected="selected"' : ''; + $s_sort_dir .= '<option value="' . $key . '"' . $selected . '>' . $value . '</option>'; + } + + if (!isset($sort_key_sql[$sort_key])) + { + $sort_key = 'a'; + } + + $order_by = $sort_key_sql[$sort_key] . ' ' . (($sort_dir == 'a') ? 'ASC' : 'DESC'); + + $sql = 'SELECT COUNT(attach_id) as num_attachments + FROM ' . ATTACHMENTS_TABLE . ' + WHERE poster_id = ' . $user->data['user_id'] . ' + AND is_orphan = 0'; + $result = $db->sql_query($sql); + $num_attachments = $db->sql_fetchfield('num_attachments'); + $db->sql_freeresult($result); + + $sql = 'SELECT a.*, t.topic_title, p.message_subject as message_title + FROM ' . ATTACHMENTS_TABLE . ' a + LEFT JOIN ' . TOPICS_TABLE . ' t ON (a.topic_id = t.topic_id AND a.in_message = 0) + LEFT JOIN ' . PRIVMSGS_TABLE . ' p ON (a.post_msg_id = p.msg_id AND a.in_message = 1) + WHERE a.poster_id = ' . $user->data['user_id'] . " + AND a.is_orphan = 0 + ORDER BY $order_by"; + $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); + + $row_count = 0; + if ($row = $db->sql_fetchrow($result)) + { + $template->assign_var('S_ATTACHMENT_ROWS', true); + + do + { + if ($row['in_message']) + { + $view_topic = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=pm&p={$row['post_msg_id']}"); + } + else + { + $view_topic = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "t={$row['topic_id']}&p={$row['post_msg_id']}") . "#p{$row['post_msg_id']}"; + } + + $template->assign_block_vars('attachrow', array( + 'ROW_NUMBER' => $row_count + ($start + 1), + 'FILENAME' => $row['real_filename'], + 'COMMENT' => bbcode_nl2br($row['attach_comment']), + 'EXTENSION' => $row['extension'], + 'SIZE' => get_formatted_filesize($row['filesize']), + 'DOWNLOAD_COUNT' => $row['download_count'], + 'POST_TIME' => $user->format_date($row['filetime']), + 'TOPIC_TITLE' => ($row['in_message']) ? $row['message_title'] : $row['topic_title'], + + 'ATTACH_ID' => $row['attach_id'], + 'POST_ID' => $row['post_msg_id'], + 'TOPIC_ID' => $row['topic_id'], + + 'S_IN_MESSAGE' => $row['in_message'], + + 'U_VIEW_ATTACHMENT' => append_sid("{$phpbb_root_path}download/file.$phpEx", 'id=' . $row['attach_id']), + 'U_VIEW_TOPIC' => $view_topic) + ); + + $row_count++; + } + while ($row = $db->sql_fetchrow($result)); + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'PAGE_NUMBER' => on_page($num_attachments, $config['topics_per_page'], $start), + 'PAGINATION' => generate_pagination($this->u_action . "&sk=$sort_key&sd=$sort_dir", $num_attachments, $config['topics_per_page'], $start), + 'TOTAL_ATTACHMENTS' => $num_attachments, + + 'L_TITLE' => $user->lang['UCP_ATTACHMENTS'], + + 'U_SORT_FILENAME' => $this->u_action . "&sk=a&sd=" . (($sort_key == 'a' && $sort_dir == 'a') ? 'd' : 'a'), + 'U_SORT_FILE_COMMENT' => $this->u_action . "&sk=b&sd=" . (($sort_key == 'b' && $sort_dir == 'a') ? 'd' : 'a'), + 'U_SORT_EXTENSION' => $this->u_action . "&sk=c&sd=" . (($sort_key == 'c' && $sort_dir == 'a') ? 'd' : 'a'), + 'U_SORT_FILESIZE' => $this->u_action . "&sk=d&sd=" . (($sort_key == 'd' && $sort_dir == 'a') ? 'd' : 'a'), + 'U_SORT_DOWNLOADS' => $this->u_action . "&sk=e&sd=" . (($sort_key == 'e' && $sort_dir == 'a') ? 'd' : 'a'), + 'U_SORT_POST_TIME' => $this->u_action . "&sk=f&sd=" . (($sort_key == 'f' && $sort_dir == 'a') ? 'd' : 'a'), + 'U_SORT_TOPIC_TITLE' => $this->u_action . "&sk=g&sd=" . (($sort_key == 'g' && $sort_dir == 'a') ? 'd' : 'a'), + + 'S_DISPLAY_MARK_ALL' => ($num_attachments) ? true : false, + 'S_DISPLAY_PAGINATION' => ($num_attachments) ? true : false, + 'S_UCP_ACTION' => $this->u_action, + 'S_SORT_OPTIONS' => $s_sort_key, + 'S_ORDER_SELECT' => $s_sort_dir) + ); + + $this->tpl_name = 'ucp_attachments'; + $this->page_title = 'UCP_ATTACHMENTS'; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/ucp_confirm.php b/phpBB/includes/ucp/ucp_confirm.php new file mode 100644 index 0000000000..445f7c7d2a --- /dev/null +++ b/phpBB/includes/ucp/ucp_confirm.php @@ -0,0 +1,50 @@ +<?php +/** +* +* @package VC +* @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; +} + +/** +* ucp_confirm +* Visual confirmation +* +* Note to potential users of this code ... +* +* Remember this is released under the _GPL_ and is subject +* to that licence. Do not incorporate this within software +* released or distributed in any way under a licence other +* than the GPL. We will be watching ... ;) +* +* @package VC +*/ +class ucp_confirm +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $phpbb_root_path, $config, $phpEx; + + include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); + $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $captcha->init(request_var('type', 0)); + $captcha->execute(); + + garbage_collection(); + exit_handler(); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/ucp_groups.php b/phpBB/includes/ucp/ucp_groups.php new file mode 100644 index 0000000000..423d9b718a --- /dev/null +++ b/phpBB/includes/ucp/ucp_groups.php @@ -0,0 +1,1117 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ucp_groups +* @package ucp +*/ +class ucp_groups +{ + var $u_action; + + function main($id, $mode) + { + global $config, $phpbb_root_path, $phpEx; + global $db, $user, $auth, $cache, $template; + + $user->add_lang('groups'); + + $return_page = '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $this->u_action . '">', '</a>'); + + $mark_ary = request_var('mark', array(0)); + $submit = (!empty($_POST['submit'])) ? true : false; + $delete = (!empty($_POST['delete'])) ? true : false; + $error = $data = array(); + + switch ($mode) + { + case 'membership': + + $this->page_title = 'UCP_USERGROUPS_MEMBER'; + + if ($submit || isset($_POST['change_default'])) + { + $action = (isset($_POST['change_default'])) ? 'change_default' : request_var('action', ''); + $group_id = ($action == 'change_default') ? request_var('default', 0) : request_var('selected', 0); + + if (!$group_id) + { + trigger_error('NO_GROUP_SELECTED'); + } + + $sql = 'SELECT group_id, group_name, group_type + FROM ' . GROUPS_TABLE . " + WHERE group_id IN ($group_id, {$user->data['group_id']})"; + $result = $db->sql_query($sql); + + $group_row = array(); + while ($row = $db->sql_fetchrow($result)) + { + $row['group_name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; + $group_row[$row['group_id']] = $row; + } + $db->sql_freeresult($result); + + if (!sizeof($group_row)) + { + trigger_error('GROUP_NOT_EXIST'); + } + + switch ($action) + { + case 'change_default': + // User already having this group set as default? + if ($group_id == $user->data['group_id']) + { + trigger_error($user->lang['ALREADY_DEFAULT_GROUP'] . $return_page); + } + + if (!$auth->acl_get('u_chggrp')) + { + trigger_error($user->lang['NOT_AUTHORISED'] . $return_page); + } + + // User needs to be member of the group in order to make it default + if (!group_memberships($group_id, $user->data['user_id'], true)) + { + trigger_error($user->lang['NOT_MEMBER_OF_GROUP'] . $return_page); + } + + if (confirm_box(true)) + { + group_user_attributes('default', $group_id, $user->data['user_id']); + + add_log('user', $user->data['user_id'], 'LOG_USER_GROUP_CHANGE', sprintf($user->lang['USER_GROUP_CHANGE'], $group_row[$user->data['group_id']]['group_name'], $group_row[$group_id]['group_name'])); + + meta_refresh(3, $this->u_action); + trigger_error($user->lang['CHANGED_DEFAULT_GROUP'] . $return_page); + } + else + { + $s_hidden_fields = array( + 'default' => $group_id, + 'change_default'=> true + ); + + confirm_box(false, sprintf($user->lang['GROUP_CHANGE_DEFAULT'], $group_row[$group_id]['group_name']), build_hidden_fields($s_hidden_fields)); + } + + break; + + case 'resign': + + // User tries to resign from default group but is not allowed to change it? + if ($group_id == $user->data['group_id'] && !$auth->acl_get('u_chggrp')) + { + trigger_error($user->lang['NOT_RESIGN_FROM_DEFAULT_GROUP'] . $return_page); + } + + if (!($row = group_memberships($group_id, $user->data['user_id']))) + { + trigger_error($user->lang['NOT_MEMBER_OF_GROUP'] . $return_page); + } + list(, $row) = each($row); + + $sql = 'SELECT group_type + FROM ' . GROUPS_TABLE . ' + WHERE group_id = ' . $group_id; + $result = $db->sql_query($sql); + $group_type = (int) $db->sql_fetchfield('group_type'); + $db->sql_freeresult($result); + + if ($group_type != GROUP_OPEN && $group_type != GROUP_FREE) + { + trigger_error($user->lang['CANNOT_RESIGN_GROUP'] . $return_page); + } + + if (confirm_box(true)) + { + group_user_del($group_id, $user->data['user_id']); + + add_log('user', $user->data['user_id'], 'LOG_USER_GROUP_RESIGN', $group_row[$group_id]['group_name']); + + meta_refresh(3, $this->u_action); + trigger_error($user->lang[($row['user_pending']) ? 'GROUP_RESIGNED_PENDING' : 'GROUP_RESIGNED_MEMBERSHIP'] . $return_page); + } + else + { + $s_hidden_fields = array( + 'selected' => $group_id, + 'action' => 'resign', + 'submit' => true + ); + + confirm_box(false, ($row['user_pending']) ? 'GROUP_RESIGN_PENDING' : 'GROUP_RESIGN_MEMBERSHIP', build_hidden_fields($s_hidden_fields)); + } + + break; + + case 'join': + + $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.group_id = ' . $group_id . ' + AND ug.user_id = ' . $user->data['user_id']; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + if ($row['user_pending']) + { + trigger_error($user->lang['ALREADY_IN_GROUP_PENDING'] . $return_page); + } + + trigger_error($user->lang['ALREADY_IN_GROUP'] . $return_page); + } + + // Check permission to join (open group or request) + if ($group_row[$group_id]['group_type'] != GROUP_OPEN && $group_row[$group_id]['group_type'] != GROUP_FREE) + { + trigger_error($user->lang['CANNOT_JOIN_GROUP'] . $return_page); + } + + if (confirm_box(true)) + { + if ($group_row[$group_id]['group_type'] == GROUP_FREE) + { + group_user_add($group_id, $user->data['user_id']); + + $email_template = 'group_added'; + } + else + { + group_user_add($group_id, $user->data['user_id'], false, false, false, 0, 1); + + $email_template = 'group_request'; + } + + include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + $messenger = new messenger(); + + $sql = 'SELECT u.username, u.username_clean, u.user_email, u.user_notify_type, u.user_jabber, u.user_lang + FROM ' . USER_GROUP_TABLE . ' ug, ' . USERS_TABLE . ' u + WHERE ug.user_id = u.user_id + AND ' . (($group_row[$group_id]['group_type'] == GROUP_FREE) ? "ug.user_id = {$user->data['user_id']}" : 'ug.group_leader = 1') . " + AND ug.group_id = $group_id"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $messenger->template($email_template, $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_row[$group_id]['group_name']), + 'REQUEST_USERNAME' => $user->data['username'], + + 'U_PENDING' => generate_board_url() . "/ucp.$phpEx?i=groups&mode=manage&action=list&g=$group_id", + 'U_GROUP' => generate_board_url() . "/memberlist.$phpEx?mode=group&g=$group_id") + ); + + $messenger->send($row['user_notify_type']); + } + $db->sql_freeresult($result); + + $messenger->save_queue(); + + add_log('user', $user->data['user_id'], 'LOG_USER_GROUP_JOIN' . (($group_row[$group_id]['group_type'] == GROUP_FREE) ? '' : '_PENDING'), $group_row[$group_id]['group_name']); + + meta_refresh(3, $this->u_action); + trigger_error($user->lang[($group_row[$group_id]['group_type'] == GROUP_FREE) ? 'GROUP_JOINED' : 'GROUP_JOINED_PENDING'] . $return_page); + } + else + { + $s_hidden_fields = array( + 'selected' => $group_id, + 'action' => 'join', + 'submit' => true + ); + + confirm_box(false, ($group_row[$group_id]['group_type'] == GROUP_FREE) ? 'GROUP_JOIN' : 'GROUP_JOIN_PENDING', build_hidden_fields($s_hidden_fields)); + } + + break; + + case 'demote': + + if (!($row = group_memberships($group_id, $user->data['user_id']))) + { + trigger_error($user->lang['NOT_MEMBER_OF_GROUP'] . $return_page); + } + list(, $row) = each($row); + + if (!$row['group_leader']) + { + trigger_error($user->lang['NOT_LEADER_OF_GROUP'] . $return_page); + } + + if (confirm_box(true)) + { + group_user_attributes('demote', $group_id, $user->data['user_id']); + + add_log('user', $user->data['user_id'], 'LOG_USER_GROUP_DEMOTE', $group_row[$group_id]['group_name']); + + meta_refresh(3, $this->u_action); + trigger_error($user->lang['USER_GROUP_DEMOTED'] . $return_page); + } + else + { + $s_hidden_fields = array( + 'selected' => $group_id, + 'action' => 'demote', + 'submit' => true + ); + + confirm_box(false, 'USER_GROUP_DEMOTE', build_hidden_fields($s_hidden_fields)); + } + + break; + } + } + + $sql = 'SELECT g.*, ug.group_leader, ug.user_pending + FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug + WHERE ug.user_id = ' . $user->data['user_id'] . ' + AND g.group_id = ug.group_id + ORDER BY g.group_type DESC, g.group_name'; + $result = $db->sql_query($sql); + + $group_id_ary = array(); + $leader_count = $member_count = $pending_count = 0; + while ($row = $db->sql_fetchrow($result)) + { + $block = ($row['group_leader']) ? 'leader' : (($row['user_pending']) ? 'pending' : 'member'); + + switch ($row['group_type']) + { + case GROUP_OPEN: + $group_status = 'OPEN'; + break; + + case GROUP_CLOSED: + $group_status = 'CLOSED'; + break; + + case GROUP_HIDDEN: + $group_status = 'HIDDEN'; + break; + + case GROUP_SPECIAL: + $group_status = 'SPECIAL'; + break; + + case GROUP_FREE: + $group_status = 'FREE'; + break; + } + + $template->assign_block_vars($block, array( + 'GROUP_ID' => $row['group_id'], + 'GROUP_NAME' => ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'], + 'GROUP_DESC' => ($row['group_type'] <> GROUP_SPECIAL) ? generate_text_for_display($row['group_desc'], $row['group_desc_uid'], $row['group_desc_bitfield'], $row['group_desc_options']) : $user->lang['GROUP_IS_SPECIAL'], + 'GROUP_SPECIAL' => ($row['group_type'] <> GROUP_SPECIAL) ? false : true, + 'GROUP_STATUS' => $user->lang['GROUP_IS_' . $group_status], + 'GROUP_COLOUR' => $row['group_colour'], + + 'U_VIEW_GROUP' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&g=' . $row['group_id']), + + 'S_GROUP_DEFAULT' => ($row['group_id'] == $user->data['group_id']) ? true : false, + 'S_ROW_COUNT' => ${$block . '_count'}++) + ); + + $group_id_ary[] = (int) $row['group_id']; + } + $db->sql_freeresult($result); + + // Hide hidden groups unless user is an admin with group privileges + $sql_and = ($auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel')) ? '<> ' . GROUP_SPECIAL : 'NOT IN (' . GROUP_SPECIAL . ', ' . GROUP_HIDDEN . ')'; + + $sql = 'SELECT group_id, group_name, group_colour, group_desc, group_desc_uid, group_desc_bitfield, group_desc_options, group_type, group_founder_manage + FROM ' . GROUPS_TABLE . ' + WHERE ' . ((sizeof($group_id_ary)) ? $db->sql_in_set('group_id', $group_id_ary, true) . ' AND ' : '') . " + group_type $sql_and + ORDER BY group_type DESC, group_name"; + $result = $db->sql_query($sql); + + $nonmember_count = 0; + while ($row = $db->sql_fetchrow($result)) + { + switch ($row['group_type']) + { + case GROUP_OPEN: + $group_status = 'OPEN'; + break; + + case GROUP_CLOSED: + $group_status = 'CLOSED'; + break; + + case GROUP_HIDDEN: + $group_status = 'HIDDEN'; + break; + + case GROUP_SPECIAL: + $group_status = 'SPECIAL'; + break; + + case GROUP_FREE: + $group_status = 'FREE'; + break; + } + + $template->assign_block_vars('nonmember', array( + 'GROUP_ID' => $row['group_id'], + 'GROUP_NAME' => ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'], + 'GROUP_DESC' => ($row['group_type'] <> GROUP_SPECIAL) ? generate_text_for_display($row['group_desc'], $row['group_desc_uid'], $row['group_desc_bitfield'], $row['group_desc_options']) : $user->lang['GROUP_IS_SPECIAL'], + 'GROUP_SPECIAL' => ($row['group_type'] <> GROUP_SPECIAL) ? false : true, + 'GROUP_CLOSED' => ($row['group_type'] <> GROUP_CLOSED || $auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel')) ? false : true, + 'GROUP_STATUS' => $user->lang['GROUP_IS_' . $group_status], + 'S_CAN_JOIN' => ($row['group_type'] == GROUP_OPEN || $row['group_type'] == GROUP_FREE) ? true : false, + 'GROUP_COLOUR' => $row['group_colour'], + + 'U_VIEW_GROUP' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&g=' . $row['group_id']), + + 'S_ROW_COUNT' => $nonmember_count++) + ); + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'S_CHANGE_DEFAULT' => ($auth->acl_get('u_chggrp')) ? true : false, + 'S_LEADER_COUNT' => $leader_count, + 'S_MEMBER_COUNT' => $member_count, + 'S_PENDING_COUNT' => $pending_count, + 'S_NONMEMBER_COUNT' => $nonmember_count, + + 'S_UCP_ACTION' => $this->u_action) + ); + + break; + + case 'manage': + + $this->page_title = 'UCP_USERGROUPS_MANAGE'; + $action = (isset($_POST['addusers'])) ? 'addusers' : request_var('action', ''); + $group_id = request_var('g', 0); + + include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + + add_form_key('ucp_groups'); + + if ($group_id) + { + $sql = 'SELECT * + FROM ' . GROUPS_TABLE . " + WHERE group_id = $group_id"; + $result = $db->sql_query($sql); + $group_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$group_row) + { + trigger_error($user->lang['NO_GROUP'] . $return_page); + } + + // Check if the user is allowed to manage this group if set to founder only. + if ($user->data['user_type'] != USER_FOUNDER && $group_row['group_founder_manage']) + { + trigger_error($user->lang['NOT_ALLOWED_MANAGE_GROUP'] . $return_page, E_USER_WARNING); + } + + $group_name = $group_row['group_name']; + $group_type = $group_row['group_type']; + + $avatar_img = (!empty($group_row['group_avatar'])) ? get_user_avatar($group_row['group_avatar'], $group_row['group_avatar_type'], $group_row['group_avatar_width'], $group_row['group_avatar_height'], 'GROUP_AVATAR') : '<img src="' . $phpbb_root_path . 'adm/images/no_avatar.gif" alt="" />'; + + $template->assign_vars(array( + 'GROUP_NAME' => ($group_type == GROUP_SPECIAL) ? $user->lang['G_' . $group_name] : $group_name, + 'GROUP_INTERNAL_NAME' => $group_name, + 'GROUP_COLOUR' => (isset($group_row['group_colour'])) ? $group_row['group_colour'] : '', + 'GROUP_DESC_DISP' => generate_text_for_display($group_row['group_desc'], $group_row['group_desc_uid'], $group_row['group_desc_bitfield'], $group_row['group_desc_options']), + 'GROUP_TYPE' => $group_row['group_type'], + + 'AVATAR' => $avatar_img, + 'AVATAR_IMAGE' => $avatar_img, + 'AVATAR_WIDTH' => (isset($group_row['group_avatar_width'])) ? $group_row['group_avatar_width'] : '', + 'AVATAR_HEIGHT' => (isset($group_row['group_avatar_height'])) ? $group_row['group_avatar_height'] : '', + )); + } + + switch ($action) + { + case 'edit': + + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . $return_page); + } + + if (!($row = group_memberships($group_id, $user->data['user_id']))) + { + trigger_error($user->lang['NOT_MEMBER_OF_GROUP'] . $return_page); + } + list(, $row) = each($row); + + if (!$row['group_leader']) + { + trigger_error($user->lang['NOT_LEADER_OF_GROUP'] . $return_page); + } + + $file_uploads = (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on') ? true : false; + $user->add_lang(array('acp/groups', 'acp/common')); + + $data = $submit_ary = array(); + + $update = (isset($_POST['update'])) ? true : false; + + $error = array(); + + $avatar_select = basename(request_var('avatar_select', '')); + $category = basename(request_var('category', '')); + + $can_upload = (file_exists($phpbb_root_path . $config['avatar_path']) && @is_writable($phpbb_root_path . $config['avatar_path']) && $file_uploads) ? true : false; + + // Did we submit? + if ($update) + { + $group_name = utf8_normalize_nfc(request_var('group_name', '', true)); + $group_desc = utf8_normalize_nfc(request_var('group_desc', '', true)); + $group_type = request_var('group_type', GROUP_FREE); + + $allow_desc_bbcode = request_var('desc_parse_bbcode', false); + $allow_desc_urls = request_var('desc_parse_urls', false); + $allow_desc_smilies = request_var('desc_parse_smilies', false); + + $submit_ary = array( + 'colour' => request_var('group_colour', ''), + 'rank' => request_var('group_rank', 0), + 'receive_pm' => isset($_REQUEST['group_receive_pm']) ? 1 : 0, + 'message_limit' => request_var('group_message_limit', 0), + 'max_recipients'=> request_var('group_max_recipients', 0), + ); + + $data['uploadurl'] = request_var('uploadurl', ''); + $data['remotelink'] = request_var('remotelink', ''); + $data['width'] = request_var('width', ''); + $data['height'] = request_var('height', ''); + $delete = request_var('delete', ''); + + if (!empty($_FILES['uploadfile']['tmp_name']) || $data['uploadurl'] || $data['remotelink']) + { + // Avatar stuff + $var_ary = 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 (!($error = validate_data($data, $var_ary))) + { + $data['user_id'] = "g$group_id"; + + if ((!empty($_FILES['uploadfile']['tmp_name']) || $data['uploadurl']) && $can_upload) + { + list($submit_ary['avatar_type'], $submit_ary['avatar'], $submit_ary['avatar_width'], $submit_ary['avatar_height']) = avatar_upload($data, $error); + } + else if ($data['remotelink']) + { + list($submit_ary['avatar_type'], $submit_ary['avatar'], $submit_ary['avatar_width'], $submit_ary['avatar_height']) = avatar_remote($data, $error); + } + } + } + else if ($avatar_select && $config['allow_avatar_local']) + { + // check avatar gallery + if (is_dir($phpbb_root_path . $config['avatar_gallery_path'] . '/' . $category)) + { + $submit_ary['avatar_type'] = AVATAR_GALLERY; + + list($submit_ary['avatar_width'], $submit_ary['avatar_height']) = getimagesize($phpbb_root_path . $config['avatar_gallery_path'] . '/' . $category . '/' . $avatar_select); + $submit_ary['avatar'] = $category . '/' . $avatar_select; + } + } + else if ($delete) + { + $submit_ary['avatar'] = ''; + $submit_ary['avatar_type'] = $submit_ary['avatar_width'] = $submit_ary['avatar_height'] = 0; + } + else if ($data['width'] && $data['height']) + { + // Only update the dimensions? + if ($config['avatar_max_width'] || $config['avatar_max_height']) + { + if ($data['width'] > $config['avatar_max_width'] || $data['height'] > $config['avatar_max_height']) + { + $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $data['width'], $data['height']); + } + } + + if (!sizeof($error)) + { + if ($config['avatar_min_width'] || $config['avatar_min_height']) + { + if ($data['width'] < $config['avatar_min_width'] || $data['height'] < $config['avatar_min_height']) + { + $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $data['width'], $data['height']); + } + } + } + + if (!sizeof($error)) + { + $submit_ary['avatar_width'] = $data['width']; + $submit_ary['avatar_height'] = $data['height']; + } + } + + if ((isset($submit_ary['avatar']) && $submit_ary['avatar'] && (!isset($group_row['group_avatar']))) || $delete) + { + if (isset($group_row['group_avatar']) && $group_row['group_avatar']) + { + avatar_delete('group', $group_row, true); + } + } + + if (!check_form_key('ucp_groups')) + { + $error[] = $user->lang['FORM_INVALID']; + } + + if (!sizeof($error)) + { + // Only set the rank, colour, etc. if it's changed or if we're adding a new + // group. This prevents existing group members being updated if no changes + // were made. + + $group_attributes = array(); + $test_variables = array( + 'rank' => 'int', + 'colour' => 'string', + 'avatar' => 'string', + 'avatar_type' => 'int', + 'avatar_width' => 'int', + 'avatar_height' => 'int', + 'receive_pm' => 'int', + 'legend' => 'int', + 'message_limit' => 'int', + 'max_recipients'=> 'int', + ); + + foreach ($test_variables as $test => $type) + { + if (isset($submit_ary[$test]) && ($action == 'add' || $group_row['group_' . $test] != $submit_ary[$test])) + { + settype($submit_ary[$test], $type); + $group_attributes['group_' . $test] = $group_row['group_' . $test] = $submit_ary[$test]; + } + } + + if (!($error = group_create($group_id, $group_type, $group_name, $group_desc, $group_attributes, $allow_desc_bbcode, $allow_desc_urls, $allow_desc_smilies))) + { + $cache->destroy('sql', GROUPS_TABLE); + + $message = ($action == 'edit') ? 'GROUP_UPDATED' : 'GROUP_CREATED'; + trigger_error($user->lang[$message] . $return_page); + } + } + + if (sizeof($error)) + { + $group_rank = $submit_ary['rank']; + + $group_desc_data = array( + 'text' => $group_desc, + 'allow_bbcode' => $allow_desc_bbcode, + 'allow_smilies' => $allow_desc_smilies, + 'allow_urls' => $allow_desc_urls + ); + } + } + else if (!$group_id) + { + $group_name = utf8_normalize_nfc(request_var('group_name', '', true)); + $group_desc_data = array( + 'text' => '', + 'allow_bbcode' => true, + 'allow_smilies' => true, + 'allow_urls' => true + ); + $group_rank = 0; + $group_type = GROUP_OPEN; + } + else + { + $group_desc_data = generate_text_for_edit($group_row['group_desc'], $group_row['group_desc_uid'], $group_row['group_desc_options']); + $group_rank = $group_row['group_rank']; + } + + $sql = 'SELECT * + FROM ' . RANKS_TABLE . ' + WHERE rank_special = 1 + ORDER BY rank_title'; + $result = $db->sql_query($sql); + + $rank_options = '<option value="0"' . ((!$group_rank) ? ' selected="selected"' : '') . '>' . $user->lang['USER_DEFAULT'] . '</option>'; + while ($row = $db->sql_fetchrow($result)) + { + $selected = ($group_rank && $row['rank_id'] == $group_rank) ? ' selected="selected"' : ''; + $rank_options .= '<option value="' . $row['rank_id'] . '"' . $selected . '>' . $row['rank_title'] . '</option>'; + } + $db->sql_freeresult($result); + + $type_free = ($group_type == GROUP_FREE) ? ' checked="checked"' : ''; + $type_open = ($group_type == GROUP_OPEN) ? ' checked="checked"' : ''; + $type_closed = ($group_type == GROUP_CLOSED) ? ' checked="checked"' : ''; + $type_hidden = ($group_type == GROUP_HIDDEN) ? ' checked="checked"' : ''; + + $display_gallery = (isset($_POST['display_gallery'])) ? true : false; + + if ($config['allow_avatar'] && $config['allow_avatar_local'] && $display_gallery) + { + avatar_gallery($category, $avatar_select, 4); + } + + $avatars_enabled = ($config['allow_avatar'] && (($can_upload && ($config['allow_avatar_upload'] || $config['allow_avatar_remote_upload'])) || ($config['allow_avatar_local'] || $config['allow_avatar_remote']))) ? true : false; + + $template->assign_vars(array( + 'S_EDIT' => true, + 'S_INCLUDE_SWATCH' => true, + 'S_FORM_ENCTYPE' => ($config['allow_avatar'] && $can_upload && ($config['allow_avatar_upload'] || $config['allow_avatar_remote_upload'])) ? ' enctype="multipart/form-data"' : '', + 'S_ERROR' => (sizeof($error)) ? true : false, + 'S_SPECIAL_GROUP' => ($group_type == GROUP_SPECIAL) ? true : false, + 'S_AVATARS_ENABLED' => $avatars_enabled, + 'S_DISPLAY_GALLERY' => ($config['allow_avatar'] && $config['allow_avatar_local'] && !$display_gallery) ? true : false, + 'S_IN_GALLERY' => ($config['allow_avatar_local'] && $display_gallery) ? true : false, + + 'S_UPLOAD_AVATAR_FILE' => ($config['allow_avatar'] && $config['allow_avatar_upload'] && $can_upload) ? true : false, + 'S_UPLOAD_AVATAR_URL' => ($config['allow_avatar'] && $config['allow_avatar_remote_upload'] && $can_upload) ? true : false, + 'S_LINK_AVATAR' => ($config['allow_avatar'] && $config['allow_avatar_remote']) ? true : false, + + 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + 'GROUP_RECEIVE_PM' => (isset($group_row['group_receive_pm']) && $group_row['group_receive_pm']) ? ' checked="checked"' : '', + 'GROUP_MESSAGE_LIMIT' => (isset($group_row['group_message_limit'])) ? $group_row['group_message_limit'] : 0, + 'GROUP_MAX_RECIPIENTS' => (isset($group_row['group_max_recipients'])) ? $group_row['group_max_recipients'] : 0, + + 'GROUP_DESC' => $group_desc_data['text'], + 'S_DESC_BBCODE_CHECKED' => $group_desc_data['allow_bbcode'], + 'S_DESC_URLS_CHECKED' => $group_desc_data['allow_urls'], + 'S_DESC_SMILIES_CHECKED'=> $group_desc_data['allow_smilies'], + + 'S_RANK_OPTIONS' => $rank_options, + 'AVATAR_MAX_FILESIZE' => $config['avatar_filesize'], + + 'GROUP_TYPE_FREE' => GROUP_FREE, + 'GROUP_TYPE_OPEN' => GROUP_OPEN, + 'GROUP_TYPE_CLOSED' => GROUP_CLOSED, + 'GROUP_TYPE_HIDDEN' => GROUP_HIDDEN, + 'GROUP_TYPE_SPECIAL' => GROUP_SPECIAL, + + 'GROUP_FREE' => $type_free, + 'GROUP_OPEN' => $type_open, + 'GROUP_CLOSED' => $type_closed, + 'GROUP_HIDDEN' => $type_hidden, + + 'U_SWATCH' => append_sid("{$phpbb_root_path}adm/swatch.$phpEx", 'form=ucp&name=group_colour'), + 'S_UCP_ACTION' => $this->u_action . "&action=$action&g=$group_id", + 'L_AVATAR_EXPLAIN' => sprintf($user->lang['AVATAR_EXPLAIN'], $config['avatar_max_width'], $config['avatar_max_height'], $config['avatar_filesize'] / 1024), + )); + + break; + + case 'list': + + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . $return_page); + } + + if (!($row = group_memberships($group_id, $user->data['user_id']))) + { + trigger_error($user->lang['NOT_MEMBER_OF_GROUP'] . $return_page); + } + list(, $row) = each($row); + + if (!$row['group_leader']) + { + trigger_error($user->lang['NOT_LEADER_OF_GROUP'] . $return_page); + } + + $user->add_lang(array('acp/groups', 'acp/common')); + $start = request_var('start', 0); + + // Grab the leaders - always, on every page... + $sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_colour, u.user_regdate, u.user_posts, u.group_id, ug.group_leader, ug.user_pending + FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . " ug + WHERE ug.group_id = $group_id + AND u.user_id = ug.user_id + AND ug.group_leader = 1 + ORDER BY ug.user_pending DESC, u.username_clean"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $template->assign_block_vars('leader', array( + 'USERNAME' => $row['username'], + 'USERNAME_COLOUR' => $row['user_colour'], + 'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']), + 'U_USER_VIEW' => get_username_string('profile', $row['user_id'], $row['username']), + 'S_GROUP_DEFAULT' => ($row['group_id'] == $group_id) ? true : false, + 'JOINED' => ($row['user_regdate']) ? $user->format_date($row['user_regdate']) : ' - ', + 'USER_POSTS' => $row['user_posts'], + 'USER_ID' => $row['user_id']) + ); + } + $db->sql_freeresult($result); + + // Total number of group members (non-leaders) + $sql = 'SELECT COUNT(user_id) AS total_members + FROM ' . USER_GROUP_TABLE . " + WHERE group_id = $group_id + AND group_leader = 0"; + $result = $db->sql_query($sql); + $total_members = (int) $db->sql_fetchfield('total_members'); + $db->sql_freeresult($result); + + // Grab the members + $sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_colour, u.user_regdate, u.user_posts, u.group_id, ug.group_leader, ug.user_pending + FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . " ug + WHERE ug.group_id = $group_id + AND u.user_id = ug.user_id + AND ug.group_leader = 0 + ORDER BY ug.user_pending DESC, u.username_clean"; + $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); + + $pending = false; + $approved = false; + + while ($row = $db->sql_fetchrow($result)) + { + if ($row['user_pending'] && !$pending) + { + $template->assign_block_vars('member', array( + 'S_PENDING' => true) + ); + $template->assign_var('S_PENDING_SET', true); + + $pending = true; + } + else if (!$row['user_pending'] && !$approved) + { + $template->assign_block_vars('member', array( + 'S_APPROVED' => true) + ); + $template->assign_var('S_APPROVED_SET', true); + + $approved = true; + } + + $template->assign_block_vars('member', array( + 'USERNAME' => $row['username'], + 'USERNAME_COLOUR' => $row['user_colour'], + 'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']), + 'U_USER_VIEW' => get_username_string('profile', $row['user_id'], $row['username']), + 'S_GROUP_DEFAULT' => ($row['group_id'] == $group_id) ? true : false, + 'JOINED' => ($row['user_regdate']) ? $user->format_date($row['user_regdate']) : ' - ', + 'USER_POSTS' => $row['user_posts'], + 'USER_ID' => $row['user_id']) + ); + } + $db->sql_freeresult($result); + + $s_action_options = ''; + $options = array('default' => 'DEFAULT', 'approve' => 'APPROVE', 'deleteusers' => 'DELETE'); + + foreach ($options as $option => $lang) + { + $s_action_options .= '<option value="' . $option . '">' . $user->lang['GROUP_' . $lang] . '</option>'; + } + + $template->assign_vars(array( + 'S_LIST' => true, + 'S_ACTION_OPTIONS' => $s_action_options, + 'S_ON_PAGE' => on_page($total_members, $config['topics_per_page'], $start), + 'PAGINATION' => generate_pagination($this->u_action . "&action=$action&g=$group_id", $total_members, $config['topics_per_page'], $start), + + 'U_ACTION' => $this->u_action . "&g=$group_id", + 'S_UCP_ACTION' => $this->u_action . "&g=$group_id", + 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=ucp&field=usernames'), + )); + + break; + + case 'approve': + + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . $return_page); + } + + if (!($row = group_memberships($group_id, $user->data['user_id']))) + { + trigger_error($user->lang['NOT_MEMBER_OF_GROUP'] . $return_page); + } + list(, $row) = each($row); + + if (!$row['group_leader']) + { + trigger_error($user->lang['NOT_LEADER_OF_GROUP'] . $return_page); + } + + $user->add_lang('acp/groups'); + + // Approve, demote or promote + group_user_attributes('approve', $group_id, $mark_ary, false, false); + + trigger_error($user->lang['USERS_APPROVED'] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $this->u_action . '&action=list&g=' . $group_id . '">', '</a>')); + + break; + + case 'default': + + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . $return_page); + } + + if (!($row = group_memberships($group_id, $user->data['user_id']))) + { + trigger_error($user->lang['NOT_MEMBER_OF_GROUP'] . $return_page); + } + list(, $row) = each($row); + + if (!$row['group_leader']) + { + trigger_error($user->lang['NOT_LEADER_OF_GROUP'] . $return_page); + } + + $group_row['group_name'] = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + + if (confirm_box(true)) + { + if (!sizeof($mark_ary)) + { + $start = 0; + + do + { + $sql = 'SELECT user_id + FROM ' . USER_GROUP_TABLE . " + WHERE group_id = $group_id + ORDER BY user_id"; + $result = $db->sql_query_limit($sql, 200, $start); + + $mark_ary = array(); + if ($row = $db->sql_fetchrow($result)) + { + do + { + $mark_ary[] = $row['user_id']; + } + while ($row = $db->sql_fetchrow($result)); + + group_user_attributes('default', $group_id, $mark_ary, false, $group_row['group_name'], $group_row); + + $start = (sizeof($mark_ary) < 200) ? 0 : $start + 200; + } + else + { + $start = 0; + } + $db->sql_freeresult($result); + } + while ($start); + } + else + { + group_user_attributes('default', $group_id, $mark_ary, false, $group_row['group_name'], $group_row); + } + + $user->add_lang('acp/groups'); + + trigger_error($user->lang['GROUP_DEFS_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $this->u_action . '&action=list&g=' . $group_id . '">', '</a>')); + } + else + { + $user->add_lang('acp/common'); + + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'mark' => $mark_ary, + 'g' => $group_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action)) + ); + } + + // redirect to last screen + redirect($this->u_action . '&action=list&g=' . $group_id); + + break; + + case 'deleteusers': + + $user->add_lang(array('acp/groups', 'acp/common')); + + if (!($row = group_memberships($group_id, $user->data['user_id']))) + { + trigger_error($user->lang['NOT_MEMBER_OF_GROUP'] . $return_page); + } + list(, $row) = each($row); + + if (!$row['group_leader']) + { + trigger_error($user->lang['NOT_LEADER_OF_GROUP'] . $return_page); + } + + $group_row['group_name'] = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + + if (confirm_box(true)) + { + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . $return_page); + } + + $error = group_user_del($group_id, $mark_ary, false, $group_row['group_name']); + + if ($error) + { + trigger_error($user->lang[$error] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $this->u_action . '&action=list&g=' . $group_id . '">', '</a>')); + } + + trigger_error($user->lang['GROUP_USERS_REMOVE'] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $this->u_action . '&action=list&g=' . $group_id . '">', '</a>')); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'mark' => $mark_ary, + 'g' => $group_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action)) + ); + } + + // redirect to last screen + redirect($this->u_action . '&action=list&g=' . $group_id); + + break; + + case 'addusers': + + $user->add_lang(array('acp/groups', 'acp/common')); + + $names = utf8_normalize_nfc(request_var('usernames', '', true)); + + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . $return_page); + } + + if (!$names) + { + trigger_error($user->lang['NO_USERS'] . $return_page); + } + + if (!($row = group_memberships($group_id, $user->data['user_id']))) + { + trigger_error($user->lang['NOT_MEMBER_OF_GROUP'] . $return_page); + } + list(, $row) = each($row); + + if (!$row['group_leader']) + { + trigger_error($user->lang['NOT_LEADER_OF_GROUP'] . $return_page); + } + + $name_ary = array_unique(explode("\n", $names)); + $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + + $default = request_var('default', 0); + + if (confirm_box(true)) + { + // Add user/s to group + if ($error = group_user_add($group_id, false, $name_ary, $group_name, $default, 0, 0, $group_row)) + { + trigger_error($user->lang[$error] . $return_page); + } + + trigger_error($user->lang['GROUP_USERS_ADDED'] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $this->u_action . '&action=list&g=' . $group_id . '">', '</a>')); + } + else + { + $s_hidden_fields = array( + 'default' => $default, + 'usernames' => $names, + 'g' => $group_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action + ); + confirm_box(false, sprintf($user->lang['GROUP_CONFIRM_ADD_USER' . ((sizeof($name_ary) == 1) ? '' : 'S')], implode(', ', $name_ary)), build_hidden_fields($s_hidden_fields)); + } + + trigger_error($user->lang['NO_USERS_ADDED'] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $this->u_action . '&action=list&g=' . $group_id . '">', '</a>')); + + break; + + default: + $user->add_lang('acp/common'); + + $sql = 'SELECT g.group_id, g.group_name, g.group_colour, g.group_desc, g.group_desc_uid, g.group_desc_bitfield, g.group_desc_options, g.group_type, ug.group_leader + FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug + WHERE ug.user_id = ' . $user->data['user_id'] . ' + AND g.group_id = ug.group_id + AND ug.group_leader = 1 + ORDER BY g.group_type DESC, g.group_name'; + $result = $db->sql_query($sql); + + while ($value = $db->sql_fetchrow($result)) + { + $template->assign_block_vars('leader', array( + 'GROUP_NAME' => ($value['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $value['group_name']] : $value['group_name'], + 'GROUP_DESC' => generate_text_for_display($value['group_desc'], $value['group_desc_uid'], $value['group_desc_bitfield'], $value['group_desc_options']), + 'GROUP_TYPE' => $value['group_type'], + 'GROUP_ID' => $value['group_id'], + 'GROUP_COLOUR' => $value['group_colour'], + + 'U_LIST' => $this->u_action . "&action=list&g={$value['group_id']}", + 'U_EDIT' => $this->u_action . "&action=edit&g={$value['group_id']}") + ); + } + $db->sql_freeresult($result); + + break; + } + + break; + } + + $this->tpl_name = 'ucp_groups_' . $mode; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/ucp_main.php b/phpBB/includes/ucp/ucp_main.php new file mode 100644 index 0000000000..6ac2412ef0 --- /dev/null +++ b/phpBB/includes/ucp/ucp_main.php @@ -0,0 +1,835 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ucp_main +* UCP Front Panel +* @package ucp +*/ +class ucp_main +{ + var $p_master; + var $u_action; + + function ucp_main(&$p_master) + { + $this->p_master = &$p_master; + } + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx; + + switch ($mode) + { + case 'front': + + $user->add_lang('memberlist'); + + $sql_from = TOPICS_TABLE . ' t '; + $sql_select = ''; + + if ($config['load_db_track']) + { + $sql_from .= ' LEFT JOIN ' . TOPICS_POSTED_TABLE . ' tp ON (tp.topic_id = t.topic_id + AND tp.user_id = ' . $user->data['user_id'] . ')'; + $sql_select .= ', tp.topic_posted'; + } + + if ($config['load_db_lastread']) + { + $sql_from .= ' LEFT JOIN ' . TOPICS_TRACK_TABLE . ' tt ON (tt.topic_id = t.topic_id + AND tt.user_id = ' . $user->data['user_id'] . ')'; + $sql_select .= ', tt.mark_time'; + } + + $topic_type = $user->lang['VIEW_TOPIC_GLOBAL']; + $folder = 'global_read'; + $folder_new = 'global_unread'; + + // Get cleaned up list... return only those forums not having the f_read permission + $forum_ary = $auth->acl_getf('!f_read', true); + $forum_ary = array_unique(array_keys($forum_ary)); + + // Determine first forum the user is able to read into - for global announcement link + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE . ' + WHERE forum_type = ' . FORUM_POST; + + if (sizeof($forum_ary)) + { + $sql .= ' AND ' . $db->sql_in_set('forum_id', $forum_ary, true); + } + $result = $db->sql_query_limit($sql, 1); + $g_forum_id = (int) $db->sql_fetchfield('forum_id'); + $db->sql_freeresult($result); + + $sql = "SELECT t.* $sql_select + FROM $sql_from + WHERE t.forum_id = 0 + AND t.topic_type = " . POST_GLOBAL . ' + ORDER BY t.topic_last_post_time DESC'; + + $topic_list = $rowset = array(); + // If the user can't see any forums, he can't read any posts because fid of 0 is invalid + if ($g_forum_id) + { + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $topic_list[] = $row['topic_id']; + $rowset[$row['topic_id']] = $row; + } + $db->sql_freeresult($result); + } + + $topic_tracking_info = array(); + if ($config['load_db_lastread']) + { + $topic_tracking_info = get_topic_tracking(0, $topic_list, $rowset, false, $topic_list); + } + else + { + $topic_tracking_info = get_complete_topic_tracking(0, $topic_list, $topic_list); + } + + foreach ($topic_list as $topic_id) + { + $row = &$rowset[$topic_id]; + + $forum_id = $row['forum_id']; + $topic_id = $row['topic_id']; + + $unread_topic = (isset($topic_tracking_info[$topic_id]) && $row['topic_last_post_time'] > $topic_tracking_info[$topic_id]) ? true : false; + + $folder_img = ($unread_topic) ? $folder_new : $folder; + $folder_alt = ($unread_topic) ? 'NEW_POSTS' : (($row['topic_status'] == ITEM_LOCKED) ? 'TOPIC_LOCKED' : 'NO_NEW_POSTS'); + + if ($row['topic_status'] == ITEM_LOCKED) + { + $folder_img .= '_locked'; + } + + // Posted image? + if (!empty($row['topic_posted']) && $row['topic_posted']) + { + $folder_img .= '_mine'; + } + + $template->assign_block_vars('topicrow', array( + 'FORUM_ID' => $forum_id, + 'TOPIC_ID' => $topic_id, + 'TOPIC_AUTHOR' => get_username_string('username', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + 'TOPIC_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + 'TOPIC_AUTHOR_FULL' => get_username_string('full', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + 'FIRST_POST_TIME' => $user->format_date($row['topic_time']), + 'LAST_POST_SUBJECT' => censor_text($row['topic_last_post_subject']), + 'LAST_POST_TIME' => $user->format_date($row['topic_last_post_time']), + 'LAST_VIEW_TIME' => $user->format_date($row['topic_last_view_time']), + 'LAST_POST_AUTHOR' => get_username_string('username', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + 'LAST_POST_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + 'LAST_POST_AUTHOR_FULL' => get_username_string('full', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + 'TOPIC_TITLE' => censor_text($row['topic_title']), + 'TOPIC_TYPE' => $topic_type, + + 'TOPIC_FOLDER_IMG' => $user->img($folder_img, $folder_alt), + 'TOPIC_FOLDER_IMG_SRC' => $user->img($folder_img, $folder_alt, false, '', 'src'), + 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_topic_attach', '') : '', + + 'S_USER_POSTED' => (!empty($row['topic_posted']) && $row['topic_posted']) ? true : false, + 'S_UNREAD' => $unread_topic, + + 'U_TOPIC_AUTHOR' => get_username_string('profile', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + 'U_LAST_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$g_forum_id&t=$topic_id&p=" . $row['topic_last_post_id']) . '#p' . $row['topic_last_post_id'], + 'U_LAST_POST_AUTHOR' => get_username_string('profile', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + 'U_NEWEST_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$g_forum_id&t=$topic_id&view=unread") . '#unread', + 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$g_forum_id&t=$topic_id")) + ); + } + + if ($config['load_user_activity']) + { + if (!function_exists('display_user_activity')) + { + include_once($phpbb_root_path . 'includes/functions_display.' . $phpEx); + } + display_user_activity($user->data); + } + + // Do the relevant calculations + $memberdays = max(1, round((time() - $user->data['user_regdate']) / 86400)); + $posts_per_day = $user->data['user_posts'] / $memberdays; + $percentage = ($config['num_posts']) ? min(100, ($user->data['user_posts'] / $config['num_posts']) * 100) : 0; + + $template->assign_vars(array( + 'USER_COLOR' => (!empty($user->data['user_colour'])) ? $user->data['user_colour'] : '', + 'JOINED' => $user->format_date($user->data['user_regdate']), + 'VISITED' => (empty($last_visit)) ? ' - ' : $user->format_date($last_visit), + 'WARNINGS' => ($user->data['user_warnings']) ? $user->data['user_warnings'] : 0, + 'POSTS' => ($user->data['user_posts']) ? $user->data['user_posts'] : 0, + 'POSTS_DAY' => sprintf($user->lang['POST_DAY'], $posts_per_day), + 'POSTS_PCT' => sprintf($user->lang['POST_PCT'], $percentage), + + 'OCCUPATION' => (!empty($row['user_occ'])) ? $row['user_occ'] : '', + 'INTERESTS' => (!empty($row['user_interests'])) ? $row['user_interests'] : '', + +// 'S_GROUP_OPTIONS' => $group_options, + + 'U_SEARCH_USER' => ($auth->acl_get('u_search')) ? append_sid("{$phpbb_root_path}search.$phpEx", 'author_id=' . $user->data['user_id'] . '&sr=posts') : '', + )); + + break; + + case 'subscribed': + + include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + + $user->add_lang('viewforum'); + + add_form_key('ucp_front_subscribed'); + + $unwatch = (isset($_POST['unwatch'])) ? true : false; + + if ($unwatch) + { + if (check_form_key('ucp_front_subscribed')) + { + $forums = array_keys(request_var('f', array(0 => 0))); + $topics = array_keys(request_var('t', array(0 => 0))); + $msg = ''; + + if (sizeof($forums) || sizeof($topics)) + { + $l_unwatch = ''; + if (sizeof($forums)) + { + $sql = 'DELETE FROM ' . FORUMS_WATCH_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forums) . ' + AND user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + + $l_unwatch .= '_FORUMS'; + } + + if (sizeof($topics)) + { + $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', $topics) . ' + AND user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + + $l_unwatch .= '_TOPICS'; + } + $msg = $user->lang['UNWATCHED' . $l_unwatch]; + } + else + { + $msg = $user->lang['NO_WATCHED_SELECTED']; + } + } + else + { + $msg = $user->lang['FORM_INVALID']; + } + $message = $msg . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . append_sid("{$phpbb_root_path}ucp.$phpEx", "i=$id&mode=subscribed") . '">', '</a>'); + meta_refresh(3, append_sid("{$phpbb_root_path}ucp.$phpEx", "i=$id&mode=subscribed")); + trigger_error($message); + } + + $forbidden_forums = array(); + + if ($config['allow_forum_notify']) + { + $forbidden_forums = $auth->acl_getf('!f_read', true); + $forbidden_forums = array_unique(array_keys($forbidden_forums)); + + $sql_array = array( + 'SELECT' => 'f.*', + + 'FROM' => array( + FORUMS_WATCH_TABLE => 'fw', + FORUMS_TABLE => 'f' + ), + + 'WHERE' => 'fw.user_id = ' . $user->data['user_id'] . ' + AND f.forum_id = fw.forum_id + AND ' . $db->sql_in_set('f.forum_id', $forbidden_forums, true, true), + + 'ORDER_BY' => 'left_id' + ); + + if ($config['load_db_lastread']) + { + $sql_array['LEFT_JOIN'] = array( + array( + 'FROM' => array(FORUMS_TRACK_TABLE => 'ft'), + 'ON' => 'ft.user_id = ' . $user->data['user_id'] . ' AND ft.forum_id = f.forum_id' + ) + ); + + $sql_array['SELECT'] .= ', ft.mark_time '; + } + else + { + $tracking_topics = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : ''; + $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array(); + } + + $sql = $db->sql_build_query('SELECT', $sql_array); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $forum_id = $row['forum_id']; + + if ($config['load_db_lastread']) + { + $forum_check = (!empty($row['mark_time'])) ? $row['mark_time'] : $user->data['user_lastmark']; + } + else + { + $forum_check = (isset($tracking_topics['f'][$forum_id])) ? (int) (base_convert($tracking_topics['f'][$forum_id], 36, 10) + $config['board_startdate']) : $user->data['user_lastmark']; + } + + $unread_forum = ($row['forum_last_post_time'] > $forum_check) ? true : false; + + // Which folder should we display? + if ($row['forum_status'] == ITEM_LOCKED) + { + $folder_image = ($unread_forum) ? 'forum_unread_locked' : 'forum_read_locked'; + $folder_alt = 'FORUM_LOCKED'; + } + else + { + $folder_image = ($unread_forum) ? 'forum_unread' : 'forum_read'; + $folder_alt = ($unread_forum) ? 'NEW_POSTS' : 'NO_NEW_POSTS'; + } + + // Create last post link information, if appropriate + if ($row['forum_last_post_id']) + { + $last_post_time = $user->format_date($row['forum_last_post_time']); + $last_post_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&p=" . $row['forum_last_post_id']) . '#p' . $row['forum_last_post_id']; + } + else + { + $last_post_time = $last_post_url = ''; + } + + $template->assign_block_vars('forumrow', array( + 'FORUM_ID' => $forum_id, + 'FORUM_FOLDER_IMG' => $user->img($folder_image, $folder_alt), + 'FORUM_FOLDER_IMG_SRC' => $user->img($folder_image, $folder_alt, false, '', 'src'), + 'FORUM_IMAGE' => ($row['forum_image']) ? '<img src="' . $phpbb_root_path . $row['forum_image'] . '" alt="' . $user->lang[$folder_alt] . '" />' : '', + 'FORUM_IMAGE_SRC' => ($row['forum_image']) ? $phpbb_root_path . $row['forum_image'] : '', + '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']), + 'LAST_POST_SUBJECT' => $row['forum_last_post_subject'], + 'LAST_POST_TIME' => $last_post_time, + + 'LAST_POST_AUTHOR' => get_username_string('username', $row['forum_last_poster_id'], $row['forum_last_poster_name'], $row['forum_last_poster_colour']), + 'LAST_POST_AUTHOR_COLOUR' => get_username_string('colour', $row['forum_last_poster_id'], $row['forum_last_poster_name'], $row['forum_last_poster_colour']), + 'LAST_POST_AUTHOR_FULL' => get_username_string('full', $row['forum_last_poster_id'], $row['forum_last_poster_name'], $row['forum_last_poster_colour']), + 'U_LAST_POST_AUTHOR' => 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, + 'U_VIEWFORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id'])) + ); + } + $db->sql_freeresult($result); + } + + // Subscribed Topics + if ($config['allow_topic_notify']) + { + if (empty($forbidden_forums)) + { + $forbidden_forums = $auth->acl_getf('!f_read', true); + $forbidden_forums = array_unique(array_keys($forbidden_forums)); + } + $this->assign_topiclist('subscribed', $forbidden_forums); + } + + $template->assign_vars(array( + 'S_TOPIC_NOTIFY' => $config['allow_topic_notify'], + 'S_FORUM_NOTIFY' => $config['allow_forum_notify'], + )); + + break; + + case 'bookmarks': + + if (!$config['allow_bookmarks']) + { + $template->assign_vars(array( + 'S_NO_DISPLAY_BOOKMARKS' => true) + ); + break; + } + + include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + + $user->add_lang('viewforum'); + + if (isset($_POST['unbookmark'])) + { + $s_hidden_fields = array('unbookmark' => 1); + $topics = (isset($_POST['t'])) ? array_keys(request_var('t', array(0 => 0))) : array(); + $url = $this->u_action; + + if (!sizeof($topics)) + { + trigger_error('NO_BOOKMARKS_SELECTED'); + } + + foreach ($topics as $topic_id) + { + $s_hidden_fields['t'][$topic_id] = 1; + } + + if (confirm_box(true)) + { + $sql = 'DELETE FROM ' . BOOKMARKS_TABLE . ' + WHERE user_id = ' . $user->data['user_id'] . ' + AND ' . $db->sql_in_set('topic_id', $topics); + $db->sql_query($sql); + + meta_refresh(3, $url); + $message = $user->lang['BOOKMARKS_REMOVED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $url . '">', '</a>'); + trigger_error($message); + } + else + { + confirm_box(false, 'REMOVE_SELECTED_BOOKMARKS', build_hidden_fields($s_hidden_fields)); + } + } + $forbidden_forums = $auth->acl_getf('!f_read', true); + $forbidden_forums = array_unique(array_keys($forbidden_forums)); + + $this->assign_topiclist('bookmarks', $forbidden_forums); + + break; + + case 'drafts': + + $pm_drafts = ($this->p_master->p_name == 'pm') ? true : false; + $template->assign_var('S_SHOW_DRAFTS', true); + + $user->add_lang('posting'); + + $edit = (isset($_REQUEST['edit'])) ? true : false; + $submit = (isset($_POST['submit'])) ? true : false; + $draft_id = ($edit) ? intval($_REQUEST['edit']) : 0; + $delete = (isset($_POST['delete'])) ? true : false; + + $s_hidden_fields = ($edit) ? '<input type="hidden" name="edit" value="' . $draft_id . '" />' : ''; + $draft_subject = $draft_message = ''; + add_form_key('ucp_draft'); + + if ($delete) + { + if (check_form_key('ucp_draft')) + { + $drafts = array_keys(request_var('d', array(0 => 0))); + + if (sizeof($drafts)) + { + $sql = 'DELETE FROM ' . DRAFTS_TABLE . ' + WHERE ' . $db->sql_in_set('draft_id', $drafts) . ' + AND user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + } + $msg = $user->lang['DRAFTS_DELETED']; + unset($drafts); + } + else + { + $msg = $user->lang['FORM_INVALID']; + } + $message = $msg . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + meta_refresh(3, $this->u_action); + trigger_error($message); + } + + if ($submit && $edit) + { + $draft_subject = utf8_normalize_nfc(request_var('subject', '', true)); + $draft_message = utf8_normalize_nfc(request_var('message', '', true)); + if (check_form_key('ucp_draft')) + { + if ($draft_message && $draft_subject) + { + $draft_row = array( + 'draft_subject' => $draft_subject, + 'draft_message' => $draft_message + ); + + $sql = 'UPDATE ' . DRAFTS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $draft_row) . " + WHERE draft_id = $draft_id + AND user_id = " . $user->data['user_id']; + $db->sql_query($sql); + + $message = $user->lang['DRAFT_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + + meta_refresh(3, $this->u_action); + trigger_error($message); + } + else + { + $template->assign_var('ERROR', ($draft_message == '') ? $user->lang['EMPTY_DRAFT'] : (($draft_subject == '') ? $user->lang['EMPTY_DRAFT_TITLE'] : '')); + } + } + else + { + $template->assign_var('ERROR', $user->lang['FORM_INVALID']); + } + } + + if (!$pm_drafts) + { + $sql = 'SELECT d.*, f.forum_name + FROM ' . DRAFTS_TABLE . ' d, ' . FORUMS_TABLE . ' f + WHERE d.user_id = ' . $user->data['user_id'] . ' ' . + (($edit) ? "AND d.draft_id = $draft_id" : '') . ' + AND f.forum_id = d.forum_id + ORDER BY d.save_time DESC'; + } + else + { + $sql = 'SELECT * FROM ' . DRAFTS_TABLE . ' + WHERE user_id = ' . $user->data['user_id'] . ' ' . + (($edit) ? "AND draft_id = $draft_id" : '') . ' + AND forum_id = 0 + AND topic_id = 0 + ORDER BY save_time DESC'; + } + $result = $db->sql_query($sql); + + $draftrows = $topic_ids = array(); + + while ($row = $db->sql_fetchrow($result)) + { + if ($row['topic_id']) + { + $topic_ids[] = (int) $row['topic_id']; + } + $draftrows[] = $row; + } + $db->sql_freeresult($result); + + if (sizeof($topic_ids)) + { + $sql = 'SELECT topic_id, forum_id, topic_title + FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', array_unique($topic_ids)); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $topic_rows[$row['topic_id']] = $row; + } + $db->sql_freeresult($result); + } + unset($topic_ids); + + $template->assign_var('S_EDIT_DRAFT', $edit); + + $row_count = 0; + foreach ($draftrows as $draft) + { + $link_topic = $link_forum = $link_pm = false; + $insert_url = $view_url = $title = ''; + + if (isset($topic_rows[$draft['topic_id']]) && $auth->acl_get('f_read', $topic_rows[$draft['topic_id']]['forum_id'])) + { + $link_topic = true; + $view_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $topic_rows[$draft['topic_id']]['forum_id'] . '&t=' . $draft['topic_id']); + $title = $topic_rows[$draft['topic_id']]['topic_title']; + + $insert_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'f=' . $topic_rows[$draft['topic_id']]['forum_id'] . '&t=' . $draft['topic_id'] . '&mode=reply&d=' . $draft['draft_id']); + } + else if ($auth->acl_get('f_read', $draft['forum_id'])) + { + $link_forum = true; + $view_url = append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $draft['forum_id']); + $title = $draft['forum_name']; + + $insert_url = append_sid("{$phpbb_root_path}posting.$phpEx", 'f=' . $draft['forum_id'] . '&mode=post&d=' . $draft['draft_id']); + } + else if ($pm_drafts) + { + $link_pm = true; + $insert_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=$id&mode=compose&d=" . $draft['draft_id']); + } + + $template_row = array( + 'DATE' => $user->format_date($draft['save_time']), + 'DRAFT_MESSAGE' => ($submit) ? $draft_message : $draft['draft_message'], + 'DRAFT_SUBJECT' => ($submit) ? $draft_subject : $draft['draft_subject'], + 'TITLE' => $title, + + 'DRAFT_ID' => $draft['draft_id'], + 'FORUM_ID' => $draft['forum_id'], + 'TOPIC_ID' => $draft['topic_id'], + + 'U_VIEW' => $view_url, + 'U_VIEW_EDIT' => $this->u_action . '&edit=' . $draft['draft_id'], + 'U_INSERT' => $insert_url, + + 'S_LINK_TOPIC' => $link_topic, + 'S_LINK_FORUM' => $link_forum, + 'S_LINK_PM' => $link_pm, + 'S_HIDDEN_FIELDS' => $s_hidden_fields + ); + $row_count++; + + ($edit) ? $template->assign_vars($template_row) : $template->assign_block_vars('draftrow', $template_row); + } + + if (!$edit) + { + $template->assign_var('S_DRAFT_ROWS', $row_count); + } + + break; + } + + + $template->assign_vars(array( + 'L_TITLE' => $user->lang['UCP_MAIN_' . strtoupper($mode)], + + 'S_DISPLAY_MARK_ALL' => ($mode == 'watched' || ($mode == 'drafts' && !isset($_GET['edit']))) ? true : false, + 'S_HIDDEN_FIELDS' => (isset($s_hidden_fields)) ? $s_hidden_fields : '', + 'S_UCP_ACTION' => $this->u_action, + + 'LAST_POST_IMG' => $user->img('icon_topic_latest', 'VIEW_LATEST_POST'), + 'NEWEST_POST_IMG' => $user->img('icon_topic_newest', 'VIEW_NEWEST_POST'), + )); + + // Set desired template + $this->tpl_name = 'ucp_main_' . $mode; + $this->page_title = 'UCP_MAIN_' . strtoupper($mode); + } + + /** + * Build and assign topiclist for bookmarks/subscribed topics + */ + function assign_topiclist($mode = 'subscribed', $forbidden_forum_ary = array()) + { + global $user, $db, $template, $config, $cache, $auth, $phpbb_root_path, $phpEx; + + $table = ($mode == 'subscribed') ? TOPICS_WATCH_TABLE : BOOKMARKS_TABLE; + $start = request_var('start', 0); + + // Grab icons + $icons = $cache->obtain_icons(); + + $sql_array = array( + 'SELECT' => 'COUNT(t.topic_id) as topics_count', + + 'FROM' => array( + $table => 'i', + TOPICS_TABLE => 't' + ), + + 'WHERE' => 'i.topic_id = t.topic_id + AND i.user_id = ' . $user->data['user_id'] . ' + AND ' . $db->sql_in_set('t.forum_id', $forbidden_forum_ary, true, true), + ); + $sql = $db->sql_build_query('SELECT', $sql_array); + $result = $db->sql_query($sql); + $topics_count = (int) $db->sql_fetchfield('topics_count'); + $db->sql_freeresult($result); + + if ($topics_count) + { + $template->assign_vars(array( + 'PAGINATION' => generate_pagination($this->u_action, $topics_count, $config['topics_per_page'], $start), + 'PAGE_NUMBER' => on_page($topics_count, $config['topics_per_page'], $start), + 'TOTAL_TOPICS' => ($topics_count == 1) ? $user->lang['VIEW_FORUM_TOPIC'] : sprintf($user->lang['VIEW_FORUM_TOPICS'], $topics_count)) + ); + } + + if ($mode == 'subscribed') + { + $sql_array = array( + 'SELECT' => 't.*, f.forum_name', + + 'FROM' => array( + TOPICS_WATCH_TABLE => 'tw', + TOPICS_TABLE => 't' + ), + + 'WHERE' => 'tw.user_id = ' . $user->data['user_id'] . ' + AND t.topic_id = tw.topic_id + AND ' . $db->sql_in_set('t.forum_id', $forbidden_forum_ary, true, true), + + + 'ORDER_BY' => 't.topic_last_post_time DESC' + ); + + $sql_array['LEFT_JOIN'] = array(); + } + else + { + $sql_array = array( + 'SELECT' => 't.*, f.forum_name, b.topic_id as b_topic_id', + + 'FROM' => array( + BOOKMARKS_TABLE => 'b', + ), + + 'WHERE' => 'b.user_id = ' . $user->data['user_id'] . ' + AND ' . $db->sql_in_set('f.forum_id', $forbidden_forum_ary, true, true), + + 'ORDER_BY' => 't.topic_last_post_time DESC' + ); + + $sql_array['LEFT_JOIN'] = array(); + $sql_array['LEFT_JOIN'][] = array('FROM' => array(TOPICS_TABLE => 't'), 'ON' => 'b.topic_id = t.topic_id'); + } + + $sql_array['LEFT_JOIN'][] = array('FROM' => array(FORUMS_TABLE => 'f'), 'ON' => 't.forum_id = f.forum_id'); + + if ($config['load_db_lastread']) + { + $sql_array['LEFT_JOIN'][] = array('FROM' => array(FORUMS_TRACK_TABLE => 'ft'), 'ON' => 'ft.forum_id = t.forum_id AND ft.user_id = ' . $user->data['user_id']); + $sql_array['LEFT_JOIN'][] = array('FROM' => array(TOPICS_TRACK_TABLE => 'tt'), 'ON' => 'tt.topic_id = t.topic_id AND tt.user_id = ' . $user->data['user_id']); + $sql_array['SELECT'] .= ', tt.mark_time, ft.mark_time AS forum_mark_time'; + } + + if ($config['load_db_track']) + { + $sql_array['LEFT_JOIN'][] = array('FROM' => array(TOPICS_POSTED_TABLE => 'tp'), 'ON' => 'tp.topic_id = t.topic_id AND tp.user_id = ' . $user->data['user_id']); + $sql_array['SELECT'] .= ', tp.topic_posted'; + } + + $sql = $db->sql_build_query('SELECT', $sql_array); + $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); + + $topic_list = $topic_forum_list = $global_announce_list = $rowset = array(); + while ($row = $db->sql_fetchrow($result)) + { + $topic_id = (isset($row['b_topic_id'])) ? $row['b_topic_id'] : $row['topic_id']; + + $topic_list[] = $topic_id; + $rowset[$topic_id] = $row; + + $topic_forum_list[$row['forum_id']]['forum_mark_time'] = ($config['load_db_lastread']) ? $row['forum_mark_time'] : 0; + $topic_forum_list[$row['forum_id']]['topics'][] = $topic_id; + + if ($row['topic_type'] == POST_GLOBAL) + { + $global_announce_list[] = $topic_id; + } + } + $db->sql_freeresult($result); + + $topic_tracking_info = array(); + if ($config['load_db_lastread']) + { + foreach ($topic_forum_list as $f_id => $topic_row) + { + $topic_tracking_info += get_topic_tracking($f_id, $topic_row['topics'], $rowset, array($f_id => $topic_row['forum_mark_time']), ($f_id == 0) ? $global_announce_list : false); + } + } + else + { + foreach ($topic_forum_list as $f_id => $topic_row) + { + $topic_tracking_info += get_complete_topic_tracking($f_id, $topic_row['topics'], $global_announce_list); + } + } + + foreach ($topic_list as $topic_id) + { + $row = &$rowset[$topic_id]; + + $forum_id = $row['forum_id']; + $topic_id = (isset($row['b_topic_id'])) ? $row['b_topic_id'] : $row['topic_id']; + + $unread_topic = (isset($topic_tracking_info[$topic_id]) && $row['topic_last_post_time'] > $topic_tracking_info[$topic_id]) ? true : false; + + // Replies + $replies = ($auth->acl_get('m_approve', $forum_id)) ? $row['topic_replies_real'] : $row['topic_replies']; + + if ($row['topic_status'] == ITEM_MOVED && !empty($row['topic_moved_id'])) + { + $topic_id = $row['topic_moved_id']; + } + + // Get folder img, topic status/type related information + $folder_img = $folder_alt = $topic_type = ''; + topic_status($row, $replies, $unread_topic, $folder_img, $folder_alt, $topic_type); + + $view_topic_url_params = "f=$forum_id&t=$topic_id"; + $view_topic_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params); + + // Send vars to template + $template->assign_block_vars('topicrow', array( + 'FORUM_ID' => $forum_id, + 'TOPIC_ID' => $topic_id, + 'FIRST_POST_TIME' => $user->format_date($row['topic_time']), + 'LAST_POST_SUBJECT' => $row['topic_last_post_subject'], + 'LAST_POST_TIME' => $user->format_date($row['topic_last_post_time']), + 'LAST_VIEW_TIME' => $user->format_date($row['topic_last_view_time']), + + 'TOPIC_AUTHOR' => get_username_string('username', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + 'TOPIC_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + 'TOPIC_AUTHOR_FULL' => get_username_string('full', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + 'U_TOPIC_AUTHOR' => get_username_string('profile', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + + 'LAST_POST_AUTHOR' => get_username_string('username', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + 'LAST_POST_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + 'LAST_POST_AUTHOR_FULL' => get_username_string('full', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + 'U_LAST_POST_AUTHOR' => get_username_string('profile', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + + 'S_DELETED_TOPIC' => (!$row['topic_id']) ? true : false, + 'S_GLOBAL_TOPIC' => (!$forum_id) ? true : false, + + 'PAGINATION' => topic_generate_pagination($replies, append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . (($row['forum_id']) ? $row['forum_id'] : $forum_id) . "&t=$topic_id")), + 'REPLIES' => $replies, + 'VIEWS' => $row['topic_views'], + 'TOPIC_TITLE' => censor_text($row['topic_title']), + 'TOPIC_TYPE' => $topic_type, + 'FORUM_NAME' => $row['forum_name'], + + 'TOPIC_FOLDER_IMG' => $user->img($folder_img, $folder_alt), + 'TOPIC_FOLDER_IMG_SRC' => $user->img($folder_img, $folder_alt, false, '', 'src'), + 'TOPIC_FOLDER_IMG_ALT' => $user->lang[$folder_alt], + 'TOPIC_ICON_IMG' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['img'] : '', + 'TOPIC_ICON_IMG_WIDTH' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['width'] : '', + 'TOPIC_ICON_IMG_HEIGHT' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['height'] : '', + 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', + + 'S_TOPIC_TYPE' => $row['topic_type'], + 'S_USER_POSTED' => (!empty($row['topic_posted'])) ? true : false, + 'S_UNREAD_TOPIC' => $unread_topic, + + 'U_NEWEST_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params . '&view=unread') . '#unread', + 'U_LAST_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params . '&p=' . $row['topic_last_post_id']) . '#p' . $row['topic_last_post_id'], + 'U_VIEW_TOPIC' => $view_topic_url, + 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id), + )); + } + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/ucp_pm.php b/phpBB/includes/ucp/ucp_pm.php new file mode 100644 index 0000000000..e1c51170db --- /dev/null +++ b/phpBB/includes/ucp/ucp_pm.php @@ -0,0 +1,416 @@ +<?php +/** +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Private Message Class +* +* $_REQUEST['folder'] display folder with the id used +* $_REQUEST['folder'] inbox|outbox|sentbox display folder with the associated name +* +* Display Messages (default to inbox) - mode=view +* Display single message - mode=view&p=[msg_id] or &p=[msg_id] (short linkage) +* +* if the folder id with (&f=[folder_id]) is used when displaying messages, one query will be saved. If it is not used, phpBB needs to grab +* the folder id first in order to display the input boxes and folder names and such things. ;) phpBB always checks this against the database to make +* sure the user is able to view the message. +* +* Composing Messages (mode=compose): +* To specific user (u=[user_id]) +* To specific group (g=[group_id]) +* Quoting a post (action=quotepost&p=[post_id]) +* Quoting a PM (action=quote&p=[msg_id]) +* Forwarding a PM (action=forward&p=[msg_id]) +* +* @package ucp +*/ +class ucp_pm +{ + var $u_action; + + function main($id, $mode) + { + global $user, $template, $phpbb_root_path, $auth, $phpEx, $db, $config; + + if (!$user->data['is_registered']) + { + trigger_error('NO_MESSAGE'); + } + + // Is PM disabled? + if (!$config['allow_privmsg']) + { + trigger_error('PM_DISABLED'); + } + + $user->add_lang('posting'); + $template->assign_var('S_PRIVMSGS', true); + + // Folder directly specified? + $folder_specified = request_var('folder', ''); + + if (!in_array($folder_specified, array('inbox', 'outbox', 'sentbox'))) + { + $folder_specified = (int) $folder_specified; + } + else + { + $folder_specified = ($folder_specified == 'inbox') ? PRIVMSGS_INBOX : (($folder_specified == 'outbox') ? PRIVMSGS_OUTBOX : PRIVMSGS_SENTBOX); + } + + if (!$folder_specified) + { + $mode = (!$mode) ? request_var('mode', 'view') : $mode; + } + else + { + $mode = 'view'; + } + + include($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx); + + switch ($mode) + { + // New private messages popup + case 'popup': + + $l_new_message = ''; + if ($user->data['is_registered']) + { + if ($user->data['user_new_privmsg']) + { + $l_new_message = ($user->data['user_new_privmsg'] == 1) ? $user->lang['YOU_NEW_PM'] : $user->lang['YOU_NEW_PMS']; + } + else + { + $l_new_message = $user->lang['YOU_NO_NEW_PM']; + } + } + + $template->assign_vars(array( + 'MESSAGE' => $l_new_message, + 'S_NOT_LOGGED_IN' => ($user->data['user_id'] == ANONYMOUS) ? true : false, + 'CLICK_TO_VIEW' => sprintf($user->lang['CLICK_VIEW_PRIVMSG'], '<a href="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=inbox') . '" onclick="jump_to_inbox(this.href); return false;">', '</a>'), + 'U_INBOX' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=inbox'), + 'UA_INBOX' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=inbox', false)) + ); + + $tpl_file = 'ucp_pm_popup'; + break; + + // Compose message + case 'compose': + $action = request_var('action', 'post'); + + get_folder($user->data['user_id']); + + if (!$auth->acl_get('u_sendpm')) + { + // trigger_error('NO_AUTH_SEND_MESSAGE'); + $template->assign_vars(array( + 'S_NO_AUTH_SEND_MESSAGE' => true, + 'S_COMPOSE_PM_VIEW' => true, + )); + + $tpl_file = 'ucp_pm_viewfolder'; + break; + } + + include($phpbb_root_path . 'includes/ucp/ucp_pm_compose.' . $phpEx); + compose_pm($id, $mode, $action); + + $tpl_file = 'posting_body'; + break; + + case 'options': + set_user_message_limit(); + get_folder($user->data['user_id']); + + include($phpbb_root_path . 'includes/ucp/ucp_pm_options.' . $phpEx); + message_options($id, $mode, $global_privmsgs_rules, $global_rule_conditions); + + $tpl_file = 'ucp_pm_options'; + break; + + case 'drafts': + + get_folder($user->data['user_id']); + $this->p_name = 'pm'; + + // Call another module... please do not try this at home... Hoochie Coochie Man + include($phpbb_root_path . 'includes/ucp/ucp_main.' . $phpEx); + + $module = new ucp_main($this); + $module->u_action = $this->u_action; + $module->main($id, $mode); + + $this->tpl_name = $module->tpl_name; + $this->page_title = 'UCP_PM_DRAFTS'; + + unset($module); + return; + + break; + + case 'view': + + set_user_message_limit(); + + if ($folder_specified) + { + $folder_id = $folder_specified; + $action = 'view_folder'; + } + else + { + $folder_id = request_var('f', PRIVMSGS_NO_BOX); + $action = request_var('action', 'view_folder'); + } + + $msg_id = request_var('p', 0); + $view = request_var('view', ''); + + // View message if specified + if ($msg_id) + { + $action = 'view_message'; + } + + if (!$auth->acl_get('u_readpm')) + { + trigger_error('NO_AUTH_READ_MESSAGE'); + } + + // Do not allow hold messages to be seen + if ($folder_id == PRIVMSGS_HOLD_BOX) + { + trigger_error('NO_AUTH_READ_HOLD_MESSAGE'); + } + + + // First Handle Mark actions and moving messages + $submit_mark = (isset($_POST['submit_mark'])) ? true : false; + $move_pm = (isset($_POST['move_pm'])) ? true : false; + $mark_option = request_var('mark_option', ''); + $dest_folder = request_var('dest_folder', PRIVMSGS_NO_BOX); + + // Is moving PM triggered through mark options? + if (!in_array($mark_option, array('mark_important', 'delete_marked')) && $submit_mark) + { + $move_pm = true; + $dest_folder = (int) $mark_option; + $submit_mark = false; + } + + // Move PM + if ($move_pm) + { + $move_msg_ids = (isset($_POST['marked_msg_id'])) ? request_var('marked_msg_id', array(0)) : array(); + $cur_folder_id = request_var('cur_folder_id', PRIVMSGS_NO_BOX); + + if (move_pm($user->data['user_id'], $user->data['message_limit'], $move_msg_ids, $dest_folder, $cur_folder_id)) + { + // Return to folder view if single message moved + if ($action == 'view_message') + { + $msg_id = 0; + $folder_id = request_var('cur_folder_id', PRIVMSGS_NO_BOX); + $action = 'view_folder'; + } + } + } + + // Message Mark Options + if ($submit_mark) + { + handle_mark_actions($user->data['user_id'], $mark_option); + } + + // If new messages arrived, place them into the appropriate folder + $num_not_moved = $num_removed = 0; + $release = request_var('release', 0); + + if ($user->data['user_new_privmsg'] && $action == 'view_folder') + { + $return = place_pm_into_folder($global_privmsgs_rules, $release); + $num_not_moved = $return['not_moved']; + $num_removed = $return['removed']; + } + + if (!$msg_id && $folder_id == PRIVMSGS_NO_BOX) + { + $folder_id = PRIVMSGS_INBOX; + } + else if ($msg_id && $folder_id == PRIVMSGS_NO_BOX) + { + $sql = 'SELECT folder_id + FROM ' . PRIVMSGS_TO_TABLE . " + WHERE msg_id = $msg_id + AND folder_id <> " . PRIVMSGS_NO_BOX . ' + AND user_id = ' . $user->data['user_id']; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error('NO_MESSAGE'); + } + $folder_id = (int) $row['folder_id']; + } + + $message_row = array(); + if ($action == 'view_message' && $msg_id) + { + // Get Message user want to see + if ($view == 'next' || $view == 'previous') + { + $sql_condition = ($view == 'next') ? '>' : '<'; + $sql_ordering = ($view == 'next') ? 'ASC' : 'DESC'; + + $sql = 'SELECT t.msg_id + FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p, ' . PRIVMSGS_TABLE . " p2 + WHERE p2.msg_id = $msg_id + AND t.folder_id = $folder_id + AND t.user_id = " . $user->data['user_id'] . " + AND t.msg_id = p.msg_id + AND p.message_time $sql_condition p2.message_time + ORDER BY p.message_time $sql_ordering"; + $result = $db->sql_query_limit($sql, 1); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + $message = ($view == 'next') ? 'NO_NEWER_PM' : 'NO_OLDER_PM'; + trigger_error($message); + } + else + { + $msg_id = $row['msg_id']; + } + } + + $sql = 'SELECT t.*, p.*, u.* + FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p, ' . USERS_TABLE . ' u + WHERE t.user_id = ' . $user->data['user_id'] . " + AND p.author_id = u.user_id + AND t.folder_id = $folder_id + AND t.msg_id = p.msg_id + AND p.msg_id = $msg_id"; + $result = $db->sql_query($sql); + $message_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$message_row) + { + trigger_error('NO_MESSAGE'); + } + + // Update unread status + update_unread_status($message_row['pm_unread'], $message_row['msg_id'], $user->data['user_id'], $folder_id); + } + + $folder = get_folder($user->data['user_id'], $folder_id); + + $s_folder_options = $s_to_folder_options = ''; + foreach ($folder as $f_id => $folder_ary) + { + $option = '<option' . ((!in_array($f_id, array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX))) ? ' class="sep"' : '') . ' value="' . $f_id . '"' . (($f_id == $folder_id) ? ' selected="selected"' : '') . '>' . $folder_ary['folder_name'] . (($folder_ary['unread_messages']) ? ' [' . $folder_ary['unread_messages'] . '] ' : '') . '</option>'; + + $s_to_folder_options .= ($f_id != PRIVMSGS_OUTBOX && $f_id != PRIVMSGS_SENTBOX) ? $option : ''; + $s_folder_options .= $option; + } + clean_sentbox($folder[PRIVMSGS_SENTBOX]['num_messages']); + + // Header for message view - folder and so on + $folder_status = get_folder_status($folder_id, $folder); + + $template->assign_vars(array( + 'CUR_FOLDER_ID' => $folder_id, + 'CUR_FOLDER_NAME' => $folder_status['folder_name'], + 'NUM_NOT_MOVED' => $num_not_moved, + 'NUM_REMOVED' => $num_removed, + 'RELEASE_MESSAGE_INFO' => sprintf($user->lang['RELEASE_MESSAGES'], '<a href="' . $this->u_action . '&folder=' . $folder_id . '&release=1">', '</a>'), + 'NOT_MOVED_MESSAGES' => ($num_not_moved == 1) ? $user->lang['NOT_MOVED_MESSAGE'] : sprintf($user->lang['NOT_MOVED_MESSAGES'], $num_not_moved), + 'RULE_REMOVED_MESSAGES' => ($num_removed == 1) ? $user->lang['RULE_REMOVED_MESSAGE'] : sprintf($user->lang['RULE_REMOVED_MESSAGES'], $num_removed), + + 'S_FOLDER_OPTIONS' => $s_folder_options, + 'S_TO_FOLDER_OPTIONS' => $s_to_folder_options, + 'S_FOLDER_ACTION' => $this->u_action . '&action=view_folder', + 'S_PM_ACTION' => $this->u_action . '&action=' . $action, + + 'U_INBOX' => $this->u_action . '&folder=inbox', + 'U_OUTBOX' => $this->u_action . '&folder=outbox', + 'U_SENTBOX' => $this->u_action . '&folder=sentbox', + 'U_CREATE_FOLDER' => $this->u_action . '&mode=options', + 'U_CURRENT_FOLDER' => $this->u_action . '&folder=' . $folder_id, + + 'S_IN_INBOX' => ($folder_id == PRIVMSGS_INBOX) ? true : false, + 'S_IN_OUTBOX' => ($folder_id == PRIVMSGS_OUTBOX) ? true : false, + 'S_IN_SENTBOX' => ($folder_id == PRIVMSGS_SENTBOX) ? true : false, + + 'FOLDER_STATUS' => $folder_status['message'], + 'FOLDER_MAX_MESSAGES' => $folder_status['max'], + 'FOLDER_CUR_MESSAGES' => $folder_status['cur'], + 'FOLDER_REMAINING_MESSAGES' => $folder_status['remaining'], + 'FOLDER_PERCENT' => $folder_status['percent']) + ); + + if ($action == 'view_folder') + { + include($phpbb_root_path . 'includes/ucp/ucp_pm_viewfolder.' . $phpEx); + view_folder($id, $mode, $folder_id, $folder); + + $tpl_file = 'ucp_pm_viewfolder'; + } + else if ($action == 'view_message') + { + $template->assign_vars(array( + 'S_VIEW_MESSAGE' => true, + 'MSG_ID' => $msg_id) + ); + + if (!$msg_id) + { + trigger_error('NO_MESSAGE'); + } + + include($phpbb_root_path . 'includes/ucp/ucp_pm_viewmessage.' . $phpEx); + view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row); + + $tpl_file = ($view == 'print') ? 'ucp_pm_viewmessage_print' : 'ucp_pm_viewmessage'; + } + + break; + + default: + trigger_error('NO_ACTION_MODE', E_USER_ERROR); + break; + } + + $template->assign_vars(array( + 'L_TITLE' => $user->lang['UCP_PM_' . strtoupper($mode)], + 'S_UCP_ACTION' => $this->u_action . ((isset($action)) ? "&action=$action" : '')) + ); + + // Set desired template + $this->tpl_name = $tpl_file; + $this->page_title = 'UCP_PM_' . strtoupper($mode); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php new file mode 100644 index 0000000000..2f56bcdf7a --- /dev/null +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -0,0 +1,1290 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Compose private message +* Called from ucp_pm with mode == 'compose' +*/ +function compose_pm($id, $mode, $action) +{ + global $template, $db, $auth, $user; + global $phpbb_root_path, $phpEx, $config; + + // Damn php and globals - i know, this is horrible + // Needed for handle_message_list_actions() + global $refresh, $submit, $preview; + + include($phpbb_root_path . 'includes/functions_posting.' . $phpEx); + include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + include($phpbb_root_path . 'includes/message_parser.' . $phpEx); + + if (!$action) + { + $action = 'post'; + } + add_form_key('ucp_pm_compose'); + + // Grab only parameters needed here + $to_user_id = request_var('u', 0); + $to_group_id = request_var('g', 0); + $msg_id = request_var('p', 0); + $draft_id = request_var('d', 0); + $lastclick = request_var('lastclick', 0); + + // Reply to all triggered (quote/reply) + $reply_to_all = request_var('reply_to_all', 0); + + // Do NOT use request_var or specialchars here + $address_list = isset($_REQUEST['address_list']) ? $_REQUEST['address_list'] : array(); + + if (!is_array($address_list)) + { + $address_list = array(); + } + + $submit = (isset($_POST['post'])) ? true : false; + $preview = (isset($_POST['preview'])) ? true : false; + $save = (isset($_POST['save'])) ? true : false; + $load = (isset($_POST['load'])) ? true : false; + $cancel = (isset($_POST['cancel']) && !isset($_POST['save'])) ? true : false; + $delete = (isset($_POST['delete'])) ? true : false; + + $remove_u = (isset($_REQUEST['remove_u'])) ? true : false; + $remove_g = (isset($_REQUEST['remove_g'])) ? true : false; + $add_to = (isset($_REQUEST['add_to'])) ? true : false; + $add_bcc = (isset($_REQUEST['add_bcc'])) ? true : false; + + $refresh = isset($_POST['add_file']) || isset($_POST['delete_file']) || $save || $load + || $remove_u || $remove_g || $add_to || $add_bcc; + + $action = ($delete && !$preview && !$refresh && $submit) ? 'delete' : $action; + $select_single = ($config['allow_mass_pm'] && $auth->acl_get('u_masspm')) ? false : true; + + $error = array(); + $current_time = time(); + + // Was cancel pressed? If so then redirect to the appropriate page + if ($cancel || ($current_time - $lastclick < 2 && $submit)) + { + if ($msg_id) + { + redirect(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&mode=view&action=view_message&p=' . $msg_id)); + } + redirect(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm')); + } + + // Since viewtopic.php language entries are used in several modes, + // we include the language file here + $user->add_lang('viewtopic'); + + // Output PM_TO box if message composing + if ($action != 'edit') + { + // Add groups to PM box + if ($config['allow_mass_pm'] && $auth->acl_get('u_masspm_group')) + { + $sql = 'SELECT g.group_id, g.group_name, g.group_type + FROM ' . GROUPS_TABLE . ' g'; + + if (!$auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel')) + { + $sql .= ' LEFT JOIN ' . USER_GROUP_TABLE . ' ug + ON ( + g.group_id = ug.group_id + AND ug.user_id = ' . $user->data['user_id'] . ' + AND ug.user_pending = 0 + ) + WHERE (g.group_type <> ' . GROUP_HIDDEN . ' OR ug.user_id = ' . $user->data['user_id'] . ')'; + } + + $sql .= ($auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel')) ? ' WHERE ' : ' AND '; + + $sql .= 'g.group_receive_pm = 1 + ORDER BY g.group_type DESC, g.group_name ASC'; + $result = $db->sql_query($sql); + + $group_options = ''; + while ($row = $db->sql_fetchrow($result)) + { + $group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '">' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>'; + } + $db->sql_freeresult($result); + } + + $template->assign_vars(array( + 'S_SHOW_PM_BOX' => true, + 'S_ALLOW_MASS_PM' => ($config['allow_mass_pm'] && $auth->acl_get('u_masspm')) ? true : false, + 'S_GROUP_OPTIONS' => ($config['allow_mass_pm'] && $auth->acl_get('u_masspm_group')) ? $group_options : '', + 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=searchuser&form=postform&field=username_list&select_single=$select_single"), + )); + } + + $sql = ''; + + // What is all this following SQL for? Well, we need to know + // some basic information in all cases before we do anything. + switch ($action) + { + case 'post': + if (!$auth->acl_get('u_sendpm')) + { + trigger_error('NO_AUTH_SEND_MESSAGE'); + } + break; + + case 'reply': + case 'quote': + case 'forward': + case 'quotepost': + if (!$msg_id) + { + trigger_error('NO_MESSAGE'); + } + + if (!$auth->acl_get('u_sendpm')) + { + trigger_error('NO_AUTH_SEND_MESSAGE'); + } + + if ($action == 'quotepost') + { + $sql = 'SELECT p.post_id as msg_id, p.forum_id, p.post_text as message_text, p.poster_id as author_id, p.post_time as message_time, p.bbcode_bitfield, p.bbcode_uid, p.enable_sig, p.enable_smilies, p.enable_magic_url, t.topic_title as message_subject, u.username as quote_username + FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t, ' . USERS_TABLE . " u + WHERE p.post_id = $msg_id + AND t.topic_id = p.topic_id + AND u.user_id = p.poster_id"; + } + else + { + $sql = 'SELECT t.folder_id, p.*, u.username as quote_username + FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p, ' . USERS_TABLE . ' u + WHERE t.user_id = ' . $user->data['user_id'] . " + AND p.author_id = u.user_id + AND t.msg_id = p.msg_id + AND p.msg_id = $msg_id"; + } + break; + + case 'edit': + if (!$msg_id) + { + trigger_error('NO_MESSAGE'); + } + + // check for outbox (not read) status, we do not allow editing if one user already having the message + $sql = 'SELECT p.*, t.folder_id + FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p + WHERE t.user_id = ' . $user->data['user_id'] . ' + AND t.folder_id = ' . PRIVMSGS_OUTBOX . " + AND t.msg_id = $msg_id + AND t.msg_id = p.msg_id"; + break; + + case 'delete': + if (!$auth->acl_get('u_pm_delete')) + { + trigger_error('NO_AUTH_DELETE_MESSAGE'); + } + + if (!$msg_id) + { + trigger_error('NO_MESSAGE'); + } + + $sql = 'SELECT msg_id, pm_unread, pm_new, author_id, folder_id + FROM ' . PRIVMSGS_TO_TABLE . ' + WHERE user_id = ' . $user->data['user_id'] . " + AND msg_id = $msg_id"; + break; + + case 'smilies': + generate_smilies('window', 0); + break; + + default: + trigger_error('NO_ACTION_MODE', E_USER_ERROR); + break; + } + + if ($action == 'forward' && (!$config['forward_pm'] || !$auth->acl_get('u_pm_forward'))) + { + trigger_error('NO_AUTH_FORWARD_MESSAGE'); + } + + if ($action == 'edit' && !$auth->acl_get('u_pm_edit')) + { + trigger_error('NO_AUTH_EDIT_MESSAGE'); + } + + if ($sql) + { + $result = $db->sql_query($sql); + $post = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$post) + { + // If editing it could be the recipient already read the message... + if ($action == 'edit') + { + $sql = 'SELECT p.*, t.folder_id + FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p + WHERE t.user_id = ' . $user->data['user_id'] . " + AND t.msg_id = $msg_id + AND t.msg_id = p.msg_id"; + $result = $db->sql_query($sql); + $post = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($post) + { + trigger_error('NO_EDIT_READ_MESSAGE'); + } + } + + trigger_error('NO_MESSAGE'); + } + + if ($action == 'quotepost') + { + if (($post['forum_id'] && !$auth->acl_get('f_read', $post['forum_id'])) || (!$post['forum_id'] && !$auth->acl_getf_global('f_read'))) + { + trigger_error('NOT_AUTHORISED'); + } + + // Passworded forum? + if ($post['forum_id']) + { + $sql = 'SELECT forum_password + FROM ' . FORUMS_TABLE . ' + WHERE forum_id = ' . (int) $post['forum_id']; + $result = $db->sql_query($sql); + $forum_password = (string) $db->sql_fetchfield('forum_password'); + $db->sql_freeresult($result); + + if ($forum_password) + { + login_forum_box(array( + 'forum_id' => $post['forum_id'], + 'forum_password' => $forum_password, + )); + } + } + } + + $msg_id = (int) $post['msg_id']; + $folder_id = (isset($post['folder_id'])) ? $post['folder_id'] : 0; + $message_text = (isset($post['message_text'])) ? $post['message_text'] : ''; + + if ((!$post['author_id'] || ($post['author_id'] == ANONYMOUS && $action != 'delete')) && $msg_id) + { + trigger_error('NO_AUTHOR'); + } + + if ($action == 'quotepost') + { + // Decode text for message display + decode_message($message_text, $post['bbcode_uid']); + } + + if ($action != 'delete') + { + $enable_urls = $post['enable_magic_url']; + $enable_sig = (isset($post['enable_sig'])) ? $post['enable_sig'] : 0; + + $message_attachment = (isset($post['message_attachment'])) ? $post['message_attachment'] : 0; + $message_subject = $post['message_subject']; + $message_time = $post['message_time']; + $bbcode_uid = $post['bbcode_uid']; + + $quote_username = (isset($post['quote_username'])) ? $post['quote_username'] : ''; + $icon_id = (isset($post['icon_id'])) ? $post['icon_id'] : 0; + + if (($action == 'reply' || $action == 'quote' || $action == 'quotepost') && !sizeof($address_list) && !$refresh && !$submit && !$preview) + { + // Add the original author as the recipient if quoting a post or only replying and not having checked "reply to all" + if ($action == 'quotepost' || !$reply_to_all) + { + $address_list = array('u' => array($post['author_id'] => 'to')); + } + else + { + // We try to include every previously listed member from the TO Header - Reply to all + $address_list = rebuild_header(array('to' => $post['to_address'])); + + // Add the author (if he is already listed then this is no shame (it will be overwritten)) + $address_list['u'][$post['author_id']] = 'to'; + + // Now, make sure the user itself is not listed. ;) + if (isset($address_list['u'][$user->data['user_id']])) + { + unset($address_list['u'][$user->data['user_id']]); + } + } + } + else if ($action == 'edit' && !sizeof($address_list) && !$refresh && !$submit && !$preview) + { + // Rebuild TO and BCC Header + $address_list = rebuild_header(array('to' => $post['to_address'], 'bcc' => $post['bcc_address'])); + } + + if ($action == 'quotepost') + { + $check_value = 0; + } + else + { + $check_value = (($post['enable_bbcode']+1) << 8) + (($post['enable_smilies']+1) << 4) + (($enable_urls+1) << 2) + (($post['enable_sig']+1) << 1); + } + } + } + else + { + $message_attachment = 0; + $message_text = $message_subject = ''; + + if ($to_user_id && $action == 'post') + { + $address_list['u'][$to_user_id] = 'to'; + } + else if ($to_group_id && $action == 'post') + { + $address_list['g'][$to_group_id] = 'to'; + } + $check_value = 0; + } + + if (($to_group_id || isset($address_list['g'])) && (!$config['allow_mass_pm'] || !$auth->acl_get('u_masspm_group'))) + { + trigger_error('NO_AUTH_GROUP_MESSAGE'); + } + + if ($action == 'edit' && !$refresh && !$preview && !$submit) + { + if (!($message_time > time() - ($config['pm_edit_time'] * 60) || !$config['pm_edit_time'])) + { + trigger_error('CANNOT_EDIT_MESSAGE_TIME'); + } + } + + if ($action == 'post') + { + $template->assign_var('S_NEW_MESSAGE', true); + } + + if (!isset($icon_id)) + { + $icon_id = 0; + } + + $message_parser = new parse_message(); + + $message_parser->message = ($action == 'reply') ? '' : $message_text; + unset($message_text); + + $s_action = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=$id&mode=$mode&action=$action", true, $user->session_id); + $s_action .= ($msg_id) ? "&p=$msg_id" : ''; + + // Delete triggered ? + if ($action == 'delete') + { + // Folder id has been determined by the SQL Statement + // $folder_id = request_var('f', PRIVMSGS_NO_BOX); + + // Do we need to confirm ? + if (confirm_box(true)) + { + delete_pm($user->data['user_id'], $msg_id, $folder_id); + + // jump to next message in "history"? nope, not for the moment. But able to be included later. + $meta_info = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=pm&folder=$folder_id"); + $message = $user->lang['MESSAGE_DELETED']; + + meta_refresh(3, $meta_info); + $message .= '<br /><br />' . sprintf($user->lang['RETURN_FOLDER'], '<a href="' . $meta_info . '">', '</a>'); + trigger_error($message); + } + else + { + $s_hidden_fields = array( + 'p' => $msg_id, + 'f' => $folder_id, + 'action' => 'delete' + ); + + // "{$phpbb_root_path}ucp.$phpEx?i=pm&mode=compose" + confirm_box(false, 'DELETE_MESSAGE', build_hidden_fields($s_hidden_fields)); + } + + redirect(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&mode=view&action=view_message&p=' . $msg_id)); + } + + // Get maximum number of allowed recipients + $sql = 'SELECT MAX(g.group_max_recipients) as max_recipients + FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug + WHERE ug.user_id = ' . $user->data['user_id'] . ' + AND ug.user_pending = 0 + AND ug.group_id = g.group_id'; + $result = $db->sql_query($sql); + $max_recipients = (int) $db->sql_fetchfield('max_recipients'); + $db->sql_freeresult($result); + + $max_recipients = (!$max_recipients) ? $config['pm_max_recipients'] : $max_recipients; + + // If this is a quote/reply "to all"... we may increase the max_recpients to the number of original recipients + if (($action == 'reply' || $action == 'quote') && $max_recipients && $reply_to_all) + { + // We try to include every previously listed member from the TO Header + $list = rebuild_header(array('to' => $post['to_address'])); + + // Can be an empty array too ;) + $list = (!empty($list['u'])) ? $list['u'] : array(); + $list[$post['author_id']] = 'to'; + + if (isset($list[$user->data['user_id']])) + { + unset($list[$user->data['user_id']]); + } + + $max_recipients = ($max_recipients < sizeof($list)) ? sizeof($list) : $max_recipients; + + unset($list); + } + + // Handle User/Group adding/removing + handle_message_list_actions($address_list, $error, $remove_u, $remove_g, $add_to, $add_bcc); + + // Check mass pm to group permission + if ((!$config['allow_mass_pm'] || !$auth->acl_get('u_masspm_group')) && !empty($address_list['g'])) + { + $address_list = array(); + $error[] = $user->lang['NO_AUTH_GROUP_MESSAGE']; + } + + // Check mass pm to users permission + if ((!$config['allow_mass_pm'] || !$auth->acl_get('u_masspm')) && num_recipients($address_list) > 1) + { + $address_list = get_recipients($address_list, 1); + $error[] = $user->lang('TOO_MANY_RECIPIENTS', 1); + } + + // Check for too many recipients + if (!empty($address_list['u']) && $max_recipients && sizeof($address_list['u']) > $max_recipients) + { + $address_list = get_recipients($address_list, $max_recipients); + $error[] = $user->lang('TOO_MANY_RECIPIENTS', $max_recipients); + } + + // Always check if the submitted attachment data is valid and belongs to the user. + // Further down (especially in submit_post()) we do not check this again. + $message_parser->get_submitted_attachment_data(); + + if ($message_attachment && !$submit && !$refresh && !$preview && $action == 'edit') + { + // Do not change to SELECT * + $sql = 'SELECT attach_id, is_orphan, attach_comment, real_filename + FROM ' . ATTACHMENTS_TABLE . " + WHERE post_msg_id = $msg_id + AND in_message = 1 + AND is_orphan = 0 + ORDER BY filetime DESC"; + $result = $db->sql_query($sql); + $message_parser->attachment_data = array_merge($message_parser->attachment_data, $db->sql_fetchrowset($result)); + $db->sql_freeresult($result); + } + + if (!in_array($action, array('quote', 'edit', 'delete', 'forward'))) + { + $enable_sig = ($config['allow_sig'] && $config['allow_sig_pm'] && $auth->acl_get('u_sig') && $user->optionget('attachsig')); + $enable_smilies = ($config['allow_smilies'] && $auth->acl_get('u_pm_smilies') && $user->optionget('smilies')); + $enable_bbcode = ($config['allow_bbcode'] && $auth->acl_get('u_pm_bbcode') && $user->optionget('bbcode')); + $enable_urls = true; + } + + $enable_magic_url = $drafts = false; + + // User own some drafts? + if ($auth->acl_get('u_savedrafts') && $action != 'delete') + { + $sql = 'SELECT draft_id + FROM ' . DRAFTS_TABLE . ' + WHERE forum_id = 0 + AND topic_id = 0 + AND user_id = ' . $user->data['user_id'] . + (($draft_id) ? " AND draft_id <> $draft_id" : ''); + $result = $db->sql_query_limit($sql, 1); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + $drafts = true; + } + } + + if ($action == 'edit') + { + $message_parser->bbcode_uid = $bbcode_uid; + } + + $bbcode_status = ($config['allow_bbcode'] && $config['auth_bbcode_pm'] && $auth->acl_get('u_pm_bbcode')) ? true : false; + $smilies_status = ($config['allow_smilies'] && $config['auth_smilies_pm'] && $auth->acl_get('u_pm_smilies')) ? true : false; + $img_status = ($config['auth_img_pm'] && $auth->acl_get('u_pm_img')) ? true : false; + $flash_status = ($config['auth_flash_pm'] && $auth->acl_get('u_pm_flash')) ? true : false; + $url_status = ($config['allow_post_links']) ? true : false; + + // Save Draft + if ($save && $auth->acl_get('u_savedrafts')) + { + $subject = utf8_normalize_nfc(request_var('subject', '', true)); + $subject = (!$subject && $action != 'post') ? $user->lang['NEW_MESSAGE'] : $subject; + $message = utf8_normalize_nfc(request_var('message', '', true)); + + if ($subject && $message) + { + if (confirm_box(true)) + { + $sql = 'INSERT INTO ' . DRAFTS_TABLE . ' ' . $db->sql_build_array('INSERT', array( + 'user_id' => $user->data['user_id'], + 'topic_id' => 0, + 'forum_id' => 0, + 'save_time' => $current_time, + 'draft_subject' => $subject, + 'draft_message' => $message + ) + ); + $db->sql_query($sql); + + $redirect_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=pm&mode=$mode"); + + meta_refresh(3, $redirect_url); + $message = $user->lang['DRAFT_SAVED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $redirect_url . '">', '</a>'); + + trigger_error($message); + } + else + { + $s_hidden_fields = build_hidden_fields(array( + 'mode' => $mode, + 'action' => $action, + 'save' => true, + 'subject' => $subject, + 'message' => $message, + 'u' => $to_user_id, + 'g' => $to_group_id, + 'p' => $msg_id) + ); + $s_hidden_fields .= build_address_field($address_list); + + + confirm_box(false, 'SAVE_DRAFT', $s_hidden_fields); + } + } + else + { + if (utf8_clean_string($subject) === '') + { + $error[] = $user->lang['EMPTY_MESSAGE_SUBJECT']; + } + + if (utf8_clean_string($message) === '') + { + $error[] = $user->lang['TOO_FEW_CHARS']; + } + } + + unset($subject, $message); + } + + // Load Draft + if ($draft_id && $auth->acl_get('u_savedrafts')) + { + $sql = 'SELECT draft_subject, draft_message + FROM ' . DRAFTS_TABLE . " + WHERE draft_id = $draft_id + AND topic_id = 0 + AND forum_id = 0 + AND user_id = " . $user->data['user_id']; + $result = $db->sql_query_limit($sql, 1); + + if ($row = $db->sql_fetchrow($result)) + { + $message_parser->message = $row['draft_message']; + $message_subject = $row['draft_subject']; + + $template->assign_var('S_DRAFT_LOADED', true); + } + else + { + $draft_id = 0; + } + $db->sql_freeresult($result); + } + + // Load Drafts + if ($load && $drafts) + { + load_drafts(0, 0, $id, $action, $msg_id); + } + + if ($submit || $preview || $refresh) + { + if (($submit || $preview) && !check_form_key('ucp_pm_compose')) + { + $error[] = $user->lang['FORM_INVALID']; + } + $subject = utf8_normalize_nfc(request_var('subject', '', true)); + $message_parser->message = utf8_normalize_nfc(request_var('message', '', true)); + + $icon_id = request_var('icon', 0); + + $enable_bbcode = (!$bbcode_status || isset($_POST['disable_bbcode'])) ? false : true; + $enable_smilies = (!$smilies_status || isset($_POST['disable_smilies'])) ? false : true; + $enable_urls = (isset($_POST['disable_magic_url'])) ? 0 : 1; + $enable_sig = (!$config['allow_sig'] ||!$config['allow_sig_pm']) ? false : ((isset($_POST['attach_sig'])) ? true : false); + + if ($submit) + { + $status_switch = (($enable_bbcode+1) << 8) + (($enable_smilies+1) << 4) + (($enable_urls+1) << 2) + (($enable_sig+1) << 1); + $status_switch = ($status_switch != $check_value); + } + else + { + $status_switch = 1; + } + + // Parse Attachments - before checksum is calculated + $message_parser->parse_attachments('fileupload', $action, 0, $submit, $preview, $refresh, true); + + if (sizeof($message_parser->warn_msg) && !($remove_u || $remove_g || $add_to || $add_bcc)) + { + $error[] = implode('<br />', $message_parser->warn_msg); + $message_parser->warn_msg = array(); + } + + // Parse message + $message_parser->parse($enable_bbcode, ($config['allow_post_links']) ? $enable_urls : false, $enable_smilies, $img_status, $flash_status, true, $config['allow_post_links']); + + // On a refresh we do not care about message parsing errors + if (sizeof($message_parser->warn_msg) && !$refresh) + { + $error[] = implode('<br />', $message_parser->warn_msg); + } + + if ($action != 'edit' && !$preview && !$refresh && $config['flood_interval'] && !$auth->acl_get('u_ignoreflood')) + { + // Flood check + $last_post_time = $user->data['user_lastpost_time']; + + if ($last_post_time) + { + if ($last_post_time && ($current_time - $last_post_time) < intval($config['flood_interval'])) + { + $error[] = $user->lang['FLOOD_ERROR']; + } + } + } + + // Subject defined + if ($submit) + { + if (utf8_clean_string($subject) === '') + { + $error[] = $user->lang['EMPTY_MESSAGE_SUBJECT']; + } + + if (!sizeof($address_list)) + { + $error[] = $user->lang['NO_RECIPIENT']; + } + } + + // Store message, sync counters + if (!sizeof($error) && $submit) + { + $pm_data = array( + 'msg_id' => (int) $msg_id, + 'from_user_id' => $user->data['user_id'], + 'from_user_ip' => $user->ip, + 'from_username' => $user->data['username'], + 'reply_from_root_level' => (isset($post['root_level'])) ? (int) $post['root_level'] : 0, + 'reply_from_msg_id' => (int) $msg_id, + 'icon_id' => (int) $icon_id, + 'enable_sig' => (bool) $enable_sig, + 'enable_bbcode' => (bool) $enable_bbcode, + 'enable_smilies' => (bool) $enable_smilies, + 'enable_urls' => (bool) $enable_urls, + 'bbcode_bitfield' => $message_parser->bbcode_bitfield, + 'bbcode_uid' => $message_parser->bbcode_uid, + 'message' => $message_parser->message, + 'attachment_data' => $message_parser->attachment_data, + 'filename_data' => $message_parser->filename_data, + 'address_list' => $address_list + ); + + // ((!$message_subject) ? $subject : $message_subject) + $msg_id = submit_pm($action, $subject, $pm_data); + + $return_message_url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&mode=view&p=' . $msg_id); + $return_folder_url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=outbox'); + meta_refresh(3, $return_message_url); + + $message = $user->lang['MESSAGE_STORED'] . '<br /><br />' . sprintf($user->lang['VIEW_PRIVATE_MESSAGE'], '<a href="' . $return_message_url . '">', '</a>') . '<br /><br />' . sprintf($user->lang['CLICK_RETURN_FOLDER'], '<a href="' . $return_folder_url . '">', '</a>', $user->lang['PM_OUTBOX']); + trigger_error($message); + } + + $message_subject = $subject; + } + + // Preview + if (!sizeof($error) && $preview) + { + $preview_message = $message_parser->format_display($enable_bbcode, $enable_urls, $enable_smilies, false); + + $preview_signature = $user->data['user_sig']; + $preview_signature_uid = $user->data['user_sig_bbcode_uid']; + $preview_signature_bitfield = $user->data['user_sig_bbcode_bitfield']; + + // Signature + if ($enable_sig && $config['allow_sig'] && $preview_signature) + { + $parse_sig = new parse_message($preview_signature); + $parse_sig->bbcode_uid = $preview_signature_uid; + $parse_sig->bbcode_bitfield = $preview_signature_bitfield; + + $parse_sig->format_display($enable_bbcode, $enable_urls, $enable_smilies); + $preview_signature = $parse_sig->message; + unset($parse_sig); + } + else + { + $preview_signature = ''; + } + + // Attachment Preview + if (sizeof($message_parser->attachment_data)) + { + $template->assign_var('S_HAS_ATTACHMENTS', true); + + $update_count = array(); + $attachment_data = $message_parser->attachment_data; + + parse_attachments(false, $preview_message, $attachment_data, $update_count, true); + + foreach ($attachment_data as $i => $attachment) + { + $template->assign_block_vars('attachment', array( + 'DISPLAY_ATTACHMENT' => $attachment) + ); + } + unset($attachment_data); + } + + $preview_subject = censor_text($subject); + + if (!sizeof($error)) + { + $template->assign_vars(array( + 'PREVIEW_SUBJECT' => $preview_subject, + 'PREVIEW_MESSAGE' => $preview_message, + 'PREVIEW_SIGNATURE' => $preview_signature, + + 'S_DISPLAY_PREVIEW' => true) + ); + } + unset($message_text); + } + + // Decode text for message display + $bbcode_uid = (($action == 'quote' || $action == 'forward') && !$preview && !$refresh) ? $bbcode_uid : $message_parser->bbcode_uid; + + $message_parser->decode_message($bbcode_uid); + + if (($action == 'quote' || $action == 'quotepost') && !$preview && !$refresh && !$submit) + { + if ($action == 'quotepost') + { + $post_id = request_var('p', 0); + if ($config['allow_post_links']) + { + $message_link = "[url=" . generate_board_url() . "/viewtopic.$phpEx?p={$post_id}#p{$post_id}]{$user->lang['SUBJECT']}: {$message_subject}[/url]\n\n"; + } + else + { + $message_link = $user->lang['SUBJECT'] . ': ' . $message_subject . " (" . generate_board_url() . "/viewtopic.$phpEx?p={$post_id}#p{$post_id})\n\n"; + } + } + else + { + $message_link = ''; + } + $message_parser->message = $message_link . '[quote="' . $quote_username . '"]' . censor_text(trim($message_parser->message)) . "[/quote]\n"; + } + + if (($action == 'reply' || $action == 'quote' || $action == 'quotepost') && !$preview && !$refresh) + { + $message_subject = ((!preg_match('/^Re:/', $message_subject)) ? 'Re: ' : '') . censor_text($message_subject); + } + + if ($action == 'forward' && !$preview && !$refresh && !$submit) + { + $fwd_to_field = write_pm_addresses(array('to' => $post['to_address']), 0, true); + + if ($config['allow_post_links']) + { + $quote_username_text = '[url=' . generate_board_url() . "/memberlist.$phpEx?mode=viewprofile&u={$post['author_id']}]{$quote_username}[/url]"; + } + else + { + $quote_username_text = $quote_username . ' (' . generate_board_url() . "/memberlist.$phpEx?mode=viewprofile&u={$post['author_id']})"; + } + + $forward_text = array(); + $forward_text[] = $user->lang['FWD_ORIGINAL_MESSAGE']; + $forward_text[] = sprintf($user->lang['FWD_SUBJECT'], censor_text($message_subject)); + $forward_text[] = sprintf($user->lang['FWD_DATE'], $user->format_date($message_time, false, true)); + $forward_text[] = sprintf($user->lang['FWD_FROM'], $quote_username_text); + $forward_text[] = sprintf($user->lang['FWD_TO'], implode(', ', $fwd_to_field['to'])); + + $message_parser->message = implode("\n", $forward_text) . "\n\n[quote="{$quote_username}"]\n" . censor_text(trim($message_parser->message)) . "\n[/quote]"; + $message_subject = ((!preg_match('/^Fwd:/', $message_subject)) ? 'Fwd: ' : '') . censor_text($message_subject); + } + + $attachment_data = $message_parser->attachment_data; + $filename_data = $message_parser->filename_data; + $message_text = $message_parser->message; + + // MAIN PM PAGE BEGINS HERE + + // Generate smiley listing + generate_smilies('inline', 0); + + // Generate PM Icons + $s_pm_icons = false; + if ($config['enable_pm_icons']) + { + $s_pm_icons = posting_gen_topic_icons($action, $icon_id); + } + + // Generate inline attachment select box + posting_gen_inline_attachments($attachment_data); + + // Build address list for display + // array('u' => array($author_id => 'to')); + if (sizeof($address_list)) + { + // Get Usernames and Group Names + $result = array(); + if (!empty($address_list['u'])) + { + $sql = 'SELECT user_id as id, username as name, user_colour as colour + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', array_map('intval', array_keys($address_list['u']))) . ' + ORDER BY username_clean ASC'; + $result['u'] = $db->sql_query($sql); + } + + if (!empty($address_list['g'])) + { + $sql = 'SELECT g.group_id AS id, g.group_name AS name, g.group_colour AS colour, g.group_type + FROM ' . GROUPS_TABLE . ' g'; + + if (!$auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel')) + { + $sql .= ' LEFT JOIN ' . USER_GROUP_TABLE . ' ug + ON ( + g.group_id = ug.group_id + AND ug.user_id = ' . $user->data['user_id'] . ' + AND ug.user_pending = 0 + ) + WHERE (g.group_type <> ' . GROUP_HIDDEN . ' OR ug.user_id = ' . $user->data['user_id'] . ')'; + } + + $sql .= ($auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel')) ? ' WHERE ' : ' AND '; + + $sql .= 'g.group_receive_pm = 1 + AND ' . $db->sql_in_set('g.group_id', array_map('intval', array_keys($address_list['g']))) . ' + ORDER BY g.group_name ASC'; + + $result['g'] = $db->sql_query($sql); + } + + $u = $g = array(); + $_types = array('u', 'g'); + foreach ($_types as $type) + { + if (isset($result[$type]) && $result[$type]) + { + while ($row = $db->sql_fetchrow($result[$type])) + { + if ($type == 'g') + { + $row['name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['name']] : $row['name']; + } + + ${$type}[$row['id']] = array('name' => $row['name'], 'colour' => $row['colour']); + } + $db->sql_freeresult($result[$type]); + } + } + + // Now Build the address list + $plain_address_field = ''; + foreach ($address_list as $type => $adr_ary) + { + foreach ($adr_ary as $id => $field) + { + if (!isset(${$type}[$id])) + { + unset($address_list[$type][$id]); + continue; + } + + $field = ($field == 'to') ? 'to' : 'bcc'; + $type = ($type == 'u') ? 'u' : 'g'; + $id = (int) $id; + + $tpl_ary = array( + 'IS_GROUP' => ($type == 'g') ? true : false, + 'IS_USER' => ($type == 'u') ? true : false, + 'UG_ID' => $id, + 'NAME' => ${$type}[$id]['name'], + 'COLOUR' => (${$type}[$id]['colour']) ? '#' . ${$type}[$id]['colour'] : '', + 'TYPE' => $type, + ); + + if ($type == 'u') + { + $tpl_ary = array_merge($tpl_ary, array( + 'U_VIEW' => get_username_string('profile', $id, ${$type}[$id]['name'], ${$type}[$id]['colour']), + 'NAME_FULL' => get_username_string('full', $id, ${$type}[$id]['name'], ${$type}[$id]['colour']), + )); + } + else + { + $tpl_ary = array_merge($tpl_ary, array( + 'U_VIEW' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&g=' . $id), + )); + } + + $template->assign_block_vars($field . '_recipient', $tpl_ary); + } + } + } + + // Build hidden address list + $s_hidden_address_field = build_address_field($address_list); + + + $bbcode_checked = (isset($enable_bbcode)) ? !$enable_bbcode : (($config['allow_bbcode'] && $auth->acl_get('u_pm_bbcode')) ? !$user->optionget('bbcode') : 1); + $smilies_checked = (isset($enable_smilies)) ? !$enable_smilies : (($config['allow_smilies'] && $auth->acl_get('u_pm_smilies')) ? !$user->optionget('smilies') : 1); + $urls_checked = (isset($enable_urls)) ? !$enable_urls : 0; + $sig_checked = $enable_sig; + + switch ($action) + { + case 'post': + $page_title = $user->lang['POST_NEW_PM']; + break; + + case 'quote': + $page_title = $user->lang['POST_QUOTE_PM']; + break; + + case 'quotepost': + $page_title = $user->lang['POST_PM_POST']; + break; + + case 'reply': + $page_title = $user->lang['POST_REPLY_PM']; + break; + + case 'edit': + $page_title = $user->lang['POST_EDIT_PM']; + break; + + case 'forward': + $page_title = $user->lang['POST_FORWARD_PM']; + break; + + default: + trigger_error('NO_ACTION_MODE', E_USER_ERROR); + break; + } + + $s_hidden_fields = '<input type="hidden" name="lastclick" value="' . $current_time . '" />'; + $s_hidden_fields .= (isset($check_value)) ? '<input type="hidden" name="status_switch" value="' . $check_value . '" />' : ''; + $s_hidden_fields .= ($draft_id || isset($_REQUEST['draft_loaded'])) ? '<input type="hidden" name="draft_loaded" value="' . ((isset($_REQUEST['draft_loaded'])) ? intval($_REQUEST['draft_loaded']) : $draft_id) . '" />' : ''; + + $form_enctype = (@ini_get('file_uploads') == '0' || strtolower(@ini_get('file_uploads')) == 'off' || !$config['allow_pm_attach'] || !$auth->acl_get('u_pm_attach')) ? '' : ' enctype="multipart/form-data"'; + + // Start assigning vars for main posting page ... + $template->assign_vars(array( + 'L_POST_A' => $page_title, + 'L_ICON' => $user->lang['PM_ICON'], + 'L_MESSAGE_BODY_EXPLAIN' => (intval($config['max_post_chars'])) ? sprintf($user->lang['MESSAGE_BODY_EXPLAIN'], intval($config['max_post_chars'])) : '', + + 'SUBJECT' => (isset($message_subject)) ? $message_subject : '', + 'MESSAGE' => $message_text, + 'BBCODE_STATUS' => ($bbcode_status) ? sprintf($user->lang['BBCODE_IS_ON'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>') : sprintf($user->lang['BBCODE_IS_OFF'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>'), + 'IMG_STATUS' => ($img_status) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'], + 'FLASH_STATUS' => ($flash_status) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], + 'SMILIES_STATUS' => ($smilies_status) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'], + 'URL_STATUS' => ($url_status) ? $user->lang['URL_IS_ON'] : $user->lang['URL_IS_OFF'], + 'MAX_FONT_SIZE' => (int) $config['max_post_font_size'], + 'MINI_POST_IMG' => $user->img('icon_post_target', $user->lang['PM']), + 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + 'MAX_RECIPIENTS' => ($config['allow_mass_pm'] && ($auth->acl_get('u_masspm') || $auth->acl_get('u_masspm_group'))) ? $max_recipients : 0, + + 'S_COMPOSE_PM' => true, + 'S_EDIT_POST' => ($action == 'edit'), + 'S_SHOW_PM_ICONS' => $s_pm_icons, + 'S_BBCODE_ALLOWED' => $bbcode_status, + 'S_BBCODE_CHECKED' => ($bbcode_checked) ? ' checked="checked"' : '', + 'S_SMILIES_ALLOWED' => $smilies_status, + 'S_SMILIES_CHECKED' => ($smilies_checked) ? ' checked="checked"' : '', + 'S_SIG_ALLOWED' => ($config['allow_sig'] && $config['allow_sig_pm'] && $auth->acl_get('u_sig')), + 'S_SIGNATURE_CHECKED' => ($sig_checked) ? ' checked="checked"' : '', + 'S_LINKS_ALLOWED' => $url_status, + 'S_MAGIC_URL_CHECKED' => ($urls_checked) ? ' checked="checked"' : '', + 'S_SAVE_ALLOWED' => ($auth->acl_get('u_savedrafts') && $action != 'edit') ? true : false, + 'S_HAS_DRAFTS' => ($auth->acl_get('u_savedrafts') && $drafts), + 'S_FORM_ENCTYPE' => $form_enctype, + + 'S_BBCODE_IMG' => $img_status, + 'S_BBCODE_FLASH' => $flash_status, + 'S_BBCODE_QUOTE' => true, + 'S_BBCODE_URL' => $url_status, + + 'S_POST_ACTION' => $s_action, + 'S_HIDDEN_ADDRESS_FIELD' => $s_hidden_address_field, + 'S_HIDDEN_FIELDS' => $s_hidden_fields, + + 'S_CLOSE_PROGRESS_WINDOW' => isset($_POST['add_file']), + 'U_PROGRESS_BAR' => append_sid("{$phpbb_root_path}posting.$phpEx", 'f=0&mode=popup'), + 'UA_PROGRESS_BAR' => addslashes(append_sid("{$phpbb_root_path}posting.$phpEx", 'f=0&mode=popup')), + )); + + // Build custom bbcodes array + display_custom_bbcodes(); + + // Show attachment box for adding attachments if true + $allowed = ($auth->acl_get('u_pm_attach') && $config['allow_pm_attach'] && $form_enctype); + + // Attachment entry + posting_gen_attachment_entry($attachment_data, $filename_data, $allowed); + + // Message History + if ($action == 'reply' || $action == 'quote' || $action == 'forward') + { + if (message_history($msg_id, $user->data['user_id'], $post, array(), true)) + { + $template->assign_var('S_DISPLAY_HISTORY', true); + } + } +} + +/** +* For composing messages, handle list actions +*/ +function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove_g, $add_to, $add_bcc) +{ + global $auth, $db, $user; + + // Delete User [TO/BCC] + if ($remove_u && !empty($_REQUEST['remove_u']) && is_array($_REQUEST['remove_u'])) + { + $remove_user_id = array_keys($_REQUEST['remove_u']); + + if (isset($remove_user_id[0])) + { + unset($address_list['u'][(int) $remove_user_id[0]]); + } + } + + // Delete Group [TO/BCC] + if ($remove_g && !empty($_REQUEST['remove_g']) && is_array($_REQUEST['remove_g'])) + { + $remove_group_id = array_keys($_REQUEST['remove_g']); + + if (isset($remove_group_id[0])) + { + unset($address_list['g'][(int) $remove_group_id[0]]); + } + } + + // Add Selected Groups + $group_list = request_var('group_list', array(0)); + + // Build usernames to add + $usernames = request_var('username', '', true); + $usernames = (empty($usernames)) ? array() : array($usernames); + + $username_list = request_var('username_list', '', true); + if ($username_list) + { + $usernames = array_merge($usernames, explode("\n", $username_list)); + } + + // If add to or add bcc not pressed, users could still have usernames listed they want to add... + if (!$add_to && !$add_bcc && (sizeof($group_list) || sizeof($usernames))) + { + $add_to = true; + + global $refresh, $submit, $preview; + + $refresh = true; + $submit = false; + + // Preview is only true if there was also a message entered + if (request_var('message', '')) + { + $preview = true; + } + } + + // Add User/Group [TO] + if ($add_to || $add_bcc) + { + $type = ($add_to) ? 'to' : 'bcc'; + + if (sizeof($group_list)) + { + foreach ($group_list as $group_id) + { + $address_list['g'][$group_id] = $type; + } + } + + // User ID's to add... + $user_id_ary = array(); + + // Reveal the correct user_ids + if (sizeof($usernames)) + { + $user_id_ary = array(); + user_get_id_name($user_id_ary, $usernames, array(USER_NORMAL, USER_FOUNDER, USER_INACTIVE)); + + // If there are users not existing, we will at least print a notice... + if (!sizeof($user_id_ary)) + { + $error[] = $user->lang['PM_NO_USERS']; + } + } + + // Add Friends if specified + $friend_list = (isset($_REQUEST['add_' . $type]) && is_array($_REQUEST['add_' . $type])) ? array_map('intval', array_keys($_REQUEST['add_' . $type])) : array(); + $user_id_ary = array_merge($user_id_ary, $friend_list); + + foreach ($user_id_ary as $user_id) + { + if ($user_id == ANONYMOUS) + { + continue; + } + + $address_list['u'][$user_id] = $type; + } + } + + // Check for disallowed recipients + if (!empty($address_list['u'])) + { + // We need to check their PM status (do they want to receive PM's?) + // Only check if not a moderator or admin, since they are allowed to override this user setting + if (!$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_')) + { + $sql = 'SELECT user_id + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', array_keys($address_list['u'])) . ' + AND user_allow_pm = 0'; + $result = $db->sql_query($sql); + + $removed = false; + while ($row = $db->sql_fetchrow($result)) + { + $removed = true; + unset($address_list['u'][$row['user_id']]); + } + $db->sql_freeresult($result); + + // print a notice about users not being added who do not want to receive pms + if ($removed) + { + $error[] = $user->lang['PM_USERS_REMOVED_NO_PM']; + } + } + } +} + +/** +* Build the hidden field for the recipients. Needed, as the variable is not read via request_var. +*/ +function build_address_field($address_list) +{ + $s_hidden_address_field = ''; + foreach ($address_list as $type => $adr_ary) + { + foreach ($adr_ary as $id => $field) + { + $s_hidden_address_field .= '<input type="hidden" name="address_list[' . (($type == 'u') ? 'u' : 'g') . '][' . (int) $id . ']" value="' . (($field == 'to') ? 'to' : 'bcc') . '" />'; + } + } + return $s_hidden_address_field; +} + +/** +* Return number of private message recipients +*/ +function num_recipients($address_list) +{ + $num_recipients = 0; + + foreach ($address_list as $field => $adr_ary) + { + $num_recipients += sizeof($adr_ary); + } + + return $num_recipients; +} + +/** +* Get number of 'num_recipients' recipients from first position +*/ +function get_recipients($address_list, $num_recipients = 1) +{ + $recipient = array(); + + $count = 0; + foreach ($address_list as $field => $adr_ary) + { + foreach ($adr_ary as $id => $type) + { + if ($count >= $num_recipients) + { + break 2; + } + $recipient[$field][$id] = $type; + $count++; + } + } + + return $recipient; +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/ucp_pm_options.php b/phpBB/includes/ucp/ucp_pm_options.php new file mode 100644 index 0000000000..e80c0672cf --- /dev/null +++ b/phpBB/includes/ucp/ucp_pm_options.php @@ -0,0 +1,836 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Execute message options +*/ +function message_options($id, $mode, $global_privmsgs_rules, $global_rule_conditions) +{ + global $phpbb_root_path, $phpEx, $user, $template, $auth, $config, $db; + + $redirect_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=pm&mode=options"); + + add_form_key('ucp_pm_options'); + // Change "full folder" setting - what to do if folder is full + if (isset($_POST['fullfolder'])) + { + check_form_key('ucp_pm_options', $config['form_token_lifetime'], $redirect_url); + $full_action = request_var('full_action', 0); + + $set_folder_id = 0; + switch ($full_action) + { + case 1: + $set_folder_id = FULL_FOLDER_DELETE; + break; + + case 2: + $set_folder_id = request_var('full_move_to', PRIVMSGS_INBOX); + break; + + case 3: + $set_folder_id = FULL_FOLDER_HOLD; + break; + + default: + $full_action = 0; + break; + } + + if ($full_action) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_full_folder = ' . $set_folder_id . ' + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + + $user->data['user_full_folder'] = $set_folder_id; + + $message = $user->lang['FULL_FOLDER_OPTION_CHANGED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $redirect_url . '">', '</a>'); + meta_refresh(3, $redirect_url); + trigger_error($message); + } + } + + // Add Folder + if (isset($_POST['addfolder'])) + { + if (check_form_key('ucp_pm_options')) + { + $folder_name = utf8_normalize_nfc(request_var('foldername', '', true)); + $msg = ''; + + if ($folder_name) + { + $sql = 'SELECT folder_name + FROM ' . PRIVMSGS_FOLDER_TABLE . " + WHERE folder_name = '" . $db->sql_escape($folder_name) . "' + AND user_id = " . $user->data['user_id']; + $result = $db->sql_query_limit($sql, 1); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + trigger_error(sprintf($user->lang['FOLDER_NAME_EXIST'], $folder_name)); + } + + $sql = 'SELECT COUNT(folder_id) as num_folder + FROM ' . PRIVMSGS_FOLDER_TABLE . ' + WHERE user_id = ' . $user->data['user_id']; + $result = $db->sql_query($sql); + $num_folder = (int) $db->sql_fetchfield('num_folder'); + $db->sql_freeresult($result); + + if ($num_folder >= $config['pm_max_boxes']) + { + trigger_error('MAX_FOLDER_REACHED'); + } + + $sql = 'INSERT INTO ' . PRIVMSGS_FOLDER_TABLE . ' ' . $db->sql_build_array('INSERT', array( + 'user_id' => (int) $user->data['user_id'], + 'folder_name' => $folder_name) + ); + $db->sql_query($sql); + $msg = $user->lang['FOLDER_ADDED']; + } + else + { + $msg = $user->lang['FOLDER_NAME_EMPTY']; + } + } + else + { + $msg = $user->lang['FORM_INVALID']; + } + $message = $msg . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $redirect_url . '">', '</a>'); + meta_refresh(3, $redirect_url); + trigger_error($message); + } + + // Rename folder + if (isset($_POST['rename_folder'])) + { + if (check_form_key('ucp_pm_options')) + { + $new_folder_name = utf8_normalize_nfc(request_var('new_folder_name', '', true)); + $rename_folder_id= request_var('rename_folder_id', 0); + + if (!$new_folder_name) + { + trigger_error('NO_NEW_FOLDER_NAME'); + } + + // Select custom folder + $sql = 'SELECT folder_name, pm_count + FROM ' . PRIVMSGS_FOLDER_TABLE . " + WHERE user_id = {$user->data['user_id']} + AND folder_id = $rename_folder_id"; + $result = $db->sql_query_limit($sql, 1); + $folder_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$folder_row) + { + trigger_error('CANNOT_RENAME_FOLDER'); + } + + $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . " + SET folder_name = '" . $db->sql_escape($new_folder_name) . "' + WHERE folder_id = $rename_folder_id + AND user_id = {$user->data['user_id']}"; + $db->sql_query($sql); + $msg = $user->lang['FOLDER_RENAMED']; + } + else + { + $msg = $user->lang['FORM_INVALID']; + } + + $message = $msg . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $redirect_url . '">', '</a>'); + + meta_refresh(3, $redirect_url); + trigger_error($message); + } + + // Remove Folder + if (isset($_POST['remove_folder'])) + { + $remove_folder_id = request_var('remove_folder_id', 0); + + // Default to "move all messages to inbox" + $remove_action = request_var('remove_action', 1); + $move_to = request_var('move_to', PRIVMSGS_INBOX); + + // Move to same folder? + if ($remove_action == 1 && $remove_folder_id == $move_to) + { + trigger_error('CANNOT_MOVE_TO_SAME_FOLDER'); + } + + // Select custom folder + $sql = 'SELECT folder_name, pm_count + FROM ' . PRIVMSGS_FOLDER_TABLE . " + WHERE user_id = {$user->data['user_id']} + AND folder_id = $remove_folder_id"; + $result = $db->sql_query_limit($sql, 1); + $folder_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$folder_row) + { + trigger_error('CANNOT_REMOVE_FOLDER'); + } + + $s_hidden_fields = array( + 'remove_folder_id' => $remove_folder_id, + 'remove_action' => $remove_action, + 'move_to' => $move_to, + 'remove_folder' => 1 + ); + + // Do we need to confirm? + if (confirm_box(true)) + { + // Gather message ids + $sql = 'SELECT msg_id + FROM ' . PRIVMSGS_TO_TABLE . ' + WHERE user_id = ' . $user->data['user_id'] . " + AND folder_id = $remove_folder_id"; + $result = $db->sql_query($sql); + + $msg_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $msg_ids[] = (int) $row['msg_id']; + } + $db->sql_freeresult($result); + + // First of all, copy all messages to another folder... or delete all messages + switch ($remove_action) + { + // Move Messages + case 1: + $num_moved = move_pm($user->data['user_id'], $user->data['message_limit'], $msg_ids, $move_to, $remove_folder_id); + + // Something went wrong, only partially moved? + if ($num_moved != $folder_row['pm_count']) + { + trigger_error(sprintf($user->lang['MOVE_PM_ERROR'], $num_moved, $folder_row['pm_count'])); + } + break; + + // Remove Messages + case 2: + delete_pm($user->data['user_id'], $msg_ids, $remove_folder_id); + break; + } + + // Remove folder + $sql = 'DELETE FROM ' . PRIVMSGS_FOLDER_TABLE . " + WHERE user_id = {$user->data['user_id']} + AND folder_id = $remove_folder_id"; + $db->sql_query($sql); + + // Check full folder option. If the removed folder has been specified as destination switch back to inbox + if ($user->data['user_full_folder'] == $remove_folder_id) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_full_folder = ' . PRIVMSGS_INBOX . ' + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + + $user->data['user_full_folder'] = PRIVMSGS_INBOX; + } + + // Now make sure the folder is not used for rules + // We assign another folder id (the one the messages got moved to) or assign the INBOX (to not have to remove any rule) + $sql = 'UPDATE ' . PRIVMSGS_RULES_TABLE . ' SET rule_folder_id = '; + $sql .= ($remove_action == 1) ? $move_to : PRIVMSGS_INBOX; + $sql .= ' WHERE rule_folder_id = ' . $remove_folder_id; + + $db->sql_query($sql); + + $meta_info = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=pm&mode=$mode"); + $message = $user->lang['FOLDER_REMOVED']; + + meta_refresh(3, $meta_info); + $message .= '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $meta_info . '">', '</a>'); + trigger_error($message); + } + else + { + confirm_box(false, 'REMOVE_FOLDER', build_hidden_fields($s_hidden_fields)); + } + } + + // Add Rule + if (isset($_POST['add_rule'])) + { + if (check_form_key('ucp_pm_options')) + { + $check_option = request_var('check_option', 0); + $rule_option = request_var('rule_option', 0); + $cond_option = request_var('cond_option', ''); + $action_option = explode('|', request_var('action_option', '')); + $rule_string = ($cond_option != 'none') ? utf8_normalize_nfc(request_var('rule_string', '', true)) : ''; + $rule_user_id = ($cond_option != 'none') ? request_var('rule_user_id', 0) : 0; + $rule_group_id = ($cond_option != 'none') ? request_var('rule_group_id', 0) : 0; + + $action = (int) $action_option[0]; + $folder_id = (int) $action_option[1]; + + if (!$action || !$check_option || !$rule_option || !$cond_option || ($cond_option != 'none' && !$rule_string)) + { + trigger_error('RULE_NOT_DEFINED'); + } + + if (($cond_option == 'user' && !$rule_user_id) || ($cond_option == 'group' && !$rule_group_id)) + { + trigger_error('RULE_NOT_DEFINED'); + } + + $rule_ary = array( + 'user_id' => $user->data['user_id'], + 'rule_check' => $check_option, + 'rule_connection' => $rule_option, + 'rule_string' => $rule_string, + 'rule_user_id' => $rule_user_id, + 'rule_group_id' => $rule_group_id, + 'rule_action' => $action, + 'rule_folder_id' => $folder_id + ); + + $sql = 'SELECT rule_id + FROM ' . PRIVMSGS_RULES_TABLE . ' + WHERE ' . $db->sql_build_array('SELECT', $rule_ary); + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + trigger_error('RULE_ALREADY_DEFINED'); + } + + $sql = 'INSERT INTO ' . PRIVMSGS_RULES_TABLE . ' ' . $db->sql_build_array('INSERT', $rule_ary); + $db->sql_query($sql); + + // Update users message rules + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_message_rules = 1 + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + + $msg = $user->lang['RULE_ADDED']; + } + else + { + $msg = $user->lang['FORM_INVALID']; + } + $message = $msg . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $redirect_url . '">', '</a>'); + meta_refresh(3, $redirect_url); + trigger_error($message); + } + + // Remove Rule + if (isset($_POST['delete_rule']) && !isset($_POST['cancel'])) + { + $delete_id = array_keys(request_var('delete_rule', array(0 => 0))); + $delete_id = (!empty($delete_id[0])) ? $delete_id[0] : 0; + + if (!$delete_id) + { + redirect(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&mode=' . $mode)); + } + + // Do we need to confirm? + if (confirm_box(true)) + { + $sql = 'DELETE FROM ' . PRIVMSGS_RULES_TABLE . ' + WHERE user_id = ' . $user->data['user_id'] . " + AND rule_id = $delete_id"; + $db->sql_query($sql); + + $meta_info = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&mode=' . $mode); + $message = $user->lang['RULE_DELETED']; + + // Reset user_message_rules if no more assigned + $sql = 'SELECT rule_id + FROM ' . PRIVMSGS_RULES_TABLE . ' + WHERE user_id = ' . $user->data['user_id']; + $result = $db->sql_query_limit($sql, 1); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + // Update users message rules + if (!$row) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_message_rules = 0 + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + } + + meta_refresh(3, $meta_info); + $message .= '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $meta_info . '">', '</a>'); + trigger_error($message); + } + else + { + confirm_box(false, 'DELETE_RULE', build_hidden_fields(array('delete_rule' => array($delete_id => 1)))); + } + } + + $folder = array(); + + $sql = 'SELECT COUNT(msg_id) as num_messages + FROM ' . PRIVMSGS_TO_TABLE . ' + WHERE user_id = ' . $user->data['user_id'] . ' + AND folder_id = ' . PRIVMSGS_INBOX; + $result = $db->sql_query($sql); + $num_messages = (int) $db->sql_fetchfield('num_messages'); + $db->sql_freeresult($result); + + $folder[PRIVMSGS_INBOX] = array( + 'folder_name' => $user->lang['PM_INBOX'], + 'message_status' => sprintf($user->lang['FOLDER_MESSAGE_STATUS'], $num_messages, $user->data['message_limit']) + ); + + $sql = 'SELECT folder_id, folder_name, pm_count + FROM ' . PRIVMSGS_FOLDER_TABLE . ' + WHERE user_id = ' . $user->data['user_id']; + $result = $db->sql_query($sql); + + $num_user_folder = 0; + while ($row = $db->sql_fetchrow($result)) + { + $num_user_folder++; + $folder[$row['folder_id']] = array( + 'folder_name' => $row['folder_name'], + 'message_status' => sprintf($user->lang['FOLDER_MESSAGE_STATUS'], $row['pm_count'], $user->data['message_limit']) + ); + } + $db->sql_freeresult($result); + + $s_full_folder_options = $s_to_folder_options = $s_folder_options = ''; + + if ($user->data['user_full_folder'] == FULL_FOLDER_NONE) + { + // -3 here to let the correct folder id be selected + $to_folder_id = $config['full_folder_action'] - 3; + } + else + { + $to_folder_id = $user->data['user_full_folder']; + } + + foreach ($folder as $folder_id => $folder_ary) + { + $s_full_folder_options .= '<option value="' . $folder_id . '"' . (($user->data['user_full_folder'] == $folder_id) ? ' selected="selected"' : '') . '>' . $folder_ary['folder_name'] . ' (' . $folder_ary['message_status'] . ')</option>'; + $s_to_folder_options .= '<option value="' . $folder_id . '"' . (($to_folder_id == $folder_id) ? ' selected="selected"' : '') . '>' . $folder_ary['folder_name'] . ' (' . $folder_ary['message_status'] . ')</option>'; + + if ($folder_id != PRIVMSGS_INBOX) + { + $s_folder_options .= '<option value="' . $folder_id . '">' . $folder_ary['folder_name'] . ' (' . $folder_ary['message_status'] . ')</option>'; + } + } + + $s_delete_checked = ($user->data['user_full_folder'] == FULL_FOLDER_DELETE) ? ' checked="checked"' : ''; + $s_hold_checked = ($user->data['user_full_folder'] == FULL_FOLDER_HOLD) ? ' checked="checked"' : ''; + $s_move_checked = ($user->data['user_full_folder'] >= 0) ? ' checked="checked"' : ''; + + if ($user->data['user_full_folder'] == FULL_FOLDER_NONE) + { + switch ($config['full_folder_action']) + { + case 1: + $s_delete_checked = ' checked="checked"'; + break; + + case 2: + $s_hold_checked = ' checked="checked"'; + break; + } + } + + $template->assign_vars(array( + 'S_FULL_FOLDER_OPTIONS' => $s_full_folder_options, + 'S_TO_FOLDER_OPTIONS' => $s_to_folder_options, + 'S_FOLDER_OPTIONS' => $s_folder_options, + 'S_DELETE_CHECKED' => $s_delete_checked, + 'S_HOLD_CHECKED' => $s_hold_checked, + 'S_MOVE_CHECKED' => $s_move_checked, + 'S_MAX_FOLDER_REACHED' => ($num_user_folder >= $config['pm_max_boxes']) ? true : false, + 'S_MAX_FOLDER_ZERO' => ($config['pm_max_boxes'] == 0) ? true : false, + + 'DEFAULT_ACTION' => ($config['full_folder_action'] == 1) ? $user->lang['DELETE_OLDEST_MESSAGES'] : $user->lang['HOLD_NEW_MESSAGES'], + + 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=ucp&field=rule_string&select_single=true'), + )); + + $rule_lang = $action_lang = $check_lang = array(); + + // Build all three language arrays + preg_replace('#^((RULE|ACTION|CHECK)_([A-Z0-9_]+))$#e', "\${strtolower('\\2') . '_lang'}[constant('\\1')] = \$user->lang['PM_\\2']['\\3']", array_keys(get_defined_constants())); + + /* + Rule Ordering: + -> CHECK_* -> RULE_* [IN $global_privmsgs_rules:CHECK_*] -> [IF $rule_conditions[RULE_*] [|text|bool|user|group|own_group]] -> ACTION_* + */ + + $check_option = request_var('check_option', 0); + $rule_option = request_var('rule_option', 0); + $cond_option = request_var('cond_option', ''); + $action_option = request_var('action_option', ''); + $back = (isset($_REQUEST['back'])) ? request_var('back', array('' => 0)) : array(); + + if (sizeof($back)) + { + if ($action_option) + { + $action_option = ''; + } + else if ($cond_option) + { + $cond_option = ''; + } + else if ($rule_option) + { + $rule_option = 0; + } + else if ($check_option) + { + $check_option = 0; + } + } + + if (isset($back['action']) && $cond_option == 'none') + { + $back['cond'] = true; + } + + // Check + if (!isset($global_privmsgs_rules[$check_option])) + { + $check_option = 0; + } + + define_check_option(($check_option && !isset($back['rule'])) ? true : false, $check_option, $check_lang); + + if ($check_option && !isset($back['rule'])) + { + define_rule_option(($rule_option && !isset($back['cond'])) ? true : false, $rule_option, $rule_lang, $global_privmsgs_rules[$check_option]); + } + + if ($rule_option && !isset($back['cond'])) + { + if (!isset($global_rule_conditions[$rule_option])) + { + $cond_option = 'none'; + $template->assign_var('NONE_CONDITION', true); + } + else + { + define_cond_option(($cond_option && !isset($back['action'])) ? true : false, $cond_option, $rule_option, $global_rule_conditions); + } + } + + if ($cond_option && !isset($back['action'])) + { + define_action_option(false, $action_option, $action_lang, $folder); + } + + show_defined_rules($user->data['user_id'], $check_lang, $rule_lang, $action_lang, $folder); +} + +/** +* Defining check option for message rules +*/ +function define_check_option($hardcoded, $check_option, $check_lang) +{ + global $template; + + $s_check_options = ''; + if (!$hardcoded) + { + foreach ($check_lang as $value => $lang) + { + $s_check_options .= '<option value="' . $value . '"' . (($value == $check_option) ? ' selected="selected"' : '') . '>' . $lang . '</option>'; + } + } + + $template->assign_vars(array( + 'S_CHECK_DEFINED' => true, + 'S_CHECK_SELECT' => ($hardcoded) ? false : true, + 'CHECK_CURRENT' => isset($check_lang[$check_option]) ? $check_lang[$check_option] : '', + 'S_CHECK_OPTIONS' => $s_check_options, + 'CHECK_OPTION' => $check_option) + ); +} + +/** +* Defining action option for message rules +*/ +function define_action_option($hardcoded, $action_option, $action_lang, $folder) +{ + global $db, $template, $user; + + $l_action = $s_action_options = ''; + if ($hardcoded) + { + $option = explode('|', $action_option); + $action = (int) $option[0]; + $folder_id = (int) $option[1]; + + $l_action = $action_lang[$action]; + if ($action == ACTION_PLACE_INTO_FOLDER) + { + $l_action .= ' -> ' . $folder[$folder_id]['folder_name']; + } + } + else + { + foreach ($action_lang as $action => $lang) + { + if ($action == ACTION_PLACE_INTO_FOLDER) + { + foreach ($folder as $folder_id => $folder_ary) + { + $s_action_options .= '<option value="' . $action . '|' . $folder_id . '"' . (($action_option == $action . '|' . $folder_id) ? ' selected="selected"' : '') . '>' . $lang . ' -> ' . $folder_ary['folder_name'] . '</option>'; + } + } + else + { + $s_action_options .= '<option value="' . $action . '|0"' . (($action_option == $action . '|0') ? ' selected="selected"' : '') . '>' . $lang . '</option>'; + } + } + } + + $template->assign_vars(array( + 'S_ACTION_DEFINED' => true, + 'S_ACTION_SELECT' => ($hardcoded) ? false : true, + 'ACTION_CURRENT' => $l_action, + 'S_ACTION_OPTIONS' => $s_action_options, + 'ACTION_OPTION' => $action_option) + ); +} + +/** +* Defining rule option for message rules +*/ +function define_rule_option($hardcoded, $rule_option, $rule_lang, $check_ary) +{ + global $template; + + $s_rule_options = ''; + if (!$hardcoded) + { + foreach ($check_ary as $value => $_check) + { + $s_rule_options .= '<option value="' . $value . '"' . (($value == $rule_option) ? ' selected="selected"' : '') . '>' . $rule_lang[$value] . '</option>'; + } + } + + $template->assign_vars(array( + 'S_RULE_DEFINED' => true, + 'S_RULE_SELECT' => !$hardcoded, + 'RULE_CURRENT' => isset($rule_lang[$rule_option]) ? $rule_lang[$rule_option] : '', + 'S_RULE_OPTIONS' => $s_rule_options, + 'RULE_OPTION' => $rule_option) + ); +} + +/** +* Defining condition option for message rules +*/ +function define_cond_option($hardcoded, $cond_option, $rule_option, $global_rule_conditions) +{ + global $db, $template, $auth, $user; + + $template->assign_vars(array( + 'S_COND_DEFINED' => true, + 'S_COND_SELECT' => (!$hardcoded && isset($global_rule_conditions[$rule_option])) ? true : false) + ); + + // Define COND_OPTION + if (!isset($global_rule_conditions[$rule_option])) + { + $template->assign_vars(array( + 'COND_OPTION' => 'none', + 'COND_CURRENT' => false) + ); + return; + } + + // Define Condition + $condition = $global_rule_conditions[$rule_option]; + $current_value = ''; + + switch ($condition) + { + case 'text': + $rule_string = utf8_normalize_nfc(request_var('rule_string', '', true)); + + $template->assign_vars(array( + 'S_TEXT_CONDITION' => true, + 'CURRENT_STRING' => $rule_string, + 'CURRENT_USER_ID' => 0, + 'CURRENT_GROUP_ID' => 0) + ); + + $current_value = $rule_string; + break; + + case 'user': + $rule_user_id = request_var('rule_user_id', 0); + $rule_string = utf8_normalize_nfc(request_var('rule_string', '', true)); + + if ($rule_string && !$rule_user_id) + { + $sql = 'SELECT user_id + FROM ' . USERS_TABLE . " + WHERE username_clean = '" . $db->sql_escape(utf8_clean_string($rule_string)) . "'"; + $result = $db->sql_query($sql); + $rule_user_id = (int) $db->sql_fetchfield('user_id'); + $db->sql_freeresult($result); + + if (!$rule_user_id) + { + $rule_string = ''; + } + } + else if (!$rule_string && $rule_user_id) + { + $sql = 'SELECT username + FROM ' . USERS_TABLE . " + WHERE user_id = $rule_user_id"; + $result = $db->sql_query($sql); + $rule_string = $db->sql_fetchfield('username'); + $db->sql_freeresult($result); + + if (!$rule_string) + { + $rule_user_id = 0; + } + } + + $template->assign_vars(array( + 'S_USER_CONDITION' => true, + 'CURRENT_STRING' => $rule_string, + 'CURRENT_USER_ID' => $rule_user_id, + 'CURRENT_GROUP_ID' => 0) + ); + + $current_value = $rule_string; + break; + + case 'group': + $rule_group_id = request_var('rule_group_id', 0); + $rule_string = utf8_normalize_nfc(request_var('rule_string', '', true)); + + $sql = 'SELECT g.group_id, g.group_name, g.group_type + FROM ' . GROUPS_TABLE . ' g '; + + if (!$auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel')) + { + $sql .= 'LEFT JOIN ' . USER_GROUP_TABLE . ' ug + ON ( + g.group_id = ug.group_id + AND ug.user_id = ' . $user->data['user_id'] . ' + AND ug.user_pending = 0 + ) + WHERE (ug.user_id = ' . $user->data['user_id'] . ' OR g.group_type <> ' . GROUP_HIDDEN . ') + AND'; + } + else + { + $sql .= 'WHERE'; + } + + $sql .= " (g.group_name NOT IN ('GUESTS', 'BOTS') OR g.group_type <> " . GROUP_SPECIAL . ') + ORDER BY g.group_type DESC, g.group_name ASC'; + + $result = $db->sql_query($sql); + + $s_group_options = ''; + while ($row = $db->sql_fetchrow($result)) + { + if ($rule_group_id && ($row['group_id'] == $rule_group_id)) + { + $rule_string = (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']); + } + + $s_class = ($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : ''; + $s_selected = ($row['group_id'] == $rule_group_id) ? ' selected="selected"' : ''; + + $s_group_options .= '<option value="' . $row['group_id'] . '"' . $s_class . $s_selected . '>' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>'; + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'S_GROUP_CONDITION' => true, + 'S_GROUP_OPTIONS' => $s_group_options, + 'CURRENT_STRING' => $rule_string, + 'CURRENT_USER_ID' => 0, + 'CURRENT_GROUP_ID' => $rule_group_id) + ); + + $current_value = $rule_string; + break; + + default: + return; + } + + $template->assign_vars(array( + 'COND_OPTION' => $condition, + 'COND_CURRENT' => $current_value) + ); +} + +/** +* Display defined message rules +*/ +function show_defined_rules($user_id, $check_lang, $rule_lang, $action_lang, $folder) +{ + global $db, $template; + + $sql = 'SELECT * + FROM ' . PRIVMSGS_RULES_TABLE . ' + WHERE user_id = ' . $user_id . ' + ORDER BY rule_id ASC'; + $result = $db->sql_query($sql); + + $count = 0; + while ($row = $db->sql_fetchrow($result)) + { + $template->assign_block_vars('rule', array( + 'COUNT' => ++$count, + 'RULE_ID' => $row['rule_id'], + 'CHECK' => $check_lang[$row['rule_check']], + 'RULE' => $rule_lang[$row['rule_connection']], + 'STRING' => $row['rule_string'], + 'ACTION' => $action_lang[$row['rule_action']], + 'FOLDER' => ($row['rule_action'] == ACTION_PLACE_INTO_FOLDER) ? $folder[$row['rule_folder_id']]['folder_name'] : '') + ); + } + $db->sql_freeresult($result); +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/ucp_pm_viewfolder.php b/phpBB/includes/ucp/ucp_pm_viewfolder.php new file mode 100644 index 0000000000..33d2c9fb6f --- /dev/null +++ b/phpBB/includes/ucp/ucp_pm_viewfolder.php @@ -0,0 +1,509 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* View message folder +* Called from ucp_pm with mode == 'view' && action == 'view_folder' +*/ +function view_folder($id, $mode, $folder_id, $folder) +{ + global $user, $template, $auth, $db, $cache; + global $phpbb_root_path, $config, $phpEx; + + $submit_export = (isset($_POST['submit_export'])) ? true : false; + + $folder_info = get_pm_from($folder_id, $folder, $user->data['user_id']); + + if (!$submit_export) + { + $user->add_lang('viewforum'); + + // Grab icons + $icons = $cache->obtain_icons(); + + $color_rows = array('marked', 'replied'); + + // only show the friend/foe color rows if the module is enabled + $zebra_enabled = false; + + $_module = new p_master(); + $_module->list_modules('ucp'); + $_module->set_active('zebra'); + + $zebra_enabled = ($_module->active_module === false) ? false : true; + + unset($_module); + + if ($zebra_enabled) + { + $color_rows = array_merge($color_rows, array('friend', 'foe')); + } + + foreach ($color_rows as $var) + { + $template->assign_block_vars('pm_colour_info', array( + 'IMG' => $user->img("pm_{$var}", ''), + 'CLASS' => "pm_{$var}_colour", + 'LANG' => $user->lang[strtoupper($var) . '_MESSAGE']) + ); + } + + $mark_options = array('mark_important', 'delete_marked'); + + $s_mark_options = ''; + foreach ($mark_options as $mark_option) + { + $s_mark_options .= '<option value="' . $mark_option . '">' . $user->lang[strtoupper($mark_option)] . '</option>'; + } + + // We do the folder moving options here too, for template authors to use... + $s_folder_move_options = ''; + if ($folder_id != PRIVMSGS_NO_BOX && $folder_id != PRIVMSGS_OUTBOX) + { + foreach ($folder as $f_id => $folder_ary) + { + if ($f_id == PRIVMSGS_OUTBOX || $f_id == PRIVMSGS_SENTBOX || $f_id == $folder_id) + { + continue; + } + + $s_folder_move_options .= '<option' . (($f_id != PRIVMSGS_INBOX) ? ' class="sep"' : '') . ' value="' . $f_id . '">'; + $s_folder_move_options .= sprintf($user->lang['MOVE_MARKED_TO_FOLDER'], $folder_ary['folder_name']); + $s_folder_move_options .= (($folder_ary['unread_messages']) ? ' [' . $folder_ary['unread_messages'] . '] ' : '') . '</option>'; + } + } + $friend = $foe = array(); + + // Get friends and foes + $sql = 'SELECT * + FROM ' . ZEBRA_TABLE . ' + WHERE user_id = ' . $user->data['user_id']; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $friend[$row['zebra_id']] = $row['friend']; + $foe[$row['zebra_id']] = $row['foe']; + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'S_MARK_OPTIONS' => $s_mark_options, + 'S_MOVE_MARKED_OPTIONS' => $s_folder_move_options) + ); + + // Okay, lets dump out the page ... + if (sizeof($folder_info['pm_list'])) + { + $address_list = array(); + + // Build Recipient List if in outbox/sentbox - max two additional queries + if ($folder_id == PRIVMSGS_OUTBOX || $folder_id == PRIVMSGS_SENTBOX) + { + $address_list = get_recipient_strings($folder_info['rowset']); + } + + foreach ($folder_info['pm_list'] as $message_id) + { + $row = &$folder_info['rowset'][$message_id]; + + $folder_img = ($row['pm_unread']) ? 'pm_unread' : 'pm_read'; + $folder_alt = ($row['pm_unread']) ? 'NEW_MESSAGES' : 'NO_NEW_MESSAGES'; + + // Generate all URIs ... + $view_message_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=$id&mode=view&f=$folder_id&p=$message_id"); + $remove_message_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=$id&mode=compose&action=delete&p=$message_id"); + + $row_indicator = ''; + foreach ($color_rows as $var) + { + if (($var != 'friend' && $var != 'foe' && $row['pm_' . $var]) + || + (($var == 'friend' || $var == 'foe') && isset(${$var}[$row['author_id']]) && ${$var}[$row['author_id']])) + { + $row_indicator = $var; + break; + } + } + + // Send vars to template + $template->assign_block_vars('messagerow', array( + 'PM_CLASS' => ($row_indicator) ? 'pm_' . $row_indicator . '_colour' : '', + + 'MESSAGE_AUTHOR_FULL' => get_username_string('full', $row['author_id'], $row['username'], $row['user_colour'], $row['username']), + 'MESSAGE_AUTHOR_COLOUR' => get_username_string('colour', $row['author_id'], $row['username'], $row['user_colour'], $row['username']), + 'MESSAGE_AUTHOR' => get_username_string('username', $row['author_id'], $row['username'], $row['user_colour'], $row['username']), + 'U_MESSAGE_AUTHOR' => get_username_string('profile', $row['author_id'], $row['username'], $row['user_colour'], $row['username']), + + 'FOLDER_ID' => $folder_id, + 'MESSAGE_ID' => $message_id, + 'SENT_TIME' => $user->format_date($row['message_time']), + 'SUBJECT' => censor_text($row['message_subject']), + 'FOLDER' => (isset($folder[$row['folder_id']])) ? $folder[$row['folder_id']]['folder_name'] : '', + 'U_FOLDER' => (isset($folder[$row['folder_id']])) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'folder=' . $row['folder_id']) : '', + 'PM_ICON_IMG' => (!empty($icons[$row['icon_id']])) ? '<img src="' . $config['icons_path'] . '/' . $icons[$row['icon_id']]['img'] . '" width="' . $icons[$row['icon_id']]['width'] . '" height="' . $icons[$row['icon_id']]['height'] . '" alt="" title="" />' : '', + 'PM_ICON_URL' => (!empty($icons[$row['icon_id']])) ? $config['icons_path'] . '/' . $icons[$row['icon_id']]['img'] : '', + 'FOLDER_IMG' => $user->img($folder_img, $folder_alt), + 'FOLDER_IMG_SRC' => $user->img($folder_img, $folder_alt, false, '', 'src'), + 'PM_IMG' => ($row_indicator) ? $user->img('pm_' . $row_indicator, '') : '', + 'ATTACH_ICON_IMG' => ($auth->acl_get('u_pm_download') && $row['message_attachment'] && $config['allow_pm_attach']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', + + 'S_PM_DELETED' => ($row['pm_deleted']) ? true : false, + 'S_AUTHOR_DELETED' => ($row['author_id'] == ANONYMOUS) ? true : false, + + 'U_VIEW_PM' => ($row['pm_deleted']) ? '' : $view_message_url, + 'U_REMOVE_PM' => ($row['pm_deleted']) ? $remove_message_url : '', + 'RECIPIENTS' => ($folder_id == PRIVMSGS_OUTBOX || $folder_id == PRIVMSGS_SENTBOX) ? implode(', ', $address_list[$message_id]) : '') + ); + } + unset($folder_info['rowset']); + + $template->assign_vars(array( + 'S_SHOW_RECIPIENTS' => ($folder_id == PRIVMSGS_OUTBOX || $folder_id == PRIVMSGS_SENTBOX) ? true : false, + 'S_SHOW_COLOUR_LEGEND' => true, + + 'S_PM_ICONS' => ($config['enable_pm_icons']) ? true : false) + ); + } + } + else + { + $export_type = request_var('export_option', ''); + $enclosure = request_var('enclosure', ''); + $delimiter = request_var('delimiter', ''); + + if ($export_type == 'CSV' && ($delimiter === '' || $enclosure === '')) + { + $template->assign_var('PROMPT', true); + } + else + { + // Build Recipient List if in outbox/sentbox + $address = $data = array(); + + if ($folder_id == PRIVMSGS_OUTBOX || $folder_id == PRIVMSGS_SENTBOX) + { + foreach ($folder_info['rowset'] as $message_id => $row) + { + $address[$message_id] = rebuild_header(array('to' => $row['to_address'], 'bcc' => $row['bcc_address'])); + } + } + + foreach ($folder_info['pm_list'] as $message_id) + { + $row = &$folder_info['rowset'][$message_id]; + + include_once($phpbb_root_path . 'includes/functions_posting.' . $phpEx); + + $sql = 'SELECT p.message_text, p.bbcode_uid + FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p, ' . USERS_TABLE . ' u + WHERE t.user_id = ' . $user->data['user_id'] . " + AND p.author_id = u.user_id + AND t.folder_id = $folder_id + AND t.msg_id = p.msg_id + AND p.msg_id = $message_id"; + $result = $db->sql_query_limit($sql, 1); + $message_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $_types = array('u', 'g'); + foreach ($_types as $ug_type) + { + if (isset($address[$message_id][$ug_type]) && sizeof($address[$message_id][$ug_type])) + { + if ($ug_type == 'u') + { + $sql = 'SELECT user_id as id, username as name + FROM ' . USERS_TABLE . ' + WHERE '; + } + else + { + $sql = 'SELECT group_id as id, group_name as name + FROM ' . GROUPS_TABLE . ' + WHERE '; + } + $sql .= $db->sql_in_set(($ug_type == 'u') ? 'user_id' : 'group_id', array_map('intval', array_keys($address[$message_id][$ug_type]))); + + $result = $db->sql_query($sql); + + while ($info_row = $db->sql_fetchrow($result)) + { + $address[$message_id][$ug_type][$address[$message_id][$ug_type][$info_row['id']]][] = $info_row['name']; + unset($address[$message_id][$ug_type][$info_row['id']]); + } + $db->sql_freeresult($result); + } + } + + decode_message($message_row['message_text'], $message_row['bbcode_uid']); + + $data[] = array( + 'subject' => censor_text($row['message_subject']), + 'sender' => $row['username'], + // ISO 8601 date. For PHP4 we are able to hardcode the timezone because $user->format_date() does not set it. + 'date' => $user->format_date($row['message_time'], (PHP_VERSION >= 5) ? 'c' : "Y-m-d\TH:i:s+00:00", true), + 'to' => ($folder_id == PRIVMSGS_OUTBOX || $folder_id == PRIVMSGS_SENTBOX) ? $address[$message_id] : '', + 'message' => $message_row['message_text'] + ); + } + + switch ($export_type) + { + case 'CSV': + case 'CSV_EXCEL': + $mimetype = 'text/csv'; + $filetype = 'csv'; + + if ($export_type == 'CSV_EXCEL') + { + $enclosure = '"'; + $delimiter = ','; + $newline = "\r\n"; + } + else + { + $newline = "\n"; + } + + $string = ''; + foreach ($data as $value) + { + $recipients = $value['to']; + $value['to'] = $value['bcc'] = ''; + + if (is_array($recipients)) + { + foreach ($recipients as $values) + { + $value['bcc'] .= (isset($values['bcc']) && is_array($values['bcc'])) ? ',' . implode(',', $values['bcc']) : ''; + $value['to'] .= (isset($values['to']) && is_array($values['to'])) ? ',' . implode(',', $values['to']) : ''; + } + + // Remove the commas which will appear before the first entry. + $value['to'] = substr($value['to'], 1); + $value['bcc'] = substr($value['bcc'], 1); + } + + foreach ($value as $tag => $text) + { + $cell = str_replace($enclosure, $enclosure . $enclosure, $text); + + if (strpos($cell, $enclosure) !== false || strpos($cell, $delimiter) !== false || strpos($cell, $newline) !== false) + { + $string .= $enclosure . $text . $enclosure . $delimiter; + } + else + { + $string .= $cell . $delimiter; + } + } + $string = substr($string, 0, -1) . $newline; + } + break; + + case 'XML': + $mimetype = 'application/xml'; + $filetype = 'xml'; + $string = '<?xml version="1.0"?>' . "\n"; + $string .= "<phpbb>\n"; + + foreach ($data as $value) + { + $string .= "\t<privmsg>\n"; + + if (is_array($value['to'])) + { + foreach ($value['to'] as $key => $values) + { + foreach ($values as $type => $types) + { + foreach ($types as $name) + { + $string .= "\t\t<recipient type=\"$type\" status=\"$key\">$name</recipient>\n"; + } + } + } + } + + unset($value['to']); + + foreach ($value as $tag => $text) + { + $string .= "\t\t<$tag>$text</$tag>\n"; + } + + $string .= "\t</privmsg>\n"; + } + $string .= '</phpbb>'; + break; + } + + header('Pragma: no-cache'); + header("Content-Type: $mimetype; name=\"data.$filetype\""); + header("Content-disposition: attachment; filename=data.$filetype"); + echo $string; + exit; + } + } +} + +/** +* Get Messages from folder/user +*/ +function get_pm_from($folder_id, $folder, $user_id) +{ + global $user, $db, $template, $config, $auth, $phpbb_root_path, $phpEx; + + $start = request_var('start', 0); + + // Additional vars later, pm ordering is mostly different from post ordering. :/ + $sort_days = request_var('st', 0); + $sort_key = request_var('sk', 't'); + $sort_dir = request_var('sd', 'd'); + + // PM ordering options + $limit_days = array(0 => $user->lang['ALL_MESSAGES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + + // No sort by Author for sentbox/outbox (already only author available) + // Also, sort by msg_id for the time - private messages are not as prone to errors as posts are. + if ($folder_id == PRIVMSGS_OUTBOX || $folder_id == PRIVMSGS_SENTBOX) + { + $sort_by_text = array('t' => $user->lang['POST_TIME'], 's' => $user->lang['SUBJECT']); + $sort_by_sql = array('t' => 'p.message_time', 's' => array('p.message_subject', 'p.message_time')); + } + else + { + $sort_by_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 's' => $user->lang['SUBJECT']); + $sort_by_sql = array('a' => array('u.username_clean', 'p.message_time'), 't' => 'p.message_time', 's' => array('p.message_subject', 'p.message_time')); + } + + $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = ''; + 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); + + $folder_sql = 't.folder_id = ' . (int) $folder_id; + + // Limit pms to certain time frame, obtain correct pm count + if ($sort_days) + { + $min_post_time = time() - ($sort_days * 86400); + + if (isset($_POST['sort'])) + { + $start = 0; + } + + $sql = 'SELECT COUNT(t.msg_id) AS pm_count + FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . " p + WHERE $folder_sql + AND t.user_id = $user_id + AND t.msg_id = p.msg_id + AND p.message_time >= $min_post_time"; + $result = $db->sql_query_limit($sql, 1); + $pm_count = (int) $db->sql_fetchfield('pm_count'); + $db->sql_freeresult($result); + + $sql_limit_time = "AND p.message_time >= $min_post_time"; + } + else + { + $pm_count = (!empty($folder[$folder_id]['num_messages'])) ? $folder[$folder_id]['num_messages'] : 0; + $sql_limit_time = ''; + } + + $template->assign_vars(array( + 'PAGINATION' => generate_pagination(append_sid("{$phpbb_root_path}ucp.$phpEx", "i=pm&mode=view&action=view_folder&f=$folder_id&$u_sort_param"), $pm_count, $config['topics_per_page'], $start), + 'PAGE_NUMBER' => on_page($pm_count, $config['topics_per_page'], $start), + 'TOTAL_MESSAGES' => (($pm_count == 1) ? $user->lang['VIEW_PM_MESSAGE'] : sprintf($user->lang['VIEW_PM_MESSAGES'], $pm_count)), + + 'POST_IMG' => (!$auth->acl_get('u_sendpm')) ? $user->img('button_topic_locked', 'POST_PM_LOCKED') : $user->img('button_pm_new', 'POST_NEW_PM'), + + 'S_NO_AUTH_SEND_MESSAGE' => !$auth->acl_get('u_sendpm'), + + 'S_SELECT_SORT_DIR' => $s_sort_dir, + 'S_SELECT_SORT_KEY' => $s_sort_key, + 'S_SELECT_SORT_DAYS' => $s_limit_days, + 'S_TOPIC_ICONS' => ($config['enable_pm_icons']) ? true : false, + + 'U_POST_NEW_TOPIC' => ($auth->acl_get('u_sendpm')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&mode=compose') : '', + 'S_PM_ACTION' => append_sid("{$phpbb_root_path}ucp.$phpEx", "i=pm&mode=view&action=view_folder&f=$folder_id" . (($start !== 0) ? "&start=$start" : '')), + )); + + // Grab all pm data + $rowset = $pm_list = array(); + + // If the user is trying to reach late pages, start searching from the end + $store_reverse = false; + $sql_limit = $config['topics_per_page']; + if ($start > $pm_count / 2) + { + $store_reverse = true; + + if ($start + $config['topics_per_page'] > $pm_count) + { + $sql_limit = min($config['topics_per_page'], max(1, $pm_count - $start)); + } + + // Select the sort order + $direction = ($sort_dir == 'd') ? 'ASC' : 'DESC'; + $sql_start = max(0, $pm_count - $sql_limit - $start); + } + else + { + // Select the sort order + $direction = ($sort_dir == 'd') ? 'DESC' : 'ASC'; + $sql_start = $start; + } + + // Sql sort order + if (is_array($sort_by_sql[$sort_key])) + { + $sql_sort_order = implode(' ' . $direction . ', ', $sort_by_sql[$sort_key]) . ' ' . $direction; + } + else + { + $sql_sort_order = $sort_by_sql[$sort_key] . ' ' . $direction; + } + + $sql = 'SELECT t.*, p.root_level, p.message_time, p.message_subject, p.icon_id, p.to_address, p.message_attachment, p.bcc_address, u.username, u.username_clean, u.user_colour + 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 $folder_sql + AND t.msg_id = p.msg_id + $sql_limit_time + ORDER BY $sql_sort_order"; + $result = $db->sql_query_limit($sql, $sql_limit, $sql_start); + + while ($row = $db->sql_fetchrow($result)) + { + $rowset[$row['msg_id']] = $row; + $pm_list[] = $row['msg_id']; + } + $db->sql_freeresult($result); + + $pm_list = ($store_reverse) ? array_reverse($pm_list) : $pm_list; + + return array( + 'pm_count' => $pm_count, + 'pm_list' => $pm_list, + 'rowset' => $rowset + ); +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/ucp_pm_viewmessage.php b/phpBB/includes/ucp/ucp_pm_viewmessage.php new file mode 100644 index 0000000000..26968e1382 --- /dev/null +++ b/phpBB/includes/ucp/ucp_pm_viewmessage.php @@ -0,0 +1,320 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* View private message +*/ +function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) +{ + global $user, $template, $auth, $db, $cache; + global $phpbb_root_path, $phpEx, $config; + + $user->add_lang(array('viewtopic', 'memberlist')); + + $msg_id = (int) $msg_id; + $folder_id = (int) $folder_id; + $author_id = (int) $message_row['author_id']; + $view = request_var('view', ''); + + // Not able to view message, it was deleted by the sender + if ($message_row['pm_deleted']) + { + $meta_info = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=pm&folder=$folder_id"); + $message = $user->lang['NO_AUTH_READ_REMOVED_MESSAGE']; + + $message .= '<br /><br />' . sprintf($user->lang['RETURN_FOLDER'], '<a href="' . $meta_info . '">', '</a>'); + trigger_error($message); + } + + // Do not allow hold messages to be seen + if ($folder_id == PRIVMSGS_HOLD_BOX) + { + trigger_error('NO_AUTH_READ_HOLD_MESSAGE'); + } + + // Grab icons + $icons = $cache->obtain_icons(); + + $bbcode = false; + + // Instantiate BBCode if need be + if ($message_row['bbcode_bitfield']) + { + include($phpbb_root_path . 'includes/bbcode.' . $phpEx); + $bbcode = new bbcode($message_row['bbcode_bitfield']); + } + + // Assign TO/BCC Addresses to template + write_pm_addresses(array('to' => $message_row['to_address'], 'bcc' => $message_row['bcc_address']), $author_id); + + $user_info = get_user_information($author_id, $message_row); + + // Parse the message and subject + $message = censor_text($message_row['message_text']); + + // Second parse bbcode here + if ($message_row['bbcode_bitfield']) + { + $bbcode->bbcode_second_pass($message, $message_row['bbcode_uid'], $message_row['bbcode_bitfield']); + } + + // Always process smilies after parsing bbcodes + $message = bbcode_nl2br($message); + $message = smiley_text($message); + + // Replace naughty words such as farty pants + $message_row['message_subject'] = censor_text($message_row['message_subject']); + + // Editing information + if ($message_row['message_edit_count'] && $config['display_last_edited']) + { + $l_edit_time_total = ($message_row['message_edit_count'] == 1) ? $user->lang['EDITED_TIME_TOTAL'] : $user->lang['EDITED_TIMES_TOTAL']; + $l_edited_by = '<br /><br />' . sprintf($l_edit_time_total, (!$message_row['message_edit_user']) ? $message_row['username'] : $message_row['message_edit_user'], $user->format_date($message_row['message_edit_time'], false, true), $message_row['message_edit_count']); + } + else + { + $l_edited_by = ''; + } + + // Pull attachment data + $display_notice = false; + $attachments = array(); + + if ($message_row['message_attachment'] && $config['allow_pm_attach']) + { + if ($auth->acl_get('u_pm_download')) + { + $sql = 'SELECT * + FROM ' . ATTACHMENTS_TABLE . " + WHERE post_msg_id = $msg_id + AND in_message = 1 + ORDER BY filetime DESC, post_msg_id ASC"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $attachments[] = $row; + } + $db->sql_freeresult($result); + + // No attachments exist, but message table thinks they do so go ahead and reset attach flags + if (!sizeof($attachments)) + { + $sql = 'UPDATE ' . PRIVMSGS_TABLE . " + SET message_attachment = 0 + WHERE msg_id = $msg_id"; + $db->sql_query($sql); + } + } + else + { + $display_notice = true; + } + } + + // Assign inline attachments + if (!empty($attachments)) + { + $update_count = array(); + parse_attachments(false, $message, $attachments, $update_count); + + // Update the attachment download counts + if (sizeof($update_count)) + { + $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' + SET download_count = download_count + 1 + WHERE ' . $db->sql_in_set('attach_id', array_unique($update_count)); + $db->sql_query($sql); + } + } + + $user_info['sig'] = ''; + + $signature = ($message_row['enable_sig'] && $config['allow_sig'] && $auth->acl_get('u_sig') && $user->optionget('viewsigs')) ? $user_info['user_sig'] : ''; + + // End signature parsing, only if needed + if ($signature) + { + $signature = censor_text($signature); + + if ($user_info['user_sig_bbcode_bitfield']) + { + if ($bbcode === false) + { + include($phpbb_root_path . 'includes/bbcode.' . $phpEx); + $bbcode = new bbcode($user_info['user_sig_bbcode_bitfield']); + } + + $bbcode->bbcode_second_pass($signature, $user_info['user_sig_bbcode_uid'], $user_info['user_sig_bbcode_bitfield']); + } + + $signature = bbcode_nl2br($signature); + $signature = smiley_text($signature); + } + + $url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm'); + + // Number of "to" recipients + $num_recipients = (int) preg_match_all('/:?(u|g)_([0-9]+):?/', $message_row['to_address'], $match); + + $template->assign_vars(array( + 'MESSAGE_AUTHOR_FULL' => get_username_string('full', $author_id, $user_info['username'], $user_info['user_colour'], $user_info['username']), + 'MESSAGE_AUTHOR_COLOUR' => get_username_string('colour', $author_id, $user_info['username'], $user_info['user_colour'], $user_info['username']), + 'MESSAGE_AUTHOR' => get_username_string('username', $author_id, $user_info['username'], $user_info['user_colour'], $user_info['username']), + 'U_MESSAGE_AUTHOR' => get_username_string('profile', $author_id, $user_info['username'], $user_info['user_colour'], $user_info['username']), + + 'RANK_TITLE' => $user_info['rank_title'], + 'RANK_IMG' => $user_info['rank_image'], + 'AUTHOR_AVATAR' => (isset($user_info['avatar'])) ? $user_info['avatar'] : '', + 'AUTHOR_JOINED' => $user->format_date($user_info['user_regdate']), + 'AUTHOR_POSTS' => (int) $user_info['user_posts'], + 'AUTHOR_FROM' => (!empty($user_info['user_from'])) ? $user_info['user_from'] : '', + + 'ONLINE_IMG' => (!$config['load_onlinetrack']) ? '' : ((isset($user_info['online']) && $user_info['online']) ? $user->img('icon_user_online', $user->lang['ONLINE']) : $user->img('icon_user_offline', $user->lang['OFFLINE'])), + 'S_ONLINE' => (!$config['load_onlinetrack']) ? false : ((isset($user_info['online']) && $user_info['online']) ? true : false), + 'DELETE_IMG' => $user->img('icon_post_delete', $user->lang['DELETE_MESSAGE']), + 'INFO_IMG' => $user->img('icon_post_info', $user->lang['VIEW_PM_INFO']), + 'PROFILE_IMG' => $user->img('icon_user_profile', $user->lang['READ_PROFILE']), + 'EMAIL_IMG' => $user->img('icon_contact_email', $user->lang['SEND_EMAIL']), + 'QUOTE_IMG' => $user->img('icon_post_quote', $user->lang['POST_QUOTE_PM']), + 'REPLY_IMG' => $user->img('button_pm_reply', $user->lang['POST_REPLY_PM']), + 'REPORT_IMG' => $user->img('icon_post_report', 'REPORT_PM'), + 'EDIT_IMG' => $user->img('icon_post_edit', $user->lang['POST_EDIT_PM']), + 'MINI_POST_IMG' => $user->img('icon_post_target', $user->lang['PM']), + + 'SENT_DATE' => ($view == 'print') ? $user->format_date($message_row['message_time'], false, true) : $user->format_date($message_row['message_time']), + 'SUBJECT' => $message_row['message_subject'], + 'MESSAGE' => $message, + 'SIGNATURE' => ($message_row['enable_sig']) ? $signature : '', + 'EDITED_MESSAGE' => $l_edited_by, + 'MESSAGE_ID' => $message_row['msg_id'], + + 'U_PM' => ($config['allow_privmsg'] && $auth->acl_get('u_sendpm') && ($user_info['user_allow_pm'] || $auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_'))) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&mode=compose&u=' . $author_id) : '', + 'U_WWW' => (!empty($user_info['user_website'])) ? $user_info['user_website'] : '', + 'U_ICQ' => ($user_info['user_icq']) ? 'http://www.icq.com/people/webmsg.php?to=' . urlencode($user_info['user_icq']) : '', + 'U_AIM' => ($user_info['user_aim'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=aim&u=' . $author_id) : '', + 'U_YIM' => ($user_info['user_yim']) ? 'http://edit.yahoo.com/config/send_webmesg?.target=' . urlencode($user_info['user_yim']) . '&.src=pg' : '', + 'U_MSN' => ($user_info['user_msnm'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=msnm&u=' . $author_id) : '', + 'U_JABBER' => ($user_info['user_jabber'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=jabber&u=' . $author_id) : '', + + 'U_DELETE' => ($auth->acl_get('u_pm_delete')) ? "$url&mode=compose&action=delete&f=$folder_id&p=" . $message_row['msg_id'] : '', + 'U_EMAIL' => $user_info['email'], + 'U_REPORT' => ($config['allow_pm_report']) ? append_sid("{$phpbb_root_path}report.$phpEx", "pm=" . $message_row['msg_id']) : '', + 'U_QUOTE' => ($auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&mode=compose&action=quote&f=$folder_id&p=" . $message_row['msg_id'] : '', + 'U_EDIT' => (($message_row['message_time'] > time() - ($config['pm_edit_time'] * 60) || !$config['pm_edit_time']) && $folder_id == PRIVMSGS_OUTBOX && $auth->acl_get('u_pm_edit')) ? "$url&mode=compose&action=edit&f=$folder_id&p=" . $message_row['msg_id'] : '', + 'U_POST_REPLY_PM' => ($auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&mode=compose&action=reply&f=$folder_id&p=" . $message_row['msg_id'] : '', + 'U_POST_REPLY_ALL' => ($auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&mode=compose&action=reply&f=$folder_id&reply_to_all=1&p=" . $message_row['msg_id'] : '', + 'U_PREVIOUS_PM' => "$url&f=$folder_id&p=" . $message_row['msg_id'] . "&view=previous", + 'U_NEXT_PM' => "$url&f=$folder_id&p=" . $message_row['msg_id'] . "&view=next", + + 'U_PM_ACTION' => $url . '&mode=compose&f=' . $folder_id . '&p=' . $message_row['msg_id'], + + 'S_HAS_ATTACHMENTS' => (sizeof($attachments)) ? true : false, + 'S_DISPLAY_NOTICE' => $display_notice && $message_row['message_attachment'], + 'S_AUTHOR_DELETED' => ($author_id == ANONYMOUS) ? true : false, + 'S_SPECIAL_FOLDER' => in_array($folder_id, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX)), + 'S_PM_RECIPIENTS' => $num_recipients, + + 'U_PRINT_PM' => ($config['print_pm'] && $auth->acl_get('u_pm_printpm')) ? "$url&f=$folder_id&p=" . $message_row['msg_id'] . "&view=print" : '', + 'U_FORWARD_PM' => ($config['forward_pm'] && $auth->acl_get('u_sendpm') && $auth->acl_get('u_pm_forward')) ? "$url&mode=compose&action=forward&f=$folder_id&p=" . $message_row['msg_id'] : '') + ); + + // Display not already displayed Attachments for this post, we already parsed them. ;) + if (isset($attachments) && sizeof($attachments)) + { + foreach ($attachments as $attachment) + { + $template->assign_block_vars('attachment', array( + 'DISPLAY_ATTACHMENT' => $attachment) + ); + } + } + + if (!isset($_REQUEST['view']) || $_REQUEST['view'] != 'print') + { + // Message History + if (message_history($msg_id, $user->data['user_id'], $message_row, $folder)) + { + $template->assign_var('S_DISPLAY_HISTORY', true); + } + } +} + +/** +* Get user information (only for message display) +*/ +function get_user_information($user_id, $user_row) +{ + global $db, $auth, $user, $cache; + global $phpbb_root_path, $phpEx, $config; + + if (!$user_id) + { + return array(); + } + + if (empty($user_row)) + { + $sql = 'SELECT * + FROM ' . USERS_TABLE . ' + WHERE user_id = ' . (int) $user_id; + $result = $db->sql_query($sql); + $user_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + } + + // Some standard values + $user_row['online'] = false; + $user_row['rank_title'] = $user_row['rank_image'] = $user_row['rank_image_src'] = $user_row['email'] = ''; + + // Generate online information for user + if ($config['load_onlinetrack']) + { + $sql = 'SELECT session_user_id, MAX(session_time) as online_time, MIN(session_viewonline) AS viewonline + FROM ' . SESSIONS_TABLE . " + WHERE session_user_id = $user_id + GROUP BY session_user_id"; + $result = $db->sql_query_limit($sql, 1); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $update_time = $config['load_online_time'] * 60; + if ($row) + { + $user_row['online'] = (time() - $update_time < $row['online_time'] && ($row['viewonline'] || $auth->acl_get('u_viewonline'))) ? true : false; + } + } + + if (!function_exists('get_user_avatar')) + { + include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + } + + $user_row['avatar'] = ($user->optionget('viewavatars')) ? get_user_avatar($user_row['user_avatar'], $user_row['user_avatar_type'], $user_row['user_avatar_width'], $user_row['user_avatar_height']) : ''; + + get_user_rank($user_row['user_rank'], $user_row['user_posts'], $user_row['rank_title'], $user_row['rank_image'], $user_row['rank_image_src']); + + if (!empty($user_row['user_allow_viewemail']) || $auth->acl_get('a_email')) + { + $user_row['email'] = ($config['board_email_form'] && $config['email_enable']) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=email&u=$user_id") : ((($config['board_hide_emails'] && !$auth->acl_get('a_email')) || empty($user_row['user_email'])) ? '' : 'mailto:' . $user_row['user_email']); + } + + return $user_row; +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/ucp_prefs.php b/phpBB/includes/ucp/ucp_prefs.php new file mode 100644 index 0000000000..cc8565e69d --- /dev/null +++ b/phpBB/includes/ucp/ucp_prefs.php @@ -0,0 +1,357 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ucp_prefs +* Changing user preferences +* @package ucp +*/ +class ucp_prefs +{ + var $u_action; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx; + + $submit = (isset($_POST['submit'])) ? true : false; + $error = $data = array(); + $s_hidden_fields = ''; + + switch ($mode) + { + case 'personal': + add_form_key('ucp_prefs_personal'); + $data = array( + 'notifymethod' => request_var('notifymethod', $user->data['user_notify_type']), + 'dateformat' => request_var('dateformat', $user->data['user_dateformat'], true), + 'lang' => basename(request_var('lang', $user->data['user_lang'])), + 'style' => request_var('style', (int) $user->data['user_style']), + 'tz' => request_var('tz', (float) $user->data['user_timezone']), + + 'dst' => request_var('dst', (bool) $user->data['user_dst']), + 'viewemail' => request_var('viewemail', (bool) $user->data['user_allow_viewemail']), + 'massemail' => request_var('massemail', (bool) $user->data['user_allow_massemail']), + 'hideonline' => request_var('hideonline', (bool) !$user->data['user_allow_viewonline']), + 'notifypm' => request_var('notifypm', (bool) $user->data['user_notify_pm']), + 'popuppm' => request_var('popuppm', (bool) $user->optionget('popuppm')), + 'allowpm' => request_var('allowpm', (bool) $user->data['user_allow_pm']), + ); + + if ($data['notifymethod'] == NOTIFY_IM && (!$config['jab_enable'] || !$user->data['user_jabber'] || !@extension_loaded('xml'))) + { + // Jabber isnt enabled, or no jabber field filled in. Update the users table to be sure its correct. + $data['notifymethod'] = NOTIFY_BOTH; + } + + if ($submit) + { + $data['style'] = ($config['override_user_style']) ? $config['default_style'] : $data['style']; + + $error = validate_data($data, array( + 'dateformat' => array('string', false, 1, 30), + 'lang' => array('match', false, '#^[a-z0-9_\-]{2,}$#i'), + 'tz' => array('num', false, -14, 14), + )); + + if (!check_form_key('ucp_prefs_personal')) + { + $error[] = 'FORM_INVALID'; + } + + if (!sizeof($error)) + { + $user->optionset('popuppm', $data['popuppm']); + + $sql_ary = array( + 'user_allow_pm' => $data['allowpm'], + 'user_allow_viewemail' => $data['viewemail'], + 'user_allow_massemail' => $data['massemail'], + 'user_allow_viewonline' => ($auth->acl_get('u_hideonline')) ? !$data['hideonline'] : $user->data['user_allow_viewonline'], + 'user_notify_type' => $data['notifymethod'], + 'user_notify_pm' => $data['notifypm'], + 'user_options' => $user->data['user_options'], + + 'user_dst' => $data['dst'], + 'user_dateformat' => $data['dateformat'], + 'user_lang' => $data['lang'], + 'user_timezone' => $data['tz'], + 'user_style' => $data['style'], + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + + meta_refresh(3, $this->u_action); + $message = $user->lang['PREFERENCES_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + trigger_error($message); + } + + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + } + + $dateformat_options = ''; + + foreach ($user->lang['dateformats'] as $format => $null) + { + $dateformat_options .= '<option value="' . $format . '"' . (($format == $data['dateformat']) ? ' selected="selected"' : '') . '>'; + $dateformat_options .= $user->format_date(time(), $format, false) . ((strpos($format, '|') !== false) ? $user->lang['VARIANT_DATE_SEPARATOR'] . $user->format_date(time(), $format, true) : ''); + $dateformat_options .= '</option>'; + } + + $s_custom = false; + + $dateformat_options .= '<option value="custom"'; + if (!isset($user->lang['dateformats'][$data['dateformat']])) + { + $dateformat_options .= ' selected="selected"'; + $s_custom = true; + } + $dateformat_options .= '>' . $user->lang['CUSTOM_DATEFORMAT'] . '</option>'; + + $template->assign_vars(array( + 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + + 'S_NOTIFY_EMAIL' => ($data['notifymethod'] == NOTIFY_EMAIL) ? true : false, + 'S_NOTIFY_IM' => ($data['notifymethod'] == NOTIFY_IM) ? true : false, + 'S_NOTIFY_BOTH' => ($data['notifymethod'] == NOTIFY_BOTH) ? true : false, + 'S_VIEW_EMAIL' => $data['viewemail'], + 'S_MASS_EMAIL' => $data['massemail'], + 'S_ALLOW_PM' => $data['allowpm'], + 'S_HIDE_ONLINE' => $data['hideonline'], + 'S_NOTIFY_PM' => $data['notifypm'], + 'S_POPUP_PM' => $data['popuppm'], + 'S_DST' => $data['dst'], + + 'DATE_FORMAT' => $data['dateformat'], + 'A_DATE_FORMAT' => addslashes($data['dateformat']), + 'S_DATEFORMAT_OPTIONS' => $dateformat_options, + 'S_CUSTOM_DATEFORMAT' => $s_custom, + 'DEFAULT_DATEFORMAT' => $config['default_dateformat'], + 'A_DEFAULT_DATEFORMAT' => addslashes($config['default_dateformat']), + + 'S_LANG_OPTIONS' => language_select($data['lang']), + 'S_STYLE_OPTIONS' => ($config['override_user_style']) ? '' : style_select($data['style']), + 'S_TZ_OPTIONS' => tz_select($data['tz'], true), + 'S_CAN_HIDE_ONLINE' => ($auth->acl_get('u_hideonline')) ? true : false, + 'S_SELECT_NOTIFY' => ($config['jab_enable'] && $user->data['user_jabber'] && @extension_loaded('xml')) ? true : false) + ); + + break; + + case 'view': + + add_form_key('ucp_prefs_view'); + + $data = array( + 'topic_sk' => request_var('topic_sk', (!empty($user->data['user_topic_sortby_type'])) ? $user->data['user_topic_sortby_type'] : 't'), + 'topic_sd' => request_var('topic_sd', (!empty($user->data['user_topic_sortby_dir'])) ? $user->data['user_topic_sortby_dir'] : 'd'), + 'topic_st' => request_var('topic_st', (!empty($user->data['user_topic_show_days'])) ? $user->data['user_topic_show_days'] : 0), + + 'post_sk' => request_var('post_sk', (!empty($user->data['user_post_sortby_type'])) ? $user->data['user_post_sortby_type'] : 't'), + 'post_sd' => request_var('post_sd', (!empty($user->data['user_post_sortby_dir'])) ? $user->data['user_post_sortby_dir'] : 'a'), + 'post_st' => request_var('post_st', (!empty($user->data['user_post_show_days'])) ? $user->data['user_post_show_days'] : 0), + + 'images' => request_var('images', (bool) $user->optionget('viewimg')), + 'flash' => request_var('flash', (bool) $user->optionget('viewflash')), + 'smilies' => request_var('smilies', (bool) $user->optionget('viewsmilies')), + 'sigs' => request_var('sigs', (bool) $user->optionget('viewsigs')), + 'avatars' => request_var('avatars', (bool) $user->optionget('viewavatars')), + 'wordcensor' => request_var('wordcensor', (bool) $user->optionget('viewcensors')), + ); + + if ($submit) + { + $error = validate_data($data, array( + 'topic_sk' => array('string', false, 1, 1), + 'topic_sd' => array('string', false, 1, 1), + 'post_sk' => array('string', false, 1, 1), + 'post_sd' => array('string', false, 1, 1), + )); + + if (!check_form_key('ucp_prefs_view')) + { + $error[] = 'FORM_INVALID'; + } + + if (!sizeof($error)) + { + $user->optionset('viewimg', $data['images']); + $user->optionset('viewflash', $data['flash']); + $user->optionset('viewsmilies', $data['smilies']); + $user->optionset('viewsigs', $data['sigs']); + $user->optionset('viewavatars', $data['avatars']); + + if ($auth->acl_get('u_chgcensors')) + { + $user->optionset('viewcensors', $data['wordcensor']); + } + + $sql_ary = array( + 'user_options' => $user->data['user_options'], + 'user_topic_sortby_type' => $data['topic_sk'], + 'user_post_sortby_type' => $data['post_sk'], + 'user_topic_sortby_dir' => $data['topic_sd'], + 'user_post_sortby_dir' => $data['post_sd'], + + 'user_topic_show_days' => $data['topic_st'], + 'user_post_show_days' => $data['post_st'], + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + + meta_refresh(3, $this->u_action); + $message = $user->lang['PREFERENCES_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + trigger_error($message); + } + + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + } + + $sort_dir_text = array('a' => $user->lang['ASCENDING'], 'd' => $user->lang['DESCENDING']); + + // Topic ordering options + $limit_topic_days = array(0 => $user->lang['ALL_TOPICS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + + $sort_by_topic_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 'r' => $user->lang['REPLIES'], 's' => $user->lang['SUBJECT'], 'v' => $user->lang['VIEWS']); + $sort_by_topic_sql = array('a' => 't.topic_first_poster_name', 't' => 't.topic_last_post_time', 'r' => 't.topic_replies', 's' => 't.topic_title', 'v' => 't.topic_views'); + + // Post ordering options + $limit_post_days = array(0 => $user->lang['ALL_POSTS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + + $sort_by_post_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 's' => $user->lang['SUBJECT']); + $sort_by_post_sql = array('a' => 'u.username_clean', 't' => 'p.post_id', 's' => 'p.post_subject'); + + $_options = array('topic', 'post'); + foreach ($_options as $sort_option) + { + ${'s_limit_' . $sort_option . '_days'} = '<select name="' . $sort_option . '_st">'; + foreach (${'limit_' . $sort_option . '_days'} as $day => $text) + { + $selected = ($data[$sort_option . '_st'] == $day) ? ' selected="selected"' : ''; + ${'s_limit_' . $sort_option . '_days'} .= '<option value="' . $day . '"' . $selected . '>' . $text . '</option>'; + } + ${'s_limit_' . $sort_option . '_days'} .= '</select>'; + + ${'s_sort_' . $sort_option . '_key'} = '<select name="' . $sort_option . '_sk">'; + foreach (${'sort_by_' . $sort_option . '_text'} as $key => $text) + { + $selected = ($data[$sort_option . '_sk'] == $key) ? ' selected="selected"' : ''; + ${'s_sort_' . $sort_option . '_key'} .= '<option value="' . $key . '"' . $selected . '>' . $text . '</option>'; + } + ${'s_sort_' . $sort_option . '_key'} .= '</select>'; + + ${'s_sort_' . $sort_option . '_dir'} = '<select name="' . $sort_option . '_sd">'; + foreach ($sort_dir_text as $key => $value) + { + $selected = ($data[$sort_option . '_sd'] == $key) ? ' selected="selected"' : ''; + ${'s_sort_' . $sort_option . '_dir'} .= '<option value="' . $key . '"' . $selected . '>' . $value . '</option>'; + } + ${'s_sort_' . $sort_option . '_dir'} .= '</select>'; + } + + $template->assign_vars(array( + 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + + 'S_IMAGES' => $data['images'], + 'S_FLASH' => $data['flash'], + 'S_SMILIES' => $data['smilies'], + 'S_SIGS' => $data['sigs'], + 'S_AVATARS' => $data['avatars'], + 'S_DISABLE_CENSORS' => $data['wordcensor'], + + 'S_CHANGE_CENSORS' => ($auth->acl_get('u_chgcensors') && $config['allow_nocensors']) ? true : false, + + 'S_TOPIC_SORT_DAYS' => $s_limit_topic_days, + 'S_TOPIC_SORT_KEY' => $s_sort_topic_key, + 'S_TOPIC_SORT_DIR' => $s_sort_topic_dir, + 'S_POST_SORT_DAYS' => $s_limit_post_days, + 'S_POST_SORT_KEY' => $s_sort_post_key, + 'S_POST_SORT_DIR' => $s_sort_post_dir) + ); + + break; + + case 'post': + + $data = array( + 'bbcode' => request_var('bbcode', $user->optionget('bbcode')), + 'smilies' => request_var('smilies', $user->optionget('smilies')), + 'sig' => request_var('sig', $user->optionget('attachsig')), + 'notify' => request_var('notify', (bool) $user->data['user_notify']), + ); + add_form_key('ucp_prefs_post'); + + if ($submit) + { + if (check_form_key('ucp_prefs_post')) + { + $user->optionset('bbcode', $data['bbcode']); + $user->optionset('smilies', $data['smilies']); + $user->optionset('attachsig', $data['sig']); + + $sql_ary = array( + 'user_options' => $user->data['user_options'], + 'user_notify' => $data['notify'], + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + + $msg = $user->lang['PREFERENCES_UPDATED']; + } + else + { + $msg = $user->lang['FORM_INVALID']; + } + meta_refresh(3, $this->u_action); + $message = $msg . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + trigger_error($message); + } + + $template->assign_vars(array( + 'S_BBCODE' => $data['bbcode'], + 'S_SMILIES' => $data['smilies'], + 'S_SIG' => $data['sig'], + 'S_NOTIFY' => $data['notify']) + ); + break; + } + + $template->assign_vars(array( + 'L_TITLE' => $user->lang['UCP_PREFS_' . strtoupper($mode)], + + 'S_HIDDEN_FIELDS' => $s_hidden_fields, + 'S_UCP_ACTION' => $this->u_action) + ); + + $this->tpl_name = 'ucp_prefs_' . $mode; + $this->page_title = 'UCP_PREFS_' . strtoupper($mode); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php new file mode 100644 index 0000000000..e24acd89fc --- /dev/null +++ b/phpBB/includes/ucp/ucp_profile.php @@ -0,0 +1,649 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ucp_profile +* Changing profile settings +* +* @todo what about pertaining user_sig_options? +* @package ucp +*/ +class ucp_profile +{ + var $u_action; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx; + + $user->add_lang('posting'); + + $preview = (!empty($_POST['preview'])) ? true : false; + $submit = (!empty($_POST['submit'])) ? true : false; + $delete = (!empty($_POST['delete'])) ? true : false; + $error = $data = array(); + $s_hidden_fields = ''; + + switch ($mode) + { + case 'reg_details': + + $data = array( + 'username' => utf8_normalize_nfc(request_var('username', $user->data['username'], true)), + 'email' => strtolower(request_var('email', $user->data['user_email'])), + 'email_confirm' => strtolower(request_var('email_confirm', '')), + 'new_password' => request_var('new_password', '', true), + 'cur_password' => request_var('cur_password', '', true), + 'password_confirm' => request_var('password_confirm', '', true), + ); + + add_form_key('ucp_reg_details'); + + if ($submit) + { + // Do not check cur_password, it is the old one. + $check_ary = array( + 'new_password' => array( + array('string', true, $config['min_pass_chars'], $config['max_pass_chars']), + array('password')), + 'password_confirm' => array('string', true, $config['min_pass_chars'], $config['max_pass_chars']), + 'email' => array( + array('string', false, 6, 60), + array('email')), + 'email_confirm' => array('string', true, 6, 60), + ); + + if ($auth->acl_get('u_chgname') && $config['allow_namechange']) + { + $check_ary['username'] = array( + array('string', false, $config['min_name_chars'], $config['max_name_chars']), + array('username'), + ); + } + + $error = validate_data($data, $check_ary); + + if ($auth->acl_get('u_chgpasswd') && $data['new_password'] && $data['password_confirm'] != $data['new_password']) + { + $error[] = 'NEW_PASSWORD_ERROR'; + } + + if (($data['new_password'] || ($auth->acl_get('u_chgemail') && $data['email'] != $user->data['user_email']) || ($data['username'] != $user->data['username'] && $auth->acl_get('u_chgname') && $config['allow_namechange'])) && !phpbb_check_hash($data['cur_password'], $user->data['user_password'])) + { + $error[] = 'CUR_PASSWORD_ERROR'; + } + + // Only check the new password against the previous password if there have been no errors + if (!sizeof($error) && $auth->acl_get('u_chgpasswd') && $data['new_password'] && phpbb_check_hash($data['new_password'], $user->data['user_password'])) + { + $error[] = 'SAME_PASSWORD_ERROR'; + } + + if ($auth->acl_get('u_chgemail') && $data['email'] != $user->data['user_email'] && $data['email_confirm'] != $data['email']) + { + $error[] = 'NEW_EMAIL_ERROR'; + } + + if (!check_form_key('ucp_reg_details')) + { + $error[] = 'FORM_INVALID'; + } + + if (!sizeof($error)) + { + $sql_ary = array( + 'username' => ($auth->acl_get('u_chgname') && $config['allow_namechange']) ? $data['username'] : $user->data['username'], + 'username_clean' => ($auth->acl_get('u_chgname') && $config['allow_namechange']) ? utf8_clean_string($data['username']) : $user->data['username_clean'], + 'user_email' => ($auth->acl_get('u_chgemail')) ? $data['email'] : $user->data['user_email'], + 'user_email_hash' => ($auth->acl_get('u_chgemail')) ? phpbb_email_hash($data['email']) : $user->data['user_email_hash'], + 'user_password' => ($auth->acl_get('u_chgpasswd') && $data['new_password']) ? phpbb_hash($data['new_password']) : $user->data['user_password'], + 'user_passchg' => ($auth->acl_get('u_chgpasswd') && $data['new_password']) ? time() : 0, + ); + + if ($auth->acl_get('u_chgname') && $config['allow_namechange'] && $data['username'] != $user->data['username']) + { + add_log('user', $user->data['user_id'], 'LOG_USER_UPDATE_NAME', $user->data['username'], $data['username']); + } + + if ($auth->acl_get('u_chgpasswd') && $data['new_password'] && !phpbb_check_hash($data['new_password'], $user->data['user_password'])) + { + $user->reset_login_keys(); + add_log('user', $user->data['user_id'], 'LOG_USER_NEW_PASSWORD', $data['username']); + } + + if ($auth->acl_get('u_chgemail') && $data['email'] != $user->data['user_email']) + { + add_log('user', $user->data['user_id'], 'LOG_USER_UPDATE_EMAIL', $data['username'], $user->data['user_email'], $data['email']); + } + + $message = 'PROFILE_UPDATED'; + + if ($config['email_enable'] && $data['email'] != $user->data['user_email'] && $user->data['user_type'] != USER_FOUNDER && ($config['require_activation'] == USER_ACTIVATION_SELF || $config['require_activation'] == USER_ACTIVATION_ADMIN)) + { + $message = ($config['require_activation'] == USER_ACTIVATION_SELF) ? 'ACCOUNT_EMAIL_CHANGED' : 'ACCOUNT_EMAIL_CHANGED_ADMIN'; + + include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + + $server_url = generate_board_url(); + + $user_actkey = gen_rand_string(10); + $key_len = 54 - (strlen($server_url)); + $key_len = ($key_len > 6) ? $key_len : 6; + $user_actkey = substr($user_actkey, 0, $key_len); + + $messenger = new messenger(false); + + $template_file = ($config['require_activation'] == USER_ACTIVATION_ADMIN) ? 'user_activate_inactive' : 'user_activate'; + $messenger->template($template_file, $user->data['user_lang']); + + $messenger->to($data['email'], $data['username']); + + $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); + $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); + $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); + $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($data['username']), + 'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u={$user->data['user_id']}&k=$user_actkey") + ); + + $messenger->send(NOTIFY_EMAIL); + + if ($config['require_activation'] == USER_ACTIVATION_ADMIN) + { + // Grab an array of user_id's with a_user permissions ... these users can activate a user + $admin_ary = $auth->acl_get_list(false, 'a_user', false); + $admin_ary = (!empty($admin_ary[0]['a_user'])) ? $admin_ary[0]['a_user'] : array(); + + // Also include founders + $where_sql = ' WHERE user_type = ' . USER_FOUNDER; + + if (sizeof($admin_ary)) + { + $where_sql .= ' OR ' . $db->sql_in_set('user_id', $admin_ary); + } + + $sql = 'SELECT user_id, username, user_email, user_lang, user_jabber, user_notify_type + FROM ' . USERS_TABLE . ' ' . + $where_sql; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $messenger->template('admin_activate', $row['user_lang']); + $messenger->to($row['user_email'], $row['username']); + $messenger->im($row['user_jabber'], $row['username']); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($data['username']), + 'U_USER_DETAILS' => "$server_url/memberlist.$phpEx?mode=viewprofile&u={$user->data['user_id']}", + 'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u={$user->data['user_id']}&k=$user_actkey") + ); + + $messenger->send($row['user_notify_type']); + } + $db->sql_freeresult($result); + } + + user_active_flip('deactivate', $user->data['user_id'], INACTIVE_PROFILE); + + // Because we want the profile to be reactivated we set user_newpasswd to empty (else the reactivation will fail) + $sql_ary['user_actkey'] = $user_actkey; + $sql_ary['user_newpasswd'] = ''; + } + + if (sizeof($sql_ary)) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + } + + // Need to update config, forum, topic, posting, messages, etc. + if ($data['username'] != $user->data['username'] && $auth->acl_get('u_chgname') && $config['allow_namechange']) + { + user_update_name($user->data['username'], $data['username']); + } + + // Now, we can remove the user completely (kill the session) - NOT BEFORE!!! + if (!empty($sql_ary['user_actkey'])) + { + meta_refresh(5, append_sid($phpbb_root_path . 'index.' . $phpEx)); + $message = $user->lang[$message] . '<br /><br />' . sprintf($user->lang['RETURN_INDEX'], '<a href="' . append_sid($phpbb_root_path . 'index.' . $phpEx) . '">', '</a>'); + + // Because the user gets deactivated we log him out too, killing his session + $user->session_kill(); + } + else + { + meta_refresh(3, $this->u_action); + $message = $user->lang[$message] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + } + + trigger_error($message); + } + + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + } + + $template->assign_vars(array( + 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + + 'USERNAME' => $data['username'], + 'EMAIL' => $data['email'], + 'PASSWORD_CONFIRM' => $data['password_confirm'], + 'NEW_PASSWORD' => $data['new_password'], + 'CUR_PASSWORD' => '', + + 'L_USERNAME_EXPLAIN' => sprintf($user->lang[$config['allow_name_chars'] . '_EXPLAIN'], $config['min_name_chars'], $config['max_name_chars']), + 'L_CHANGE_PASSWORD_EXPLAIN' => sprintf($user->lang[$config['pass_complex'] . '_EXPLAIN'], $config['min_pass_chars'], $config['max_pass_chars']), + + 'S_FORCE_PASSWORD' => ($auth->acl_get('u_chgpasswd') && $config['chg_passforce'] && $user->data['user_passchg'] < time() - ($config['chg_passforce'] * 86400)) ? true : false, + 'S_CHANGE_USERNAME' => ($config['allow_namechange'] && $auth->acl_get('u_chgname')) ? true : false, + 'S_CHANGE_EMAIL' => ($auth->acl_get('u_chgemail')) ? true : false, + 'S_CHANGE_PASSWORD' => ($auth->acl_get('u_chgpasswd')) ? true : false) + ); + break; + + case 'profile_info': + + include($phpbb_root_path . 'includes/functions_profile_fields.' . $phpEx); + + $cp = new custom_profile(); + + $cp_data = $cp_error = array(); + + $data = array( + 'icq' => request_var('icq', $user->data['user_icq']), + 'aim' => request_var('aim', $user->data['user_aim']), + 'msn' => request_var('msn', $user->data['user_msnm']), + 'yim' => request_var('yim', $user->data['user_yim']), + 'jabber' => utf8_normalize_nfc(request_var('jabber', $user->data['user_jabber'], true)), + 'website' => request_var('website', $user->data['user_website']), + 'location' => utf8_normalize_nfc(request_var('location', $user->data['user_from'], true)), + 'occupation' => utf8_normalize_nfc(request_var('occupation', $user->data['user_occ'], true)), + 'interests' => utf8_normalize_nfc(request_var('interests', $user->data['user_interests'], true)), + ); + + if ($config['allow_birthdays']) + { + $data['bday_day'] = $data['bday_month'] = $data['bday_year'] = 0; + + if ($user->data['user_birthday']) + { + list($data['bday_day'], $data['bday_month'], $data['bday_year']) = explode('-', $user->data['user_birthday']); + } + + $data['bday_day'] = request_var('bday_day', $data['bday_day']); + $data['bday_month'] = request_var('bday_month', $data['bday_month']); + $data['bday_year'] = request_var('bday_year', $data['bday_year']); + $data['user_birthday'] = sprintf('%2d-%2d-%4d', $data['bday_day'], $data['bday_month'], $data['bday_year']); + } + + add_form_key('ucp_profile_info'); + + if ($submit) + { + $validate_array = array( + 'icq' => array( + array('string', true, 3, 15), + array('match', true, '#^[0-9]+$#i')), + 'aim' => array('string', true, 3, 255), + 'msn' => array('string', true, 5, 255), + 'jabber' => array( + array('string', true, 5, 255), + array('jabber')), + 'yim' => array('string', true, 5, 255), + 'website' => array( + array('string', true, 12, 255), + array('match', true, '#^http[s]?://(.*?\.)*?[a-z0-9\-]+\.[a-z]{2,4}#i')), + 'location' => array('string', true, 2, 100), + 'occupation' => array('string', true, 2, 500), + 'interests' => array('string', true, 2, 500), + ); + + if ($config['allow_birthdays']) + { + $validate_array = array_merge($validate_array, array( + 'bday_day' => array('num', true, 1, 31), + 'bday_month' => array('num', true, 1, 12), + 'bday_year' => array('num', true, 1901, gmdate('Y', time()) + 50), + 'user_birthday' => array('date', true), + )); + } + + $error = validate_data($data, $validate_array); + + // validate custom profile fields + $cp->submit_cp_field('profile', $user->get_iso_lang_id(), $cp_data, $cp_error); + + if (sizeof($cp_error)) + { + $error = array_merge($error, $cp_error); + } + + if (!check_form_key('ucp_profile_info')) + { + $error[] = 'FORM_INVALID'; + } + + if (!sizeof($error)) + { + $data['notify'] = $user->data['user_notify_type']; + + if ($data['notify'] == NOTIFY_IM && (!$config['jab_enable'] || !$data['jabber'] || !@extension_loaded('xml'))) + { + // User has not filled in a jabber address (Or one of the modules is disabled or jabber is disabled) + // Disable notify by Jabber now for this user. + $data['notify'] = NOTIFY_EMAIL; + } + + $sql_ary = array( + 'user_icq' => $data['icq'], + 'user_aim' => $data['aim'], + 'user_msnm' => $data['msn'], + 'user_yim' => $data['yim'], + 'user_jabber' => $data['jabber'], + 'user_website' => $data['website'], + 'user_from' => $data['location'], + 'user_occ' => $data['occupation'], + 'user_interests'=> $data['interests'], + 'user_notify_type' => $data['notify'], + ); + + if ($config['allow_birthdays']) + { + $sql_ary['user_birthday'] = $data['user_birthday']; + } + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + + // Update Custom Fields + $cp->update_profile_field_data($user->data['user_id'], $cp_data); + + meta_refresh(3, $this->u_action); + $message = $user->lang['PROFILE_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + trigger_error($message); + } + + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + } + + if ($config['allow_birthdays']) + { + $s_birthday_day_options = '<option value="0"' . ((!$data['bday_day']) ? ' selected="selected"' : '') . '>--</option>'; + for ($i = 1; $i < 32; $i++) + { + $selected = ($i == $data['bday_day']) ? ' selected="selected"' : ''; + $s_birthday_day_options .= "<option value=\"$i\"$selected>$i</option>"; + } + + $s_birthday_month_options = '<option value="0"' . ((!$data['bday_month']) ? ' selected="selected"' : '') . '>--</option>'; + for ($i = 1; $i < 13; $i++) + { + $selected = ($i == $data['bday_month']) ? ' selected="selected"' : ''; + $s_birthday_month_options .= "<option value=\"$i\"$selected>$i</option>"; + } + $s_birthday_year_options = ''; + + $now = getdate(); + $s_birthday_year_options = '<option value="0"' . ((!$data['bday_year']) ? ' selected="selected"' : '') . '>--</option>'; + for ($i = $now['year'] - 100; $i <= $now['year']; $i++) + { + $selected = ($i == $data['bday_year']) ? ' selected="selected"' : ''; + $s_birthday_year_options .= "<option value=\"$i\"$selected>$i</option>"; + } + unset($now); + + $template->assign_vars(array( + 'S_BIRTHDAY_DAY_OPTIONS' => $s_birthday_day_options, + 'S_BIRTHDAY_MONTH_OPTIONS' => $s_birthday_month_options, + 'S_BIRTHDAY_YEAR_OPTIONS' => $s_birthday_year_options, + 'S_BIRTHDAYS_ENABLED' => true, + )); + } + + $template->assign_vars(array( + 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + + 'ICQ' => $data['icq'], + 'YIM' => $data['yim'], + 'AIM' => $data['aim'], + 'MSN' => $data['msn'], + 'JABBER' => $data['jabber'], + 'WEBSITE' => $data['website'], + 'LOCATION' => $data['location'], + 'OCCUPATION'=> $data['occupation'], + 'INTERESTS' => $data['interests'], + )); + + // Get additional profile fields and assign them to the template block var 'profile_fields' + $user->get_profile_fields($user->data['user_id']); + + $cp->generate_profile_fields('profile', $user->get_iso_lang_id()); + + break; + + case 'signature': + + if (!$auth->acl_get('u_sig')) + { + trigger_error('NO_AUTH_SIGNATURE'); + } + + include($phpbb_root_path . 'includes/functions_posting.' . $phpEx); + include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + + $enable_bbcode = ($config['allow_sig_bbcode']) ? (bool) $user->optionget('sig_bbcode') : false; + $enable_smilies = ($config['allow_sig_smilies']) ? (bool) $user->optionget('sig_smilies') : false; + $enable_urls = ($config['allow_sig_links']) ? (bool) $user->optionget('sig_links') : false; + + $signature = utf8_normalize_nfc(request_var('signature', (string) $user->data['user_sig'], true)); + + add_form_key('ucp_sig'); + + if ($submit || $preview) + { + include($phpbb_root_path . 'includes/message_parser.' . $phpEx); + + $enable_bbcode = ($config['allow_sig_bbcode']) ? ((request_var('disable_bbcode', false)) ? false : true) : false; + $enable_smilies = ($config['allow_sig_smilies']) ? ((request_var('disable_smilies', false)) ? false : true) : false; + $enable_urls = ($config['allow_sig_links']) ? ((request_var('disable_magic_url', false)) ? false : true) : false; + + if (!sizeof($error)) + { + $message_parser = new parse_message($signature); + + // Allowing Quote BBCode + $message_parser->parse($enable_bbcode, $enable_urls, $enable_smilies, $config['allow_sig_img'], $config['allow_sig_flash'], true, $config['allow_sig_links'], true, 'sig'); + + if (sizeof($message_parser->warn_msg)) + { + $error[] = implode('<br />', $message_parser->warn_msg); + } + + if (!check_form_key('ucp_sig')) + { + $error[] = 'FORM_INVALID'; + } + + if (!sizeof($error) && $submit) + { + $user->optionset('sig_bbcode', $enable_bbcode); + $user->optionset('sig_smilies', $enable_smilies); + $user->optionset('sig_links', $enable_urls); + + $sql_ary = array( + 'user_sig' => (string) $message_parser->message, + 'user_options' => $user->data['user_options'], + 'user_sig_bbcode_uid' => (string) $message_parser->bbcode_uid, + 'user_sig_bbcode_bitfield' => $message_parser->bbcode_bitfield + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + + $message = $user->lang['PROFILE_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + trigger_error($message); + } + } + + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + } + + $signature_preview = ''; + if ($preview) + { + // Now parse it for displaying + $signature_preview = $message_parser->format_display($enable_bbcode, $enable_urls, $enable_smilies, false); + unset($message_parser); + } + + decode_message($signature, $user->data['user_sig_bbcode_uid']); + + $template->assign_vars(array( + 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + 'SIGNATURE' => $signature, + 'SIGNATURE_PREVIEW' => $signature_preview, + + 'S_BBCODE_CHECKED' => (!$enable_bbcode) ? ' checked="checked"' : '', + 'S_SMILIES_CHECKED' => (!$enable_smilies) ? ' checked="checked"' : '', + 'S_MAGIC_URL_CHECKED' => (!$enable_urls) ? ' checked="checked"' : '', + + 'BBCODE_STATUS' => ($config['allow_sig_bbcode']) ? sprintf($user->lang['BBCODE_IS_ON'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>') : sprintf($user->lang['BBCODE_IS_OFF'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>'), + 'SMILIES_STATUS' => ($config['allow_sig_smilies']) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'], + 'IMG_STATUS' => ($config['allow_sig_img']) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'], + 'FLASH_STATUS' => ($config['allow_sig_flash']) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], + 'URL_STATUS' => ($config['allow_sig_links']) ? $user->lang['URL_IS_ON'] : $user->lang['URL_IS_OFF'], + 'MAX_FONT_SIZE' => (int) $config['max_sig_font_size'], + + 'L_SIGNATURE_EXPLAIN' => sprintf($user->lang['SIGNATURE_EXPLAIN'], $config['max_sig_chars']), + + 'S_BBCODE_ALLOWED' => $config['allow_sig_bbcode'], + 'S_SMILIES_ALLOWED' => $config['allow_sig_smilies'], + 'S_BBCODE_IMG' => ($config['allow_sig_img']) ? true : false, + 'S_BBCODE_FLASH' => ($config['allow_sig_flash']) ? true : false, + 'S_LINKS_ALLOWED' => ($config['allow_sig_links']) ? true : false) + ); + + // Build custom bbcodes array + display_custom_bbcodes(); + + break; + + case 'avatar': + + include($phpbb_root_path . 'includes/functions_display.' . $phpEx); + + $display_gallery = request_var('display_gallery', '0'); + $avatar_select = basename(request_var('avatar_select', '')); + $category = basename(request_var('category', '')); + + $can_upload = (file_exists($phpbb_root_path . $config['avatar_path']) && @is_writable($phpbb_root_path . $config['avatar_path']) && $auth->acl_get('u_chgavatar') && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on')) ? true : false; + + add_form_key('ucp_avatar'); + + if ($submit) + { + if (check_form_key('ucp_avatar')) + { + if (avatar_process_user($error)) + { + meta_refresh(3, $this->u_action); + $message = $user->lang['PROFILE_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + trigger_error($message); + } + } + else + { + $error[] = 'FORM_INVALID'; + } + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + } + + if (!$config['allow_avatar'] && $user->data['user_avatar_type']) + { + $error[] = $user->lang['AVATAR_NOT_ALLOWED']; + } + else if ((($user->data['user_avatar_type'] == AVATAR_UPLOAD) && !$config['allow_avatar_upload']) || + (($user->data['user_avatar_type'] == AVATAR_REMOTE) && !$config['allow_avatar_remote']) || + (($user->data['user_avatar_type'] == AVATAR_GALLERY) && !$config['allow_avatar_local'])) + { + $error[] = $user->lang['AVATAR_TYPE_NOT_ALLOWED']; + } + + $template->assign_vars(array( + 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + 'AVATAR' => get_user_avatar($user->data['user_avatar'], $user->data['user_avatar_type'], $user->data['user_avatar_width'], $user->data['user_avatar_height'], 'USER_AVATAR', true), + 'AVATAR_SIZE' => $config['avatar_filesize'], + + 'U_GALLERY' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=profile&mode=avatar&display_gallery=1'), + + 'S_FORM_ENCTYPE' => ($can_upload && ($config['allow_avatar_upload'] || $config['allow_avatar_remote_upload'])) ? ' enctype="multipart/form-data"' : '', + + 'L_AVATAR_EXPLAIN' => sprintf($user->lang['AVATAR_EXPLAIN'], $config['avatar_max_width'], $config['avatar_max_height'], $config['avatar_filesize'] / 1024), + )); + + if ($config['allow_avatar'] && $display_gallery && $auth->acl_get('u_chgavatar') && $config['allow_avatar_local']) + { + avatar_gallery($category, $avatar_select, 4); + } + else if ($config['allow_avatar']) + { + $avatars_enabled = (($can_upload && ($config['allow_avatar_upload'] || $config['allow_avatar_remote_upload'])) || ($auth->acl_get('u_chgavatar') && ($config['allow_avatar_local'] || $config['allow_avatar_remote']))) ? true : false; + + $template->assign_vars(array( + 'AVATAR_WIDTH' => request_var('width', $user->data['user_avatar_width']), + 'AVATAR_HEIGHT' => request_var('height', $user->data['user_avatar_height']), + + 'S_AVATARS_ENABLED' => $avatars_enabled, + 'S_UPLOAD_AVATAR_FILE' => ($can_upload && $config['allow_avatar_upload']) ? true : false, + 'S_UPLOAD_AVATAR_URL' => ($can_upload && $config['allow_avatar_remote_upload']) ? true : false, + 'S_LINK_AVATAR' => ($auth->acl_get('u_chgavatar') && $config['allow_avatar_remote']) ? true : false, + 'S_DISPLAY_GALLERY' => ($auth->acl_get('u_chgavatar') && $config['allow_avatar_local']) ? true : false) + ); + } + + break; + } + + $template->assign_vars(array( + 'L_TITLE' => $user->lang['UCP_PROFILE_' . strtoupper($mode)], + + 'S_HIDDEN_FIELDS' => $s_hidden_fields, + 'S_UCP_ACTION' => $this->u_action) + ); + + // Set desired template + $this->tpl_name = 'ucp_profile_' . $mode; + $this->page_title = 'UCP_PROFILE_' . strtoupper($mode); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php new file mode 100644 index 0000000000..8359c223e0 --- /dev/null +++ b/phpBB/includes/ucp/ucp_register.php @@ -0,0 +1,503 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ucp_register +* Board registration +* @package ucp +*/ +class ucp_register +{ + var $u_action; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx; + + // + if ($config['require_activation'] == USER_ACTIVATION_DISABLE) + { + trigger_error('UCP_REGISTER_DISABLE'); + } + + include($phpbb_root_path . 'includes/functions_profile_fields.' . $phpEx); + + $coppa = (isset($_REQUEST['coppa'])) ? ((!empty($_REQUEST['coppa'])) ? 1 : 0) : false; + $agreed = (!empty($_POST['agreed'])) ? 1 : 0; + $submit = (isset($_POST['submit'])) ? true : false; + $change_lang = request_var('change_lang', ''); + $user_lang = request_var('lang', $user->lang_name); + + if ($agreed) + { + add_form_key('ucp_register'); + } + else + { + add_form_key('ucp_register_terms'); + } + + if ($change_lang || $user_lang != $config['default_lang']) + { + $use_lang = ($change_lang) ? basename($change_lang) : basename($user_lang); + + if (file_exists($user->lang_path . $use_lang . '/')) + { + if ($change_lang) + { + $submit = false; + + // Setting back agreed to let the user view the agreement in his/her language + $agreed = (empty($_GET['change_lang'])) ? 0 : $agreed; + } + + $user->lang_name = $user_lang = $use_lang; + $user->lang = array(); + $user->data['user_lang'] = $user->lang_name; + $user->add_lang(array('common', 'ucp')); + } + else + { + $change_lang = ''; + $user_lang = $user->lang_name; + } + } + + + $cp = new custom_profile(); + + $error = $cp_data = $cp_error = array(); + + if (!$agreed || ($coppa === false && $config['coppa_enable']) || ($coppa && !$config['coppa_enable'])) + { + $add_lang = ($change_lang) ? '&change_lang=' . urlencode($change_lang) : ''; + $add_coppa = ($coppa !== false) ? '&coppa=' . $coppa : ''; + + $s_hidden_fields = array( + 'change_lang' => $change_lang, + ); + + // If we change the language, we want to pass on some more possible parameter. + if ($change_lang) + { + // We do not include the password + $s_hidden_fields = array_merge($s_hidden_fields, array( + 'username' => utf8_normalize_nfc(request_var('username', '', true)), + 'email' => strtolower(request_var('email', '')), + 'email_confirm' => strtolower(request_var('email_confirm', '')), + 'lang' => $user->lang_name, + 'tz' => request_var('tz', (float) $config['board_timezone']), + )); + + } + + // Checking amount of available languages + $sql = 'SELECT lang_id + FROM ' . LANG_TABLE; + $result = $db->sql_query($sql); + + $lang_row = array(); + while ($row = $db->sql_fetchrow($result)) + { + $lang_row[] = $row; + } + $db->sql_freeresult($result); + + if ($coppa === false && $config['coppa_enable']) + { + $now = getdate(); + $coppa_birthday = $user->format_date(mktime($now['hours'] + $user->data['user_dst'], $now['minutes'], $now['seconds'], $now['mon'], $now['mday'] - 1, $now['year'] - 13), $user->lang['DATE_FORMAT']); + unset($now); + + $template->assign_vars(array( + 'S_LANG_OPTIONS' => (sizeof($lang_row) > 1) ? language_select($user_lang) : '', + 'L_COPPA_NO' => sprintf($user->lang['UCP_COPPA_BEFORE'], $coppa_birthday), + 'L_COPPA_YES' => sprintf($user->lang['UCP_COPPA_ON_AFTER'], $coppa_birthday), + + 'U_COPPA_NO' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register&coppa=0' . $add_lang), + 'U_COPPA_YES' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register&coppa=1' . $add_lang), + + 'S_SHOW_COPPA' => true, + 'S_HIDDEN_FIELDS' => build_hidden_fields($s_hidden_fields), + 'S_UCP_ACTION' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register' . $add_lang), + )); + } + else + { + $template->assign_vars(array( + 'S_LANG_OPTIONS' => (sizeof($lang_row) > 1) ? language_select($user_lang) : '', + 'L_TERMS_OF_USE' => sprintf($user->lang['TERMS_OF_USE_CONTENT'], $config['sitename'], generate_board_url()), + + 'S_SHOW_COPPA' => false, + 'S_REGISTRATION' => true, + 'S_HIDDEN_FIELDS' => build_hidden_fields($s_hidden_fields), + 'S_UCP_ACTION' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register' . $add_lang . $add_coppa), + ) + ); + } + unset($lang_row); + + $this->tpl_name = 'ucp_agreement'; + return; + } + + + // The CAPTCHA kicks in here. We can't help that the information gets lost on language change. + if ($config['enable_confirm']) + { + include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); + $captcha =& phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $captcha->init(CONFIRM_REG); + } + + // Try to manually determine the timezone and adjust the dst if the server date/time complies with the default setting +/- 1 + $timezone = date('Z') / 3600; + $is_dst = date('I'); + + if ($config['board_timezone'] == $timezone || $config['board_timezone'] == ($timezone - 1)) + { + $timezone = ($is_dst) ? $timezone - 1 : $timezone; + + if (!isset($user->lang['tz_zones'][(string) $timezone])) + { + $timezone = $config['board_timezone']; + } + } + else + { + $is_dst = $config['board_dst']; + $timezone = $config['board_timezone']; + } + + $data = array( + 'username' => utf8_normalize_nfc(request_var('username', '', true)), + 'new_password' => request_var('new_password', '', true), + 'password_confirm' => request_var('password_confirm', '', true), + 'email' => strtolower(request_var('email', '')), + 'email_confirm' => strtolower(request_var('email_confirm', '')), + 'lang' => basename(request_var('lang', $user->lang_name)), + 'tz' => request_var('tz', (float) $timezone), + ); + + // Check and initialize some variables if needed + if ($submit) + { + $error = validate_data($data, array( + 'username' => array( + array('string', false, $config['min_name_chars'], $config['max_name_chars']), + array('username', '')), + 'new_password' => array( + array('string', false, $config['min_pass_chars'], $config['max_pass_chars']), + array('password')), + 'password_confirm' => array('string', false, $config['min_pass_chars'], $config['max_pass_chars']), + 'email' => array( + array('string', false, 6, 60), + array('email')), + 'email_confirm' => array('string', false, 6, 60), + 'tz' => array('num', false, -14, 14), + 'lang' => array('match', false, '#^[a-z_\-]{2,}$#i'), + )); + + if (!check_form_key('ucp_register')) + { + $error[] = $user->lang['FORM_INVALID']; + } + + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + + if ($config['enable_confirm']) + { + $vc_response = $captcha->validate($data); + if ($vc_response !== false) + { + $error[] = $vc_response; + } + + if ($config['max_reg_attempts'] && $captcha->get_attempt_count() > $config['max_reg_attempts']) + { + $error[] = $user->lang['TOO_MANY_REGISTERS']; + } + } + + // DNSBL check + if ($config['check_dnsbl']) + { + if (($dnsbl = $user->check_dnsbl('register')) !== false) + { + $error[] = sprintf($user->lang['IP_BLACKLISTED'], $user->ip, $dnsbl[1]); + } + } + + // validate custom profile fields + $cp->submit_cp_field('register', $user->get_iso_lang_id(), $cp_data, $error); + + if (!sizeof($error)) + { + if ($data['new_password'] != $data['password_confirm']) + { + $error[] = $user->lang['NEW_PASSWORD_ERROR']; + } + + if ($data['email'] != $data['email_confirm']) + { + $error[] = $user->lang['NEW_EMAIL_ERROR']; + } + } + + if (!sizeof($error)) + { + $server_url = generate_board_url(); + + // Which group by default? + $group_name = ($coppa) ? 'REGISTERED_COPPA' : 'REGISTERED'; + + $sql = 'SELECT group_id + FROM ' . GROUPS_TABLE . " + WHERE group_name = '" . $db->sql_escape($group_name) . "' + AND group_type = " . GROUP_SPECIAL; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error('NO_GROUP'); + } + + $group_id = $row['group_id']; + + if (($coppa || + $config['require_activation'] == USER_ACTIVATION_SELF || + $config['require_activation'] == USER_ACTIVATION_ADMIN) && $config['email_enable']) + { + $user_actkey = gen_rand_string(10); + $key_len = 54 - (strlen($server_url)); + $key_len = ($key_len < 6) ? 6 : $key_len; + $user_actkey = substr($user_actkey, 0, $key_len); + + $user_type = USER_INACTIVE; + $user_inactive_reason = INACTIVE_REGISTER; + $user_inactive_time = time(); + } + else + { + $user_type = USER_NORMAL; + $user_actkey = ''; + $user_inactive_reason = 0; + $user_inactive_time = 0; + } + + $user_row = array( + 'username' => $data['username'], + 'user_password' => phpbb_hash($data['new_password']), + 'user_email' => $data['email'], + 'group_id' => (int) $group_id, + 'user_timezone' => (float) $data['tz'], + 'user_dst' => $is_dst, + 'user_lang' => $data['lang'], + 'user_type' => $user_type, + 'user_actkey' => $user_actkey, + 'user_ip' => $user->ip, + 'user_regdate' => time(), + 'user_inactive_reason' => $user_inactive_reason, + 'user_inactive_time' => $user_inactive_time, + ); + + if ($config['new_member_post_limit']) + { + $user_row['user_new'] = 1; + } + + // Register user... + $user_id = user_add($user_row, $cp_data); + + // This should not happen, because the required variables are listed above... + if ($user_id === false) + { + trigger_error('NO_USER', E_USER_ERROR); + } + + if ($coppa && $config['email_enable']) + { + $message = $user->lang['ACCOUNT_COPPA']; + $email_template = 'coppa_welcome_inactive'; + } + else if ($config['require_activation'] == USER_ACTIVATION_SELF && $config['email_enable']) + { + $message = $user->lang['ACCOUNT_INACTIVE']; + $email_template = 'user_welcome_inactive'; + } + else if ($config['require_activation'] == USER_ACTIVATION_ADMIN && $config['email_enable']) + { + $message = $user->lang['ACCOUNT_INACTIVE_ADMIN']; + $email_template = 'admin_welcome_inactive'; + } + else + { + $message = $user->lang['ACCOUNT_ADDED']; + $email_template = 'user_welcome'; + } + + if ($config['email_enable']) + { + include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + + $messenger = new messenger(false); + + $messenger->template($email_template, $data['lang']); + + $messenger->to($data['email'], $data['username']); + + $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); + $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); + $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); + $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + + $messenger->assign_vars(array( + 'WELCOME_MSG' => htmlspecialchars_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename'])), + 'USERNAME' => htmlspecialchars_decode($data['username']), + 'PASSWORD' => htmlspecialchars_decode($data['new_password']), + 'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u=$user_id&k=$user_actkey") + ); + + if ($coppa) + { + $messenger->assign_vars(array( + 'FAX_INFO' => $config['coppa_fax'], + 'MAIL_INFO' => $config['coppa_mail'], + 'EMAIL_ADDRESS' => $data['email']) + ); + } + + $messenger->send(NOTIFY_EMAIL); + + if ($config['require_activation'] == USER_ACTIVATION_ADMIN) + { + // Grab an array of user_id's with a_user permissions ... these users can activate a user + $admin_ary = $auth->acl_get_list(false, 'a_user', false); + $admin_ary = (!empty($admin_ary[0]['a_user'])) ? $admin_ary[0]['a_user'] : array(); + + // Also include founders + $where_sql = ' WHERE user_type = ' . USER_FOUNDER; + + if (sizeof($admin_ary)) + { + $where_sql .= ' OR ' . $db->sql_in_set('user_id', $admin_ary); + } + + $sql = 'SELECT user_id, username, user_email, user_lang, user_jabber, user_notify_type + FROM ' . USERS_TABLE . ' ' . + $where_sql; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $messenger->template('admin_activate', $row['user_lang']); + $messenger->to($row['user_email'], $row['username']); + $messenger->im($row['user_jabber'], $row['username']); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($data['username']), + 'U_USER_DETAILS' => "$server_url/memberlist.$phpEx?mode=viewprofile&u=$user_id", + 'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u=$user_id&k=$user_actkey") + ); + + $messenger->send($row['user_notify_type']); + } + $db->sql_freeresult($result); + } + } + + $message = $message . '<br /><br />' . sprintf($user->lang['RETURN_INDEX'], '<a href="' . append_sid("{$phpbb_root_path}index.$phpEx") . '">', '</a>'); + trigger_error($message); + } + } + + $s_hidden_fields = array( + 'agreed' => 'true', + 'change_lang' => 0, + ); + + if ($config['coppa_enable']) + { + $s_hidden_fields['coppa'] = $coppa; + } + + if ($config['enable_confirm']) + { + $s_hidden_fields = array_merge($s_hidden_fields, $captcha->get_hidden_fields()); + } + $s_hidden_fields = build_hidden_fields($s_hidden_fields); + $confirm_image = ''; + + // Visual Confirmation - Show images + if ($config['enable_confirm']) + { + $template->assign_vars(array( + 'CAPTCHA_TEMPLATE' => $captcha->get_template(), + )); + } + + // + $l_reg_cond = ''; + switch ($config['require_activation']) + { + case USER_ACTIVATION_SELF: + $l_reg_cond = $user->lang['UCP_EMAIL_ACTIVATE']; + break; + + case USER_ACTIVATION_ADMIN: + $l_reg_cond = $user->lang['UCP_ADMIN_ACTIVATE']; + break; + } + + $template->assign_vars(array( + 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + 'USERNAME' => $data['username'], + 'PASSWORD' => $data['new_password'], + 'PASSWORD_CONFIRM' => $data['password_confirm'], + 'EMAIL' => $data['email'], + 'EMAIL_CONFIRM' => $data['email_confirm'], + + 'L_REG_COND' => $l_reg_cond, + 'L_USERNAME_EXPLAIN' => sprintf($user->lang[$config['allow_name_chars'] . '_EXPLAIN'], $config['min_name_chars'], $config['max_name_chars']), + 'L_PASSWORD_EXPLAIN' => sprintf($user->lang[$config['pass_complex'] . '_EXPLAIN'], $config['min_pass_chars'], $config['max_pass_chars']), + + 'S_LANG_OPTIONS' => language_select($data['lang']), + 'S_TZ_OPTIONS' => tz_select($data['tz']), + 'S_CONFIRM_REFRESH' => ($config['enable_confirm'] && $config['confirm_refresh']) ? true : false, + 'S_REGISTRATION' => true, + 'S_COPPA' => $coppa, + 'S_HIDDEN_FIELDS' => $s_hidden_fields, + 'S_UCP_ACTION' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register'), + )); + + // + $user->profile_fields = array(); + + // Generate profile fields -> Template Block Variable profile_fields + $cp->generate_profile_fields('register', $user->get_iso_lang_id()); + + // + $this->tpl_name = 'ucp_register'; + $this->page_title = 'UCP_REGISTRATION'; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/ucp_remind.php b/phpBB/includes/ucp/ucp_remind.php new file mode 100644 index 0000000000..df6733d038 --- /dev/null +++ b/phpBB/includes/ucp/ucp_remind.php @@ -0,0 +1,125 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ucp_remind +* Sending password reminders +* @package ucp +*/ +class ucp_remind +{ + var $u_action; + + function main($id, $mode) + { + global $config, $phpbb_root_path, $phpEx; + global $db, $user, $auth, $template; + + $username = request_var('username', '', true); + $email = strtolower(request_var('email', '')); + $submit = (isset($_POST['submit'])) ? true : false; + + if ($submit) + { + $sql = 'SELECT user_id, username, user_permissions, user_email, user_jabber, user_notify_type, user_type, user_lang, user_inactive_reason + FROM ' . USERS_TABLE . " + WHERE user_email_hash = '" . $db->sql_escape(phpbb_email_hash($email)) . "' + AND username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'"; + $result = $db->sql_query($sql); + $user_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$user_row) + { + trigger_error('NO_EMAIL_USER'); + } + + if ($user_row['user_type'] == USER_IGNORE) + { + trigger_error('NO_USER'); + } + + if ($user_row['user_type'] == USER_INACTIVE) + { + if ($user_row['user_inactive_reason'] == INACTIVE_MANUAL) + { + trigger_error('ACCOUNT_DEACTIVATED'); + } + else + { + trigger_error('ACCOUNT_NOT_ACTIVATED'); + } + } + + // Check users permissions + $auth2 = new auth(); + $auth2->acl($user_row); + + if (!$auth2->acl_get('u_chgpasswd')) + { + trigger_error('NO_AUTH_PASSWORD_REMINDER'); + } + + $server_url = generate_board_url(); + + $key_len = 54 - strlen($server_url); + $key_len = max(6, $key_len); // we want at least 6 + $key_len = ($config['max_pass_chars']) ? min($key_len, $config['max_pass_chars']) : $key_len; // we want at most $config['max_pass_chars'] + $user_actkey = substr(gen_rand_string(10), 0, $key_len); + $user_password = gen_rand_string(8); + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_newpasswd = '" . $db->sql_escape(phpbb_hash($user_password)) . "', user_actkey = '" . $db->sql_escape($user_actkey) . "' + WHERE user_id = " . $user_row['user_id']; + $db->sql_query($sql); + + include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + + $messenger = new messenger(false); + + $messenger->template('user_activate_passwd', $user_row['user_lang']); + + $messenger->to($user_row['user_email'], $user_row['username']); + $messenger->im($user_row['user_jabber'], $user_row['username']); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($user_row['username']), + 'PASSWORD' => htmlspecialchars_decode($user_password), + 'U_ACTIVATE' => "$server_url/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k=$user_actkey") + ); + + $messenger->send($user_row['user_notify_type']); + + meta_refresh(3, append_sid("{$phpbb_root_path}index.$phpEx")); + + $message = $user->lang['PASSWORD_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_INDEX'], '<a href="' . append_sid("{$phpbb_root_path}index.$phpEx") . '">', '</a>'); + trigger_error($message); + } + + $template->assign_vars(array( + 'USERNAME' => $username, + 'EMAIL' => $email, + 'S_PROFILE_ACTION' => append_sid($phpbb_root_path . 'ucp.' . $phpEx, 'mode=sendpassword')) + ); + + $this->tpl_name = 'ucp_remind'; + $this->page_title = 'UCP_REMIND'; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/ucp_resend.php b/phpBB/includes/ucp/ucp_resend.php new file mode 100644 index 0000000000..39e9be24a1 --- /dev/null +++ b/phpBB/includes/ucp/ucp_resend.php @@ -0,0 +1,170 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ucp_resend +* Resending activation emails +* @package ucp +*/ +class ucp_resend +{ + var $u_action; + + function main($id, $mode) + { + global $config, $phpbb_root_path, $phpEx; + global $db, $user, $auth, $template; + + $username = request_var('username', '', true); + $email = strtolower(request_var('email', '')); + $submit = (isset($_POST['submit'])) ? true : false; + + add_form_key('ucp_resend'); + + if ($submit) + { + if (!check_form_key('ucp_resend')) + { + trigger_error('FORM_INVALID'); + } + + $sql = 'SELECT user_id, group_id, username, user_email, user_type, user_lang, user_actkey, user_inactive_reason + FROM ' . USERS_TABLE . " + WHERE user_email_hash = '" . $db->sql_escape(phpbb_email_hash($email)) . "' + AND username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'"; + $result = $db->sql_query($sql); + $user_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$user_row) + { + trigger_error('NO_EMAIL_USER'); + } + + if ($user_row['user_type'] == USER_IGNORE) + { + trigger_error('NO_USER'); + } + + if (!$user_row['user_actkey'] && $user_row['user_type'] != USER_INACTIVE) + { + trigger_error('ACCOUNT_ALREADY_ACTIVATED'); + } + + if (!$user_row['user_actkey'] || ($user_row['user_type'] == USER_INACTIVE && $user_row['user_inactive_reason'] == INACTIVE_MANUAL)) + { + trigger_error('ACCOUNT_DEACTIVATED'); + } + + // Determine coppa status on group (REGISTERED(_COPPA)) + $sql = 'SELECT group_name, group_type + FROM ' . GROUPS_TABLE . ' + WHERE group_id = ' . $user_row['group_id']; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error('NO_GROUP'); + } + + $coppa = ($row['group_name'] == 'REGISTERED_COPPA' && $row['group_type'] == GROUP_SPECIAL) ? true : false; + + include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + $messenger = new messenger(false); + + if ($config['require_activation'] == USER_ACTIVATION_SELF || $coppa) + { + $messenger->template(($coppa) ? 'coppa_resend_inactive' : 'user_resend_inactive', $user_row['user_lang']); + $messenger->to($user_row['user_email'], $user_row['username']); + + $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); + $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); + $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); + $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + + $messenger->assign_vars(array( + 'WELCOME_MSG' => htmlspecialchars_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename'])), + 'USERNAME' => htmlspecialchars_decode($user_row['username']), + 'U_ACTIVATE' => generate_board_url() . "/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k={$user_row['user_actkey']}") + ); + + if ($coppa) + { + $messenger->assign_vars(array( + 'FAX_INFO' => $config['coppa_fax'], + 'MAIL_INFO' => $config['coppa_mail'], + 'EMAIL_ADDRESS' => $user_row['user_email']) + ); + } + + $messenger->send(NOTIFY_EMAIL); + } + + if ($config['require_activation'] == USER_ACTIVATION_ADMIN) + { + // Grab an array of user_id's with a_user permissions ... these users can activate a user + $admin_ary = $auth->acl_get_list(false, 'a_user', false); + + $sql = 'SELECT user_id, username, user_email, user_lang, user_jabber, user_notify_type + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', $admin_ary[0]['a_user']); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $messenger->template('admin_activate', $row['user_lang']); + $messenger->to($row['user_email'], $row['username']); + $messenger->im($row['user_jabber'], $row['username']); + + $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); + $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); + $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); + $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($user_row['username']), + 'U_USER_DETAILS' => generate_board_url() . "/memberlist.$phpEx?mode=viewprofile&u={$user_row['user_id']}", + 'U_ACTIVATE' => generate_board_url() . "/ucp.$phpEx?mode=activate&u={$user_row['user_id']}&k={$user_row['user_actkey']}") + ); + + $messenger->send($row['user_notify_type']); + } + $db->sql_freeresult($result); + } + + meta_refresh(3, append_sid("{$phpbb_root_path}index.$phpEx")); + + $message = ($config['require_activation'] == USER_ACTIVATION_ADMIN) ? $user->lang['ACTIVATION_EMAIL_SENT_ADMIN'] : $user->lang['ACTIVATION_EMAIL_SENT']; + $message .= '<br /><br />' . sprintf($user->lang['RETURN_INDEX'], '<a href="' . append_sid("{$phpbb_root_path}index.$phpEx") . '">', '</a>'); + trigger_error($message); + } + + $template->assign_vars(array( + 'USERNAME' => $username, + 'EMAIL' => $email, + 'S_PROFILE_ACTION' => append_sid($phpbb_root_path . 'ucp.' . $phpEx, 'mode=resend_act')) + ); + + $this->tpl_name = 'ucp_resend'; + $this->page_title = 'UCP_RESEND'; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/ucp/ucp_zebra.php b/phpBB/includes/ucp/ucp_zebra.php new file mode 100644 index 0000000000..5ed4db7520 --- /dev/null +++ b/phpBB/includes/ucp/ucp_zebra.php @@ -0,0 +1,257 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ucp_zebra +* @package ucp +*/ +class ucp_zebra +{ + var $u_action; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx; + + $submit = (isset($_POST['submit']) || isset($_GET['add']) || isset($_GET['remove'])) ? true : false; + $s_hidden_fields = ''; + + $l_mode = strtoupper($mode); + + if ($submit) + { + $data = $error = array(); + $updated = false; + + $var_ary = array( + 'usernames' => array(0), + 'add' => '', + ); + + foreach ($var_ary as $var => $default) + { + $data[$var] = request_var($var, $default, true); + } + + if (!empty($data['add']) || sizeof($data['usernames'])) + { + if (confirm_box(true)) + { + // Remove users + if (!empty($data['usernames'])) + { + $sql = 'DELETE FROM ' . ZEBRA_TABLE . ' + WHERE user_id = ' . $user->data['user_id'] . ' + AND ' . $db->sql_in_set('zebra_id', $data['usernames']); + $db->sql_query($sql); + + $updated = true; + } + + // Add users + if ($data['add']) + { + $data['add'] = array_map('trim', array_map('utf8_clean_string', explode("\n", $data['add']))); + + // Do these name/s exist on a list already? If so, ignore ... we could be + // 'nice' and automatically handle names added to one list present on + // the other (by removing the existing one) ... but I have a feeling this + // may lead to complaints + $sql = 'SELECT z.*, u.username, u.username_clean + FROM ' . ZEBRA_TABLE . ' z, ' . USERS_TABLE . ' u + WHERE z.user_id = ' . $user->data['user_id'] . ' + AND u.user_id = z.zebra_id'; + $result = $db->sql_query($sql); + + $friends = $foes = array(); + while ($row = $db->sql_fetchrow($result)) + { + if ($row['friend']) + { + $friends[] = utf8_clean_string($row['username']); + } + else + { + $foes[] = utf8_clean_string($row['username']); + } + } + $db->sql_freeresult($result); + + // remove friends from the username array + $n = sizeof($data['add']); + $data['add'] = array_diff($data['add'], $friends); + + if (sizeof($data['add']) < $n && $mode == 'foes') + { + $error[] = $user->lang['NOT_ADDED_FOES_FRIENDS']; + } + + // remove foes from the username array + $n = sizeof($data['add']); + $data['add'] = array_diff($data['add'], $foes); + + if (sizeof($data['add']) < $n && $mode == 'friends') + { + $error[] = $user->lang['NOT_ADDED_FRIENDS_FOES']; + } + + // remove the user himself from the username array + $n = sizeof($data['add']); + $data['add'] = array_diff($data['add'], array(utf8_clean_string($user->data['username']))); + + if (sizeof($data['add']) < $n) + { + $error[] = $user->lang['NOT_ADDED_' . $l_mode . '_SELF']; + } + + unset($friends, $foes, $n); + + if (sizeof($data['add'])) + { + $sql = 'SELECT user_id, user_type + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('username_clean', $data['add']) . ' + AND user_type <> ' . USER_INACTIVE; + $result = $db->sql_query($sql); + + $user_id_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + if ($row['user_id'] != ANONYMOUS && $row['user_type'] != USER_IGNORE) + { + $user_id_ary[] = $row['user_id']; + } + else if ($row['user_id'] != ANONYMOUS) + { + $error[] = $user->lang['NOT_ADDED_' . $l_mode . '_BOTS']; + } + else + { + $error[] = $user->lang['NOT_ADDED_' . $l_mode . '_ANONYMOUS']; + } + } + $db->sql_freeresult($result); + + if (sizeof($user_id_ary)) + { + // Remove users from foe list if they are admins or moderators + if ($mode == 'foes') + { + $perms = array(); + foreach ($auth->acl_get_list($user_id_ary, array('a_', 'm_')) as $forum_id => $forum_ary) + { + foreach ($forum_ary as $auth_option => $user_ary) + { + $perms = array_merge($perms, $user_ary); + } + } + + $perms = array_unique($perms); + + if (sizeof($perms)) + { + $error[] = $user->lang['NOT_ADDED_FOES_MOD_ADMIN']; + } + + // This may not be right ... it may yield true when perms equate to deny + $user_id_ary = array_diff($user_id_ary, $perms); + unset($perms); + } + + if (sizeof($user_id_ary)) + { + $sql_mode = ($mode == 'friends') ? 'friend' : 'foe'; + + $sql_ary = array(); + foreach ($user_id_ary as $zebra_id) + { + $sql_ary[] = array( + 'user_id' => (int) $user->data['user_id'], + 'zebra_id' => (int) $zebra_id, + $sql_mode => 1 + ); + } + + $db->sql_multi_insert(ZEBRA_TABLE, $sql_ary); + + $updated = true; + } + unset($user_id_ary); + } + else if (!sizeof($error)) + { + $error[] = $user->lang['USER_NOT_FOUND_OR_INACTIVE']; + } + } + } + + if ($updated) + { + meta_refresh(3, $this->u_action); + $message = $user->lang[$l_mode . '_UPDATED'] . '<br />' . implode('<br />', $error) . ((sizeof($error)) ? '<br />' : '') . '<br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + trigger_error($message); + } + else + { + $template->assign_var('ERROR', implode('<br />', $error)); + } + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'mode' => $mode, + 'submit' => true, + 'usernames' => $data['usernames'], + 'add' => $data['add'])) + ); + } + } + } + + $sql_and = ($mode == 'friends') ? 'z.friend = 1' : 'z.foe = 1'; + $sql = 'SELECT z.*, u.username, u.username_clean + FROM ' . ZEBRA_TABLE . ' z, ' . USERS_TABLE . ' u + WHERE z.user_id = ' . $user->data['user_id'] . " + AND $sql_and + AND u.user_id = z.zebra_id + ORDER BY u.username_clean ASC"; + $result = $db->sql_query($sql); + + $s_username_options = ''; + while ($row = $db->sql_fetchrow($result)) + { + $s_username_options .= '<option value="' . $row['zebra_id'] . '">' . $row['username'] . '</option>'; + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'L_TITLE' => $user->lang['UCP_ZEBRA_' . $l_mode], + + 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=ucp&field=add'), + + 'S_USERNAME_OPTIONS' => $s_username_options, + 'S_HIDDEN_FIELDS' => $s_hidden_fields, + 'S_UCP_ACTION' => $this->u_action) + ); + + $this->tpl_name = 'ucp_zebra_' . $mode; + $this->page_title = 'UCP_ZEBRA_' . $l_mode; + } +} + +?>
\ 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 new file mode 100644 index 0000000000..00de1ba349 --- /dev/null +++ b/phpBB/includes/utf/data/case_fold_c.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..7e2ffb25ec --- /dev/null +++ b/phpBB/includes/utf/data/case_fold_f.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..5f09ffa1dd --- /dev/null +++ b/phpBB/includes/utf/data/case_fold_s.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..7564978a26 --- /dev/null +++ b/phpBB/includes/utf/data/confusables.php @@ -0,0 +1 @@ +<?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/recode_basic.php b/phpBB/includes/utf/data/recode_basic.php new file mode 100644 index 0000000000..02e44d3e0d --- /dev/null +++ b/phpBB/includes/utf/data/recode_basic.php @@ -0,0 +1,1543 @@ +<?php +function iso_8859_1($string) +{ + return utf8_encode($string); +} + +function iso_8859_2($string) +{ + static $transform = array( + "\x80" => "\xC2\x80", + "\x81" => "\xC2\x81", + "\x82" => "\xC2\x82", + "\x83" => "\xC2\x83", + "\x84" => "\xC2\x84", + "\x85" => "\xC2\x85", + "\x86" => "\xC2\x86", + "\x87" => "\xC2\x87", + "\x88" => "\xC2\x88", + "\x89" => "\xC2\x89", + "\x8A" => "\xC2\x8A", + "\x8B" => "\xC2\x8B", + "\x8C" => "\xC2\x8C", + "\x8D" => "\xC2\x8D", + "\x8E" => "\xC2\x8E", + "\x8F" => "\xC2\x8F", + "\x90" => "\xC2\x90", + "\x91" => "\xC2\x91", + "\x92" => "\xC2\x92", + "\x93" => "\xC2\x93", + "\x94" => "\xC2\x94", + "\x95" => "\xC2\x95", + "\x96" => "\xC2\x96", + "\x97" => "\xC2\x97", + "\x98" => "\xC2\x98", + "\x99" => "\xC2\x99", + "\x9A" => "\xC2\x9A", + "\x9B" => "\xC2\x9B", + "\x9C" => "\xC2\x9C", + "\x9D" => "\xC2\x9D", + "\x9E" => "\xC2\x9E", + "\x9F" => "\xC2\x9F", + "\xA0" => "\xC2\xA0", + "\xA1" => "\xC4\x84", + "\xA2" => "\xCB\x98", + "\xA3" => "\xC5\x81", + "\xA4" => "\xC2\xA4", + "\xA5" => "\xC4\xBD", + "\xA6" => "\xC5\x9A", + "\xA7" => "\xC2\xA7", + "\xA8" => "\xC2\xA8", + "\xA9" => "\xC5\xA0", + "\xAA" => "\xC5\x9E", + "\xAB" => "\xC5\xA4", + "\xAC" => "\xC5\xB9", + "\xAD" => "\xC2\xAD", + "\xAE" => "\xC5\xBD", + "\xAF" => "\xC5\xBB", + "\xB0" => "\xC2\xB0", + "\xB1" => "\xC4\x85", + "\xB2" => "\xCB\x9B", + "\xB3" => "\xC5\x82", + "\xB4" => "\xC2\xB4", + "\xB5" => "\xC4\xBE", + "\xB6" => "\xC5\x9B", + "\xB7" => "\xCB\x87", + "\xB8" => "\xC2\xB8", + "\xB9" => "\xC5\xA1", + "\xBA" => "\xC5\x9F", + "\xBB" => "\xC5\xA5", + "\xBC" => "\xC5\xBA", + "\xBD" => "\xCB\x9D", + "\xBE" => "\xC5\xBE", + "\xBF" => "\xC5\xBC", + "\xC0" => "\xC5\x94", + "\xC1" => "\xC3\x81", + "\xC2" => "\xC3\x82", + "\xC3" => "\xC4\x82", + "\xC4" => "\xC3\x84", + "\xC5" => "\xC4\xB9", + "\xC6" => "\xC4\x86", + "\xC7" => "\xC3\x87", + "\xC8" => "\xC4\x8C", + "\xC9" => "\xC3\x89", + "\xCA" => "\xC4\x98", + "\xCB" => "\xC3\x8B", + "\xCC" => "\xC4\x9A", + "\xCD" => "\xC3\x8D", + "\xCE" => "\xC3\x8E", + "\xCF" => "\xC4\x8E", + "\xD0" => "\xC4\x90", + "\xD1" => "\xC5\x83", + "\xD2" => "\xC5\x87", + "\xD3" => "\xC3\x93", + "\xD4" => "\xC3\x94", + "\xD5" => "\xC5\x90", + "\xD6" => "\xC3\x96", + "\xD7" => "\xC3\x97", + "\xD8" => "\xC5\x98", + "\xD9" => "\xC5\xAE", + "\xDA" => "\xC3\x9A", + "\xDB" => "\xC5\xB0", + "\xDC" => "\xC3\x9C", + "\xDD" => "\xC3\x9D", + "\xDE" => "\xC5\xA2", + "\xDF" => "\xC3\x9F", + "\xE0" => "\xC5\x95", + "\xE1" => "\xC3\xA1", + "\xE2" => "\xC3\xA2", + "\xE3" => "\xC4\x83", + "\xE4" => "\xC3\xA4", + "\xE5" => "\xC4\xBA", + "\xE6" => "\xC4\x87", + "\xE7" => "\xC3\xA7", + "\xE8" => "\xC4\x8D", + "\xE9" => "\xC3\xA9", + "\xEA" => "\xC4\x99", + "\xEB" => "\xC3\xAB", + "\xEC" => "\xC4\x9B", + "\xED" => "\xC3\xAD", + "\xEE" => "\xC3\xAE", + "\xEF" => "\xC4\x8F", + "\xF0" => "\xC4\x91", + "\xF1" => "\xC5\x84", + "\xF2" => "\xC5\x88", + "\xF3" => "\xC3\xB3", + "\xF4" => "\xC3\xB4", + "\xF5" => "\xC5\x91", + "\xF6" => "\xC3\xB6", + "\xF7" => "\xC3\xB7", + "\xF8" => "\xC5\x99", + "\xF9" => "\xC5\xAF", + "\xFA" => "\xC3\xBA", + "\xFB" => "\xC5\xB1", + "\xFC" => "\xC3\xBC", + "\xFD" => "\xC3\xBD", + "\xFE" => "\xC5\xA3", + "\xFF" => "\xCB\x99", + ); + return strtr($string, $transform); +} + +function iso_8859_4($string) +{ + static $transform = array( + "\x80" => "\xC2\x80", + "\x81" => "\xC2\x81", + "\x82" => "\xC2\x82", + "\x83" => "\xC2\x83", + "\x84" => "\xC2\x84", + "\x85" => "\xC2\x85", + "\x86" => "\xC2\x86", + "\x87" => "\xC2\x87", + "\x88" => "\xC2\x88", + "\x89" => "\xC2\x89", + "\x8A" => "\xC2\x8A", + "\x8B" => "\xC2\x8B", + "\x8C" => "\xC2\x8C", + "\x8D" => "\xC2\x8D", + "\x8E" => "\xC2\x8E", + "\x8F" => "\xC2\x8F", + "\x90" => "\xC2\x90", + "\x91" => "\xC2\x91", + "\x92" => "\xC2\x92", + "\x93" => "\xC2\x93", + "\x94" => "\xC2\x94", + "\x95" => "\xC2\x95", + "\x96" => "\xC2\x96", + "\x97" => "\xC2\x97", + "\x98" => "\xC2\x98", + "\x99" => "\xC2\x99", + "\x9A" => "\xC2\x9A", + "\x9B" => "\xC2\x9B", + "\x9C" => "\xC2\x9C", + "\x9D" => "\xC2\x9D", + "\x9E" => "\xC2\x9E", + "\x9F" => "\xC2\x9F", + "\xA0" => "\xC2\xA0", + "\xA1" => "\xC4\x84", + "\xA2" => "\xC4\xB8", + "\xA3" => "\xC5\x96", + "\xA4" => "\xC2\xA4", + "\xA5" => "\xC4\xA8", + "\xA6" => "\xC4\xBB", + "\xA7" => "\xC2\xA7", + "\xA8" => "\xC2\xA8", + "\xA9" => "\xC5\xA0", + "\xAA" => "\xC4\x92", + "\xAB" => "\xC4\xA2", + "\xAC" => "\xC5\xA6", + "\xAD" => "\xC2\xAD", + "\xAE" => "\xC5\xBD", + "\xAF" => "\xC2\xAF", + "\xB0" => "\xC2\xB0", + "\xB1" => "\xC4\x85", + "\xB2" => "\xCB\x9B", + "\xB3" => "\xC5\x97", + "\xB4" => "\xC2\xB4", + "\xB5" => "\xC4\xA9", + "\xB6" => "\xC4\xBC", + "\xB7" => "\xCB\x87", + "\xB8" => "\xC2\xB8", + "\xB9" => "\xC5\xA1", + "\xBA" => "\xC4\x93", + "\xBB" => "\xC4\xA3", + "\xBC" => "\xC5\xA7", + "\xBD" => "\xC5\x8A", + "\xBE" => "\xC5\xBE", + "\xBF" => "\xC5\x8B", + "\xC0" => "\xC4\x80", + "\xC1" => "\xC3\x81", + "\xC2" => "\xC3\x82", + "\xC3" => "\xC3\x83", + "\xC4" => "\xC3\x84", + "\xC5" => "\xC3\x85", + "\xC6" => "\xC3\x86", + "\xC7" => "\xC4\xAE", + "\xC8" => "\xC4\x8C", + "\xC9" => "\xC3\x89", + "\xCA" => "\xC4\x98", + "\xCB" => "\xC3\x8B", + "\xCC" => "\xC4\x96", + "\xCD" => "\xC3\x8D", + "\xCE" => "\xC3\x8E", + "\xCF" => "\xC4\xAA", + "\xD0" => "\xC4\x90", + "\xD1" => "\xC5\x85", + "\xD2" => "\xC5\x8C", + "\xD3" => "\xC4\xB6", + "\xD4" => "\xC3\x94", + "\xD5" => "\xC3\x95", + "\xD6" => "\xC3\x96", + "\xD7" => "\xC3\x97", + "\xD8" => "\xC3\x98", + "\xD9" => "\xC5\xB2", + "\xDA" => "\xC3\x9A", + "\xDB" => "\xC3\x9B", + "\xDC" => "\xC3\x9C", + "\xDD" => "\xC5\xA8", + "\xDE" => "\xC5\xAA", + "\xDF" => "\xC3\x9F", + "\xE0" => "\xC4\x81", + "\xE1" => "\xC3\xA1", + "\xE2" => "\xC3\xA2", + "\xE3" => "\xC3\xA3", + "\xE4" => "\xC3\xA4", + "\xE5" => "\xC3\xA5", + "\xE6" => "\xC3\xA6", + "\xE7" => "\xC4\xAF", + "\xE8" => "\xC4\x8D", + "\xE9" => "\xC3\xA9", + "\xEA" => "\xC4\x99", + "\xEB" => "\xC3\xAB", + "\xEC" => "\xC4\x97", + "\xED" => "\xC3\xAD", + "\xEE" => "\xC3\xAE", + "\xEF" => "\xC4\xAB", + "\xF0" => "\xC4\x91", + "\xF1" => "\xC5\x86", + "\xF2" => "\xC5\x8D", + "\xF3" => "\xC4\xB7", + "\xF4" => "\xC3\xB4", + "\xF5" => "\xC3\xB5", + "\xF6" => "\xC3\xB6", + "\xF7" => "\xC3\xB7", + "\xF8" => "\xC3\xB8", + "\xF9" => "\xC5\xB3", + "\xFA" => "\xC3\xBA", + "\xFB" => "\xC3\xBB", + "\xFC" => "\xC3\xBC", + "\xFD" => "\xC5\xA9", + "\xFE" => "\xC5\xAB", + "\xFF" => "\xCB\x99", + ); + return strtr($string, $transform); +} + +function iso_8859_7($string) +{ + static $transform = array( + "\x80" => "\xC2\x80", + "\x81" => "\xC2\x81", + "\x82" => "\xC2\x82", + "\x83" => "\xC2\x83", + "\x84" => "\xC2\x84", + "\x85" => "\xC2\x85", + "\x86" => "\xC2\x86", + "\x87" => "\xC2\x87", + "\x88" => "\xC2\x88", + "\x89" => "\xC2\x89", + "\x8A" => "\xC2\x8A", + "\x8B" => "\xC2\x8B", + "\x8C" => "\xC2\x8C", + "\x8D" => "\xC2\x8D", + "\x8E" => "\xC2\x8E", + "\x8F" => "\xC2\x8F", + "\x90" => "\xC2\x90", + "\x91" => "\xC2\x91", + "\x92" => "\xC2\x92", + "\x93" => "\xC2\x93", + "\x94" => "\xC2\x94", + "\x95" => "\xC2\x95", + "\x96" => "\xC2\x96", + "\x97" => "\xC2\x97", + "\x98" => "\xC2\x98", + "\x99" => "\xC2\x99", + "\x9A" => "\xC2\x9A", + "\x9B" => "\xC2\x9B", + "\x9C" => "\xC2\x9C", + "\x9D" => "\xC2\x9D", + "\x9E" => "\xC2\x9E", + "\x9F" => "\xC2\x9F", + "\xA0" => "\xC2\xA0", + "\xA1" => "\xE2\x80\x98", + "\xA2" => "\xE2\x80\x99", + "\xA3" => "\xC2\xA3", + "\xA4" => "\xE2\x82\xAC", + "\xA5" => "\xE2\x82\xAF", + "\xA6" => "\xC2\xA6", + "\xA7" => "\xC2\xA7", + "\xA8" => "\xC2\xA8", + "\xA9" => "\xC2\xA9", + "\xAA" => "\xCD\xBA", + "\xAB" => "\xC2\xAB", + "\xAC" => "\xC2\xAC", + "\xAD" => "\xC2\xAD", + "\xAF" => "\xE2\x80\x95", + "\xB0" => "\xC2\xB0", + "\xB1" => "\xC2\xB1", + "\xB2" => "\xC2\xB2", + "\xB3" => "\xC2\xB3", + "\xB4" => "\xCE\x84", + "\xB5" => "\xCE\x85", + "\xB6" => "\xCE\x86", + "\xB7" => "\xC2\xB7", + "\xB8" => "\xCE\x88", + "\xB9" => "\xCE\x89", + "\xBA" => "\xCE\x8A", + "\xBB" => "\xC2\xBB", + "\xBC" => "\xCE\x8C", + "\xBD" => "\xC2\xBD", + "\xBE" => "\xCE\x8E", + "\xBF" => "\xCE\x8F", + "\xC0" => "\xCE\x90", + "\xC1" => "\xCE\x91", + "\xC2" => "\xCE\x92", + "\xC3" => "\xCE\x93", + "\xC4" => "\xCE\x94", + "\xC5" => "\xCE\x95", + "\xC6" => "\xCE\x96", + "\xC7" => "\xCE\x97", + "\xC8" => "\xCE\x98", + "\xC9" => "\xCE\x99", + "\xCA" => "\xCE\x9A", + "\xCB" => "\xCE\x9B", + "\xCC" => "\xCE\x9C", + "\xCD" => "\xCE\x9D", + "\xCE" => "\xCE\x9E", + "\xCF" => "\xCE\x9F", + "\xD0" => "\xCE\xA0", + "\xD1" => "\xCE\xA1", + "\xD3" => "\xCE\xA3", + "\xD4" => "\xCE\xA4", + "\xD5" => "\xCE\xA5", + "\xD6" => "\xCE\xA6", + "\xD7" => "\xCE\xA7", + "\xD8" => "\xCE\xA8", + "\xD9" => "\xCE\xA9", + "\xDA" => "\xCE\xAA", + "\xDB" => "\xCE\xAB", + "\xDC" => "\xCE\xAC", + "\xDD" => "\xCE\xAD", + "\xDE" => "\xCE\xAE", + "\xDF" => "\xCE\xAF", + "\xE0" => "\xCE\xB0", + "\xE1" => "\xCE\xB1", + "\xE2" => "\xCE\xB2", + "\xE3" => "\xCE\xB3", + "\xE4" => "\xCE\xB4", + "\xE5" => "\xCE\xB5", + "\xE6" => "\xCE\xB6", + "\xE7" => "\xCE\xB7", + "\xE8" => "\xCE\xB8", + "\xE9" => "\xCE\xB9", + "\xEA" => "\xCE\xBA", + "\xEB" => "\xCE\xBB", + "\xEC" => "\xCE\xBC", + "\xED" => "\xCE\xBD", + "\xEE" => "\xCE\xBE", + "\xEF" => "\xCE\xBF", + "\xF0" => "\xCF\x80", + "\xF1" => "\xCF\x81", + "\xF2" => "\xCF\x82", + "\xF3" => "\xCF\x83", + "\xF4" => "\xCF\x84", + "\xF5" => "\xCF\x85", + "\xF6" => "\xCF\x86", + "\xF7" => "\xCF\x87", + "\xF8" => "\xCF\x88", + "\xF9" => "\xCF\x89", + "\xFA" => "\xCF\x8A", + "\xFB" => "\xCF\x8B", + "\xFC" => "\xCF\x8C", + "\xFD" => "\xCF\x8D", + "\xFE" => "\xCF\x8E", + ); + return strtr($string, $transform); +} + +function iso_8859_8($string) +{ + static $transform = array( + "\xC2\xAA" => "\xC3\x97", + "\xC2\xBA" => "\xC3\xB7", + "\xC3\x9F" => "\xE2\x80\x97", + "\xC3\xA0" => "\xD7\x90", + "\xC3\xA1" => "\xD7\x91", + "\xC3\xA2" => "\xD7\x92", + "\xC3\xA3" => "\xD7\x93", + "\xC3\xA4" => "\xD7\x94", + "\xC3\xA5" => "\xD7\x95", + "\xC3\xA6" => "\xD7\x96", + "\xC3\xA7" => "\xD7\x97", + "\xC3\xA8" => "\xD7\x98", + "\xC3\xA9" => "\xD7\x99", + "\xC3\xAA" => "\xD7\x9A", + "\xC3\xAB" => "\xD7\x9B", + "\xC3\xAC" => "\xD7\x9C", + "\xC3\xAD" => "\xD7\x9D", + "\xC3\xAE" => "\xD7\x9E", + "\xC3\xAF" => "\xD7\x9F", + "\xC3\xB0" => "\xD7\xA0", + "\xC3\xB1" => "\xD7\xA1", + "\xC3\xB2" => "\xD7\xA2", + "\xC3\xB3" => "\xD7\xA3", + "\xC3\xB4" => "\xD7\xA4", + "\xC3\xB5" => "\xD7\xA5", + "\xC3\xB6" => "\xD7\xA6", + "\xC3\xB7" => "\xD7\xA7", + "\xC3\xB8" => "\xD7\xA8", + "\xC3\xB9" => "\xD7\xA9", + "\xC3\xBA" => "\xD7\xAA", + "\xC3\xBD" => "\xE2\x80\x8E", + "\xC3\xBE" => "\xE2\x80\x8F", + ); + return strtr(utf8_encode($string), $transform); +} + +function iso_8859_9($string) +{ + static $transform = array( + "\xC3\x90" => "\xC4\x9E", + "\xC3\x9D" => "\xC4\xB0", + "\xC3\x9E" => "\xC5\x9E", + "\xC3\xB0" => "\xC4\x9F", + "\xC3\xBD" => "\xC4\xB1", + "\xC3\xBE" => "\xC5\x9F", + ); + return strtr(utf8_encode($string), $transform); +} + +function iso_8859_15($string) +{ + static $transform = array( + "\xC2\xA4" => "\xE2\x82\xAC", + "\xC2\xA6" => "\xC5\xA0", + "\xC2\xA8" => "\xC5\xA1", + "\xC2\xB4" => "\xC5\xBD", + "\xC2\xB8" => "\xC5\xBE", + "\xC2\xBC" => "\xC5\x92", + "\xC2\xBD" => "\xC5\x93", + "\xC2\xBE" => "\xC5\xB8", + ); + return strtr(utf8_encode($string), $transform); +} + +// nearly the same as iso-8859-11 +function tis_620($string) +{ + static $transform = array( + "\x80" => "\xC2\x80", + "\x81" => "\xC2\x81", + "\x82" => "\xC2\x82", + "\x83" => "\xC2\x83", + "\x84" => "\xC2\x84", + "\x85" => "\xC2\x85", + "\x86" => "\xC2\x86", + "\x87" => "\xC2\x87", + "\x88" => "\xC2\x88", + "\x89" => "\xC2\x89", + "\x8A" => "\xC2\x8A", + "\x8B" => "\xC2\x8B", + "\x8C" => "\xC2\x8C", + "\x8D" => "\xC2\x8D", + "\x8E" => "\xC2\x8E", + "\x8F" => "\xC2\x8F", + "\x90" => "\xC2\x90", + "\x91" => "\xC2\x91", + "\x92" => "\xC2\x92", + "\x93" => "\xC2\x93", + "\x94" => "\xC2\x94", + "\x95" => "\xC2\x95", + "\x96" => "\xC2\x96", + "\x97" => "\xC2\x97", + "\x98" => "\xC2\x98", + "\x99" => "\xC2\x99", + "\x9A" => "\xC2\x9A", + "\x9B" => "\xC2\x9B", + "\x9C" => "\xC2\x9C", + "\x9D" => "\xC2\x9D", + "\x9E" => "\xC2\x9E", + "\x9F" => "\xC2\x9F", + "\xA1" => "\xE0\xB8\x81", + "\xA2" => "\xE0\xB8\x82", + "\xA3" => "\xE0\xB8\x83", + "\xA4" => "\xE0\xB8\x84", + "\xA5" => "\xE0\xB8\x85", + "\xA6" => "\xE0\xB8\x86", + "\xA7" => "\xE0\xB8\x87", + "\xA8" => "\xE0\xB8\x88", + "\xA9" => "\xE0\xB8\x89", + "\xAA" => "\xE0\xB8\x8A", + "\xAB" => "\xE0\xB8\x8B", + "\xAC" => "\xE0\xB8\x8C", + "\xAD" => "\xE0\xB8\x8D", + "\xAE" => "\xE0\xB8\x8E", + "\xAF" => "\xE0\xB8\x8F", + "\xB0" => "\xE0\xB8\x90", + "\xB1" => "\xE0\xB8\x91", + "\xB2" => "\xE0\xB8\x92", + "\xB3" => "\xE0\xB8\x93", + "\xB4" => "\xE0\xB8\x94", + "\xB5" => "\xE0\xB8\x95", + "\xB6" => "\xE0\xB8\x96", + "\xB7" => "\xE0\xB8\x97", + "\xB8" => "\xE0\xB8\x98", + "\xB9" => "\xE0\xB8\x99", + "\xBA" => "\xE0\xB8\x9A", + "\xBB" => "\xE0\xB8\x9B", + "\xBC" => "\xE0\xB8\x9C", + "\xBD" => "\xE0\xB8\x9D", + "\xBE" => "\xE0\xB8\x9E", + "\xBF" => "\xE0\xB8\x9F", + "\xC0" => "\xE0\xB8\xA0", + "\xC1" => "\xE0\xB8\xA1", + "\xC2" => "\xE0\xB8\xA2", + "\xC3" => "\xE0\xB8\xA3", + "\xC4" => "\xE0\xB8\xA4", + "\xC5" => "\xE0\xB8\xA5", + "\xC6" => "\xE0\xB8\xA6", + "\xC7" => "\xE0\xB8\xA7", + "\xC8" => "\xE0\xB8\xA8", + "\xC9" => "\xE0\xB8\xA9", + "\xCA" => "\xE0\xB8\xAA", + "\xCB" => "\xE0\xB8\xAB", + "\xCC" => "\xE0\xB8\xAC", + "\xCD" => "\xE0\xB8\xAD", + "\xCE" => "\xE0\xB8\xAE", + "\xCF" => "\xE0\xB8\xAF", + "\xD0" => "\xE0\xB8\xB0", + "\xD1" => "\xE0\xB8\xB1", + "\xD2" => "\xE0\xB8\xB2", + "\xD3" => "\xE0\xB8\xB3", + "\xD4" => "\xE0\xB8\xB4", + "\xD5" => "\xE0\xB8\xB5", + "\xD6" => "\xE0\xB8\xB6", + "\xD7" => "\xE0\xB8\xB7", + "\xD8" => "\xE0\xB8\xB8", + "\xD9" => "\xE0\xB8\xB9", + "\xDA" => "\xE0\xB8\xBA", + "\xDF" => "\xE0\xB8\xBF", + "\xE0" => "\xE0\xB9\x80", + "\xE1" => "\xE0\xB9\x81", + "\xE2" => "\xE0\xB9\x82", + "\xE3" => "\xE0\xB9\x83", + "\xE4" => "\xE0\xB9\x84", + "\xE5" => "\xE0\xB9\x85", + "\xE6" => "\xE0\xB9\x86", + "\xE7" => "\xE0\xB9\x87", + "\xE8" => "\xE0\xB9\x88", + "\xE9" => "\xE0\xB9\x89", + "\xEA" => "\xE0\xB9\x8A", + "\xEB" => "\xE0\xB9\x8B", + "\xEC" => "\xE0\xB9\x8C", + "\xED" => "\xE0\xB9\x8D", + "\xEE" => "\xE0\xB9\x8E", + "\xEF" => "\xE0\xB9\x8F", + "\xF0" => "\xE0\xB9\x90", + "\xF1" => "\xE0\xB9\x91", + "\xF2" => "\xE0\xB9\x92", + "\xF3" => "\xE0\xB9\x93", + "\xF4" => "\xE0\xB9\x94", + "\xF5" => "\xE0\xB9\x95", + "\xF6" => "\xE0\xB9\x96", + "\xF7" => "\xE0\xB9\x97", + "\xF8" => "\xE0\xB9\x98", + "\xF9" => "\xE0\xB9\x99", + "\xFA" => "\xE0\xB9\x9A", + "\xFB" => "\xE0\xB9\x9B", + ); + return strtr($string, $transform); +} + +function cp874($string) +{ + static $transform = array( + "\x80" => "\xE2\x82\xAC", + "\x85" => "\xE2\x80\xA6", + "\x91" => "\xE2\x80\x98", + "\x92" => "\xE2\x80\x99", + "\x93" => "\xE2\x80\x9C", + "\x94" => "\xE2\x80\x9D", + "\x95" => "\xE2\x80\xA2", + "\x96" => "\xE2\x80\x93", + "\x97" => "\xE2\x80\x94", + "\xA0" => "\xC2\xA0", + "\xA1" => "\xE0\xB8\x81", + "\xA2" => "\xE0\xB8\x82", + "\xA3" => "\xE0\xB8\x83", + "\xA4" => "\xE0\xB8\x84", + "\xA5" => "\xE0\xB8\x85", + "\xA6" => "\xE0\xB8\x86", + "\xA7" => "\xE0\xB8\x87", + "\xA8" => "\xE0\xB8\x88", + "\xA9" => "\xE0\xB8\x89", + "\xAA" => "\xE0\xB8\x8A", + "\xAB" => "\xE0\xB8\x8B", + "\xAC" => "\xE0\xB8\x8C", + "\xAD" => "\xE0\xB8\x8D", + "\xAE" => "\xE0\xB8\x8E", + "\xAF" => "\xE0\xB8\x8F", + "\xB0" => "\xE0\xB8\x90", + "\xB1" => "\xE0\xB8\x91", + "\xB2" => "\xE0\xB8\x92", + "\xB3" => "\xE0\xB8\x93", + "\xB4" => "\xE0\xB8\x94", + "\xB5" => "\xE0\xB8\x95", + "\xB6" => "\xE0\xB8\x96", + "\xB7" => "\xE0\xB8\x97", + "\xB8" => "\xE0\xB8\x98", + "\xB9" => "\xE0\xB8\x99", + "\xBA" => "\xE0\xB8\x9A", + "\xBB" => "\xE0\xB8\x9B", + "\xBC" => "\xE0\xB8\x9C", + "\xBD" => "\xE0\xB8\x9D", + "\xBE" => "\xE0\xB8\x9E", + "\xBF" => "\xE0\xB8\x9F", + "\xC0" => "\xE0\xB8\xA0", + "\xC1" => "\xE0\xB8\xA1", + "\xC2" => "\xE0\xB8\xA2", + "\xC3" => "\xE0\xB8\xA3", + "\xC4" => "\xE0\xB8\xA4", + "\xC5" => "\xE0\xB8\xA5", + "\xC6" => "\xE0\xB8\xA6", + "\xC7" => "\xE0\xB8\xA7", + "\xC8" => "\xE0\xB8\xA8", + "\xC9" => "\xE0\xB8\xA9", + "\xCA" => "\xE0\xB8\xAA", + "\xCB" => "\xE0\xB8\xAB", + "\xCC" => "\xE0\xB8\xAC", + "\xCD" => "\xE0\xB8\xAD", + "\xCE" => "\xE0\xB8\xAE", + "\xCF" => "\xE0\xB8\xAF", + "\xD0" => "\xE0\xB8\xB0", + "\xD1" => "\xE0\xB8\xB1", + "\xD2" => "\xE0\xB8\xB2", + "\xD3" => "\xE0\xB8\xB3", + "\xD4" => "\xE0\xB8\xB4", + "\xD5" => "\xE0\xB8\xB5", + "\xD6" => "\xE0\xB8\xB6", + "\xD7" => "\xE0\xB8\xB7", + "\xD8" => "\xE0\xB8\xB8", + "\xD9" => "\xE0\xB8\xB9", + "\xDA" => "\xE0\xB8\xBA", + "\xDF" => "\xE0\xB8\xBF", + "\xE0" => "\xE0\xB9\x80", + "\xE1" => "\xE0\xB9\x81", + "\xE2" => "\xE0\xB9\x82", + "\xE3" => "\xE0\xB9\x83", + "\xE4" => "\xE0\xB9\x84", + "\xE5" => "\xE0\xB9\x85", + "\xE6" => "\xE0\xB9\x86", + "\xE7" => "\xE0\xB9\x87", + "\xE8" => "\xE0\xB9\x88", + "\xE9" => "\xE0\xB9\x89", + "\xEA" => "\xE0\xB9\x8A", + "\xEB" => "\xE0\xB9\x8B", + "\xEC" => "\xE0\xB9\x8C", + "\xED" => "\xE0\xB9\x8D", + "\xEE" => "\xE0\xB9\x8E", + "\xEF" => "\xE0\xB9\x8F", + "\xF0" => "\xE0\xB9\x90", + "\xF1" => "\xE0\xB9\x91", + "\xF2" => "\xE0\xB9\x92", + "\xF3" => "\xE0\xB9\x93", + "\xF4" => "\xE0\xB9\x94", + "\xF5" => "\xE0\xB9\x95", + "\xF6" => "\xE0\xB9\x96", + "\xF7" => "\xE0\xB9\x97", + "\xF8" => "\xE0\xB9\x98", + "\xF9" => "\xE0\xB9\x99", + "\xFA" => "\xE0\xB9\x9A", + "\xFB" => "\xE0\xB9\x9B", + ); + return strtr($string, $transform); +} + +function cp1250($string) +{ + static $transform = array( + "\x80" => "\xE2\x82\xAC", + "\x82" => "\xE2\x80\x9A", + "\x84" => "\xE2\x80\x9E", + "\x85" => "\xE2\x80\xA6", + "\x86" => "\xE2\x80\xA0", + "\x87" => "\xE2\x80\xA1", + "\x89" => "\xE2\x80\xB0", + "\x8A" => "\xC5\xA0", + "\x8B" => "\xE2\x80\xB9", + "\x8C" => "\xC5\x9A", + "\x8D" => "\xC5\xA4", + "\x8E" => "\xC5\xBD", + "\x8F" => "\xC5\xB9", + "\x91" => "\xE2\x80\x98", + "\x92" => "\xE2\x80\x99", + "\x93" => "\xE2\x80\x9C", + "\x94" => "\xE2\x80\x9D", + "\x95" => "\xE2\x80\xA2", + "\x96" => "\xE2\x80\x93", + "\x97" => "\xE2\x80\x94", + "\x99" => "\xE2\x84\xA2", + "\x9A" => "\xC5\xA1", + "\x9B" => "\xE2\x80\xBA", + "\x9C" => "\xC5\x9B", + "\x9D" => "\xC5\xA5", + "\x9E" => "\xC5\xBE", + "\x9F" => "\xC5\xBA", + "\xA0" => "\xC2\xA0", + "\xA1" => "\xCB\x87", + "\xA2" => "\xCB\x98", + "\xA3" => "\xC5\x81", + "\xA4" => "\xC2\xA4", + "\xA5" => "\xC4\x84", + "\xA6" => "\xC2\xA6", + "\xA7" => "\xC2\xA7", + "\xA8" => "\xC2\xA8", + "\xA9" => "\xC2\xA9", + "\xAA" => "\xC5\x9E", + "\xAB" => "\xC2\xAB", + "\xAC" => "\xC2\xAC", + "\xAD" => "\xC2\xAD", + "\xAE" => "\xC2\xAE", + "\xAF" => "\xC5\xBB", + "\xB0" => "\xC2\xB0", + "\xB1" => "\xC2\xB1", + "\xB2" => "\xCB\x9B", + "\xB3" => "\xC5\x82", + "\xB4" => "\xC2\xB4", + "\xB5" => "\xC2\xB5", + "\xB6" => "\xC2\xB6", + "\xB7" => "\xC2\xB7", + "\xB8" => "\xC2\xB8", + "\xB9" => "\xC4\x85", + "\xBA" => "\xC5\x9F", + "\xBB" => "\xC2\xBB", + "\xBC" => "\xC4\xBD", + "\xBD" => "\xCB\x9D", + "\xBE" => "\xC4\xBE", + "\xBF" => "\xC5\xBC", + "\xC0" => "\xC5\x94", + "\xC1" => "\xC3\x81", + "\xC2" => "\xC3\x82", + "\xC3" => "\xC4\x82", + "\xC4" => "\xC3\x84", + "\xC5" => "\xC4\xB9", + "\xC6" => "\xC4\x86", + "\xC7" => "\xC3\x87", + "\xC8" => "\xC4\x8C", + "\xC9" => "\xC3\x89", + "\xCA" => "\xC4\x98", + "\xCB" => "\xC3\x8B", + "\xCC" => "\xC4\x9A", + "\xCD" => "\xC3\x8D", + "\xCE" => "\xC3\x8E", + "\xCF" => "\xC4\x8E", + "\xD0" => "\xC4\x90", + "\xD1" => "\xC5\x83", + "\xD2" => "\xC5\x87", + "\xD3" => "\xC3\x93", + "\xD4" => "\xC3\x94", + "\xD5" => "\xC5\x90", + "\xD6" => "\xC3\x96", + "\xD7" => "\xC3\x97", + "\xD8" => "\xC5\x98", + "\xD9" => "\xC5\xAE", + "\xDA" => "\xC3\x9A", + "\xDB" => "\xC5\xB0", + "\xDC" => "\xC3\x9C", + "\xDD" => "\xC3\x9D", + "\xDE" => "\xC5\xA2", + "\xDF" => "\xC3\x9F", + "\xE0" => "\xC5\x95", + "\xE1" => "\xC3\xA1", + "\xE2" => "\xC3\xA2", + "\xE3" => "\xC4\x83", + "\xE4" => "\xC3\xA4", + "\xE5" => "\xC4\xBA", + "\xE6" => "\xC4\x87", + "\xE7" => "\xC3\xA7", + "\xE8" => "\xC4\x8D", + "\xE9" => "\xC3\xA9", + "\xEA" => "\xC4\x99", + "\xEB" => "\xC3\xAB", + "\xEC" => "\xC4\x9B", + "\xED" => "\xC3\xAD", + "\xEE" => "\xC3\xAE", + "\xEF" => "\xC4\x8F", + "\xF0" => "\xC4\x91", + "\xF1" => "\xC5\x84", + "\xF2" => "\xC5\x88", + "\xF3" => "\xC3\xB3", + "\xF4" => "\xC3\xB4", + "\xF5" => "\xC5\x91", + "\xF6" => "\xC3\xB6", + "\xF7" => "\xC3\xB7", + "\xF8" => "\xC5\x99", + "\xF9" => "\xC5\xAF", + "\xFA" => "\xC3\xBA", + "\xFB" => "\xC5\xB1", + "\xFC" => "\xC3\xBC", + "\xFD" => "\xC3\xBD", + "\xFE" => "\xC5\xA3", + "\xFF" => "\xCB\x99", + ); + return strtr($string, $transform); +} + +function cp1251($string) +{ + static $transform = array( + "\x80" => "\xD0\x82", + "\x81" => "\xD0\x83", + "\x82" => "\xE2\x80\x9A", + "\x83" => "\xD1\x93", + "\x84" => "\xE2\x80\x9E", + "\x85" => "\xE2\x80\xA6", + "\x86" => "\xE2\x80\xA0", + "\x87" => "\xE2\x80\xA1", + "\x88" => "\xE2\x82\xAC", + "\x89" => "\xE2\x80\xB0", + "\x8A" => "\xD0\x89", + "\x8B" => "\xE2\x80\xB9", + "\x8C" => "\xD0\x8A", + "\x8D" => "\xD0\x8C", + "\x8E" => "\xD0\x8B", + "\x8F" => "\xD0\x8F", + "\x90" => "\xD1\x92", + "\x91" => "\xE2\x80\x98", + "\x92" => "\xE2\x80\x99", + "\x93" => "\xE2\x80\x9C", + "\x94" => "\xE2\x80\x9D", + "\x95" => "\xE2\x80\xA2", + "\x96" => "\xE2\x80\x93", + "\x97" => "\xE2\x80\x94", + "\x99" => "\xE2\x84\xA2", + "\x9A" => "\xD1\x99", + "\x9B" => "\xE2\x80\xBA", + "\x9C" => "\xD1\x9A", + "\x9D" => "\xD1\x9C", + "\x9E" => "\xD1\x9B", + "\x9F" => "\xD1\x9F", + "\xA0" => "\xC2\xA0", + "\xA1" => "\xD0\x8E", + "\xA2" => "\xD1\x9E", + "\xA3" => "\xD0\x88", + "\xA4" => "\xC2\xA4", + "\xA5" => "\xD2\x90", + "\xA6" => "\xC2\xA6", + "\xA7" => "\xC2\xA7", + "\xA8" => "\xD0\x81", + "\xA9" => "\xC2\xA9", + "\xAA" => "\xD0\x84", + "\xAB" => "\xC2\xAB", + "\xAC" => "\xC2\xAC", + "\xAD" => "\xC2\xAD", + "\xAE" => "\xC2\xAE", + "\xAF" => "\xD0\x87", + "\xB0" => "\xC2\xB0", + "\xB1" => "\xC2\xB1", + "\xB2" => "\xD0\x86", + "\xB3" => "\xD1\x96", + "\xB4" => "\xD2\x91", + "\xB5" => "\xC2\xB5", + "\xB6" => "\xC2\xB6", + "\xB7" => "\xC2\xB7", + "\xB8" => "\xD1\x91", + "\xB9" => "\xE2\x84\x96", + "\xBA" => "\xD1\x94", + "\xBB" => "\xC2\xBB", + "\xBC" => "\xD1\x98", + "\xBD" => "\xD0\x85", + "\xBE" => "\xD1\x95", + "\xBF" => "\xD1\x97", + "\xC0" => "\xD0\x90", + "\xC1" => "\xD0\x91", + "\xC2" => "\xD0\x92", + "\xC3" => "\xD0\x93", + "\xC4" => "\xD0\x94", + "\xC5" => "\xD0\x95", + "\xC6" => "\xD0\x96", + "\xC7" => "\xD0\x97", + "\xC8" => "\xD0\x98", + "\xC9" => "\xD0\x99", + "\xCA" => "\xD0\x9A", + "\xCB" => "\xD0\x9B", + "\xCC" => "\xD0\x9C", + "\xCD" => "\xD0\x9D", + "\xCE" => "\xD0\x9E", + "\xCF" => "\xD0\x9F", + "\xD0" => "\xD0\xA0", + "\xD1" => "\xD0\xA1", + "\xD2" => "\xD0\xA2", + "\xD3" => "\xD0\xA3", + "\xD4" => "\xD0\xA4", + "\xD5" => "\xD0\xA5", + "\xD6" => "\xD0\xA6", + "\xD7" => "\xD0\xA7", + "\xD8" => "\xD0\xA8", + "\xD9" => "\xD0\xA9", + "\xDA" => "\xD0\xAA", + "\xDB" => "\xD0\xAB", + "\xDC" => "\xD0\xAC", + "\xDD" => "\xD0\xAD", + "\xDE" => "\xD0\xAE", + "\xDF" => "\xD0\xAF", + "\xE0" => "\xD0\xB0", + "\xE1" => "\xD0\xB1", + "\xE2" => "\xD0\xB2", + "\xE3" => "\xD0\xB3", + "\xE4" => "\xD0\xB4", + "\xE5" => "\xD0\xB5", + "\xE6" => "\xD0\xB6", + "\xE7" => "\xD0\xB7", + "\xE8" => "\xD0\xB8", + "\xE9" => "\xD0\xB9", + "\xEA" => "\xD0\xBA", + "\xEB" => "\xD0\xBB", + "\xEC" => "\xD0\xBC", + "\xED" => "\xD0\xBD", + "\xEE" => "\xD0\xBE", + "\xEF" => "\xD0\xBF", + "\xF0" => "\xD1\x80", + "\xF1" => "\xD1\x81", + "\xF2" => "\xD1\x82", + "\xF3" => "\xD1\x83", + "\xF4" => "\xD1\x84", + "\xF5" => "\xD1\x85", + "\xF6" => "\xD1\x86", + "\xF7" => "\xD1\x87", + "\xF8" => "\xD1\x88", + "\xF9" => "\xD1\x89", + "\xFA" => "\xD1\x8A", + "\xFB" => "\xD1\x8B", + "\xFC" => "\xD1\x8C", + "\xFD" => "\xD1\x8D", + "\xFE" => "\xD1\x8E", + "\xFF" => "\xD1\x8F", + ); + return strtr($string, $transform); +} + +function cp1252($string) +{ + static $transform = array( + "\xC2\x80" => "\xE2\x82\xAC", + "\xC2\x82" => "\xE2\x80\x9A", + "\xC2\x83" => "\xC6\x92", + "\xC2\x84" => "\xE2\x80\x9E", + "\xC2\x85" => "\xE2\x80\xA6", + "\xC2\x86" => "\xE2\x80\xA0", + "\xC2\x87" => "\xE2\x80\xA1", + "\xC2\x88" => "\xCB\x86", + "\xC2\x89" => "\xE2\x80\xB0", + "\xC2\x8A" => "\xC5\xA0", + "\xC2\x8B" => "\xE2\x80\xB9", + "\xC2\x8C" => "\xC5\x92", + "\xC2\x8E" => "\xC5\xBD", + "\xC2\x91" => "\xE2\x80\x98", + "\xC2\x92" => "\xE2\x80\x99", + "\xC2\x93" => "\xE2\x80\x9C", + "\xC2\x94" => "\xE2\x80\x9D", + "\xC2\x95" => "\xE2\x80\xA2", + "\xC2\x96" => "\xE2\x80\x93", + "\xC2\x97" => "\xE2\x80\x94", + "\xC2\x98" => "\xCB\x9C", + "\xC2\x99" => "\xE2\x84\xA2", + "\xC2\x9A" => "\xC5\xA1", + "\xC2\x9B" => "\xE2\x80\xBA", + "\xC2\x9C" => "\xC5\x93", + "\xC2\x9E" => "\xC5\xBE", + "\xC2\x9F" => "\xC5\xB8" + ); + return strtr(utf8_encode($string), $transform); +} + +function cp1254($string) +{ + static $transform = array( + "\xC2\x80" => "\xE2\x82\xAC", + "\xC2\x82" => "\xE2\x80\x9A", + "\xC2\x83" => "\xC6\x92", + "\xC2\x84" => "\xE2\x80\x9E", + "\xC2\x85" => "\xE2\x80\xA6", + "\xC2\x86" => "\xE2\x80\xA0", + "\xC2\x87" => "\xE2\x80\xA1", + "\xC2\x88" => "\xCB\x86", + "\xC2\x89" => "\xE2\x80\xB0", + "\xC2\x8A" => "\xC5\xA0", + "\xC2\x8B" => "\xE2\x80\xB9", + "\xC2\x8C" => "\xC5\x92", + "\xC2\x91" => "\xE2\x80\x98", + "\xC2\x92" => "\xE2\x80\x99", + "\xC2\x93" => "\xE2\x80\x9C", + "\xC2\x94" => "\xE2\x80\x9D", + "\xC2\x95" => "\xE2\x80\xA2", + "\xC2\x96" => "\xE2\x80\x93", + "\xC2\x97" => "\xE2\x80\x94", + "\xC2\x98" => "\xCB\x9C", + "\xC2\x99" => "\xE2\x84\xA2", + "\xC2\x9A" => "\xC5\xA1", + "\xC2\x9B" => "\xE2\x80\xBA", + "\xC2\x9C" => "\xC5\x93", + "\xC2\x9F" => "\xC5\xB8", + "\xC3\x90" => "\xC4\x9E", + "\xC3\x9D" => "\xC4\xB0", + "\xC3\x9E" => "\xC5\x9E", + "\xC3\xB0" => "\xC4\x9F", + "\xC3\xBD" => "\xC4\xB1", + "\xC3\xBE" => "\xC5\x9F", + ); + return strtr(utf8_encode($string), $transform); +} + +function cp1255($string) +{ + static $transform = array( + "\x80" => "\xE2\x82\xAC", + "\x82" => "\xE2\x80\x9A", + "\x83" => "\xC6\x92", + "\x84" => "\xE2\x80\x9E", + "\x85" => "\xE2\x80\xA6", + "\x86" => "\xE2\x80\xA0", + "\x87" => "\xE2\x80\xA1", + "\x88" => "\xCB\x86", + "\x89" => "\xE2\x80\xB0", + "\x8B" => "\xE2\x80\xB9", + "\x91" => "\xE2\x80\x98", + "\x92" => "\xE2\x80\x99", + "\x93" => "\xE2\x80\x9C", + "\x94" => "\xE2\x80\x9D", + "\x95" => "\xE2\x80\xA2", + "\x96" => "\xE2\x80\x93", + "\x97" => "\xE2\x80\x94", + "\x98" => "\xCB\x9C", + "\x99" => "\xE2\x84\xA2", + "\x9B" => "\xE2\x80\xBA", + "\xA0" => "\xC2\xA0", + "\xA1" => "\xC2\xA1", + "\xA2" => "\xC2\xA2", + "\xA3" => "\xC2\xA3", + "\xA4" => "\xE2\x82\xAA", + "\xA5" => "\xC2\xA5", + "\xA6" => "\xC2\xA6", + "\xA7" => "\xC2\xA7", + "\xA8" => "\xC2\xA8", + "\xA9" => "\xC2\xA9", + "\xAA" => "\xC3\x97", + "\xAB" => "\xC2\xAB", + "\xAC" => "\xC2\xAC", + "\xAD" => "\xC2\xAD", + "\xAE" => "\xC2\xAE", + "\xAF" => "\xC2\xAF", + "\xB0" => "\xC2\xB0", + "\xB1" => "\xC2\xB1", + "\xB2" => "\xC2\xB2", + "\xB3" => "\xC2\xB3", + "\xB4" => "\xC2\xB4", + "\xB5" => "\xC2\xB5", + "\xB6" => "\xC2\xB6", + "\xB7" => "\xC2\xB7", + "\xB8" => "\xC2\xB8", + "\xB9" => "\xC2\xB9", + "\xBA" => "\xC3\xB7", + "\xBB" => "\xC2\xBB", + "\xBC" => "\xC2\xBC", + "\xBD" => "\xC2\xBD", + "\xBE" => "\xC2\xBE", + "\xBF" => "\xC2\xBF", + "\xC0" => "\xD6\xB0", + "\xC1" => "\xD6\xB1", + "\xC2" => "\xD6\xB2", + "\xC3" => "\xD6\xB3", + "\xC4" => "\xD6\xB4", + "\xC5" => "\xD6\xB5", + "\xC6" => "\xD6\xB6", + "\xC7" => "\xD6\xB7", + "\xC8" => "\xD6\xB8", + "\xC9" => "\xD6\xB9", + "\xCB" => "\xD6\xBB", + "\xCC" => "\xD6\xBC", + "\xCD" => "\xD6\xBD", + "\xCE" => "\xD6\xBE", + "\xCF" => "\xD6\xBF", + "\xD0" => "\xD7\x80", + "\xD1" => "\xD7\x81", + "\xD2" => "\xD7\x82", + "\xD3" => "\xD7\x83", + "\xD4" => "\xD7\xB0", + "\xD5" => "\xD7\xB1", + "\xD6" => "\xD7\xB2", + "\xD7" => "\xD7\xB3", + "\xD8" => "\xD7\xB4", + "\xE0" => "\xD7\x90", + "\xE1" => "\xD7\x91", + "\xE2" => "\xD7\x92", + "\xE3" => "\xD7\x93", + "\xE4" => "\xD7\x94", + "\xE5" => "\xD7\x95", + "\xE6" => "\xD7\x96", + "\xE7" => "\xD7\x97", + "\xE8" => "\xD7\x98", + "\xE9" => "\xD7\x99", + "\xEA" => "\xD7\x9A", + "\xEB" => "\xD7\x9B", + "\xEC" => "\xD7\x9C", + "\xED" => "\xD7\x9D", + "\xEE" => "\xD7\x9E", + "\xEF" => "\xD7\x9F", + "\xF0" => "\xD7\xA0", + "\xF1" => "\xD7\xA1", + "\xF2" => "\xD7\xA2", + "\xF3" => "\xD7\xA3", + "\xF4" => "\xD7\xA4", + "\xF5" => "\xD7\xA5", + "\xF6" => "\xD7\xA6", + "\xF7" => "\xD7\xA7", + "\xF8" => "\xD7\xA8", + "\xF9" => "\xD7\xA9", + "\xFA" => "\xD7\xAA", + "\xFD" => "\xE2\x80\x8E", + "\xFE" => "\xE2\x80\x8F", + ); + return strtr($string, $transform); +} + +function cp1256($string) +{ + static $transform = array( + "\x80" => "\xE2\x82\xAC", + "\x81" => "\xD9\xBE", + "\x82" => "\xE2\x80\x9A", + "\x83" => "\xC6\x92", + "\x84" => "\xE2\x80\x9E", + "\x85" => "\xE2\x80\xA6", + "\x86" => "\xE2\x80\xA0", + "\x87" => "\xE2\x80\xA1", + "\x88" => "\xCB\x86", + "\x89" => "\xE2\x80\xB0", + "\x8A" => "\xD9\xB9", + "\x8B" => "\xE2\x80\xB9", + "\x8C" => "\xC5\x92", + "\x8D" => "\xDA\x86", + "\x8E" => "\xDA\x98", + "\x8F" => "\xDA\x88", + "\x90" => "\xDA\xAF", + "\x91" => "\xE2\x80\x98", + "\x92" => "\xE2\x80\x99", + "\x93" => "\xE2\x80\x9C", + "\x94" => "\xE2\x80\x9D", + "\x95" => "\xE2\x80\xA2", + "\x96" => "\xE2\x80\x93", + "\x97" => "\xE2\x80\x94", + "\x98" => "\xDA\xA9", + "\x99" => "\xE2\x84\xA2", + "\x9A" => "\xDA\x91", + "\x9B" => "\xE2\x80\xBA", + "\x9C" => "\xC5\x93", + "\x9D" => "\xE2\x80\x8C", + "\x9E" => "\xE2\x80\x8D", + "\x9F" => "\xDA\xBA", + "\xA0" => "\xC2\xA0", + "\xA1" => "\xD8\x8C", + "\xA2" => "\xC2\xA2", + "\xA3" => "\xC2\xA3", + "\xA4" => "\xC2\xA4", + "\xA5" => "\xC2\xA5", + "\xA6" => "\xC2\xA6", + "\xA7" => "\xC2\xA7", + "\xA8" => "\xC2\xA8", + "\xA9" => "\xC2\xA9", + "\xAA" => "\xDA\xBE", + "\xAB" => "\xC2\xAB", + "\xAC" => "\xC2\xAC", + "\xAD" => "\xC2\xAD", + "\xAE" => "\xC2\xAE", + "\xAF" => "\xC2\xAF", + "\xB0" => "\xC2\xB0", + "\xB1" => "\xC2\xB1", + "\xB2" => "\xC2\xB2", + "\xB3" => "\xC2\xB3", + "\xB4" => "\xC2\xB4", + "\xB5" => "\xC2\xB5", + "\xB6" => "\xC2\xB6", + "\xB7" => "\xC2\xB7", + "\xB8" => "\xC2\xB8", + "\xB9" => "\xC2\xB9", + "\xBA" => "\xD8\x9B", + "\xBB" => "\xC2\xBB", + "\xBC" => "\xC2\xBC", + "\xBD" => "\xC2\xBD", + "\xBE" => "\xC2\xBE", + "\xBF" => "\xD8\x9F", + "\xC0" => "\xDB\x81", + "\xC1" => "\xD8\xA1", + "\xC2" => "\xD8\xA2", + "\xC3" => "\xD8\xA3", + "\xC4" => "\xD8\xA4", + "\xC5" => "\xD8\xA5", + "\xC6" => "\xD8\xA6", + "\xC7" => "\xD8\xA7", + "\xC8" => "\xD8\xA8", + "\xC9" => "\xD8\xA9", + "\xCA" => "\xD8\xAA", + "\xCB" => "\xD8\xAB", + "\xCC" => "\xD8\xAC", + "\xCD" => "\xD8\xAD", + "\xCE" => "\xD8\xAE", + "\xCF" => "\xD8\xAF", + "\xD0" => "\xD8\xB0", + "\xD1" => "\xD8\xB1", + "\xD2" => "\xD8\xB2", + "\xD3" => "\xD8\xB3", + "\xD4" => "\xD8\xB4", + "\xD5" => "\xD8\xB5", + "\xD6" => "\xD8\xB6", + "\xD7" => "\xC3\x97", + "\xD8" => "\xD8\xB7", + "\xD9" => "\xD8\xB8", + "\xDA" => "\xD8\xB9", + "\xDB" => "\xD8\xBA", + "\xDC" => "\xD9\x80", + "\xDD" => "\xD9\x81", + "\xDE" => "\xD9\x82", + "\xDF" => "\xD9\x83", + "\xE0" => "\xC3\xA0", + "\xE1" => "\xD9\x84", + "\xE2" => "\xC3\xA2", + "\xE3" => "\xD9\x85", + "\xE4" => "\xD9\x86", + "\xE5" => "\xD9\x87", + "\xE6" => "\xD9\x88", + "\xE7" => "\xC3\xA7", + "\xE8" => "\xC3\xA8", + "\xE9" => "\xC3\xA9", + "\xEA" => "\xC3\xAA", + "\xEB" => "\xC3\xAB", + "\xEC" => "\xD9\x89", + "\xED" => "\xD9\x8A", + "\xEE" => "\xC3\xAE", + "\xEF" => "\xC3\xAF", + "\xF0" => "\xD9\x8B", + "\xF1" => "\xD9\x8C", + "\xF2" => "\xD9\x8D", + "\xF3" => "\xD9\x8E", + "\xF4" => "\xC3\xB4", + "\xF5" => "\xD9\x8F", + "\xF6" => "\xD9\x90", + "\xF7" => "\xC3\xB7", + "\xF8" => "\xD9\x91", + "\xF9" => "\xC3\xB9", + "\xFA" => "\xD9\x92", + "\xFB" => "\xC3\xBB", + "\xFC" => "\xC3\xBC", + "\xFD" => "\xE2\x80\x8E", + "\xFE" => "\xE2\x80\x8F", + "\xFF" => "\xDB\x92", + ); + return strtr($string, $transform); +} + +function cp1257($string) +{ + static $transform = array( + "\x80" => "\xE2\x82\xAC", + "\x82" => "\xE2\x80\x9A", + "\x84" => "\xE2\x80\x9E", + "\x85" => "\xE2\x80\xA6", + "\x86" => "\xE2\x80\xA0", + "\x87" => "\xE2\x80\xA1", + "\x89" => "\xE2\x80\xB0", + "\x8B" => "\xE2\x80\xB9", + "\x8D" => "\xC2\xA8", + "\x8E" => "\xCB\x87", + "\x8F" => "\xC2\xB8", + "\x91" => "\xE2\x80\x98", + "\x92" => "\xE2\x80\x99", + "\x93" => "\xE2\x80\x9C", + "\x94" => "\xE2\x80\x9D", + "\x95" => "\xE2\x80\xA2", + "\x96" => "\xE2\x80\x93", + "\x97" => "\xE2\x80\x94", + "\x99" => "\xE2\x84\xA2", + "\x9B" => "\xE2\x80\xBA", + "\x9D" => "\xC2\xAF", + "\x9E" => "\xCB\x9B", + "\xA0" => "\xC2\xA0", + "\xA2" => "\xC2\xA2", + "\xA3" => "\xC2\xA3", + "\xA4" => "\xC2\xA4", + "\xA6" => "\xC2\xA6", + "\xA7" => "\xC2\xA7", + "\xA8" => "\xC3\x98", + "\xA9" => "\xC2\xA9", + "\xAA" => "\xC5\x96", + "\xAB" => "\xC2\xAB", + "\xAC" => "\xC2\xAC", + "\xAD" => "\xC2\xAD", + "\xAE" => "\xC2\xAE", + "\xAF" => "\xC3\x86", + "\xB0" => "\xC2\xB0", + "\xB1" => "\xC2\xB1", + "\xB2" => "\xC2\xB2", + "\xB3" => "\xC2\xB3", + "\xB4" => "\xC2\xB4", + "\xB5" => "\xC2\xB5", + "\xB6" => "\xC2\xB6", + "\xB7" => "\xC2\xB7", + "\xB8" => "\xC3\xB8", + "\xB9" => "\xC2\xB9", + "\xBA" => "\xC5\x97", + "\xBB" => "\xC2\xBB", + "\xBC" => "\xC2\xBC", + "\xBD" => "\xC2\xBD", + "\xBE" => "\xC2\xBE", + "\xBF" => "\xC3\xA6", + "\xC0" => "\xC4\x84", + "\xC1" => "\xC4\xAE", + "\xC2" => "\xC4\x80", + "\xC3" => "\xC4\x86", + "\xC4" => "\xC3\x84", + "\xC5" => "\xC3\x85", + "\xC6" => "\xC4\x98", + "\xC7" => "\xC4\x92", + "\xC8" => "\xC4\x8C", + "\xC9" => "\xC3\x89", + "\xCA" => "\xC5\xB9", + "\xCB" => "\xC4\x96", + "\xCC" => "\xC4\xA2", + "\xCD" => "\xC4\xB6", + "\xCE" => "\xC4\xAA", + "\xCF" => "\xC4\xBB", + "\xD0" => "\xC5\xA0", + "\xD1" => "\xC5\x83", + "\xD2" => "\xC5\x85", + "\xD3" => "\xC3\x93", + "\xD4" => "\xC5\x8C", + "\xD5" => "\xC3\x95", + "\xD6" => "\xC3\x96", + "\xD7" => "\xC3\x97", + "\xD8" => "\xC5\xB2", + "\xD9" => "\xC5\x81", + "\xDA" => "\xC5\x9A", + "\xDB" => "\xC5\xAA", + "\xDC" => "\xC3\x9C", + "\xDD" => "\xC5\xBB", + "\xDE" => "\xC5\xBD", + "\xDF" => "\xC3\x9F", + "\xE0" => "\xC4\x85", + "\xE1" => "\xC4\xAF", + "\xE2" => "\xC4\x81", + "\xE3" => "\xC4\x87", + "\xE4" => "\xC3\xA4", + "\xE5" => "\xC3\xA5", + "\xE6" => "\xC4\x99", + "\xE7" => "\xC4\x93", + "\xE8" => "\xC4\x8D", + "\xE9" => "\xC3\xA9", + "\xEA" => "\xC5\xBA", + "\xEB" => "\xC4\x97", + "\xEC" => "\xC4\xA3", + "\xED" => "\xC4\xB7", + "\xEE" => "\xC4\xAB", + "\xEF" => "\xC4\xBC", + "\xF0" => "\xC5\xA1", + "\xF1" => "\xC5\x84", + "\xF2" => "\xC5\x86", + "\xF3" => "\xC3\xB3", + "\xF4" => "\xC5\x8D", + "\xF5" => "\xC3\xB5", + "\xF6" => "\xC3\xB6", + "\xF7" => "\xC3\xB7", + "\xF8" => "\xC5\xB3", + "\xF9" => "\xC5\x82", + "\xFA" => "\xC5\x9B", + "\xFB" => "\xC5\xAB", + "\xFC" => "\xC3\xBC", + "\xFD" => "\xC5\xBC", + "\xFE" => "\xC5\xBE", + "\xFF" => "\xCB\x99", + ); + return strtr($string, $transform); +} + +function utf8_to_cp1252($string) +{ + static $transform = array( + "\xE2\x82\xAC" => "\x80", + "\xE2\x80\x9A" => "\x82", + "\xC6\x92" => "\x83", + "\xE2\x80\x9E" => "\x84", + "\xE2\x80\xA6" => "\x85", + "\xE2\x80\xA0" => "\x86", + "\xE2\x80\xA1" => "\x87", + "\xCB\x86" => "\x88", + "\xE2\x80\xB0" => "\x89", + "\xC5\xA0" => "\x8A", + "\xE2\x80\xB9" => "\x8B", + "\xC5\x92" => "\x8C", + "\xC5\xBD" => "\x8E", + "\xE2\x80\x98" => "\x91", + "\xE2\x80\x99" => "\x92", + "\xE2\x80\x9C" => "\x93", + "\xE2\x80\x9D" => "\x94", + "\xE2\x80\xA2" => "\x95", + "\xE2\x80\x93" => "\x96", + "\xE2\x80\x94" => "\x97", + "\xCB\x9C" => "\x98", + "\xE2\x84\xA2" => "\x99", + "\xC5\xA1" => "\x9A", + "\xE2\x80\xBA" => "\x9B", + "\xC5\x93" => "\x9C", + "\xC5\xBE" => "\x9E", + "\xC5\xB8" => "\x9F", + "\xC2\xA0" => "\xA0", + "\xC2\xA1" => "\xA1", + "\xC2\xA2" => "\xA2", + "\xC2\xA3" => "\xA3", + "\xC2\xA4" => "\xA4", + "\xC2\xA5" => "\xA5", + "\xC2\xA6" => "\xA6", + "\xC2\xA7" => "\xA7", + "\xC2\xA8" => "\xA8", + "\xC2\xA9" => "\xA9", + "\xC2\xAA" => "\xAA", + "\xC2\xAB" => "\xAB", + "\xC2\xAC" => "\xAC", + "\xC2\xAD" => "\xAD", + "\xC2\xAE" => "\xAE", + "\xC2\xAF" => "\xAF", + "\xC2\xB0" => "\xB0", + "\xC2\xB1" => "\xB1", + "\xC2\xB2" => "\xB2", + "\xC2\xB3" => "\xB3", + "\xC2\xB4" => "\xB4", + "\xC2\xB5" => "\xB5", + "\xC2\xB6" => "\xB6", + "\xC2\xB7" => "\xB7", + "\xC2\xB8" => "\xB8", + "\xC2\xB9" => "\xB9", + "\xC2\xBA" => "\xBA", + "\xC2\xBB" => "\xBB", + "\xC2\xBC" => "\xBC", + "\xC2\xBD" => "\xBD", + "\xC2\xBE" => "\xBE", + "\xC2\xBF" => "\xBF", + "\xC3\x80" => "\xC0", + "\xC3\x81" => "\xC1", + "\xC3\x82" => "\xC2", + "\xC3\x83" => "\xC3", + "\xC3\x84" => "\xC4", + "\xC3\x85" => "\xC5", + "\xC3\x86" => "\xC6", + "\xC3\x87" => "\xC7", + "\xC3\x88" => "\xC8", + "\xC3\x89" => "\xC9", + "\xC3\x8A" => "\xCA", + "\xC3\x8B" => "\xCB", + "\xC3\x8C" => "\xCC", + "\xC3\x8D" => "\xCD", + "\xC3\x8E" => "\xCE", + "\xC3\x8F" => "\xCF", + "\xC3\x90" => "\xD0", + "\xC3\x91" => "\xD1", + "\xC3\x92" => "\xD2", + "\xC3\x93" => "\xD3", + "\xC3\x94" => "\xD4", + "\xC3\x95" => "\xD5", + "\xC3\x96" => "\xD6", + "\xC3\x97" => "\xD7", + "\xC3\x98" => "\xD8", + "\xC3\x99" => "\xD9", + "\xC3\x9A" => "\xDA", + "\xC3\x9B" => "\xDB", + "\xC3\x9C" => "\xDC", + "\xC3\x9D" => "\xDD", + "\xC3\x9E" => "\xDE", + "\xC3\x9F" => "\xDF", + "\xC3\xA0" => "\xE0", + "\xC3\xA1" => "\xE1", + "\xC3\xA2" => "\xE2", + "\xC3\xA3" => "\xE3", + "\xC3\xA4" => "\xE4", + "\xC3\xA5" => "\xE5", + "\xC3\xA6" => "\xE6", + "\xC3\xA7" => "\xE7", + "\xC3\xA8" => "\xE8", + "\xC3\xA9" => "\xE9", + "\xC3\xAA" => "\xEA", + "\xC3\xAB" => "\xEB", + "\xC3\xAC" => "\xEC", + "\xC3\xAD" => "\xED", + "\xC3\xAE" => "\xEE", + "\xC3\xAF" => "\xEF", + "\xC3\xB0" => "\xF0", + "\xC3\xB1" => "\xF1", + "\xC3\xB2" => "\xF2", + "\xC3\xB3" => "\xF3", + "\xC3\xB4" => "\xF4", + "\xC3\xB5" => "\xF5", + "\xC3\xB6" => "\xF6", + "\xC3\xB7" => "\xF7", + "\xC3\xB8" => "\xF8", + "\xC3\xB9" => "\xF9", + "\xC3\xBA" => "\xFA", + "\xC3\xBB" => "\xFB", + "\xC3\xBC" => "\xFC", + "\xC3\xBD" => "\xFD", + "\xC3\xBE" => "\xFE", + "\xC3\xBF" => "\xFF" + ); + return strtr($string, $transform); +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/utf/data/recode_cjk.php b/phpBB/includes/utf/data/recode_cjk.php new file mode 100644 index 0000000000..f3f9a256d7 --- /dev/null +++ b/phpBB/includes/utf/data/recode_cjk.php @@ -0,0 +1,45179 @@ +<?php +// Not inluded within the standard distribution + +function gb2312($string) +{ + static $transform = array( + "\xA1\xA1" => "\xE3\x80\x80", + "\xA1\xA2" => "\xE3\x80\x81", + "\xA1\xA3" => "\xE3\x80\x82", + "\xA1\xA4" => "\xE3\x83\xBB", + "\xA1\xA5" => "\xCB\x89", + "\xA1\xA6" => "\xCB\x87", + "\xA1\xA7" => "\xC2\xA8", + "\xA1\xA8" => "\xE3\x80\x83", + "\xA1\xA9" => "\xE3\x80\x85", + "\xA1\xAA" => "\xE2\x80\x95", + "\xA1\xAB" => "\xEF\xBD\x9E", + "\xA1\xAC" => "\xE2\x80\x96", + "\xA1\xAD" => "\xE2\x80\xA6", + "\xA1\xAE" => "\xE2\x80\x98", + "\xA1\xAF" => "\xE2\x80\x99", + "\xA1\xB0" => "\xE2\x80\x9C", + "\xA1\xB1" => "\xE2\x80\x9D", + "\xA1\xB2" => "\xE3\x80\x94", + "\xA1\xB3" => "\xE3\x80\x95", + "\xA1\xB4" => "\xE3\x80\x88", + "\xA1\xB5" => "\xE3\x80\x89", + "\xA1\xB6" => "\xE3\x80\x8A", + "\xA1\xB7" => "\xE3\x80\x8B", + "\xA1\xB8" => "\xE3\x80\x8C", + "\xA1\xB9" => "\xE3\x80\x8D", + "\xA1\xBA" => "\xE3\x80\x8E", + "\xA1\xBB" => "\xE3\x80\x8F", + "\xA1\xBC" => "\xE3\x80\x96", + "\xA1\xBD" => "\xE3\x80\x97", + "\xA1\xBE" => "\xE3\x80\x90", + "\xA1\xBF" => "\xE3\x80\x91", + "\xA1\xC0" => "\xC2\xB1", + "\xA1\xC1" => "\xC3\x97", + "\xA1\xC2" => "\xC3\xB7", + "\xA1\xC3" => "\xE2\x88\xB6", + "\xA1\xC4" => "\xE2\x88\xA7", + "\xA1\xC5" => "\xE2\x88\xA8", + "\xA1\xC6" => "\xE2\x88\x91", + "\xA1\xC7" => "\xE2\x88\x8F", + "\xA1\xC8" => "\xE2\x88\xAA", + "\xA1\xC9" => "\xE2\x88\xA9", + "\xA1\xCA" => "\xE2\x88\x88", + "\xA1\xCB" => "\xE2\x88\xB7", + "\xA1\xCC" => "\xE2\x88\x9A", + "\xA1\xCD" => "\xE2\x8A\xA5", + "\xA1\xCE" => "\xE2\x88\xA5", + "\xA1\xCF" => "\xE2\x88\xA0", + "\xA1\xD0" => "\xE2\x8C\x92", + "\xA1\xD1" => "\xE2\x8A\x99", + "\xA1\xD2" => "\xE2\x88\xAB", + "\xA1\xD3" => "\xE2\x88\xAE", + "\xA1\xD4" => "\xE2\x89\xA1", + "\xA1\xD5" => "\xE2\x89\x8C", + "\xA1\xD6" => "\xE2\x89\x88", + "\xA1\xD7" => "\xE2\x88\xBD", + "\xA1\xD8" => "\xE2\x88\x9D", + "\xA1\xD9" => "\xE2\x89\xA0", + "\xA1\xDA" => "\xE2\x89\xAE", + "\xA1\xDB" => "\xE2\x89\xAF", + "\xA1\xDC" => "\xE2\x89\xA4", + "\xA1\xDD" => "\xE2\x89\xA5", + "\xA1\xDE" => "\xE2\x88\x9E", + "\xA1\xDF" => "\xE2\x88\xB5", + "\xA1\xE0" => "\xE2\x88\xB4", + "\xA1\xE1" => "\xE2\x99\x82", + "\xA1\xE2" => "\xE2\x99\x80", + "\xA1\xE3" => "\xC2\xB0", + "\xA1\xE4" => "\xE2\x80\xB2", + "\xA1\xE5" => "\xE2\x80\xB3", + "\xA1\xE6" => "\xE2\x84\x83", + "\xA1\xE7" => "\xEF\xBC\x84", + "\xA1\xE8" => "\xC2\xA4", + "\xA1\xE9" => "\xEF\xBF\xA0", + "\xA1\xEA" => "\xEF\xBF\xA1", + "\xA1\xEB" => "\xE2\x80\xB0", + "\xA1\xEC" => "\xC2\xA7", + "\xA1\xED" => "\xE2\x84\x96", + "\xA1\xEE" => "\xE2\x98\x86", + "\xA1\xEF" => "\xE2\x98\x85", + "\xA1\xF0" => "\xE2\x97\x8B", + "\xA1\xF1" => "\xE2\x97\x8F", + "\xA1\xF2" => "\xE2\x97\x8E", + "\xA1\xF3" => "\xE2\x97\x87", + "\xA1\xF4" => "\xE2\x97\x86", + "\xA1\xF5" => "\xE2\x96\xA1", + "\xA1\xF6" => "\xE2\x96\xA0", + "\xA1\xF7" => "\xE2\x96\xB3", + "\xA1\xF8" => "\xE2\x96\xB2", + "\xA1\xF9" => "\xE2\x80\xBB", + "\xA1\xFA" => "\xE2\x86\x92", + "\xA1\xFB" => "\xE2\x86\x90", + "\xA1\xFC" => "\xE2\x86\x91", + "\xA1\xFD" => "\xE2\x86\x93", + "\xA1\xFE" => "\xE3\x80\x93", + "\xA2\xB1" => "\xE2\x92\x88", + "\xA2\xB2" => "\xE2\x92\x89", + "\xA2\xB3" => "\xE2\x92\x8A", + "\xA2\xB4" => "\xE2\x92\x8B", + "\xA2\xB5" => "\xE2\x92\x8C", + "\xA2\xB6" => "\xE2\x92\x8D", + "\xA2\xB7" => "\xE2\x92\x8E", + "\xA2\xB8" => "\xE2\x92\x8F", + "\xA2\xB9" => "\xE2\x92\x90", + "\xA2\xBA" => "\xE2\x92\x91", + "\xA2\xBB" => "\xE2\x92\x92", + "\xA2\xBC" => "\xE2\x92\x93", + "\xA2\xBD" => "\xE2\x92\x94", + "\xA2\xBE" => "\xE2\x92\x95", + "\xA2\xBF" => "\xE2\x92\x96", + "\xA2\xC0" => "\xE2\x92\x97", + "\xA2\xC1" => "\xE2\x92\x98", + "\xA2\xC2" => "\xE2\x92\x99", + "\xA2\xC3" => "\xE2\x92\x9A", + "\xA2\xC4" => "\xE2\x92\x9B", + "\xA2\xC5" => "\xE2\x91\xB4", + "\xA2\xC6" => "\xE2\x91\xB5", + "\xA2\xC7" => "\xE2\x91\xB6", + "\xA2\xC8" => "\xE2\x91\xB7", + "\xA2\xC9" => "\xE2\x91\xB8", + "\xA2\xCA" => "\xE2\x91\xB9", + "\xA2\xCB" => "\xE2\x91\xBA", + "\xA2\xCC" => "\xE2\x91\xBB", + "\xA2\xCD" => "\xE2\x91\xBC", + "\xA2\xCE" => "\xE2\x91\xBD", + "\xA2\xCF" => "\xE2\x91\xBE", + "\xA2\xD0" => "\xE2\x91\xBF", + "\xA2\xD1" => "\xE2\x92\x80", + "\xA2\xD2" => "\xE2\x92\x81", + "\xA2\xD3" => "\xE2\x92\x82", + "\xA2\xD4" => "\xE2\x92\x83", + "\xA2\xD5" => "\xE2\x92\x84", + "\xA2\xD6" => "\xE2\x92\x85", + "\xA2\xD7" => "\xE2\x92\x86", + "\xA2\xD8" => "\xE2\x92\x87", + "\xA2\xD9" => "\xE2\x91\xA0", + "\xA2\xDA" => "\xE2\x91\xA1", + "\xA2\xDB" => "\xE2\x91\xA2", + "\xA2\xDC" => "\xE2\x91\xA3", + "\xA2\xDD" => "\xE2\x91\xA4", + "\xA2\xDE" => "\xE2\x91\xA5", + "\xA2\xDF" => "\xE2\x91\xA6", + "\xA2\xE0" => "\xE2\x91\xA7", + "\xA2\xE1" => "\xE2\x91\xA8", + "\xA2\xE2" => "\xE2\x91\xA9", + "\xA2\xE5" => "\xE3\x88\xA0", + "\xA2\xE6" => "\xE3\x88\xA1", + "\xA2\xE7" => "\xE3\x88\xA2", + "\xA2\xE8" => "\xE3\x88\xA3", + "\xA2\xE9" => "\xE3\x88\xA4", + "\xA2\xEA" => "\xE3\x88\xA5", + "\xA2\xEB" => "\xE3\x88\xA6", + "\xA2\xEC" => "\xE3\x88\xA7", + "\xA2\xED" => "\xE3\x88\xA8", + "\xA2\xEE" => "\xE3\x88\xA9", + "\xA2\xF1" => "\xE2\x85\xA0", + "\xA2\xF2" => "\xE2\x85\xA1", + "\xA2\xF3" => "\xE2\x85\xA2", + "\xA2\xF4" => "\xE2\x85\xA3", + "\xA2\xF5" => "\xE2\x85\xA4", + "\xA2\xF6" => "\xE2\x85\xA5", + "\xA2\xF7" => "\xE2\x85\xA6", + "\xA2\xF8" => "\xE2\x85\xA7", + "\xA2\xF9" => "\xE2\x85\xA8", + "\xA2\xFA" => "\xE2\x85\xA9", + "\xA2\xFB" => "\xE2\x85\xAA", + "\xA2\xFC" => "\xE2\x85\xAB", + "\xA3\xA1" => "\xEF\xBC\x81", + "\xA3\xA2" => "\xEF\xBC\x82", + "\xA3\xA3" => "\xEF\xBC\x83", + "\xA3\xA4" => "\xEF\xBF\xA5", + "\xA3\xA5" => "\xEF\xBC\x85", + "\xA3\xA6" => "\xEF\xBC\x86", + "\xA3\xA7" => "\xEF\xBC\x87", + "\xA3\xA8" => "\xEF\xBC\x88", + "\xA3\xA9" => "\xEF\xBC\x89", + "\xA3\xAA" => "\xEF\xBC\x8A", + "\xA3\xAB" => "\xEF\xBC\x8B", + "\xA3\xAC" => "\xEF\xBC\x8C", + "\xA3\xAD" => "\xEF\xBC\x8D", + "\xA3\xAE" => "\xEF\xBC\x8E", + "\xA3\xAF" => "\xEF\xBC\x8F", + "\xA3\xB0" => "\xEF\xBC\x90", + "\xA3\xB1" => "\xEF\xBC\x91", + "\xA3\xB2" => "\xEF\xBC\x92", + "\xA3\xB3" => "\xEF\xBC\x93", + "\xA3\xB4" => "\xEF\xBC\x94", + "\xA3\xB5" => "\xEF\xBC\x95", + "\xA3\xB6" => "\xEF\xBC\x96", + "\xA3\xB7" => "\xEF\xBC\x97", + "\xA3\xB8" => "\xEF\xBC\x98", + "\xA3\xB9" => "\xEF\xBC\x99", + "\xA3\xBA" => "\xEF\xBC\x9A", + "\xA3\xBB" => "\xEF\xBC\x9B", + "\xA3\xBC" => "\xEF\xBC\x9C", + "\xA3\xBD" => "\xEF\xBC\x9D", + "\xA3\xBE" => "\xEF\xBC\x9E", + "\xA3\xBF" => "\xEF\xBC\x9F", + "\xA3\xC0" => "\xEF\xBC\xA0", + "\xA3\xC1" => "\xEF\xBC\xA1", + "\xA3\xC2" => "\xEF\xBC\xA2", + "\xA3\xC3" => "\xEF\xBC\xA3", + "\xA3\xC4" => "\xEF\xBC\xA4", + "\xA3\xC5" => "\xEF\xBC\xA5", + "\xA3\xC6" => "\xEF\xBC\xA6", + "\xA3\xC7" => "\xEF\xBC\xA7", + "\xA3\xC8" => "\xEF\xBC\xA8", + "\xA3\xC9" => "\xEF\xBC\xA9", + "\xA3\xCA" => "\xEF\xBC\xAA", + "\xA3\xCB" => "\xEF\xBC\xAB", + "\xA3\xCC" => "\xEF\xBC\xAC", + "\xA3\xCD" => "\xEF\xBC\xAD", + "\xA3\xCE" => "\xEF\xBC\xAE", + "\xA3\xCF" => "\xEF\xBC\xAF", + "\xA3\xD0" => "\xEF\xBC\xB0", + "\xA3\xD1" => "\xEF\xBC\xB1", + "\xA3\xD2" => "\xEF\xBC\xB2", + "\xA3\xD3" => "\xEF\xBC\xB3", + "\xA3\xD4" => "\xEF\xBC\xB4", + "\xA3\xD5" => "\xEF\xBC\xB5", + "\xA3\xD6" => "\xEF\xBC\xB6", + "\xA3\xD7" => "\xEF\xBC\xB7", + "\xA3\xD8" => "\xEF\xBC\xB8", + "\xA3\xD9" => "\xEF\xBC\xB9", + "\xA3\xDA" => "\xEF\xBC\xBA", + "\xA3\xDB" => "\xEF\xBC\xBB", + "\xA3\xDC" => "\xEF\xBC\xBC", + "\xA3\xDD" => "\xEF\xBC\xBD", + "\xA3\xDE" => "\xEF\xBC\xBE", + "\xA3\xDF" => "\xEF\xBC\xBF", + "\xA3\xE0" => "\xEF\xBD\x80", + "\xA3\xE1" => "\xEF\xBD\x81", + "\xA3\xE2" => "\xEF\xBD\x82", + "\xA3\xE3" => "\xEF\xBD\x83", + "\xA3\xE4" => "\xEF\xBD\x84", + "\xA3\xE5" => "\xEF\xBD\x85", + "\xA3\xE6" => "\xEF\xBD\x86", + "\xA3\xE7" => "\xEF\xBD\x87", + "\xA3\xE8" => "\xEF\xBD\x88", + "\xA3\xE9" => "\xEF\xBD\x89", + "\xA3\xEA" => "\xEF\xBD\x8A", + "\xA3\xEB" => "\xEF\xBD\x8B", + "\xA3\xEC" => "\xEF\xBD\x8C", + "\xA3\xED" => "\xEF\xBD\x8D", + "\xA3\xEE" => "\xEF\xBD\x8E", + "\xA3\xEF" => "\xEF\xBD\x8F", + "\xA3\xF0" => "\xEF\xBD\x90", + "\xA3\xF1" => "\xEF\xBD\x91", + "\xA3\xF2" => "\xEF\xBD\x92", + "\xA3\xF3" => "\xEF\xBD\x93", + "\xA3\xF4" => "\xEF\xBD\x94", + "\xA3\xF5" => "\xEF\xBD\x95", + "\xA3\xF6" => "\xEF\xBD\x96", + "\xA3\xF7" => "\xEF\xBD\x97", + "\xA3\xF8" => "\xEF\xBD\x98", + "\xA3\xF9" => "\xEF\xBD\x99", + "\xA3\xFA" => "\xEF\xBD\x9A", + "\xA3\xFB" => "\xEF\xBD\x9B", + "\xA3\xFC" => "\xEF\xBD\x9C", + "\xA3\xFD" => "\xEF\xBD\x9D", + "\xA3\xFE" => "\xEF\xBF\xA3", + "\xA4\xA1" => "\xE3\x81\x81", + "\xA4\xA2" => "\xE3\x81\x82", + "\xA4\xA3" => "\xE3\x81\x83", + "\xA4\xA4" => "\xE3\x81\x84", + "\xA4\xA5" => "\xE3\x81\x85", + "\xA4\xA6" => "\xE3\x81\x86", + "\xA4\xA7" => "\xE3\x81\x87", + "\xA4\xA8" => "\xE3\x81\x88", + "\xA4\xA9" => "\xE3\x81\x89", + "\xA4\xAA" => "\xE3\x81\x8A", + "\xA4\xAB" => "\xE3\x81\x8B", + "\xA4\xAC" => "\xE3\x81\x8C", + "\xA4\xAD" => "\xE3\x81\x8D", + "\xA4\xAE" => "\xE3\x81\x8E", + "\xA4\xAF" => "\xE3\x81\x8F", + "\xA4\xB0" => "\xE3\x81\x90", + "\xA4\xB1" => "\xE3\x81\x91", + "\xA4\xB2" => "\xE3\x81\x92", + "\xA4\xB3" => "\xE3\x81\x93", + "\xA4\xB4" => "\xE3\x81\x94", + "\xA4\xB5" => "\xE3\x81\x95", + "\xA4\xB6" => "\xE3\x81\x96", + "\xA4\xB7" => "\xE3\x81\x97", + "\xA4\xB8" => "\xE3\x81\x98", + "\xA4\xB9" => "\xE3\x81\x99", + "\xA4\xBA" => "\xE3\x81\x9A", + "\xA4\xBB" => "\xE3\x81\x9B", + "\xA4\xBC" => "\xE3\x81\x9C", + "\xA4\xBD" => "\xE3\x81\x9D", + "\xA4\xBE" => "\xE3\x81\x9E", + "\xA4\xBF" => "\xE3\x81\x9F", + "\xA4\xC0" => "\xE3\x81\xA0", + "\xA4\xC1" => "\xE3\x81\xA1", + "\xA4\xC2" => "\xE3\x81\xA2", + "\xA4\xC3" => "\xE3\x81\xA3", + "\xA4\xC4" => "\xE3\x81\xA4", + "\xA4\xC5" => "\xE3\x81\xA5", + "\xA4\xC6" => "\xE3\x81\xA6", + "\xA4\xC7" => "\xE3\x81\xA7", + "\xA4\xC8" => "\xE3\x81\xA8", + "\xA4\xC9" => "\xE3\x81\xA9", + "\xA4\xCA" => "\xE3\x81\xAA", + "\xA4\xCB" => "\xE3\x81\xAB", + "\xA4\xCC" => "\xE3\x81\xAC", + "\xA4\xCD" => "\xE3\x81\xAD", + "\xA4\xCE" => "\xE3\x81\xAE", + "\xA4\xCF" => "\xE3\x81\xAF", + "\xA4\xD0" => "\xE3\x81\xB0", + "\xA4\xD1" => "\xE3\x81\xB1", + "\xA4\xD2" => "\xE3\x81\xB2", + "\xA4\xD3" => "\xE3\x81\xB3", + "\xA4\xD4" => "\xE3\x81\xB4", + "\xA4\xD5" => "\xE3\x81\xB5", + "\xA4\xD6" => "\xE3\x81\xB6", + "\xA4\xD7" => "\xE3\x81\xB7", + "\xA4\xD8" => "\xE3\x81\xB8", + "\xA4\xD9" => "\xE3\x81\xB9", + "\xA4\xDA" => "\xE3\x81\xBA", + "\xA4\xDB" => "\xE3\x81\xBB", + "\xA4\xDC" => "\xE3\x81\xBC", + "\xA4\xDD" => "\xE3\x81\xBD", + "\xA4\xDE" => "\xE3\x81\xBE", + "\xA4\xDF" => "\xE3\x81\xBF", + "\xA4\xE0" => "\xE3\x82\x80", + "\xA4\xE1" => "\xE3\x82\x81", + "\xA4\xE2" => "\xE3\x82\x82", + "\xA4\xE3" => "\xE3\x82\x83", + "\xA4\xE4" => "\xE3\x82\x84", + "\xA4\xE5" => "\xE3\x82\x85", + "\xA4\xE6" => "\xE3\x82\x86", + "\xA4\xE7" => "\xE3\x82\x87", + "\xA4\xE8" => "\xE3\x82\x88", + "\xA4\xE9" => "\xE3\x82\x89", + "\xA4\xEA" => "\xE3\x82\x8A", + "\xA4\xEB" => "\xE3\x82\x8B", + "\xA4\xEC" => "\xE3\x82\x8C", + "\xA4\xED" => "\xE3\x82\x8D", + "\xA4\xEE" => "\xE3\x82\x8E", + "\xA4\xEF" => "\xE3\x82\x8F", + "\xA4\xF0" => "\xE3\x82\x90", + "\xA4\xF1" => "\xE3\x82\x91", + "\xA4\xF2" => "\xE3\x82\x92", + "\xA4\xF3" => "\xE3\x82\x93", + "\xA5\xA1" => "\xE3\x82\xA1", + "\xA5\xA2" => "\xE3\x82\xA2", + "\xA5\xA3" => "\xE3\x82\xA3", + "\xA5\xA4" => "\xE3\x82\xA4", + "\xA5\xA5" => "\xE3\x82\xA5", + "\xA5\xA6" => "\xE3\x82\xA6", + "\xA5\xA7" => "\xE3\x82\xA7", + "\xA5\xA8" => "\xE3\x82\xA8", + "\xA5\xA9" => "\xE3\x82\xA9", + "\xA5\xAA" => "\xE3\x82\xAA", + "\xA5\xAB" => "\xE3\x82\xAB", + "\xA5\xAC" => "\xE3\x82\xAC", + "\xA5\xAD" => "\xE3\x82\xAD", + "\xA5\xAE" => "\xE3\x82\xAE", + "\xA5\xAF" => "\xE3\x82\xAF", + "\xA5\xB0" => "\xE3\x82\xB0", + "\xA5\xB1" => "\xE3\x82\xB1", + "\xA5\xB2" => "\xE3\x82\xB2", + "\xA5\xB3" => "\xE3\x82\xB3", + "\xA5\xB4" => "\xE3\x82\xB4", + "\xA5\xB5" => "\xE3\x82\xB5", + "\xA5\xB6" => "\xE3\x82\xB6", + "\xA5\xB7" => "\xE3\x82\xB7", + "\xA5\xB8" => "\xE3\x82\xB8", + "\xA5\xB9" => "\xE3\x82\xB9", + "\xA5\xBA" => "\xE3\x82\xBA", + "\xA5\xBB" => "\xE3\x82\xBB", + "\xA5\xBC" => "\xE3\x82\xBC", + "\xA5\xBD" => "\xE3\x82\xBD", + "\xA5\xBE" => "\xE3\x82\xBE", + "\xA5\xBF" => "\xE3\x82\xBF", + "\xA5\xC0" => "\xE3\x83\x80", + "\xA5\xC1" => "\xE3\x83\x81", + "\xA5\xC2" => "\xE3\x83\x82", + "\xA5\xC3" => "\xE3\x83\x83", + "\xA5\xC4" => "\xE3\x83\x84", + "\xA5\xC5" => "\xE3\x83\x85", + "\xA5\xC6" => "\xE3\x83\x86", + "\xA5\xC7" => "\xE3\x83\x87", + "\xA5\xC8" => "\xE3\x83\x88", + "\xA5\xC9" => "\xE3\x83\x89", + "\xA5\xCA" => "\xE3\x83\x8A", + "\xA5\xCB" => "\xE3\x83\x8B", + "\xA5\xCC" => "\xE3\x83\x8C", + "\xA5\xCD" => "\xE3\x83\x8D", + "\xA5\xCE" => "\xE3\x83\x8E", + "\xA5\xCF" => "\xE3\x83\x8F", + "\xA5\xD0" => "\xE3\x83\x90", + "\xA5\xD1" => "\xE3\x83\x91", + "\xA5\xD2" => "\xE3\x83\x92", + "\xA5\xD3" => "\xE3\x83\x93", + "\xA5\xD4" => "\xE3\x83\x94", + "\xA5\xD5" => "\xE3\x83\x95", + "\xA5\xD6" => "\xE3\x83\x96", + "\xA5\xD7" => "\xE3\x83\x97", + "\xA5\xD8" => "\xE3\x83\x98", + "\xA5\xD9" => "\xE3\x83\x99", + "\xA5\xDA" => "\xE3\x83\x9A", + "\xA5\xDB" => "\xE3\x83\x9B", + "\xA5\xDC" => "\xE3\x83\x9C", + "\xA5\xDD" => "\xE3\x83\x9D", + "\xA5\xDE" => "\xE3\x83\x9E", + "\xA5\xDF" => "\xE3\x83\x9F", + "\xA5\xE0" => "\xE3\x83\xA0", + "\xA5\xE1" => "\xE3\x83\xA1", + "\xA5\xE2" => "\xE3\x83\xA2", + "\xA5\xE3" => "\xE3\x83\xA3", + "\xA5\xE4" => "\xE3\x83\xA4", + "\xA5\xE5" => "\xE3\x83\xA5", + "\xA5\xE6" => "\xE3\x83\xA6", + "\xA5\xE7" => "\xE3\x83\xA7", + "\xA5\xE8" => "\xE3\x83\xA8", + "\xA5\xE9" => "\xE3\x83\xA9", + "\xA5\xEA" => "\xE3\x83\xAA", + "\xA5\xEB" => "\xE3\x83\xAB", + "\xA5\xEC" => "\xE3\x83\xAC", + "\xA5\xED" => "\xE3\x83\xAD", + "\xA5\xEE" => "\xE3\x83\xAE", + "\xA5\xEF" => "\xE3\x83\xAF", + "\xA5\xF0" => "\xE3\x83\xB0", + "\xA5\xF1" => "\xE3\x83\xB1", + "\xA5\xF2" => "\xE3\x83\xB2", + "\xA5\xF3" => "\xE3\x83\xB3", + "\xA5\xF4" => "\xE3\x83\xB4", + "\xA5\xF5" => "\xE3\x83\xB5", + "\xA5\xF6" => "\xE3\x83\xB6", + "\xA6\xA1" => "\xCE\x91", + "\xA6\xA2" => "\xCE\x92", + "\xA6\xA3" => "\xCE\x93", + "\xA6\xA4" => "\xCE\x94", + "\xA6\xA5" => "\xCE\x95", + "\xA6\xA6" => "\xCE\x96", + "\xA6\xA7" => "\xCE\x97", + "\xA6\xA8" => "\xCE\x98", + "\xA6\xA9" => "\xCE\x99", + "\xA6\xAA" => "\xCE\x9A", + "\xA6\xAB" => "\xCE\x9B", + "\xA6\xAC" => "\xCE\x9C", + "\xA6\xAD" => "\xCE\x9D", + "\xA6\xAE" => "\xCE\x9E", + "\xA6\xAF" => "\xCE\x9F", + "\xA6\xB0" => "\xCE\xA0", + "\xA6\xB1" => "\xCE\xA1", + "\xA6\xB2" => "\xCE\xA3", + "\xA6\xB3" => "\xCE\xA4", + "\xA6\xB4" => "\xCE\xA5", + "\xA6\xB5" => "\xCE\xA6", + "\xA6\xB6" => "\xCE\xA7", + "\xA6\xB7" => "\xCE\xA8", + "\xA6\xB8" => "\xCE\xA9", + "\xA6\xC1" => "\xCE\xB1", + "\xA6\xC2" => "\xCE\xB2", + "\xA6\xC3" => "\xCE\xB3", + "\xA6\xC4" => "\xCE\xB4", + "\xA6\xC5" => "\xCE\xB5", + "\xA6\xC6" => "\xCE\xB6", + "\xA6\xC7" => "\xCE\xB7", + "\xA6\xC8" => "\xCE\xB8", + "\xA6\xC9" => "\xCE\xB9", + "\xA6\xCA" => "\xCE\xBA", + "\xA6\xCB" => "\xCE\xBB", + "\xA6\xCC" => "\xCE\xBC", + "\xA6\xCD" => "\xCE\xBD", + "\xA6\xCE" => "\xCE\xBE", + "\xA6\xCF" => "\xCE\xBF", + "\xA6\xD0" => "\xCF\x80", + "\xA6\xD1" => "\xCF\x81", + "\xA6\xD2" => "\xCF\x83", + "\xA6\xD3" => "\xCF\x84", + "\xA6\xD4" => "\xCF\x85", + "\xA6\xD5" => "\xCF\x86", + "\xA6\xD6" => "\xCF\x87", + "\xA6\xD7" => "\xCF\x88", + "\xA6\xD8" => "\xCF\x89", + "\xA7\xA1" => "\xD0\x90", + "\xA7\xA2" => "\xD0\x91", + "\xA7\xA3" => "\xD0\x92", + "\xA7\xA4" => "\xD0\x93", + "\xA7\xA5" => "\xD0\x94", + "\xA7\xA6" => "\xD0\x95", + "\xA7\xA7" => "\xD0\x81", + "\xA7\xA8" => "\xD0\x96", + "\xA7\xA9" => "\xD0\x97", + "\xA7\xAA" => "\xD0\x98", + "\xA7\xAB" => "\xD0\x99", + "\xA7\xAC" => "\xD0\x9A", + "\xA7\xAD" => "\xD0\x9B", + "\xA7\xAE" => "\xD0\x9C", + "\xA7\xAF" => "\xD0\x9D", + "\xA7\xB0" => "\xD0\x9E", + "\xA7\xB1" => "\xD0\x9F", + "\xA7\xB2" => "\xD0\xA0", + "\xA7\xB3" => "\xD0\xA1", + "\xA7\xB4" => "\xD0\xA2", + "\xA7\xB5" => "\xD0\xA3", + "\xA7\xB6" => "\xD0\xA4", + "\xA7\xB7" => "\xD0\xA5", + "\xA7\xB8" => "\xD0\xA6", + "\xA7\xB9" => "\xD0\xA7", + "\xA7\xBA" => "\xD0\xA8", + "\xA7\xBB" => "\xD0\xA9", + "\xA7\xBC" => "\xD0\xAA", + "\xA7\xBD" => "\xD0\xAB", + "\xA7\xBE" => "\xD0\xAC", + "\xA7\xBF" => "\xD0\xAD", + "\xA7\xC0" => "\xD0\xAE", + "\xA7\xC1" => "\xD0\xAF", + "\xA7\xD1" => "\xD0\xB0", + "\xA7\xD2" => "\xD0\xB1", + "\xA7\xD3" => "\xD0\xB2", + "\xA7\xD4" => "\xD0\xB3", + "\xA7\xD5" => "\xD0\xB4", + "\xA7\xD6" => "\xD0\xB5", + "\xA7\xD7" => "\xD1\x91", + "\xA7\xD8" => "\xD0\xB6", + "\xA7\xD9" => "\xD0\xB7", + "\xA7\xDA" => "\xD0\xB8", + "\xA7\xDB" => "\xD0\xB9", + "\xA7\xDC" => "\xD0\xBA", + "\xA7\xDD" => "\xD0\xBB", + "\xA7\xDE" => "\xD0\xBC", + "\xA7\xDF" => "\xD0\xBD", + "\xA7\xE0" => "\xD0\xBE", + "\xA7\xE1" => "\xD0\xBF", + "\xA7\xE2" => "\xD1\x80", + "\xA7\xE3" => "\xD1\x81", + "\xA7\xE4" => "\xD1\x82", + "\xA7\xE5" => "\xD1\x83", + "\xA7\xE6" => "\xD1\x84", + "\xA7\xE7" => "\xD1\x85", + "\xA7\xE8" => "\xD1\x86", + "\xA7\xE9" => "\xD1\x87", + "\xA7\xEA" => "\xD1\x88", + "\xA7\xEB" => "\xD1\x89", + "\xA7\xEC" => "\xD1\x8A", + "\xA7\xED" => "\xD1\x8B", + "\xA7\xEE" => "\xD1\x8C", + "\xA7\xEF" => "\xD1\x8D", + "\xA7\xF0" => "\xD1\x8E", + "\xA7\xF1" => "\xD1\x8F", + "\xA8\xA1" => "\xC4\x81", + "\xA8\xA2" => "\xC3\xA1", + "\xA8\xA3" => "\xC7\x8E", + "\xA8\xA4" => "\xC3\xA0", + "\xA8\xA5" => "\xC4\x93", + "\xA8\xA6" => "\xC3\xA9", + "\xA8\xA7" => "\xC4\x9B", + "\xA8\xA8" => "\xC3\xA8", + "\xA8\xA9" => "\xC4\xAB", + "\xA8\xAA" => "\xC3\xAD", + "\xA8\xAB" => "\xC7\x90", + "\xA8\xAC" => "\xC3\xAC", + "\xA8\xAD" => "\xC5\x8D", + "\xA8\xAE" => "\xC3\xB3", + "\xA8\xAF" => "\xC7\x92", + "\xA8\xB0" => "\xC3\xB2", + "\xA8\xB1" => "\xC5\xAB", + "\xA8\xB2" => "\xC3\xBA", + "\xA8\xB3" => "\xC7\x94", + "\xA8\xB4" => "\xC3\xB9", + "\xA8\xB5" => "\xC7\x96", + "\xA8\xB6" => "\xC7\x98", + "\xA8\xB7" => "\xC7\x9A", + "\xA8\xB8" => "\xC7\x9C", + "\xA8\xB9" => "\xC3\xBC", + "\xA8\xBA" => "\xC3\xAA", + "\xA8\xC5" => "\xE3\x84\x85", + "\xA8\xC6" => "\xE3\x84\x86", + "\xA8\xC7" => "\xE3\x84\x87", + "\xA8\xC8" => "\xE3\x84\x88", + "\xA8\xC9" => "\xE3\x84\x89", + "\xA8\xCA" => "\xE3\x84\x8A", + "\xA8\xCB" => "\xE3\x84\x8B", + "\xA8\xCC" => "\xE3\x84\x8C", + "\xA8\xCD" => "\xE3\x84\x8D", + "\xA8\xCE" => "\xE3\x84\x8E", + "\xA8\xCF" => "\xE3\x84\x8F", + "\xA8\xD0" => "\xE3\x84\x90", + "\xA8\xD1" => "\xE3\x84\x91", + "\xA8\xD2" => "\xE3\x84\x92", + "\xA8\xD3" => "\xE3\x84\x93", + "\xA8\xD4" => "\xE3\x84\x94", + "\xA8\xD5" => "\xE3\x84\x95", + "\xA8\xD6" => "\xE3\x84\x96", + "\xA8\xD7" => "\xE3\x84\x97", + "\xA8\xD8" => "\xE3\x84\x98", + "\xA8\xD9" => "\xE3\x84\x99", + "\xA8\xDA" => "\xE3\x84\x9A", + "\xA8\xDB" => "\xE3\x84\x9B", + "\xA8\xDC" => "\xE3\x84\x9C", + "\xA8\xDD" => "\xE3\x84\x9D", + "\xA8\xDE" => "\xE3\x84\x9E", + "\xA8\xDF" => "\xE3\x84\x9F", + "\xA8\xE0" => "\xE3\x84\xA0", + "\xA8\xE1" => "\xE3\x84\xA1", + "\xA8\xE2" => "\xE3\x84\xA2", + "\xA8\xE3" => "\xE3\x84\xA3", + "\xA8\xE4" => "\xE3\x84\xA4", + "\xA8\xE5" => "\xE3\x84\xA5", + "\xA8\xE6" => "\xE3\x84\xA6", + "\xA8\xE7" => "\xE3\x84\xA7", + "\xA8\xE8" => "\xE3\x84\xA8", + "\xA8\xE9" => "\xE3\x84\xA9", + "\xA9\xA4" => "\xE2\x94\x80", + "\xA9\xA5" => "\xE2\x94\x81", + "\xA9\xA6" => "\xE2\x94\x82", + "\xA9\xA7" => "\xE2\x94\x83", + "\xA9\xA8" => "\xE2\x94\x84", + "\xA9\xA9" => "\xE2\x94\x85", + "\xA9\xAA" => "\xE2\x94\x86", + "\xA9\xAB" => "\xE2\x94\x87", + "\xA9\xAC" => "\xE2\x94\x88", + "\xA9\xAD" => "\xE2\x94\x89", + "\xA9\xAE" => "\xE2\x94\x8A", + "\xA9\xAF" => "\xE2\x94\x8B", + "\xA9\xB0" => "\xE2\x94\x8C", + "\xA9\xB1" => "\xE2\x94\x8D", + "\xA9\xB2" => "\xE2\x94\x8E", + "\xA9\xB3" => "\xE2\x94\x8F", + "\xA9\xB4" => "\xE2\x94\x90", + "\xA9\xB5" => "\xE2\x94\x91", + "\xA9\xB6" => "\xE2\x94\x92", + "\xA9\xB7" => "\xE2\x94\x93", + "\xA9\xB8" => "\xE2\x94\x94", + "\xA9\xB9" => "\xE2\x94\x95", + "\xA9\xBA" => "\xE2\x94\x96", + "\xA9\xBB" => "\xE2\x94\x97", + "\xA9\xBC" => "\xE2\x94\x98", + "\xA9\xBD" => "\xE2\x94\x99", + "\xA9\xBE" => "\xE2\x94\x9A", + "\xA9\xBF" => "\xE2\x94\x9B", + "\xA9\xC0" => "\xE2\x94\x9C", + "\xA9\xC1" => "\xE2\x94\x9D", + "\xA9\xC2" => "\xE2\x94\x9E", + "\xA9\xC3" => "\xE2\x94\x9F", + "\xA9\xC4" => "\xE2\x94\xA0", + "\xA9\xC5" => "\xE2\x94\xA1", + "\xA9\xC6" => "\xE2\x94\xA2", + "\xA9\xC7" => "\xE2\x94\xA3", + "\xA9\xC8" => "\xE2\x94\xA4", + "\xA9\xC9" => "\xE2\x94\xA5", + "\xA9\xCA" => "\xE2\x94\xA6", + "\xA9\xCB" => "\xE2\x94\xA7", + "\xA9\xCC" => "\xE2\x94\xA8", + "\xA9\xCD" => "\xE2\x94\xA9", + "\xA9\xCE" => "\xE2\x94\xAA", + "\xA9\xCF" => "\xE2\x94\xAB", + "\xA9\xD0" => "\xE2\x94\xAC", + "\xA9\xD1" => "\xE2\x94\xAD", + "\xA9\xD2" => "\xE2\x94\xAE", + "\xA9\xD3" => "\xE2\x94\xAF", + "\xA9\xD4" => "\xE2\x94\xB0", + "\xA9\xD5" => "\xE2\x94\xB1", + "\xA9\xD6" => "\xE2\x94\xB2", + "\xA9\xD7" => "\xE2\x94\xB3", + "\xA9\xD8" => "\xE2\x94\xB4", + "\xA9\xD9" => "\xE2\x94\xB5", + "\xA9\xDA" => "\xE2\x94\xB6", + "\xA9\xDB" => "\xE2\x94\xB7", + "\xA9\xDC" => "\xE2\x94\xB8", + "\xA9\xDD" => "\xE2\x94\xB9", + "\xA9\xDE" => "\xE2\x94\xBA", + "\xA9\xDF" => "\xE2\x94\xBB", + "\xA9\xE0" => "\xE2\x94\xBC", + "\xA9\xE1" => "\xE2\x94\xBD", + "\xA9\xE2" => "\xE2\x94\xBE", + "\xA9\xE3" => "\xE2\x94\xBF", + "\xA9\xE4" => "\xE2\x95\x80", + "\xA9\xE5" => "\xE2\x95\x81", + "\xA9\xE6" => "\xE2\x95\x82", + "\xA9\xE7" => "\xE2\x95\x83", + "\xA9\xE8" => "\xE2\x95\x84", + "\xA9\xE9" => "\xE2\x95\x85", + "\xA9\xEA" => "\xE2\x95\x86", + "\xA9\xEB" => "\xE2\x95\x87", + "\xA9\xEC" => "\xE2\x95\x88", + "\xA9\xED" => "\xE2\x95\x89", + "\xA9\xEE" => "\xE2\x95\x8A", + "\xA9\xEF" => "\xE2\x95\x8B", + "\xB0\xA1" => "\xE5\x95\x8A", + "\xB0\xA2" => "\xE9\x98\xBF", + "\xB0\xA3" => "\xE5\x9F\x83", + "\xB0\xA4" => "\xE6\x8C\xA8", + "\xB0\xA5" => "\xE5\x93\x8E", + "\xB0\xA6" => "\xE5\x94\x89", + "\xB0\xA7" => "\xE5\x93\x80", + "\xB0\xA8" => "\xE7\x9A\x91", + "\xB0\xA9" => "\xE7\x99\x8C", + "\xB0\xAA" => "\xE8\x94\xBC", + "\xB0\xAB" => "\xE7\x9F\xAE", + "\xB0\xAC" => "\xE8\x89\xBE", + "\xB0\xAD" => "\xE7\xA2\x8D", + "\xB0\xAE" => "\xE7\x88\xB1", + "\xB0\xAF" => "\xE9\x9A\x98", + "\xB0\xB0" => "\xE9\x9E\x8D", + "\xB0\xB1" => "\xE6\xB0\xA8", + "\xB0\xB2" => "\xE5\xAE\x89", + "\xB0\xB3" => "\xE4\xBF\xBA", + "\xB0\xB4" => "\xE6\x8C\x89", + "\xB0\xB5" => "\xE6\x9A\x97", + "\xB0\xB6" => "\xE5\xB2\xB8", + "\xB0\xB7" => "\xE8\x83\xBA", + "\xB0\xB8" => "\xE6\xA1\x88", + "\xB0\xB9" => "\xE8\x82\xAE", + "\xB0\xBA" => "\xE6\x98\x82", + "\xB0\xBB" => "\xE7\x9B\x8E", + "\xB0\xBC" => "\xE5\x87\xB9", + "\xB0\xBD" => "\xE6\x95\x96", + "\xB0\xBE" => "\xE7\x86\xAC", + "\xB0\xBF" => "\xE7\xBF\xB1", + "\xB0\xC0" => "\xE8\xA2\x84", + "\xB0\xC1" => "\xE5\x82\xB2", + "\xB0\xC2" => "\xE5\xA5\xA5", + "\xB0\xC3" => "\xE6\x87\x8A", + "\xB0\xC4" => "\xE6\xBE\xB3", + "\xB0\xC5" => "\xE8\x8A\xAD", + "\xB0\xC6" => "\xE6\x8D\x8C", + "\xB0\xC7" => "\xE6\x89\x92", + "\xB0\xC8" => "\xE5\x8F\xAD", + "\xB0\xC9" => "\xE5\x90\xA7", + "\xB0\xCA" => "\xE7\xAC\x86", + "\xB0\xCB" => "\xE5\x85\xAB", + "\xB0\xCC" => "\xE7\x96\xA4", + "\xB0\xCD" => "\xE5\xB7\xB4", + "\xB0\xCE" => "\xE6\x8B\x94", + "\xB0\xCF" => "\xE8\xB7\x8B", + "\xB0\xD0" => "\xE9\x9D\xB6", + "\xB0\xD1" => "\xE6\x8A\x8A", + "\xB0\xD2" => "\xE8\x80\x99", + "\xB0\xD3" => "\xE5\x9D\x9D", + "\xB0\xD4" => "\xE9\x9C\xB8", + "\xB0\xD5" => "\xE7\xBD\xA2", + "\xB0\xD6" => "\xE7\x88\xB8", + "\xB0\xD7" => "\xE7\x99\xBD", + "\xB0\xD8" => "\xE6\x9F\x8F", + "\xB0\xD9" => "\xE7\x99\xBE", + "\xB0\xDA" => "\xE6\x91\x86", + "\xB0\xDB" => "\xE4\xBD\xB0", + "\xB0\xDC" => "\xE8\xB4\xA5", + "\xB0\xDD" => "\xE6\x8B\x9C", + "\xB0\xDE" => "\xE7\xA8\x97", + "\xB0\xDF" => "\xE6\x96\x91", + "\xB0\xE0" => "\xE7\x8F\xAD", + "\xB0\xE1" => "\xE6\x90\xAC", + "\xB0\xE2" => "\xE6\x89\xB3", + "\xB0\xE3" => "\xE8\x88\xAC", + "\xB0\xE4" => "\xE9\xA2\x81", + "\xB0\xE5" => "\xE6\x9D\xBF", + "\xB0\xE6" => "\xE7\x89\x88", + "\xB0\xE7" => "\xE6\x89\xAE", + "\xB0\xE8" => "\xE6\x8B\x8C", + "\xB0\xE9" => "\xE4\xBC\xB4", + "\xB0\xEA" => "\xE7\x93\xA3", + "\xB0\xEB" => "\xE5\x8D\x8A", + "\xB0\xEC" => "\xE5\x8A\x9E", + "\xB0\xED" => "\xE7\xBB\x8A", + "\xB0\xEE" => "\xE9\x82\xA6", + "\xB0\xEF" => "\xE5\xB8\xAE", + "\xB0\xF0" => "\xE6\xA2\x86", + "\xB0\xF1" => "\xE6\xA6\x9C", + "\xB0\xF2" => "\xE8\x86\x80", + "\xB0\xF3" => "\xE7\xBB\x91", + "\xB0\xF4" => "\xE6\xA3\x92", + "\xB0\xF5" => "\xE7\xA3\x85", + "\xB0\xF6" => "\xE8\x9A\x8C", + "\xB0\xF7" => "\xE9\x95\x91", + "\xB0\xF8" => "\xE5\x82\x8D", + "\xB0\xF9" => "\xE8\xB0\xA4", + "\xB0\xFA" => "\xE8\x8B\x9E", + "\xB0\xFB" => "\xE8\x83\x9E", + "\xB0\xFC" => "\xE5\x8C\x85", + "\xB0\xFD" => "\xE8\xA4\x92", + "\xB0\xFE" => "\xE5\x89\xA5", + "\xB1\xA1" => "\xE8\x96\x84", + "\xB1\xA2" => "\xE9\x9B\xB9", + "\xB1\xA3" => "\xE4\xBF\x9D", + "\xB1\xA4" => "\xE5\xA0\xA1", + "\xB1\xA5" => "\xE9\xA5\xB1", + "\xB1\xA6" => "\xE5\xAE\x9D", + "\xB1\xA7" => "\xE6\x8A\xB1", + "\xB1\xA8" => "\xE6\x8A\xA5", + "\xB1\xA9" => "\xE6\x9A\xB4", + "\xB1\xAA" => "\xE8\xB1\xB9", + "\xB1\xAB" => "\xE9\xB2\x8D", + "\xB1\xAC" => "\xE7\x88\x86", + "\xB1\xAD" => "\xE6\x9D\xAF", + "\xB1\xAE" => "\xE7\xA2\x91", + "\xB1\xAF" => "\xE6\x82\xB2", + "\xB1\xB0" => "\xE5\x8D\x91", + "\xB1\xB1" => "\xE5\x8C\x97", + "\xB1\xB2" => "\xE8\xBE\x88", + "\xB1\xB3" => "\xE8\x83\x8C", + "\xB1\xB4" => "\xE8\xB4\x9D", + "\xB1\xB5" => "\xE9\x92\xA1", + "\xB1\xB6" => "\xE5\x80\x8D", + "\xB1\xB7" => "\xE7\x8B\x88", + "\xB1\xB8" => "\xE5\xA4\x87", + "\xB1\xB9" => "\xE6\x83\xAB", + "\xB1\xBA" => "\xE7\x84\x99", + "\xB1\xBB" => "\xE8\xA2\xAB", + "\xB1\xBC" => "\xE5\xA5\x94", + "\xB1\xBD" => "\xE8\x8B\xAF", + "\xB1\xBE" => "\xE6\x9C\xAC", + "\xB1\xBF" => "\xE7\xAC\xA8", + "\xB1\xC0" => "\xE5\xB4\xA9", + "\xB1\xC1" => "\xE7\xBB\xB7", + "\xB1\xC2" => "\xE7\x94\xAD", + "\xB1\xC3" => "\xE6\xB3\xB5", + "\xB1\xC4" => "\xE8\xB9\xA6", + "\xB1\xC5" => "\xE8\xBF\xB8", + "\xB1\xC6" => "\xE9\x80\xBC", + "\xB1\xC7" => "\xE9\xBC\xBB", + "\xB1\xC8" => "\xE6\xAF\x94", + "\xB1\xC9" => "\xE9\x84\x99", + "\xB1\xCA" => "\xE7\xAC\x94", + "\xB1\xCB" => "\xE5\xBD\xBC", + "\xB1\xCC" => "\xE7\xA2\xA7", + "\xB1\xCD" => "\xE8\x93\x96", + "\xB1\xCE" => "\xE8\x94\xBD", + "\xB1\xCF" => "\xE6\xAF\x95", + "\xB1\xD0" => "\xE6\xAF\x99", + "\xB1\xD1" => "\xE6\xAF\x96", + "\xB1\xD2" => "\xE5\xB8\x81", + "\xB1\xD3" => "\xE5\xBA\x87", + "\xB1\xD4" => "\xE7\x97\xB9", + "\xB1\xD5" => "\xE9\x97\xAD", + "\xB1\xD6" => "\xE6\x95\x9D", + "\xB1\xD7" => "\xE5\xBC\x8A", + "\xB1\xD8" => "\xE5\xBF\x85", + "\xB1\xD9" => "\xE8\xBE\x9F", + "\xB1\xDA" => "\xE5\xA3\x81", + "\xB1\xDB" => "\xE8\x87\x82", + "\xB1\xDC" => "\xE9\x81\xBF", + "\xB1\xDD" => "\xE9\x99\x9B", + "\xB1\xDE" => "\xE9\x9E\xAD", + "\xB1\xDF" => "\xE8\xBE\xB9", + "\xB1\xE0" => "\xE7\xBC\x96", + "\xB1\xE1" => "\xE8\xB4\xAC", + "\xB1\xE2" => "\xE6\x89\x81", + "\xB1\xE3" => "\xE4\xBE\xBF", + "\xB1\xE4" => "\xE5\x8F\x98", + "\xB1\xE5" => "\xE5\x8D\x9E", + "\xB1\xE6" => "\xE8\xBE\xA8", + "\xB1\xE7" => "\xE8\xBE\xA9", + "\xB1\xE8" => "\xE8\xBE\xAB", + "\xB1\xE9" => "\xE9\x81\x8D", + "\xB1\xEA" => "\xE6\xA0\x87", + "\xB1\xEB" => "\xE5\xBD\xAA", + "\xB1\xEC" => "\xE8\x86\x98", + "\xB1\xED" => "\xE8\xA1\xA8", + "\xB1\xEE" => "\xE9\xB3\x96", + "\xB1\xEF" => "\xE6\x86\x8B", + "\xB1\xF0" => "\xE5\x88\xAB", + "\xB1\xF1" => "\xE7\x98\xAA", + "\xB1\xF2" => "\xE5\xBD\xAC", + "\xB1\xF3" => "\xE6\x96\x8C", + "\xB1\xF4" => "\xE6\xBF\x92", + "\xB1\xF5" => "\xE6\xBB\xA8", + "\xB1\xF6" => "\xE5\xAE\xBE", + "\xB1\xF7" => "\xE6\x91\x88", + "\xB1\xF8" => "\xE5\x85\xB5", + "\xB1\xF9" => "\xE5\x86\xB0", + "\xB1\xFA" => "\xE6\x9F\x84", + "\xB1\xFB" => "\xE4\xB8\x99", + "\xB1\xFC" => "\xE7\xA7\x89", + "\xB1\xFD" => "\xE9\xA5\xBC", + "\xB1\xFE" => "\xE7\x82\xB3", + "\xB2\xA1" => "\xE7\x97\x85", + "\xB2\xA2" => "\xE5\xB9\xB6", + "\xB2\xA3" => "\xE7\x8E\xBB", + "\xB2\xA4" => "\xE8\x8F\xA0", + "\xB2\xA5" => "\xE6\x92\xAD", + "\xB2\xA6" => "\xE6\x8B\xA8", + "\xB2\xA7" => "\xE9\x92\xB5", + "\xB2\xA8" => "\xE6\xB3\xA2", + "\xB2\xA9" => "\xE5\x8D\x9A", + "\xB2\xAA" => "\xE5\x8B\x83", + "\xB2\xAB" => "\xE6\x90\x8F", + "\xB2\xAC" => "\xE9\x93\x82", + "\xB2\xAD" => "\xE7\xAE\x94", + "\xB2\xAE" => "\xE4\xBC\xAF", + "\xB2\xAF" => "\xE5\xB8\x9B", + "\xB2\xB0" => "\xE8\x88\xB6", + "\xB2\xB1" => "\xE8\x84\x96", + "\xB2\xB2" => "\xE8\x86\x8A", + "\xB2\xB3" => "\xE6\xB8\xA4", + "\xB2\xB4" => "\xE6\xB3\x8A", + "\xB2\xB5" => "\xE9\xA9\xB3", + "\xB2\xB6" => "\xE6\x8D\x95", + "\xB2\xB7" => "\xE5\x8D\x9C", + "\xB2\xB8" => "\xE5\x93\xBA", + "\xB2\xB9" => "\xE8\xA1\xA5", + "\xB2\xBA" => "\xE5\x9F\xA0", + "\xB2\xBB" => "\xE4\xB8\x8D", + "\xB2\xBC" => "\xE5\xB8\x83", + "\xB2\xBD" => "\xE6\xAD\xA5", + "\xB2\xBE" => "\xE7\xB0\xBF", + "\xB2\xBF" => "\xE9\x83\xA8", + "\xB2\xC0" => "\xE6\x80\x96", + "\xB2\xC1" => "\xE6\x93\xA6", + "\xB2\xC2" => "\xE7\x8C\x9C", + "\xB2\xC3" => "\xE8\xA3\x81", + "\xB2\xC4" => "\xE6\x9D\x90", + "\xB2\xC5" => "\xE6\x89\x8D", + "\xB2\xC6" => "\xE8\xB4\xA2", + "\xB2\xC7" => "\xE7\x9D\xAC", + "\xB2\xC8" => "\xE8\xB8\xA9", + "\xB2\xC9" => "\xE9\x87\x87", + "\xB2\xCA" => "\xE5\xBD\xA9", + "\xB2\xCB" => "\xE8\x8F\x9C", + "\xB2\xCC" => "\xE8\x94\xA1", + "\xB2\xCD" => "\xE9\xA4\x90", + "\xB2\xCE" => "\xE5\x8F\x82", + "\xB2\xCF" => "\xE8\x9A\x95", + "\xB2\xD0" => "\xE6\xAE\x8B", + "\xB2\xD1" => "\xE6\x83\xAD", + "\xB2\xD2" => "\xE6\x83\xA8", + "\xB2\xD3" => "\xE7\x81\xBF", + "\xB2\xD4" => "\xE8\x8B\x8D", + "\xB2\xD5" => "\xE8\x88\xB1", + "\xB2\xD6" => "\xE4\xBB\x93", + "\xB2\xD7" => "\xE6\xB2\xA7", + "\xB2\xD8" => "\xE8\x97\x8F", + "\xB2\xD9" => "\xE6\x93\x8D", + "\xB2\xDA" => "\xE7\xB3\x99", + "\xB2\xDB" => "\xE6\xA7\xBD", + "\xB2\xDC" => "\xE6\x9B\xB9", + "\xB2\xDD" => "\xE8\x8D\x89", + "\xB2\xDE" => "\xE5\x8E\x95", + "\xB2\xDF" => "\xE7\xAD\x96", + "\xB2\xE0" => "\xE4\xBE\xA7", + "\xB2\xE1" => "\xE5\x86\x8C", + "\xB2\xE2" => "\xE6\xB5\x8B", + "\xB2\xE3" => "\xE5\xB1\x82", + "\xB2\xE4" => "\xE8\xB9\xAD", + "\xB2\xE5" => "\xE6\x8F\x92", + "\xB2\xE6" => "\xE5\x8F\x89", + "\xB2\xE7" => "\xE8\x8C\xAC", + "\xB2\xE8" => "\xE8\x8C\xB6", + "\xB2\xE9" => "\xE6\x9F\xA5", + "\xB2\xEA" => "\xE7\xA2\xB4", + "\xB2\xEB" => "\xE6\x90\xBD", + "\xB2\xEC" => "\xE5\xAF\x9F", + "\xB2\xED" => "\xE5\xB2\x94", + "\xB2\xEE" => "\xE5\xB7\xAE", + "\xB2\xEF" => "\xE8\xAF\xA7", + "\xB2\xF0" => "\xE6\x8B\x86", + "\xB2\xF1" => "\xE6\x9F\xB4", + "\xB2\xF2" => "\xE8\xB1\xBA", + "\xB2\xF3" => "\xE6\x90\x80", + "\xB2\xF4" => "\xE6\x8E\xBA", + "\xB2\xF5" => "\xE8\x9D\x89", + "\xB2\xF6" => "\xE9\xA6\x8B", + "\xB2\xF7" => "\xE8\xB0\x97", + "\xB2\xF8" => "\xE7\xBC\xA0", + "\xB2\xF9" => "\xE9\x93\xB2", + "\xB2\xFA" => "\xE4\xBA\xA7", + "\xB2\xFB" => "\xE9\x98\x90", + "\xB2\xFC" => "\xE9\xA2\xA4", + "\xB2\xFD" => "\xE6\x98\x8C", + "\xB2\xFE" => "\xE7\x8C\x96", + "\xB3\xA1" => "\xE5\x9C\xBA", + "\xB3\xA2" => "\xE5\xB0\x9D", + "\xB3\xA3" => "\xE5\xB8\xB8", + "\xB3\xA4" => "\xE9\x95\xBF", + "\xB3\xA5" => "\xE5\x81\xBF", + "\xB3\xA6" => "\xE8\x82\xA0", + "\xB3\xA7" => "\xE5\x8E\x82", + "\xB3\xA8" => "\xE6\x95\x9E", + "\xB3\xA9" => "\xE7\x95\x85", + "\xB3\xAA" => "\xE5\x94\xB1", + "\xB3\xAB" => "\xE5\x80\xA1", + "\xB3\xAC" => "\xE8\xB6\x85", + "\xB3\xAD" => "\xE6\x8A\x84", + "\xB3\xAE" => "\xE9\x92\x9E", + "\xB3\xAF" => "\xE6\x9C\x9D", + "\xB3\xB0" => "\xE5\x98\xB2", + "\xB3\xB1" => "\xE6\xBD\xAE", + "\xB3\xB2" => "\xE5\xB7\xA2", + "\xB3\xB3" => "\xE5\x90\xB5", + "\xB3\xB4" => "\xE7\x82\x92", + "\xB3\xB5" => "\xE8\xBD\xA6", + "\xB3\xB6" => "\xE6\x89\xAF", + "\xB3\xB7" => "\xE6\x92\xA4", + "\xB3\xB8" => "\xE6\x8E\xA3", + "\xB3\xB9" => "\xE5\xBD\xBB", + "\xB3\xBA" => "\xE6\xBE\x88", + "\xB3\xBB" => "\xE9\x83\xB4", + "\xB3\xBC" => "\xE8\x87\xA3", + "\xB3\xBD" => "\xE8\xBE\xB0", + "\xB3\xBE" => "\xE5\xB0\x98", + "\xB3\xBF" => "\xE6\x99\xA8", + "\xB3\xC0" => "\xE5\xBF\xB1", + "\xB3\xC1" => "\xE6\xB2\x89", + "\xB3\xC2" => "\xE9\x99\x88", + "\xB3\xC3" => "\xE8\xB6\x81", + "\xB3\xC4" => "\xE8\xA1\xAC", + "\xB3\xC5" => "\xE6\x92\x91", + "\xB3\xC6" => "\xE7\xA7\xB0", + "\xB3\xC7" => "\xE5\x9F\x8E", + "\xB3\xC8" => "\xE6\xA9\x99", + "\xB3\xC9" => "\xE6\x88\x90", + "\xB3\xCA" => "\xE5\x91\x88", + "\xB3\xCB" => "\xE4\xB9\x98", + "\xB3\xCC" => "\xE7\xA8\x8B", + "\xB3\xCD" => "\xE6\x83\xA9", + "\xB3\xCE" => "\xE6\xBE\x84", + "\xB3\xCF" => "\xE8\xAF\x9A", + "\xB3\xD0" => "\xE6\x89\xBF", + "\xB3\xD1" => "\xE9\x80\x9E", + "\xB3\xD2" => "\xE9\xAA\x8B", + "\xB3\xD3" => "\xE7\xA7\xA4", + "\xB3\xD4" => "\xE5\x90\x83", + "\xB3\xD5" => "\xE7\x97\xB4", + "\xB3\xD6" => "\xE6\x8C\x81", + "\xB3\xD7" => "\xE5\x8C\x99", + "\xB3\xD8" => "\xE6\xB1\xA0", + "\xB3\xD9" => "\xE8\xBF\x9F", + "\xB3\xDA" => "\xE5\xBC\x9B", + "\xB3\xDB" => "\xE9\xA9\xB0", + "\xB3\xDC" => "\xE8\x80\xBB", + "\xB3\xDD" => "\xE9\xBD\xBF", + "\xB3\xDE" => "\xE4\xBE\x88", + "\xB3\xDF" => "\xE5\xB0\xBA", + "\xB3\xE0" => "\xE8\xB5\xA4", + "\xB3\xE1" => "\xE7\xBF\x85", + "\xB3\xE2" => "\xE6\x96\xA5", + "\xB3\xE3" => "\xE7\x82\xBD", + "\xB3\xE4" => "\xE5\x85\x85", + "\xB3\xE5" => "\xE5\x86\xB2", + "\xB3\xE6" => "\xE8\x99\xAB", + "\xB3\xE7" => "\xE5\xB4\x87", + "\xB3\xE8" => "\xE5\xAE\xA0", + "\xB3\xE9" => "\xE6\x8A\xBD", + "\xB3\xEA" => "\xE9\x85\xAC", + "\xB3\xEB" => "\xE7\x95\xB4", + "\xB3\xEC" => "\xE8\xB8\x8C", + "\xB3\xED" => "\xE7\xA8\xA0", + "\xB3\xEE" => "\xE6\x84\x81", + "\xB3\xEF" => "\xE7\xAD\xB9", + "\xB3\xF0" => "\xE4\xBB\x87", + "\xB3\xF1" => "\xE7\xBB\xB8", + "\xB3\xF2" => "\xE7\x9E\x85", + "\xB3\xF3" => "\xE4\xB8\x91", + "\xB3\xF4" => "\xE8\x87\xAD", + "\xB3\xF5" => "\xE5\x88\x9D", + "\xB3\xF6" => "\xE5\x87\xBA", + "\xB3\xF7" => "\xE6\xA9\xB1", + "\xB3\xF8" => "\xE5\x8E\xA8", + "\xB3\xF9" => "\xE8\xBA\x87", + "\xB3\xFA" => "\xE9\x94\x84", + "\xB3\xFB" => "\xE9\x9B\x8F", + "\xB3\xFC" => "\xE6\xBB\x81", + "\xB3\xFD" => "\xE9\x99\xA4", + "\xB3\xFE" => "\xE6\xA5\x9A", + "\xB4\xA1" => "\xE7\xA1\x80", + "\xB4\xA2" => "\xE5\x82\xA8", + "\xB4\xA3" => "\xE7\x9F\x97", + "\xB4\xA4" => "\xE6\x90\x90", + "\xB4\xA5" => "\xE8\xA7\xA6", + "\xB4\xA6" => "\xE5\xA4\x84", + "\xB4\xA7" => "\xE6\x8F\xA3", + "\xB4\xA8" => "\xE5\xB7\x9D", + "\xB4\xA9" => "\xE7\xA9\xBF", + "\xB4\xAA" => "\xE6\xA4\xBD", + "\xB4\xAB" => "\xE4\xBC\xA0", + "\xB4\xAC" => "\xE8\x88\xB9", + "\xB4\xAD" => "\xE5\x96\x98", + "\xB4\xAE" => "\xE4\xB8\xB2", + "\xB4\xAF" => "\xE7\x96\xAE", + "\xB4\xB0" => "\xE7\xAA\x97", + "\xB4\xB1" => "\xE5\xB9\xA2", + "\xB4\xB2" => "\xE5\xBA\x8A", + "\xB4\xB3" => "\xE9\x97\xAF", + "\xB4\xB4" => "\xE5\x88\x9B", + "\xB4\xB5" => "\xE5\x90\xB9", + "\xB4\xB6" => "\xE7\x82\x8A", + "\xB4\xB7" => "\xE6\x8D\xB6", + "\xB4\xB8" => "\xE9\x94\xA4", + "\xB4\xB9" => "\xE5\x9E\x82", + "\xB4\xBA" => "\xE6\x98\xA5", + "\xB4\xBB" => "\xE6\xA4\xBF", + "\xB4\xBC" => "\xE9\x86\x87", + "\xB4\xBD" => "\xE5\x94\x87", + "\xB4\xBE" => "\xE6\xB7\xB3", + "\xB4\xBF" => "\xE7\xBA\xAF", + "\xB4\xC0" => "\xE8\xA0\xA2", + "\xB4\xC1" => "\xE6\x88\xB3", + "\xB4\xC2" => "\xE7\xBB\xB0", + "\xB4\xC3" => "\xE7\x96\xB5", + "\xB4\xC4" => "\xE8\x8C\xA8", + "\xB4\xC5" => "\xE7\xA3\x81", + "\xB4\xC6" => "\xE9\x9B\x8C", + "\xB4\xC7" => "\xE8\xBE\x9E", + "\xB4\xC8" => "\xE6\x85\x88", + "\xB4\xC9" => "\xE7\x93\xB7", + "\xB4\xCA" => "\xE8\xAF\x8D", + "\xB4\xCB" => "\xE6\xAD\xA4", + "\xB4\xCC" => "\xE5\x88\xBA", + "\xB4\xCD" => "\xE8\xB5\x90", + "\xB4\xCE" => "\xE6\xAC\xA1", + "\xB4\xCF" => "\xE8\x81\xAA", + "\xB4\xD0" => "\xE8\x91\xB1", + "\xB4\xD1" => "\xE5\x9B\xB1", + "\xB4\xD2" => "\xE5\x8C\x86", + "\xB4\xD3" => "\xE4\xBB\x8E", + "\xB4\xD4" => "\xE4\xB8\x9B", + "\xB4\xD5" => "\xE5\x87\x91", + "\xB4\xD6" => "\xE7\xB2\x97", + "\xB4\xD7" => "\xE9\x86\x8B", + "\xB4\xD8" => "\xE7\xB0\x87", + "\xB4\xD9" => "\xE4\xBF\x83", + "\xB4\xDA" => "\xE8\xB9\xBF", + "\xB4\xDB" => "\xE7\xAF\xA1", + "\xB4\xDC" => "\xE7\xAA\x9C", + "\xB4\xDD" => "\xE6\x91\xA7", + "\xB4\xDE" => "\xE5\xB4\x94", + "\xB4\xDF" => "\xE5\x82\xAC", + "\xB4\xE0" => "\xE8\x84\x86", + "\xB4\xE1" => "\xE7\x98\x81", + "\xB4\xE2" => "\xE7\xB2\xB9", + "\xB4\xE3" => "\xE6\xB7\xAC", + "\xB4\xE4" => "\xE7\xBF\xA0", + "\xB4\xE5" => "\xE6\x9D\x91", + "\xB4\xE6" => "\xE5\xAD\x98", + "\xB4\xE7" => "\xE5\xAF\xB8", + "\xB4\xE8" => "\xE7\xA3\x8B", + "\xB4\xE9" => "\xE6\x92\xAE", + "\xB4\xEA" => "\xE6\x90\x93", + "\xB4\xEB" => "\xE6\x8E\xAA", + "\xB4\xEC" => "\xE6\x8C\xAB", + "\xB4\xED" => "\xE9\x94\x99", + "\xB4\xEE" => "\xE6\x90\xAD", + "\xB4\xEF" => "\xE8\xBE\xBE", + "\xB4\xF0" => "\xE7\xAD\x94", + "\xB4\xF1" => "\xE7\x98\xA9", + "\xB4\xF2" => "\xE6\x89\x93", + "\xB4\xF3" => "\xE5\xA4\xA7", + "\xB4\xF4" => "\xE5\x91\x86", + "\xB4\xF5" => "\xE6\xAD\xB9", + "\xB4\xF6" => "\xE5\x82\xA3", + "\xB4\xF7" => "\xE6\x88\xB4", + "\xB4\xF8" => "\xE5\xB8\xA6", + "\xB4\xF9" => "\xE6\xAE\x86", + "\xB4\xFA" => "\xE4\xBB\xA3", + "\xB4\xFB" => "\xE8\xB4\xB7", + "\xB4\xFC" => "\xE8\xA2\x8B", + "\xB4\xFD" => "\xE5\xBE\x85", + "\xB4\xFE" => "\xE9\x80\xAE", + "\xB5\xA1" => "\xE6\x80\xA0", + "\xB5\xA2" => "\xE8\x80\xBD", + "\xB5\xA3" => "\xE6\x8B\x85", + "\xB5\xA4" => "\xE4\xB8\xB9", + "\xB5\xA5" => "\xE5\x8D\x95", + "\xB5\xA6" => "\xE9\x83\xB8", + "\xB5\xA7" => "\xE6\x8E\xB8", + "\xB5\xA8" => "\xE8\x83\x86", + "\xB5\xA9" => "\xE6\x97\xA6", + "\xB5\xAA" => "\xE6\xB0\xAE", + "\xB5\xAB" => "\xE4\xBD\x86", + "\xB5\xAC" => "\xE6\x83\xAE", + "\xB5\xAD" => "\xE6\xB7\xA1", + "\xB5\xAE" => "\xE8\xAF\x9E", + "\xB5\xAF" => "\xE5\xBC\xB9", + "\xB5\xB0" => "\xE8\x9B\x8B", + "\xB5\xB1" => "\xE5\xBD\x93", + "\xB5\xB2" => "\xE6\x8C\xA1", + "\xB5\xB3" => "\xE5\x85\x9A", + "\xB5\xB4" => "\xE8\x8D\xA1", + "\xB5\xB5" => "\xE6\xA1\xA3", + "\xB5\xB6" => "\xE5\x88\x80", + "\xB5\xB7" => "\xE6\x8D\xA3", + "\xB5\xB8" => "\xE8\xB9\x88", + "\xB5\xB9" => "\xE5\x80\x92", + "\xB5\xBA" => "\xE5\xB2\x9B", + "\xB5\xBB" => "\xE7\xA5\xB7", + "\xB5\xBC" => "\xE5\xAF\xBC", + "\xB5\xBD" => "\xE5\x88\xB0", + "\xB5\xBE" => "\xE7\xA8\xBB", + "\xB5\xBF" => "\xE6\x82\xBC", + "\xB5\xC0" => "\xE9\x81\x93", + "\xB5\xC1" => "\xE7\x9B\x97", + "\xB5\xC2" => "\xE5\xBE\xB7", + "\xB5\xC3" => "\xE5\xBE\x97", + "\xB5\xC4" => "\xE7\x9A\x84", + "\xB5\xC5" => "\xE8\xB9\xAC", + "\xB5\xC6" => "\xE7\x81\xAF", + "\xB5\xC7" => "\xE7\x99\xBB", + "\xB5\xC8" => "\xE7\xAD\x89", + "\xB5\xC9" => "\xE7\x9E\xAA", + "\xB5\xCA" => "\xE5\x87\xB3", + "\xB5\xCB" => "\xE9\x82\x93", + "\xB5\xCC" => "\xE5\xA0\xA4", + "\xB5\xCD" => "\xE4\xBD\x8E", + "\xB5\xCE" => "\xE6\xBB\xB4", + "\xB5\xCF" => "\xE8\xBF\xAA", + "\xB5\xD0" => "\xE6\x95\x8C", + "\xB5\xD1" => "\xE7\xAC\x9B", + "\xB5\xD2" => "\xE7\x8B\x84", + "\xB5\xD3" => "\xE6\xB6\xA4", + "\xB5\xD4" => "\xE7\xBF\x9F", + "\xB5\xD5" => "\xE5\xAB\xA1", + "\xB5\xD6" => "\xE6\x8A\xB5", + "\xB5\xD7" => "\xE5\xBA\x95", + "\xB5\xD8" => "\xE5\x9C\xB0", + "\xB5\xD9" => "\xE8\x92\x82", + "\xB5\xDA" => "\xE7\xAC\xAC", + "\xB5\xDB" => "\xE5\xB8\x9D", + "\xB5\xDC" => "\xE5\xBC\x9F", + "\xB5\xDD" => "\xE9\x80\x92", + "\xB5\xDE" => "\xE7\xBC\x94", + "\xB5\xDF" => "\xE9\xA2\xA0", + "\xB5\xE0" => "\xE6\x8E\x82", + "\xB5\xE1" => "\xE6\xBB\x87", + "\xB5\xE2" => "\xE7\xA2\x98", + "\xB5\xE3" => "\xE7\x82\xB9", + "\xB5\xE4" => "\xE5\x85\xB8", + "\xB5\xE5" => "\xE9\x9D\x9B", + "\xB5\xE6" => "\xE5\x9E\xAB", + "\xB5\xE7" => "\xE7\x94\xB5", + "\xB5\xE8" => "\xE4\xBD\x83", + "\xB5\xE9" => "\xE7\x94\xB8", + "\xB5\xEA" => "\xE5\xBA\x97", + "\xB5\xEB" => "\xE6\x83\xA6", + "\xB5\xEC" => "\xE5\xA5\xA0", + "\xB5\xED" => "\xE6\xB7\x80", + "\xB5\xEE" => "\xE6\xAE\xBF", + "\xB5\xEF" => "\xE7\xA2\x89", + "\xB5\xF0" => "\xE5\x8F\xBC", + "\xB5\xF1" => "\xE9\x9B\x95", + "\xB5\xF2" => "\xE5\x87\x8B", + "\xB5\xF3" => "\xE5\x88\x81", + "\xB5\xF4" => "\xE6\x8E\x89", + "\xB5\xF5" => "\xE5\x90\x8A", + "\xB5\xF6" => "\xE9\x92\x93", + "\xB5\xF7" => "\xE8\xB0\x83", + "\xB5\xF8" => "\xE8\xB7\x8C", + "\xB5\xF9" => "\xE7\x88\xB9", + "\xB5\xFA" => "\xE7\xA2\x9F", + "\xB5\xFB" => "\xE8\x9D\xB6", + "\xB5\xFC" => "\xE8\xBF\xAD", + "\xB5\xFD" => "\xE8\xB0\x8D", + "\xB5\xFE" => "\xE5\x8F\xA0", + "\xB6\xA1" => "\xE4\xB8\x81", + "\xB6\xA2" => "\xE7\x9B\xAF", + "\xB6\xA3" => "\xE5\x8F\xAE", + "\xB6\xA4" => "\xE9\x92\x89", + "\xB6\xA5" => "\xE9\xA1\xB6", + "\xB6\xA6" => "\xE9\xBC\x8E", + "\xB6\xA7" => "\xE9\x94\xAD", + "\xB6\xA8" => "\xE5\xAE\x9A", + "\xB6\xA9" => "\xE8\xAE\xA2", + "\xB6\xAA" => "\xE4\xB8\xA2", + "\xB6\xAB" => "\xE4\xB8\x9C", + "\xB6\xAC" => "\xE5\x86\xAC", + "\xB6\xAD" => "\xE8\x91\xA3", + "\xB6\xAE" => "\xE6\x87\x82", + "\xB6\xAF" => "\xE5\x8A\xA8", + "\xB6\xB0" => "\xE6\xA0\x8B", + "\xB6\xB1" => "\xE4\xBE\x97", + "\xB6\xB2" => "\xE6\x81\xAB", + "\xB6\xB3" => "\xE5\x86\xBB", + "\xB6\xB4" => "\xE6\xB4\x9E", + "\xB6\xB5" => "\xE5\x85\x9C", + "\xB6\xB6" => "\xE6\x8A\x96", + "\xB6\xB7" => "\xE6\x96\x97", + "\xB6\xB8" => "\xE9\x99\xA1", + "\xB6\xB9" => "\xE8\xB1\x86", + "\xB6\xBA" => "\xE9\x80\x97", + "\xB6\xBB" => "\xE7\x97\x98", + "\xB6\xBC" => "\xE9\x83\xBD", + "\xB6\xBD" => "\xE7\x9D\xA3", + "\xB6\xBE" => "\xE6\xAF\x92", + "\xB6\xBF" => "\xE7\x8A\x8A", + "\xB6\xC0" => "\xE7\x8B\xAC", + "\xB6\xC1" => "\xE8\xAF\xBB", + "\xB6\xC2" => "\xE5\xA0\xB5", + "\xB6\xC3" => "\xE7\x9D\xB9", + "\xB6\xC4" => "\xE8\xB5\x8C", + "\xB6\xC5" => "\xE6\x9D\x9C", + "\xB6\xC6" => "\xE9\x95\x80", + "\xB6\xC7" => "\xE8\x82\x9A", + "\xB6\xC8" => "\xE5\xBA\xA6", + "\xB6\xC9" => "\xE6\xB8\xA1", + "\xB6\xCA" => "\xE5\xA6\x92", + "\xB6\xCB" => "\xE7\xAB\xAF", + "\xB6\xCC" => "\xE7\x9F\xAD", + "\xB6\xCD" => "\xE9\x94\xBB", + "\xB6\xCE" => "\xE6\xAE\xB5", + "\xB6\xCF" => "\xE6\x96\xAD", + "\xB6\xD0" => "\xE7\xBC\x8E", + "\xB6\xD1" => "\xE5\xA0\x86", + "\xB6\xD2" => "\xE5\x85\x91", + "\xB6\xD3" => "\xE9\x98\x9F", + "\xB6\xD4" => "\xE5\xAF\xB9", + "\xB6\xD5" => "\xE5\xA2\xA9", + "\xB6\xD6" => "\xE5\x90\xA8", + "\xB6\xD7" => "\xE8\xB9\xB2", + "\xB6\xD8" => "\xE6\x95\xA6", + "\xB6\xD9" => "\xE9\xA1\xBF", + "\xB6\xDA" => "\xE5\x9B\xA4", + "\xB6\xDB" => "\xE9\x92\x9D", + "\xB6\xDC" => "\xE7\x9B\xBE", + "\xB6\xDD" => "\xE9\x81\x81", + "\xB6\xDE" => "\xE6\x8E\x87", + "\xB6\xDF" => "\xE5\x93\x86", + "\xB6\xE0" => "\xE5\xA4\x9A", + "\xB6\xE1" => "\xE5\xA4\xBA", + "\xB6\xE2" => "\xE5\x9E\x9B", + "\xB6\xE3" => "\xE8\xBA\xB2", + "\xB6\xE4" => "\xE6\x9C\xB5", + "\xB6\xE5" => "\xE8\xB7\xBA", + "\xB6\xE6" => "\xE8\x88\xB5", + "\xB6\xE7" => "\xE5\x89\x81", + "\xB6\xE8" => "\xE6\x83\xB0", + "\xB6\xE9" => "\xE5\xA0\x95", + "\xB6\xEA" => "\xE8\x9B\xBE", + "\xB6\xEB" => "\xE5\xB3\xA8", + "\xB6\xEC" => "\xE9\xB9\x85", + "\xB6\xED" => "\xE4\xBF\x84", + "\xB6\xEE" => "\xE9\xA2\x9D", + "\xB6\xEF" => "\xE8\xAE\xB9", + "\xB6\xF0" => "\xE5\xA8\xA5", + "\xB6\xF1" => "\xE6\x81\xB6", + "\xB6\xF2" => "\xE5\x8E\x84", + "\xB6\xF3" => "\xE6\x89\xBC", + "\xB6\xF4" => "\xE9\x81\x8F", + "\xB6\xF5" => "\xE9\x84\x82", + "\xB6\xF6" => "\xE9\xA5\xBF", + "\xB6\xF7" => "\xE6\x81\xA9", + "\xB6\xF8" => "\xE8\x80\x8C", + "\xB6\xF9" => "\xE5\x84\xBF", + "\xB6\xFA" => "\xE8\x80\xB3", + "\xB6\xFB" => "\xE5\xB0\x94", + "\xB6\xFC" => "\xE9\xA5\xB5", + "\xB6\xFD" => "\xE6\xB4\xB1", + "\xB6\xFE" => "\xE4\xBA\x8C", + "\xB7\xA1" => "\xE8\xB4\xB0", + "\xB7\xA2" => "\xE5\x8F\x91", + "\xB7\xA3" => "\xE7\xBD\x9A", + "\xB7\xA4" => "\xE7\xAD\x8F", + "\xB7\xA5" => "\xE4\xBC\x90", + "\xB7\xA6" => "\xE4\xB9\x8F", + "\xB7\xA7" => "\xE9\x98\x80", + "\xB7\xA8" => "\xE6\xB3\x95", + "\xB7\xA9" => "\xE7\x8F\x90", + "\xB7\xAA" => "\xE8\x97\xA9", + "\xB7\xAB" => "\xE5\xB8\x86", + "\xB7\xAC" => "\xE7\x95\xAA", + "\xB7\xAD" => "\xE7\xBF\xBB", + "\xB7\xAE" => "\xE6\xA8\x8A", + "\xB7\xAF" => "\xE7\x9F\xBE", + "\xB7\xB0" => "\xE9\x92\x92", + "\xB7\xB1" => "\xE7\xB9\x81", + "\xB7\xB2" => "\xE5\x87\xA1", + "\xB7\xB3" => "\xE7\x83\xA6", + "\xB7\xB4" => "\xE5\x8F\x8D", + "\xB7\xB5" => "\xE8\xBF\x94", + "\xB7\xB6" => "\xE8\x8C\x83", + "\xB7\xB7" => "\xE8\xB4\xA9", + "\xB7\xB8" => "\xE7\x8A\xAF", + "\xB7\xB9" => "\xE9\xA5\xAD", + "\xB7\xBA" => "\xE6\xB3\x9B", + "\xB7\xBB" => "\xE5\x9D\x8A", + "\xB7\xBC" => "\xE8\x8A\xB3", + "\xB7\xBD" => "\xE6\x96\xB9", + "\xB7\xBE" => "\xE8\x82\xAA", + "\xB7\xBF" => "\xE6\x88\xBF", + "\xB7\xC0" => "\xE9\x98\xB2", + "\xB7\xC1" => "\xE5\xA6\xA8", + "\xB7\xC2" => "\xE4\xBB\xBF", + "\xB7\xC3" => "\xE8\xAE\xBF", + "\xB7\xC4" => "\xE7\xBA\xBA", + "\xB7\xC5" => "\xE6\x94\xBE", + "\xB7\xC6" => "\xE8\x8F\xB2", + "\xB7\xC7" => "\xE9\x9D\x9E", + "\xB7\xC8" => "\xE5\x95\xA1", + "\xB7\xC9" => "\xE9\xA3\x9E", + "\xB7\xCA" => "\xE8\x82\xA5", + "\xB7\xCB" => "\xE5\x8C\xAA", + "\xB7\xCC" => "\xE8\xAF\xBD", + "\xB7\xCD" => "\xE5\x90\xA0", + "\xB7\xCE" => "\xE8\x82\xBA", + "\xB7\xCF" => "\xE5\xBA\x9F", + "\xB7\xD0" => "\xE6\xB2\xB8", + "\xB7\xD1" => "\xE8\xB4\xB9", + "\xB7\xD2" => "\xE8\x8A\xAC", + "\xB7\xD3" => "\xE9\x85\x9A", + "\xB7\xD4" => "\xE5\x90\xA9", + "\xB7\xD5" => "\xE6\xB0\x9B", + "\xB7\xD6" => "\xE5\x88\x86", + "\xB7\xD7" => "\xE7\xBA\xB7", + "\xB7\xD8" => "\xE5\x9D\x9F", + "\xB7\xD9" => "\xE7\x84\x9A", + "\xB7\xDA" => "\xE6\xB1\xBE", + "\xB7\xDB" => "\xE7\xB2\x89", + "\xB7\xDC" => "\xE5\xA5\x8B", + "\xB7\xDD" => "\xE4\xBB\xBD", + "\xB7\xDE" => "\xE5\xBF\xBF", + "\xB7\xDF" => "\xE6\x84\xA4", + "\xB7\xE0" => "\xE7\xB2\xAA", + "\xB7\xE1" => "\xE4\xB8\xB0", + "\xB7\xE2" => "\xE5\xB0\x81", + "\xB7\xE3" => "\xE6\x9E\xAB", + "\xB7\xE4" => "\xE8\x9C\x82", + "\xB7\xE5" => "\xE5\xB3\xB0", + "\xB7\xE6" => "\xE9\x94\x8B", + "\xB7\xE7" => "\xE9\xA3\x8E", + "\xB7\xE8" => "\xE7\x96\xAF", + "\xB7\xE9" => "\xE7\x83\xBD", + "\xB7\xEA" => "\xE9\x80\xA2", + "\xB7\xEB" => "\xE5\x86\xAF", + "\xB7\xEC" => "\xE7\xBC\x9D", + "\xB7\xED" => "\xE8\xAE\xBD", + "\xB7\xEE" => "\xE5\xA5\x89", + "\xB7\xEF" => "\xE5\x87\xA4", + "\xB7\xF0" => "\xE4\xBD\x9B", + "\xB7\xF1" => "\xE5\x90\xA6", + "\xB7\xF2" => "\xE5\xA4\xAB", + "\xB7\xF3" => "\xE6\x95\xB7", + "\xB7\xF4" => "\xE8\x82\xA4", + "\xB7\xF5" => "\xE5\xAD\xB5", + "\xB7\xF6" => "\xE6\x89\xB6", + "\xB7\xF7" => "\xE6\x8B\x82", + "\xB7\xF8" => "\xE8\xBE\x90", + "\xB7\xF9" => "\xE5\xB9\x85", + "\xB7\xFA" => "\xE6\xB0\x9F", + "\xB7\xFB" => "\xE7\xAC\xA6", + "\xB7\xFC" => "\xE4\xBC\x8F", + "\xB7\xFD" => "\xE4\xBF\x98", + "\xB7\xFE" => "\xE6\x9C\x8D", + "\xB8\xA1" => "\xE6\xB5\xAE", + "\xB8\xA2" => "\xE6\xB6\xAA", + "\xB8\xA3" => "\xE7\xA6\x8F", + "\xB8\xA4" => "\xE8\xA2\xB1", + "\xB8\xA5" => "\xE5\xBC\x97", + "\xB8\xA6" => "\xE7\x94\xAB", + "\xB8\xA7" => "\xE6\x8A\x9A", + "\xB8\xA8" => "\xE8\xBE\x85", + "\xB8\xA9" => "\xE4\xBF\xAF", + "\xB8\xAA" => "\xE9\x87\x9C", + "\xB8\xAB" => "\xE6\x96\xA7", + "\xB8\xAC" => "\xE8\x84\xAF", + "\xB8\xAD" => "\xE8\x85\x91", + "\xB8\xAE" => "\xE5\xBA\x9C", + "\xB8\xAF" => "\xE8\x85\x90", + "\xB8\xB0" => "\xE8\xB5\xB4", + "\xB8\xB1" => "\xE5\x89\xAF", + "\xB8\xB2" => "\xE8\xA6\x86", + "\xB8\xB3" => "\xE8\xB5\x8B", + "\xB8\xB4" => "\xE5\xA4\x8D", + "\xB8\xB5" => "\xE5\x82\x85", + "\xB8\xB6" => "\xE4\xBB\x98", + "\xB8\xB7" => "\xE9\x98\x9C", + "\xB8\xB8" => "\xE7\x88\xB6", + "\xB8\xB9" => "\xE8\x85\xB9", + "\xB8\xBA" => "\xE8\xB4\x9F", + "\xB8\xBB" => "\xE5\xAF\x8C", + "\xB8\xBC" => "\xE8\xAE\xA3", + "\xB8\xBD" => "\xE9\x99\x84", + "\xB8\xBE" => "\xE5\xA6\x87", + "\xB8\xBF" => "\xE7\xBC\x9A", + "\xB8\xC0" => "\xE5\x92\x90", + "\xB8\xC1" => "\xE5\x99\xB6", + "\xB8\xC2" => "\xE5\x98\x8E", + "\xB8\xC3" => "\xE8\xAF\xA5", + "\xB8\xC4" => "\xE6\x94\xB9", + "\xB8\xC5" => "\xE6\xA6\x82", + "\xB8\xC6" => "\xE9\x92\x99", + "\xB8\xC7" => "\xE7\x9B\x96", + "\xB8\xC8" => "\xE6\xBA\x89", + "\xB8\xC9" => "\xE5\xB9\xB2", + "\xB8\xCA" => "\xE7\x94\x98", + "\xB8\xCB" => "\xE6\x9D\x86", + "\xB8\xCC" => "\xE6\x9F\x91", + "\xB8\xCD" => "\xE7\xAB\xBF", + "\xB8\xCE" => "\xE8\x82\x9D", + "\xB8\xCF" => "\xE8\xB5\xB6", + "\xB8\xD0" => "\xE6\x84\x9F", + "\xB8\xD1" => "\xE7\xA7\x86", + "\xB8\xD2" => "\xE6\x95\xA2", + "\xB8\xD3" => "\xE8\xB5\xA3", + "\xB8\xD4" => "\xE5\x86\x88", + "\xB8\xD5" => "\xE5\x88\x9A", + "\xB8\xD6" => "\xE9\x92\xA2", + "\xB8\xD7" => "\xE7\xBC\xB8", + "\xB8\xD8" => "\xE8\x82\x9B", + "\xB8\xD9" => "\xE7\xBA\xB2", + "\xB8\xDA" => "\xE5\xB2\x97", + "\xB8\xDB" => "\xE6\xB8\xAF", + "\xB8\xDC" => "\xE6\x9D\xA0", + "\xB8\xDD" => "\xE7\xAF\x99", + "\xB8\xDE" => "\xE7\x9A\x8B", + "\xB8\xDF" => "\xE9\xAB\x98", + "\xB8\xE0" => "\xE8\x86\x8F", + "\xB8\xE1" => "\xE7\xBE\x94", + "\xB8\xE2" => "\xE7\xB3\x95", + "\xB8\xE3" => "\xE6\x90\x9E", + "\xB8\xE4" => "\xE9\x95\x90", + "\xB8\xE5" => "\xE7\xA8\xBF", + "\xB8\xE6" => "\xE5\x91\x8A", + "\xB8\xE7" => "\xE5\x93\xA5", + "\xB8\xE8" => "\xE6\xAD\x8C", + "\xB8\xE9" => "\xE6\x90\x81", + "\xB8\xEA" => "\xE6\x88\x88", + "\xB8\xEB" => "\xE9\xB8\xBD", + "\xB8\xEC" => "\xE8\x83\xB3", + "\xB8\xED" => "\xE7\x96\x99", + "\xB8\xEE" => "\xE5\x89\xB2", + "\xB8\xEF" => "\xE9\x9D\xA9", + "\xB8\xF0" => "\xE8\x91\x9B", + "\xB8\xF1" => "\xE6\xA0\xBC", + "\xB8\xF2" => "\xE8\x9B\xA4", + "\xB8\xF3" => "\xE9\x98\x81", + "\xB8\xF4" => "\xE9\x9A\x94", + "\xB8\xF5" => "\xE9\x93\xAC", + "\xB8\xF6" => "\xE4\xB8\xAA", + "\xB8\xF7" => "\xE5\x90\x84", + "\xB8\xF8" => "\xE7\xBB\x99", + "\xB8\xF9" => "\xE6\xA0\xB9", + "\xB8\xFA" => "\xE8\xB7\x9F", + "\xB8\xFB" => "\xE8\x80\x95", + "\xB8\xFC" => "\xE6\x9B\xB4", + "\xB8\xFD" => "\xE5\xBA\x9A", + "\xB8\xFE" => "\xE7\xBE\xB9", + "\xB9\xA1" => "\xE5\x9F\x82", + "\xB9\xA2" => "\xE8\x80\xBF", + "\xB9\xA3" => "\xE6\xA2\x97", + "\xB9\xA4" => "\xE5\xB7\xA5", + "\xB9\xA5" => "\xE6\x94\xBB", + "\xB9\xA6" => "\xE5\x8A\x9F", + "\xB9\xA7" => "\xE6\x81\xAD", + "\xB9\xA8" => "\xE9\xBE\x9A", + "\xB9\xA9" => "\xE4\xBE\x9B", + "\xB9\xAA" => "\xE8\xBA\xAC", + "\xB9\xAB" => "\xE5\x85\xAC", + "\xB9\xAC" => "\xE5\xAE\xAB", + "\xB9\xAD" => "\xE5\xBC\x93", + "\xB9\xAE" => "\xE5\xB7\xA9", + "\xB9\xAF" => "\xE6\xB1\x9E", + "\xB9\xB0" => "\xE6\x8B\xB1", + "\xB9\xB1" => "\xE8\xB4\xA1", + "\xB9\xB2" => "\xE5\x85\xB1", + "\xB9\xB3" => "\xE9\x92\xA9", + "\xB9\xB4" => "\xE5\x8B\xBE", + "\xB9\xB5" => "\xE6\xB2\x9F", + "\xB9\xB6" => "\xE8\x8B\x9F", + "\xB9\xB7" => "\xE7\x8B\x97", + "\xB9\xB8" => "\xE5\x9E\xA2", + "\xB9\xB9" => "\xE6\x9E\x84", + "\xB9\xBA" => "\xE8\xB4\xAD", + "\xB9\xBB" => "\xE5\xA4\x9F", + "\xB9\xBC" => "\xE8\xBE\x9C", + "\xB9\xBD" => "\xE8\x8F\x87", + "\xB9\xBE" => "\xE5\x92\x95", + "\xB9\xBF" => "\xE7\xAE\x8D", + "\xB9\xC0" => "\xE4\xBC\xB0", + "\xB9\xC1" => "\xE6\xB2\xBD", + "\xB9\xC2" => "\xE5\xAD\xA4", + "\xB9\xC3" => "\xE5\xA7\x91", + "\xB9\xC4" => "\xE9\xBC\x93", + "\xB9\xC5" => "\xE5\x8F\xA4", + "\xB9\xC6" => "\xE8\x9B\x8A", + "\xB9\xC7" => "\xE9\xAA\xA8", + "\xB9\xC8" => "\xE8\xB0\xB7", + "\xB9\xC9" => "\xE8\x82\xA1", + "\xB9\xCA" => "\xE6\x95\x85", + "\xB9\xCB" => "\xE9\xA1\xBE", + "\xB9\xCC" => "\xE5\x9B\xBA", + "\xB9\xCD" => "\xE9\x9B\x87", + "\xB9\xCE" => "\xE5\x88\xAE", + "\xB9\xCF" => "\xE7\x93\x9C", + "\xB9\xD0" => "\xE5\x89\x90", + "\xB9\xD1" => "\xE5\xAF\xA1", + "\xB9\xD2" => "\xE6\x8C\x82", + "\xB9\xD3" => "\xE8\xA4\x82", + "\xB9\xD4" => "\xE4\xB9\x96", + "\xB9\xD5" => "\xE6\x8B\x90", + "\xB9\xD6" => "\xE6\x80\xAA", + "\xB9\xD7" => "\xE6\xA3\xBA", + "\xB9\xD8" => "\xE5\x85\xB3", + "\xB9\xD9" => "\xE5\xAE\x98", + "\xB9\xDA" => "\xE5\x86\xA0", + "\xB9\xDB" => "\xE8\xA7\x82", + "\xB9\xDC" => "\xE7\xAE\xA1", + "\xB9\xDD" => "\xE9\xA6\x86", + "\xB9\xDE" => "\xE7\xBD\x90", + "\xB9\xDF" => "\xE6\x83\xAF", + "\xB9\xE0" => "\xE7\x81\x8C", + "\xB9\xE1" => "\xE8\xB4\xAF", + "\xB9\xE2" => "\xE5\x85\x89", + "\xB9\xE3" => "\xE5\xB9\xBF", + "\xB9\xE4" => "\xE9\x80\x9B", + "\xB9\xE5" => "\xE7\x91\xB0", + "\xB9\xE6" => "\xE8\xA7\x84", + "\xB9\xE7" => "\xE5\x9C\xAD", + "\xB9\xE8" => "\xE7\xA1\x85", + "\xB9\xE9" => "\xE5\xBD\x92", + "\xB9\xEA" => "\xE9\xBE\x9F", + "\xB9\xEB" => "\xE9\x97\xBA", + "\xB9\xEC" => "\xE8\xBD\xA8", + "\xB9\xED" => "\xE9\xAC\xBC", + "\xB9\xEE" => "\xE8\xAF\xA1", + "\xB9\xEF" => "\xE7\x99\xB8", + "\xB9\xF0" => "\xE6\xA1\x82", + "\xB9\xF1" => "\xE6\x9F\x9C", + "\xB9\xF2" => "\xE8\xB7\xAA", + "\xB9\xF3" => "\xE8\xB4\xB5", + "\xB9\xF4" => "\xE5\x88\xBD", + "\xB9\xF5" => "\xE8\xBE\x8A", + "\xB9\xF6" => "\xE6\xBB\x9A", + "\xB9\xF7" => "\xE6\xA3\x8D", + "\xB9\xF8" => "\xE9\x94\x85", + "\xB9\xF9" => "\xE9\x83\xAD", + "\xB9\xFA" => "\xE5\x9B\xBD", + "\xB9\xFB" => "\xE6\x9E\x9C", + "\xB9\xFC" => "\xE8\xA3\xB9", + "\xB9\xFD" => "\xE8\xBF\x87", + "\xB9\xFE" => "\xE5\x93\x88", + "\xBA\xA1" => "\xE9\xAA\xB8", + "\xBA\xA2" => "\xE5\xAD\xA9", + "\xBA\xA3" => "\xE6\xB5\xB7", + "\xBA\xA4" => "\xE6\xB0\xA6", + "\xBA\xA5" => "\xE4\xBA\xA5", + "\xBA\xA6" => "\xE5\xAE\xB3", + "\xBA\xA7" => "\xE9\xAA\x87", + "\xBA\xA8" => "\xE9\x85\xA3", + "\xBA\xA9" => "\xE6\x86\xA8", + "\xBA\xAA" => "\xE9\x82\xAF", + "\xBA\xAB" => "\xE9\x9F\xA9", + "\xBA\xAC" => "\xE5\x90\xAB", + "\xBA\xAD" => "\xE6\xB6\xB5", + "\xBA\xAE" => "\xE5\xAF\x92", + "\xBA\xAF" => "\xE5\x87\xBD", + "\xBA\xB0" => "\xE5\x96\x8A", + "\xBA\xB1" => "\xE7\xBD\x95", + "\xBA\xB2" => "\xE7\xBF\xB0", + "\xBA\xB3" => "\xE6\x92\xBC", + "\xBA\xB4" => "\xE6\x8D\x8D", + "\xBA\xB5" => "\xE6\x97\xB1", + "\xBA\xB6" => "\xE6\x86\xBE", + "\xBA\xB7" => "\xE6\x82\x8D", + "\xBA\xB8" => "\xE7\x84\x8A", + "\xBA\xB9" => "\xE6\xB1\x97", + "\xBA\xBA" => "\xE6\xB1\x89", + "\xBA\xBB" => "\xE5\xA4\xAF", + "\xBA\xBC" => "\xE6\x9D\xAD", + "\xBA\xBD" => "\xE8\x88\xAA", + "\xBA\xBE" => "\xE5\xA3\x95", + "\xBA\xBF" => "\xE5\x9A\x8E", + "\xBA\xC0" => "\xE8\xB1\xAA", + "\xBA\xC1" => "\xE6\xAF\xAB", + "\xBA\xC2" => "\xE9\x83\x9D", + "\xBA\xC3" => "\xE5\xA5\xBD", + "\xBA\xC4" => "\xE8\x80\x97", + "\xBA\xC5" => "\xE5\x8F\xB7", + "\xBA\xC6" => "\xE6\xB5\xA9", + "\xBA\xC7" => "\xE5\x91\xB5", + "\xBA\xC8" => "\xE5\x96\x9D", + "\xBA\xC9" => "\xE8\x8D\xB7", + "\xBA\xCA" => "\xE8\x8F\x8F", + "\xBA\xCB" => "\xE6\xA0\xB8", + "\xBA\xCC" => "\xE7\xA6\xBE", + "\xBA\xCD" => "\xE5\x92\x8C", + "\xBA\xCE" => "\xE4\xBD\x95", + "\xBA\xCF" => "\xE5\x90\x88", + "\xBA\xD0" => "\xE7\x9B\x92", + "\xBA\xD1" => "\xE8\xB2\x89", + "\xBA\xD2" => "\xE9\x98\x82", + "\xBA\xD3" => "\xE6\xB2\xB3", + "\xBA\xD4" => "\xE6\xB6\xB8", + "\xBA\xD5" => "\xE8\xB5\xAB", + "\xBA\xD6" => "\xE8\xA4\x90", + "\xBA\xD7" => "\xE9\xB9\xA4", + "\xBA\xD8" => "\xE8\xB4\xBA", + "\xBA\xD9" => "\xE5\x98\xBF", + "\xBA\xDA" => "\xE9\xBB\x91", + "\xBA\xDB" => "\xE7\x97\x95", + "\xBA\xDC" => "\xE5\xBE\x88", + "\xBA\xDD" => "\xE7\x8B\xA0", + "\xBA\xDE" => "\xE6\x81\xA8", + "\xBA\xDF" => "\xE5\x93\xBC", + "\xBA\xE0" => "\xE4\xBA\xA8", + "\xBA\xE1" => "\xE6\xA8\xAA", + "\xBA\xE2" => "\xE8\xA1\xA1", + "\xBA\xE3" => "\xE6\x81\x92", + "\xBA\xE4" => "\xE8\xBD\xB0", + "\xBA\xE5" => "\xE5\x93\x84", + "\xBA\xE6" => "\xE7\x83\x98", + "\xBA\xE7" => "\xE8\x99\xB9", + "\xBA\xE8" => "\xE9\xB8\xBF", + "\xBA\xE9" => "\xE6\xB4\xAA", + "\xBA\xEA" => "\xE5\xAE\x8F", + "\xBA\xEB" => "\xE5\xBC\x98", + "\xBA\xEC" => "\xE7\xBA\xA2", + "\xBA\xED" => "\xE5\x96\x89", + "\xBA\xEE" => "\xE4\xBE\xAF", + "\xBA\xEF" => "\xE7\x8C\xB4", + "\xBA\xF0" => "\xE5\x90\xBC", + "\xBA\xF1" => "\xE5\x8E\x9A", + "\xBA\xF2" => "\xE5\x80\x99", + "\xBA\xF3" => "\xE5\x90\x8E", + "\xBA\xF4" => "\xE5\x91\xBC", + "\xBA\xF5" => "\xE4\xB9\x8E", + "\xBA\xF6" => "\xE5\xBF\xBD", + "\xBA\xF7" => "\xE7\x91\x9A", + "\xBA\xF8" => "\xE5\xA3\xB6", + "\xBA\xF9" => "\xE8\x91\xAB", + "\xBA\xFA" => "\xE8\x83\xA1", + "\xBA\xFB" => "\xE8\x9D\xB4", + "\xBA\xFC" => "\xE7\x8B\x90", + "\xBA\xFD" => "\xE7\xB3\x8A", + "\xBA\xFE" => "\xE6\xB9\x96", + "\xBB\xA1" => "\xE5\xBC\xA7", + "\xBB\xA2" => "\xE8\x99\x8E", + "\xBB\xA3" => "\xE5\x94\xAC", + "\xBB\xA4" => "\xE6\x8A\xA4", + "\xBB\xA5" => "\xE4\xBA\x92", + "\xBB\xA6" => "\xE6\xB2\xAA", + "\xBB\xA7" => "\xE6\x88\xB7", + "\xBB\xA8" => "\xE8\x8A\xB1", + "\xBB\xA9" => "\xE5\x93\x97", + "\xBB\xAA" => "\xE5\x8D\x8E", + "\xBB\xAB" => "\xE7\x8C\xBE", + "\xBB\xAC" => "\xE6\xBB\x91", + "\xBB\xAD" => "\xE7\x94\xBB", + "\xBB\xAE" => "\xE5\x88\x92", + "\xBB\xAF" => "\xE5\x8C\x96", + "\xBB\xB0" => "\xE8\xAF\x9D", + "\xBB\xB1" => "\xE6\xA7\x90", + "\xBB\xB2" => "\xE5\xBE\x8A", + "\xBB\xB3" => "\xE6\x80\x80", + "\xBB\xB4" => "\xE6\xB7\xAE", + "\xBB\xB5" => "\xE5\x9D\x8F", + "\xBB\xB6" => "\xE6\xAC\xA2", + "\xBB\xB7" => "\xE7\x8E\xAF", + "\xBB\xB8" => "\xE6\xA1\x93", + "\xBB\xB9" => "\xE8\xBF\x98", + "\xBB\xBA" => "\xE7\xBC\x93", + "\xBB\xBB" => "\xE6\x8D\xA2", + "\xBB\xBC" => "\xE6\x82\xA3", + "\xBB\xBD" => "\xE5\x94\xA4", + "\xBB\xBE" => "\xE7\x97\xAA", + "\xBB\xBF" => "\xE8\xB1\xA2", + "\xBB\xC0" => "\xE7\x84\x95", + "\xBB\xC1" => "\xE6\xB6\xA3", + "\xBB\xC2" => "\xE5\xAE\xA6", + "\xBB\xC3" => "\xE5\xB9\xBB", + "\xBB\xC4" => "\xE8\x8D\x92", + "\xBB\xC5" => "\xE6\x85\x8C", + "\xBB\xC6" => "\xE9\xBB\x84", + "\xBB\xC7" => "\xE7\xA3\xBA", + "\xBB\xC8" => "\xE8\x9D\x97", + "\xBB\xC9" => "\xE7\xB0\xA7", + "\xBB\xCA" => "\xE7\x9A\x87", + "\xBB\xCB" => "\xE5\x87\xB0", + "\xBB\xCC" => "\xE6\x83\xB6", + "\xBB\xCD" => "\xE7\x85\x8C", + "\xBB\xCE" => "\xE6\x99\x83", + "\xBB\xCF" => "\xE5\xB9\x8C", + "\xBB\xD0" => "\xE6\x81\x8D", + "\xBB\xD1" => "\xE8\xB0\x8E", + "\xBB\xD2" => "\xE7\x81\xB0", + "\xBB\xD3" => "\xE6\x8C\xA5", + "\xBB\xD4" => "\xE8\xBE\x89", + "\xBB\xD5" => "\xE5\xBE\xBD", + "\xBB\xD6" => "\xE6\x81\xA2", + "\xBB\xD7" => "\xE8\x9B\x94", + "\xBB\xD8" => "\xE5\x9B\x9E", + "\xBB\xD9" => "\xE6\xAF\x81", + "\xBB\xDA" => "\xE6\x82\x94", + "\xBB\xDB" => "\xE6\x85\xA7", + "\xBB\xDC" => "\xE5\x8D\x89", + "\xBB\xDD" => "\xE6\x83\xA0", + "\xBB\xDE" => "\xE6\x99\xA6", + "\xBB\xDF" => "\xE8\xB4\xBF", + "\xBB\xE0" => "\xE7\xA7\xBD", + "\xBB\xE1" => "\xE4\xBC\x9A", + "\xBB\xE2" => "\xE7\x83\xA9", + "\xBB\xE3" => "\xE6\xB1\x87", + "\xBB\xE4" => "\xE8\xAE\xB3", + "\xBB\xE5" => "\xE8\xAF\xB2", + "\xBB\xE6" => "\xE7\xBB\x98", + "\xBB\xE7" => "\xE8\x8D\xA4", + "\xBB\xE8" => "\xE6\x98\x8F", + "\xBB\xE9" => "\xE5\xA9\x9A", + "\xBB\xEA" => "\xE9\xAD\x82", + "\xBB\xEB" => "\xE6\xB5\x91", + "\xBB\xEC" => "\xE6\xB7\xB7", + "\xBB\xED" => "\xE8\xB1\x81", + "\xBB\xEE" => "\xE6\xB4\xBB", + "\xBB\xEF" => "\xE4\xBC\x99", + "\xBB\xF0" => "\xE7\x81\xAB", + "\xBB\xF1" => "\xE8\x8E\xB7", + "\xBB\xF2" => "\xE6\x88\x96", + "\xBB\xF3" => "\xE6\x83\x91", + "\xBB\xF4" => "\xE9\x9C\x8D", + "\xBB\xF5" => "\xE8\xB4\xA7", + "\xBB\xF6" => "\xE7\xA5\xB8", + "\xBB\xF7" => "\xE5\x87\xBB", + "\xBB\xF8" => "\xE5\x9C\xBE", + "\xBB\xF9" => "\xE5\x9F\xBA", + "\xBB\xFA" => "\xE6\x9C\xBA", + "\xBB\xFB" => "\xE7\x95\xB8", + "\xBB\xFC" => "\xE7\xA8\xBD", + "\xBB\xFD" => "\xE7\xA7\xAF", + "\xBB\xFE" => "\xE7\xAE\x95", + "\xBC\xA1" => "\xE8\x82\x8C", + "\xBC\xA2" => "\xE9\xA5\xA5", + "\xBC\xA3" => "\xE8\xBF\xB9", + "\xBC\xA4" => "\xE6\xBF\x80", + "\xBC\xA5" => "\xE8\xAE\xA5", + "\xBC\xA6" => "\xE9\xB8\xA1", + "\xBC\xA7" => "\xE5\xA7\xAC", + "\xBC\xA8" => "\xE7\xBB\xA9", + "\xBC\xA9" => "\xE7\xBC\x89", + "\xBC\xAA" => "\xE5\x90\x89", + "\xBC\xAB" => "\xE6\x9E\x81", + "\xBC\xAC" => "\xE6\xA3\x98", + "\xBC\xAD" => "\xE8\xBE\x91", + "\xBC\xAE" => "\xE7\xB1\x8D", + "\xBC\xAF" => "\xE9\x9B\x86", + "\xBC\xB0" => "\xE5\x8F\x8A", + "\xBC\xB1" => "\xE6\x80\xA5", + "\xBC\xB2" => "\xE7\x96\xBE", + "\xBC\xB3" => "\xE6\xB1\xB2", + "\xBC\xB4" => "\xE5\x8D\xB3", + "\xBC\xB5" => "\xE5\xAB\x89", + "\xBC\xB6" => "\xE7\xBA\xA7", + "\xBC\xB7" => "\xE6\x8C\xA4", + "\xBC\xB8" => "\xE5\x87\xA0", + "\xBC\xB9" => "\xE8\x84\x8A", + "\xBC\xBA" => "\xE5\xB7\xB1", + "\xBC\xBB" => "\xE8\x93\x9F", + "\xBC\xBC" => "\xE6\x8A\x80", + "\xBC\xBD" => "\xE5\x86\x80", + "\xBC\xBE" => "\xE5\xAD\xA3", + "\xBC\xBF" => "\xE4\xBC\x8E", + "\xBC\xC0" => "\xE7\xA5\xAD", + "\xBC\xC1" => "\xE5\x89\x82", + "\xBC\xC2" => "\xE6\x82\xB8", + "\xBC\xC3" => "\xE6\xB5\x8E", + "\xBC\xC4" => "\xE5\xAF\x84", + "\xBC\xC5" => "\xE5\xAF\x82", + "\xBC\xC6" => "\xE8\xAE\xA1", + "\xBC\xC7" => "\xE8\xAE\xB0", + "\xBC\xC8" => "\xE6\x97\xA2", + "\xBC\xC9" => "\xE5\xBF\x8C", + "\xBC\xCA" => "\xE9\x99\x85", + "\xBC\xCB" => "\xE5\xA6\x93", + "\xBC\xCC" => "\xE7\xBB\xA7", + "\xBC\xCD" => "\xE7\xBA\xAA", + "\xBC\xCE" => "\xE5\x98\x89", + "\xBC\xCF" => "\xE6\x9E\xB7", + "\xBC\xD0" => "\xE5\xA4\xB9", + "\xBC\xD1" => "\xE4\xBD\xB3", + "\xBC\xD2" => "\xE5\xAE\xB6", + "\xBC\xD3" => "\xE5\x8A\xA0", + "\xBC\xD4" => "\xE8\x8D\x9A", + "\xBC\xD5" => "\xE9\xA2\x8A", + "\xBC\xD6" => "\xE8\xB4\xBE", + "\xBC\xD7" => "\xE7\x94\xB2", + "\xBC\xD8" => "\xE9\x92\xBE", + "\xBC\xD9" => "\xE5\x81\x87", + "\xBC\xDA" => "\xE7\xA8\xBC", + "\xBC\xDB" => "\xE4\xBB\xB7", + "\xBC\xDC" => "\xE6\x9E\xB6", + "\xBC\xDD" => "\xE9\xA9\xBE", + "\xBC\xDE" => "\xE5\xAB\x81", + "\xBC\xDF" => "\xE6\xAD\xBC", + "\xBC\xE0" => "\xE7\x9B\x91", + "\xBC\xE1" => "\xE5\x9D\x9A", + "\xBC\xE2" => "\xE5\xB0\x96", + "\xBC\xE3" => "\xE7\xAC\xBA", + "\xBC\xE4" => "\xE9\x97\xB4", + "\xBC\xE5" => "\xE7\x85\x8E", + "\xBC\xE6" => "\xE5\x85\xBC", + "\xBC\xE7" => "\xE8\x82\xA9", + "\xBC\xE8" => "\xE8\x89\xB0", + "\xBC\xE9" => "\xE5\xA5\xB8", + "\xBC\xEA" => "\xE7\xBC\x84", + "\xBC\xEB" => "\xE8\x8C\xA7", + "\xBC\xEC" => "\xE6\xA3\x80", + "\xBC\xED" => "\xE6\x9F\xAC", + "\xBC\xEE" => "\xE7\xA2\xB1", + "\xBC\xEF" => "\xE7\xA1\xB7", + "\xBC\xF0" => "\xE6\x8B\xA3", + "\xBC\xF1" => "\xE6\x8D\xA1", + "\xBC\xF2" => "\xE7\xAE\x80", + "\xBC\xF3" => "\xE4\xBF\xAD", + "\xBC\xF4" => "\xE5\x89\xAA", + "\xBC\xF5" => "\xE5\x87\x8F", + "\xBC\xF6" => "\xE8\x8D\x90", + "\xBC\xF7" => "\xE6\xA7\x9B", + "\xBC\xF8" => "\xE9\x89\xB4", + "\xBC\xF9" => "\xE8\xB7\xB5", + "\xBC\xFA" => "\xE8\xB4\xB1", + "\xBC\xFB" => "\xE8\xA7\x81", + "\xBC\xFC" => "\xE9\x94\xAE", + "\xBC\xFD" => "\xE7\xAE\xAD", + "\xBC\xFE" => "\xE4\xBB\xB6", + "\xBD\xA1" => "\xE5\x81\xA5", + "\xBD\xA2" => "\xE8\x88\xB0", + "\xBD\xA3" => "\xE5\x89\x91", + "\xBD\xA4" => "\xE9\xA5\xAF", + "\xBD\xA5" => "\xE6\xB8\x90", + "\xBD\xA6" => "\xE6\xBA\x85", + "\xBD\xA7" => "\xE6\xB6\xA7", + "\xBD\xA8" => "\xE5\xBB\xBA", + "\xBD\xA9" => "\xE5\x83\xB5", + "\xBD\xAA" => "\xE5\xA7\x9C", + "\xBD\xAB" => "\xE5\xB0\x86", + "\xBD\xAC" => "\xE6\xB5\x86", + "\xBD\xAD" => "\xE6\xB1\x9F", + "\xBD\xAE" => "\xE7\x96\x86", + "\xBD\xAF" => "\xE8\x92\x8B", + "\xBD\xB0" => "\xE6\xA1\xA8", + "\xBD\xB1" => "\xE5\xA5\x96", + "\xBD\xB2" => "\xE8\xAE\xB2", + "\xBD\xB3" => "\xE5\x8C\xA0", + "\xBD\xB4" => "\xE9\x85\xB1", + "\xBD\xB5" => "\xE9\x99\x8D", + "\xBD\xB6" => "\xE8\x95\x89", + "\xBD\xB7" => "\xE6\xA4\x92", + "\xBD\xB8" => "\xE7\xA4\x81", + "\xBD\xB9" => "\xE7\x84\xA6", + "\xBD\xBA" => "\xE8\x83\xB6", + "\xBD\xBB" => "\xE4\xBA\xA4", + "\xBD\xBC" => "\xE9\x83\x8A", + "\xBD\xBD" => "\xE6\xB5\x87", + "\xBD\xBE" => "\xE9\xAA\x84", + "\xBD\xBF" => "\xE5\xA8\x87", + "\xBD\xC0" => "\xE5\x9A\xBC", + "\xBD\xC1" => "\xE6\x90\x85", + "\xBD\xC2" => "\xE9\x93\xB0", + "\xBD\xC3" => "\xE7\x9F\xAB", + "\xBD\xC4" => "\xE4\xBE\xA5", + "\xBD\xC5" => "\xE8\x84\x9A", + "\xBD\xC6" => "\xE7\x8B\xA1", + "\xBD\xC7" => "\xE8\xA7\x92", + "\xBD\xC8" => "\xE9\xA5\xBA", + "\xBD\xC9" => "\xE7\xBC\xB4", + "\xBD\xCA" => "\xE7\xBB\x9E", + "\xBD\xCB" => "\xE5\x89\xBF", + "\xBD\xCC" => "\xE6\x95\x99", + "\xBD\xCD" => "\xE9\x85\xB5", + "\xBD\xCE" => "\xE8\xBD\xBF", + "\xBD\xCF" => "\xE8\xBE\x83", + "\xBD\xD0" => "\xE5\x8F\xAB", + "\xBD\xD1" => "\xE7\xAA\x96", + "\xBD\xD2" => "\xE6\x8F\xAD", + "\xBD\xD3" => "\xE6\x8E\xA5", + "\xBD\xD4" => "\xE7\x9A\x86", + "\xBD\xD5" => "\xE7\xA7\xB8", + "\xBD\xD6" => "\xE8\xA1\x97", + "\xBD\xD7" => "\xE9\x98\xB6", + "\xBD\xD8" => "\xE6\x88\xAA", + "\xBD\xD9" => "\xE5\x8A\xAB", + "\xBD\xDA" => "\xE8\x8A\x82", + "\xBD\xDB" => "\xE6\xA1\x94", + "\xBD\xDC" => "\xE6\x9D\xB0", + "\xBD\xDD" => "\xE6\x8D\xB7", + "\xBD\xDE" => "\xE7\x9D\xAB", + "\xBD\xDF" => "\xE7\xAB\xAD", + "\xBD\xE0" => "\xE6\xB4\x81", + "\xBD\xE1" => "\xE7\xBB\x93", + "\xBD\xE2" => "\xE8\xA7\xA3", + "\xBD\xE3" => "\xE5\xA7\x90", + "\xBD\xE4" => "\xE6\x88\x92", + "\xBD\xE5" => "\xE8\x97\x89", + "\xBD\xE6" => "\xE8\x8A\xA5", + "\xBD\xE7" => "\xE7\x95\x8C", + "\xBD\xE8" => "\xE5\x80\x9F", + "\xBD\xE9" => "\xE4\xBB\x8B", + "\xBD\xEA" => "\xE7\x96\xA5", + "\xBD\xEB" => "\xE8\xAF\xAB", + "\xBD\xEC" => "\xE5\xB1\x8A", + "\xBD\xED" => "\xE5\xB7\xBE", + "\xBD\xEE" => "\xE7\xAD\x8B", + "\xBD\xEF" => "\xE6\x96\xA4", + "\xBD\xF0" => "\xE9\x87\x91", + "\xBD\xF1" => "\xE4\xBB\x8A", + "\xBD\xF2" => "\xE6\xB4\xA5", + "\xBD\xF3" => "\xE8\xA5\x9F", + "\xBD\xF4" => "\xE7\xB4\xA7", + "\xBD\xF5" => "\xE9\x94\xA6", + "\xBD\xF6" => "\xE4\xBB\x85", + "\xBD\xF7" => "\xE8\xB0\xA8", + "\xBD\xF8" => "\xE8\xBF\x9B", + "\xBD\xF9" => "\xE9\x9D\xB3", + "\xBD\xFA" => "\xE6\x99\x8B", + "\xBD\xFB" => "\xE7\xA6\x81", + "\xBD\xFC" => "\xE8\xBF\x91", + "\xBD\xFD" => "\xE7\x83\xAC", + "\xBD\xFE" => "\xE6\xB5\xB8", + "\xBE\xA1" => "\xE5\xB0\xBD", + "\xBE\xA2" => "\xE5\x8A\xB2", + "\xBE\xA3" => "\xE8\x8D\x86", + "\xBE\xA4" => "\xE5\x85\xA2", + "\xBE\xA5" => "\xE8\x8C\x8E", + "\xBE\xA6" => "\xE7\x9D\x9B", + "\xBE\xA7" => "\xE6\x99\xB6", + "\xBE\xA8" => "\xE9\xB2\xB8", + "\xBE\xA9" => "\xE4\xBA\xAC", + "\xBE\xAA" => "\xE6\x83\x8A", + "\xBE\xAB" => "\xE7\xB2\xBE", + "\xBE\xAC" => "\xE7\xB2\xB3", + "\xBE\xAD" => "\xE7\xBB\x8F", + "\xBE\xAE" => "\xE4\xBA\x95", + "\xBE\xAF" => "\xE8\xAD\xA6", + "\xBE\xB0" => "\xE6\x99\xAF", + "\xBE\xB1" => "\xE9\xA2\x88", + "\xBE\xB2" => "\xE9\x9D\x99", + "\xBE\xB3" => "\xE5\xA2\x83", + "\xBE\xB4" => "\xE6\x95\xAC", + "\xBE\xB5" => "\xE9\x95\x9C", + "\xBE\xB6" => "\xE5\xBE\x84", + "\xBE\xB7" => "\xE7\x97\x89", + "\xBE\xB8" => "\xE9\x9D\x96", + "\xBE\xB9" => "\xE7\xAB\x9F", + "\xBE\xBA" => "\xE7\xAB\x9E", + "\xBE\xBB" => "\xE5\x87\x80", + "\xBE\xBC" => "\xE7\x82\xAF", + "\xBE\xBD" => "\xE7\xAA\x98", + "\xBE\xBE" => "\xE6\x8F\xAA", + "\xBE\xBF" => "\xE7\xA9\xB6", + "\xBE\xC0" => "\xE7\xBA\xA0", + "\xBE\xC1" => "\xE7\x8E\x96", + "\xBE\xC2" => "\xE9\x9F\xAD", + "\xBE\xC3" => "\xE4\xB9\x85", + "\xBE\xC4" => "\xE7\x81\xB8", + "\xBE\xC5" => "\xE4\xB9\x9D", + "\xBE\xC6" => "\xE9\x85\x92", + "\xBE\xC7" => "\xE5\x8E\xA9", + "\xBE\xC8" => "\xE6\x95\x91", + "\xBE\xC9" => "\xE6\x97\xA7", + "\xBE\xCA" => "\xE8\x87\xBC", + "\xBE\xCB" => "\xE8\x88\x85", + "\xBE\xCC" => "\xE5\x92\x8E", + "\xBE\xCD" => "\xE5\xB0\xB1", + "\xBE\xCE" => "\xE7\x96\x9A", + "\xBE\xCF" => "\xE9\x9E\xA0", + "\xBE\xD0" => "\xE6\x8B\x98", + "\xBE\xD1" => "\xE7\x8B\x99", + "\xBE\xD2" => "\xE7\x96\xBD", + "\xBE\xD3" => "\xE5\xB1\x85", + "\xBE\xD4" => "\xE9\xA9\xB9", + "\xBE\xD5" => "\xE8\x8F\x8A", + "\xBE\xD6" => "\xE5\xB1\x80", + "\xBE\xD7" => "\xE5\x92\x80", + "\xBE\xD8" => "\xE7\x9F\xA9", + "\xBE\xD9" => "\xE4\xB8\xBE", + "\xBE\xDA" => "\xE6\xB2\xAE", + "\xBE\xDB" => "\xE8\x81\x9A", + "\xBE\xDC" => "\xE6\x8B\x92", + "\xBE\xDD" => "\xE6\x8D\xAE", + "\xBE\xDE" => "\xE5\xB7\xA8", + "\xBE\xDF" => "\xE5\x85\xB7", + "\xBE\xE0" => "\xE8\xB7\x9D", + "\xBE\xE1" => "\xE8\xB8\x9E", + "\xBE\xE2" => "\xE9\x94\xAF", + "\xBE\xE3" => "\xE4\xBF\xB1", + "\xBE\xE4" => "\xE5\x8F\xA5", + "\xBE\xE5" => "\xE6\x83\xA7", + "\xBE\xE6" => "\xE7\x82\xAC", + "\xBE\xE7" => "\xE5\x89\xA7", + "\xBE\xE8" => "\xE6\x8D\x90", + "\xBE\xE9" => "\xE9\xB9\x83", + "\xBE\xEA" => "\xE5\xA8\x9F", + "\xBE\xEB" => "\xE5\x80\xA6", + "\xBE\xEC" => "\xE7\x9C\xB7", + "\xBE\xED" => "\xE5\x8D\xB7", + "\xBE\xEE" => "\xE7\xBB\xA2", + "\xBE\xEF" => "\xE6\x92\x85", + "\xBE\xF0" => "\xE6\x94\xAB", + "\xBE\xF1" => "\xE6\x8A\x89", + "\xBE\xF2" => "\xE6\x8E\x98", + "\xBE\xF3" => "\xE5\x80\x94", + "\xBE\xF4" => "\xE7\x88\xB5", + "\xBE\xF5" => "\xE8\xA7\x89", + "\xBE\xF6" => "\xE5\x86\xB3", + "\xBE\xF7" => "\xE8\xAF\x80", + "\xBE\xF8" => "\xE7\xBB\x9D", + "\xBE\xF9" => "\xE5\x9D\x87", + "\xBE\xFA" => "\xE8\x8F\x8C", + "\xBE\xFB" => "\xE9\x92\xA7", + "\xBE\xFC" => "\xE5\x86\x9B", + "\xBE\xFD" => "\xE5\x90\x9B", + "\xBE\xFE" => "\xE5\xB3\xBB", + "\xBF\xA1" => "\xE4\xBF\x8A", + "\xBF\xA2" => "\xE7\xAB\xA3", + "\xBF\xA3" => "\xE6\xB5\x9A", + "\xBF\xA4" => "\xE9\x83\xA1", + "\xBF\xA5" => "\xE9\xAA\x8F", + "\xBF\xA6" => "\xE5\x96\x80", + "\xBF\xA7" => "\xE5\x92\x96", + "\xBF\xA8" => "\xE5\x8D\xA1", + "\xBF\xA9" => "\xE5\x92\xAF", + "\xBF\xAA" => "\xE5\xBC\x80", + "\xBF\xAB" => "\xE6\x8F\xA9", + "\xBF\xAC" => "\xE6\xA5\xB7", + "\xBF\xAD" => "\xE5\x87\xAF", + "\xBF\xAE" => "\xE6\x85\xA8", + "\xBF\xAF" => "\xE5\x88\x8A", + "\xBF\xB0" => "\xE5\xA0\xAA", + "\xBF\xB1" => "\xE5\x8B\x98", + "\xBF\xB2" => "\xE5\x9D\x8E", + "\xBF\xB3" => "\xE7\xA0\x8D", + "\xBF\xB4" => "\xE7\x9C\x8B", + "\xBF\xB5" => "\xE5\xBA\xB7", + "\xBF\xB6" => "\xE6\x85\xB7", + "\xBF\xB7" => "\xE7\xB3\xA0", + "\xBF\xB8" => "\xE6\x89\x9B", + "\xBF\xB9" => "\xE6\x8A\x97", + "\xBF\xBA" => "\xE4\xBA\xA2", + "\xBF\xBB" => "\xE7\x82\x95", + "\xBF\xBC" => "\xE8\x80\x83", + "\xBF\xBD" => "\xE6\x8B\xB7", + "\xBF\xBE" => "\xE7\x83\xA4", + "\xBF\xBF" => "\xE9\x9D\xA0", + "\xBF\xC0" => "\xE5\x9D\xB7", + "\xBF\xC1" => "\xE8\x8B\x9B", + "\xBF\xC2" => "\xE6\x9F\xAF", + "\xBF\xC3" => "\xE6\xA3\xB5", + "\xBF\xC4" => "\xE7\xA3\x95", + "\xBF\xC5" => "\xE9\xA2\x97", + "\xBF\xC6" => "\xE7\xA7\x91", + "\xBF\xC7" => "\xE5\xA3\xB3", + "\xBF\xC8" => "\xE5\x92\xB3", + "\xBF\xC9" => "\xE5\x8F\xAF", + "\xBF\xCA" => "\xE6\xB8\xB4", + "\xBF\xCB" => "\xE5\x85\x8B", + "\xBF\xCC" => "\xE5\x88\xBB", + "\xBF\xCD" => "\xE5\xAE\xA2", + "\xBF\xCE" => "\xE8\xAF\xBE", + "\xBF\xCF" => "\xE8\x82\xAF", + "\xBF\xD0" => "\xE5\x95\x83", + "\xBF\xD1" => "\xE5\x9E\xA6", + "\xBF\xD2" => "\xE6\x81\xB3", + "\xBF\xD3" => "\xE5\x9D\x91", + "\xBF\xD4" => "\xE5\x90\xAD", + "\xBF\xD5" => "\xE7\xA9\xBA", + "\xBF\xD6" => "\xE6\x81\x90", + "\xBF\xD7" => "\xE5\xAD\x94", + "\xBF\xD8" => "\xE6\x8E\xA7", + "\xBF\xD9" => "\xE6\x8A\xA0", + "\xBF\xDA" => "\xE5\x8F\xA3", + "\xBF\xDB" => "\xE6\x89\xA3", + "\xBF\xDC" => "\xE5\xAF\x87", + "\xBF\xDD" => "\xE6\x9E\xAF", + "\xBF\xDE" => "\xE5\x93\xAD", + "\xBF\xDF" => "\xE7\xAA\x9F", + "\xBF\xE0" => "\xE8\x8B\xA6", + "\xBF\xE1" => "\xE9\x85\xB7", + "\xBF\xE2" => "\xE5\xBA\x93", + "\xBF\xE3" => "\xE8\xA3\xA4", + "\xBF\xE4" => "\xE5\xA4\xB8", + "\xBF\xE5" => "\xE5\x9E\xAE", + "\xBF\xE6" => "\xE6\x8C\x8E", + "\xBF\xE7" => "\xE8\xB7\xA8", + "\xBF\xE8" => "\xE8\x83\xAF", + "\xBF\xE9" => "\xE5\x9D\x97", + "\xBF\xEA" => "\xE7\xAD\xB7", + "\xBF\xEB" => "\xE4\xBE\xA9", + "\xBF\xEC" => "\xE5\xBF\xAB", + "\xBF\xED" => "\xE5\xAE\xBD", + "\xBF\xEE" => "\xE6\xAC\xBE", + "\xBF\xEF" => "\xE5\x8C\xA1", + "\xBF\xF0" => "\xE7\xAD\x90", + "\xBF\xF1" => "\xE7\x8B\x82", + "\xBF\xF2" => "\xE6\xA1\x86", + "\xBF\xF3" => "\xE7\x9F\xBF", + "\xBF\xF4" => "\xE7\x9C\xB6", + "\xBF\xF5" => "\xE6\x97\xB7", + "\xBF\xF6" => "\xE5\x86\xB5", + "\xBF\xF7" => "\xE4\xBA\x8F", + "\xBF\xF8" => "\xE7\x9B\x94", + "\xBF\xF9" => "\xE5\xB2\xBF", + "\xBF\xFA" => "\xE7\xAA\xA5", + "\xBF\xFB" => "\xE8\x91\xB5", + "\xBF\xFC" => "\xE5\xA5\x8E", + "\xBF\xFD" => "\xE9\xAD\x81", + "\xBF\xFE" => "\xE5\x82\x80", + "\xC0\xA1" => "\xE9\xA6\x88", + "\xC0\xA2" => "\xE6\x84\xA7", + "\xC0\xA3" => "\xE6\xBA\x83", + "\xC0\xA4" => "\xE5\x9D\xA4", + "\xC0\xA5" => "\xE6\x98\x86", + "\xC0\xA6" => "\xE6\x8D\x86", + "\xC0\xA7" => "\xE5\x9B\xB0", + "\xC0\xA8" => "\xE6\x8B\xAC", + "\xC0\xA9" => "\xE6\x89\xA9", + "\xC0\xAA" => "\xE5\xBB\x93", + "\xC0\xAB" => "\xE9\x98\x94", + "\xC0\xAC" => "\xE5\x9E\x83", + "\xC0\xAD" => "\xE6\x8B\x89", + "\xC0\xAE" => "\xE5\x96\x87", + "\xC0\xAF" => "\xE8\x9C\xA1", + "\xC0\xB0" => "\xE8\x85\x8A", + "\xC0\xB1" => "\xE8\xBE\xA3", + "\xC0\xB2" => "\xE5\x95\xA6", + "\xC0\xB3" => "\xE8\x8E\xB1", + "\xC0\xB4" => "\xE6\x9D\xA5", + "\xC0\xB5" => "\xE8\xB5\x96", + "\xC0\xB6" => "\xE8\x93\x9D", + "\xC0\xB7" => "\xE5\xA9\xAA", + "\xC0\xB8" => "\xE6\xA0\x8F", + "\xC0\xB9" => "\xE6\x8B\xA6", + "\xC0\xBA" => "\xE7\xAF\xAE", + "\xC0\xBB" => "\xE9\x98\x91", + "\xC0\xBC" => "\xE5\x85\xB0", + "\xC0\xBD" => "\xE6\xBE\x9C", + "\xC0\xBE" => "\xE8\xB0\xB0", + "\xC0\xBF" => "\xE6\x8F\xBD", + "\xC0\xC0" => "\xE8\xA7\x88", + "\xC0\xC1" => "\xE6\x87\x92", + "\xC0\xC2" => "\xE7\xBC\x86", + "\xC0\xC3" => "\xE7\x83\x82", + "\xC0\xC4" => "\xE6\xBB\xA5", + "\xC0\xC5" => "\xE7\x90\x85", + "\xC0\xC6" => "\xE6\xA6\x94", + "\xC0\xC7" => "\xE7\x8B\xBC", + "\xC0\xC8" => "\xE5\xBB\x8A", + "\xC0\xC9" => "\xE9\x83\x8E", + "\xC0\xCA" => "\xE6\x9C\x97", + "\xC0\xCB" => "\xE6\xB5\xAA", + "\xC0\xCC" => "\xE6\x8D\x9E", + "\xC0\xCD" => "\xE5\x8A\xB3", + "\xC0\xCE" => "\xE7\x89\xA2", + "\xC0\xCF" => "\xE8\x80\x81", + "\xC0\xD0" => "\xE4\xBD\xAC", + "\xC0\xD1" => "\xE5\xA7\xA5", + "\xC0\xD2" => "\xE9\x85\xAA", + "\xC0\xD3" => "\xE7\x83\x99", + "\xC0\xD4" => "\xE6\xB6\x9D", + "\xC0\xD5" => "\xE5\x8B\x92", + "\xC0\xD6" => "\xE4\xB9\x90", + "\xC0\xD7" => "\xE9\x9B\xB7", + "\xC0\xD8" => "\xE9\x95\xAD", + "\xC0\xD9" => "\xE8\x95\xBE", + "\xC0\xDA" => "\xE7\xA3\x8A", + "\xC0\xDB" => "\xE7\xB4\xAF", + "\xC0\xDC" => "\xE5\x84\xA1", + "\xC0\xDD" => "\xE5\x9E\x92", + "\xC0\xDE" => "\xE6\x93\x82", + "\xC0\xDF" => "\xE8\x82\x8B", + "\xC0\xE0" => "\xE7\xB1\xBB", + "\xC0\xE1" => "\xE6\xB3\xAA", + "\xC0\xE2" => "\xE6\xA3\xB1", + "\xC0\xE3" => "\xE6\xA5\x9E", + "\xC0\xE4" => "\xE5\x86\xB7", + "\xC0\xE5" => "\xE5\x8E\x98", + "\xC0\xE6" => "\xE6\xA2\xA8", + "\xC0\xE7" => "\xE7\x8A\x81", + "\xC0\xE8" => "\xE9\xBB\x8E", + "\xC0\xE9" => "\xE7\xAF\xB1", + "\xC0\xEA" => "\xE7\x8B\xB8", + "\xC0\xEB" => "\xE7\xA6\xBB", + "\xC0\xEC" => "\xE6\xBC\x93", + "\xC0\xED" => "\xE7\x90\x86", + "\xC0\xEE" => "\xE6\x9D\x8E", + "\xC0\xEF" => "\xE9\x87\x8C", + "\xC0\xF0" => "\xE9\xB2\xA4", + "\xC0\xF1" => "\xE7\xA4\xBC", + "\xC0\xF2" => "\xE8\x8E\x89", + "\xC0\xF3" => "\xE8\x8D\x94", + "\xC0\xF4" => "\xE5\x90\x8F", + "\xC0\xF5" => "\xE6\xA0\x97", + "\xC0\xF6" => "\xE4\xB8\xBD", + "\xC0\xF7" => "\xE5\x8E\x89", + "\xC0\xF8" => "\xE5\x8A\xB1", + "\xC0\xF9" => "\xE7\xA0\xBE", + "\xC0\xFA" => "\xE5\x8E\x86", + "\xC0\xFB" => "\xE5\x88\xA9", + "\xC0\xFC" => "\xE5\x82\x88", + "\xC0\xFD" => "\xE4\xBE\x8B", + "\xC0\xFE" => "\xE4\xBF\x90", + "\xC1\xA1" => "\xE7\x97\xA2", + "\xC1\xA2" => "\xE7\xAB\x8B", + "\xC1\xA3" => "\xE7\xB2\x92", + "\xC1\xA4" => "\xE6\xB2\xA5", + "\xC1\xA5" => "\xE9\x9A\xB6", + "\xC1\xA6" => "\xE5\x8A\x9B", + "\xC1\xA7" => "\xE7\x92\x83", + "\xC1\xA8" => "\xE5\x93\xA9", + "\xC1\xA9" => "\xE4\xBF\xA9", + "\xC1\xAA" => "\xE8\x81\x94", + "\xC1\xAB" => "\xE8\x8E\xB2", + "\xC1\xAC" => "\xE8\xBF\x9E", + "\xC1\xAD" => "\xE9\x95\xB0", + "\xC1\xAE" => "\xE5\xBB\x89", + "\xC1\xAF" => "\xE6\x80\x9C", + "\xC1\xB0" => "\xE6\xB6\x9F", + "\xC1\xB1" => "\xE5\xB8\x98", + "\xC1\xB2" => "\xE6\x95\x9B", + "\xC1\xB3" => "\xE8\x84\xB8", + "\xC1\xB4" => "\xE9\x93\xBE", + "\xC1\xB5" => "\xE6\x81\x8B", + "\xC1\xB6" => "\xE7\x82\xBC", + "\xC1\xB7" => "\xE7\xBB\x83", + "\xC1\xB8" => "\xE7\xB2\xAE", + "\xC1\xB9" => "\xE5\x87\x89", + "\xC1\xBA" => "\xE6\xA2\x81", + "\xC1\xBB" => "\xE7\xB2\xB1", + "\xC1\xBC" => "\xE8\x89\xAF", + "\xC1\xBD" => "\xE4\xB8\xA4", + "\xC1\xBE" => "\xE8\xBE\x86", + "\xC1\xBF" => "\xE9\x87\x8F", + "\xC1\xC0" => "\xE6\x99\xBE", + "\xC1\xC1" => "\xE4\xBA\xAE", + "\xC1\xC2" => "\xE8\xB0\x85", + "\xC1\xC3" => "\xE6\x92\xA9", + "\xC1\xC4" => "\xE8\x81\x8A", + "\xC1\xC5" => "\xE5\x83\x9A", + "\xC1\xC6" => "\xE7\x96\x97", + "\xC1\xC7" => "\xE7\x87\x8E", + "\xC1\xC8" => "\xE5\xAF\xA5", + "\xC1\xC9" => "\xE8\xBE\xBD", + "\xC1\xCA" => "\xE6\xBD\xA6", + "\xC1\xCB" => "\xE4\xBA\x86", + "\xC1\xCC" => "\xE6\x92\x82", + "\xC1\xCD" => "\xE9\x95\xA3", + "\xC1\xCE" => "\xE5\xBB\x96", + "\xC1\xCF" => "\xE6\x96\x99", + "\xC1\xD0" => "\xE5\x88\x97", + "\xC1\xD1" => "\xE8\xA3\x82", + "\xC1\xD2" => "\xE7\x83\x88", + "\xC1\xD3" => "\xE5\x8A\xA3", + "\xC1\xD4" => "\xE7\x8C\x8E", + "\xC1\xD5" => "\xE7\x90\xB3", + "\xC1\xD6" => "\xE6\x9E\x97", + "\xC1\xD7" => "\xE7\xA3\xB7", + "\xC1\xD8" => "\xE9\x9C\x96", + "\xC1\xD9" => "\xE4\xB8\xB4", + "\xC1\xDA" => "\xE9\x82\xBB", + "\xC1\xDB" => "\xE9\xB3\x9E", + "\xC1\xDC" => "\xE6\xB7\x8B", + "\xC1\xDD" => "\xE5\x87\x9B", + "\xC1\xDE" => "\xE8\xB5\x81", + "\xC1\xDF" => "\xE5\x90\x9D", + "\xC1\xE0" => "\xE6\x8B\x8E", + "\xC1\xE1" => "\xE7\x8E\xB2", + "\xC1\xE2" => "\xE8\x8F\xB1", + "\xC1\xE3" => "\xE9\x9B\xB6", + "\xC1\xE4" => "\xE9\xBE\x84", + "\xC1\xE5" => "\xE9\x93\x83", + "\xC1\xE6" => "\xE4\xBC\xB6", + "\xC1\xE7" => "\xE7\xBE\x9A", + "\xC1\xE8" => "\xE5\x87\x8C", + "\xC1\xE9" => "\xE7\x81\xB5", + "\xC1\xEA" => "\xE9\x99\xB5", + "\xC1\xEB" => "\xE5\xB2\xAD", + "\xC1\xEC" => "\xE9\xA2\x86", + "\xC1\xED" => "\xE5\x8F\xA6", + "\xC1\xEE" => "\xE4\xBB\xA4", + "\xC1\xEF" => "\xE6\xBA\x9C", + "\xC1\xF0" => "\xE7\x90\x89", + "\xC1\xF1" => "\xE6\xA6\xB4", + "\xC1\xF2" => "\xE7\xA1\xAB", + "\xC1\xF3" => "\xE9\xA6\x8F", + "\xC1\xF4" => "\xE7\x95\x99", + "\xC1\xF5" => "\xE5\x88\x98", + "\xC1\xF6" => "\xE7\x98\xA4", + "\xC1\xF7" => "\xE6\xB5\x81", + "\xC1\xF8" => "\xE6\x9F\xB3", + "\xC1\xF9" => "\xE5\x85\xAD", + "\xC1\xFA" => "\xE9\xBE\x99", + "\xC1\xFB" => "\xE8\x81\x8B", + "\xC1\xFC" => "\xE5\x92\x99", + "\xC1\xFD" => "\xE7\xAC\xBC", + "\xC1\xFE" => "\xE7\xAA\xBF", + "\xC2\xA1" => "\xE9\x9A\x86", + "\xC2\xA2" => "\xE5\x9E\x84", + "\xC2\xA3" => "\xE6\x8B\xA2", + "\xC2\xA4" => "\xE9\x99\x87", + "\xC2\xA5" => "\xE6\xA5\xBC", + "\xC2\xA6" => "\xE5\xA8\x84", + "\xC2\xA7" => "\xE6\x90\x82", + "\xC2\xA8" => "\xE7\xAF\x93", + "\xC2\xA9" => "\xE6\xBC\x8F", + "\xC2\xAA" => "\xE9\x99\x8B", + "\xC2\xAB" => "\xE8\x8A\xA6", + "\xC2\xAC" => "\xE5\x8D\xA2", + "\xC2\xAD" => "\xE9\xA2\x85", + "\xC2\xAE" => "\xE5\xBA\x90", + "\xC2\xAF" => "\xE7\x82\x89", + "\xC2\xB0" => "\xE6\x8E\xB3", + "\xC2\xB1" => "\xE5\x8D\xA4", + "\xC2\xB2" => "\xE8\x99\x8F", + "\xC2\xB3" => "\xE9\xB2\x81", + "\xC2\xB4" => "\xE9\xBA\x93", + "\xC2\xB5" => "\xE7\xA2\x8C", + "\xC2\xB6" => "\xE9\x9C\xB2", + "\xC2\xB7" => "\xE8\xB7\xAF", + "\xC2\xB8" => "\xE8\xB5\x82", + "\xC2\xB9" => "\xE9\xB9\xBF", + "\xC2\xBA" => "\xE6\xBD\x9E", + "\xC2\xBB" => "\xE7\xA6\x84", + "\xC2\xBC" => "\xE5\xBD\x95", + "\xC2\xBD" => "\xE9\x99\x86", + "\xC2\xBE" => "\xE6\x88\xAE", + "\xC2\xBF" => "\xE9\xA9\xB4", + "\xC2\xC0" => "\xE5\x90\x95", + "\xC2\xC1" => "\xE9\x93\x9D", + "\xC2\xC2" => "\xE4\xBE\xA3", + "\xC2\xC3" => "\xE6\x97\x85", + "\xC2\xC4" => "\xE5\xB1\xA5", + "\xC2\xC5" => "\xE5\xB1\xA1", + "\xC2\xC6" => "\xE7\xBC\x95", + "\xC2\xC7" => "\xE8\x99\x91", + "\xC2\xC8" => "\xE6\xB0\xAF", + "\xC2\xC9" => "\xE5\xBE\x8B", + "\xC2\xCA" => "\xE7\x8E\x87", + "\xC2\xCB" => "\xE6\xBB\xA4", + "\xC2\xCC" => "\xE7\xBB\xBF", + "\xC2\xCD" => "\xE5\xB3\xA6", + "\xC2\xCE" => "\xE6\x8C\x9B", + "\xC2\xCF" => "\xE5\xAD\xAA", + "\xC2\xD0" => "\xE6\xBB\xA6", + "\xC2\xD1" => "\xE5\x8D\xB5", + "\xC2\xD2" => "\xE4\xB9\xB1", + "\xC2\xD3" => "\xE6\x8E\xA0", + "\xC2\xD4" => "\xE7\x95\xA5", + "\xC2\xD5" => "\xE6\x8A\xA1", + "\xC2\xD6" => "\xE8\xBD\xAE", + "\xC2\xD7" => "\xE4\xBC\xA6", + "\xC2\xD8" => "\xE4\xBB\x91", + "\xC2\xD9" => "\xE6\xB2\xA6", + "\xC2\xDA" => "\xE7\xBA\xB6", + "\xC2\xDB" => "\xE8\xAE\xBA", + "\xC2\xDC" => "\xE8\x90\x9D", + "\xC2\xDD" => "\xE8\x9E\xBA", + "\xC2\xDE" => "\xE7\xBD\x97", + "\xC2\xDF" => "\xE9\x80\xBB", + "\xC2\xE0" => "\xE9\x94\xA3", + "\xC2\xE1" => "\xE7\xAE\xA9", + "\xC2\xE2" => "\xE9\xAA\xA1", + "\xC2\xE3" => "\xE8\xA3\xB8", + "\xC2\xE4" => "\xE8\x90\xBD", + "\xC2\xE5" => "\xE6\xB4\x9B", + "\xC2\xE6" => "\xE9\xAA\x86", + "\xC2\xE7" => "\xE7\xBB\x9C", + "\xC2\xE8" => "\xE5\xA6\x88", + "\xC2\xE9" => "\xE9\xBA\xBB", + "\xC2\xEA" => "\xE7\x8E\x9B", + "\xC2\xEB" => "\xE7\xA0\x81", + "\xC2\xEC" => "\xE8\x9A\x82", + "\xC2\xED" => "\xE9\xA9\xAC", + "\xC2\xEE" => "\xE9\xAA\x82", + "\xC2\xEF" => "\xE5\x98\x9B", + "\xC2\xF0" => "\xE5\x90\x97", + "\xC2\xF1" => "\xE5\x9F\x8B", + "\xC2\xF2" => "\xE4\xB9\xB0", + "\xC2\xF3" => "\xE9\xBA\xA6", + "\xC2\xF4" => "\xE5\x8D\x96", + "\xC2\xF5" => "\xE8\xBF\x88", + "\xC2\xF6" => "\xE8\x84\x89", + "\xC2\xF7" => "\xE7\x9E\x92", + "\xC2\xF8" => "\xE9\xA6\x92", + "\xC2\xF9" => "\xE8\x9B\xAE", + "\xC2\xFA" => "\xE6\xBB\xA1", + "\xC2\xFB" => "\xE8\x94\x93", + "\xC2\xFC" => "\xE6\x9B\xBC", + "\xC2\xFD" => "\xE6\x85\xA2", + "\xC2\xFE" => "\xE6\xBC\xAB", + "\xC3\xA1" => "\xE8\xB0\xA9", + "\xC3\xA2" => "\xE8\x8A\x92", + "\xC3\xA3" => "\xE8\x8C\xAB", + "\xC3\xA4" => "\xE7\x9B\xB2", + "\xC3\xA5" => "\xE6\xB0\x93", + "\xC3\xA6" => "\xE5\xBF\x99", + "\xC3\xA7" => "\xE8\x8E\xBD", + "\xC3\xA8" => "\xE7\x8C\xAB", + "\xC3\xA9" => "\xE8\x8C\x85", + "\xC3\xAA" => "\xE9\x94\x9A", + "\xC3\xAB" => "\xE6\xAF\x9B", + "\xC3\xAC" => "\xE7\x9F\x9B", + "\xC3\xAD" => "\xE9\x93\x86", + "\xC3\xAE" => "\xE5\x8D\xAF", + "\xC3\xAF" => "\xE8\x8C\x82", + "\xC3\xB0" => "\xE5\x86\x92", + "\xC3\xB1" => "\xE5\xB8\xBD", + "\xC3\xB2" => "\xE8\xB2\x8C", + "\xC3\xB3" => "\xE8\xB4\xB8", + "\xC3\xB4" => "\xE4\xB9\x88", + "\xC3\xB5" => "\xE7\x8E\xAB", + "\xC3\xB6" => "\xE6\x9E\x9A", + "\xC3\xB7" => "\xE6\xA2\x85", + "\xC3\xB8" => "\xE9\x85\xB6", + "\xC3\xB9" => "\xE9\x9C\x89", + "\xC3\xBA" => "\xE7\x85\xA4", + "\xC3\xBB" => "\xE6\xB2\xA1", + "\xC3\xBC" => "\xE7\x9C\x89", + "\xC3\xBD" => "\xE5\xAA\x92", + "\xC3\xBE" => "\xE9\x95\x81", + "\xC3\xBF" => "\xE6\xAF\x8F", + "\xC3\xC0" => "\xE7\xBE\x8E", + "\xC3\xC1" => "\xE6\x98\xA7", + "\xC3\xC2" => "\xE5\xAF\x90", + "\xC3\xC3" => "\xE5\xA6\xB9", + "\xC3\xC4" => "\xE5\xAA\x9A", + "\xC3\xC5" => "\xE9\x97\xA8", + "\xC3\xC6" => "\xE9\x97\xB7", + "\xC3\xC7" => "\xE4\xBB\xAC", + "\xC3\xC8" => "\xE8\x90\x8C", + "\xC3\xC9" => "\xE8\x92\x99", + "\xC3\xCA" => "\xE6\xAA\xAC", + "\xC3\xCB" => "\xE7\x9B\x9F", + "\xC3\xCC" => "\xE9\x94\xB0", + "\xC3\xCD" => "\xE7\x8C\x9B", + "\xC3\xCE" => "\xE6\xA2\xA6", + "\xC3\xCF" => "\xE5\xAD\x9F", + "\xC3\xD0" => "\xE7\x9C\xAF", + "\xC3\xD1" => "\xE9\x86\x9A", + "\xC3\xD2" => "\xE9\x9D\xA1", + "\xC3\xD3" => "\xE7\xB3\x9C", + "\xC3\xD4" => "\xE8\xBF\xB7", + "\xC3\xD5" => "\xE8\xB0\x9C", + "\xC3\xD6" => "\xE5\xBC\xA5", + "\xC3\xD7" => "\xE7\xB1\xB3", + "\xC3\xD8" => "\xE7\xA7\x98", + "\xC3\xD9" => "\xE8\xA7\x85", + "\xC3\xDA" => "\xE6\xB3\x8C", + "\xC3\xDB" => "\xE8\x9C\x9C", + "\xC3\xDC" => "\xE5\xAF\x86", + "\xC3\xDD" => "\xE5\xB9\x82", + "\xC3\xDE" => "\xE6\xA3\x89", + "\xC3\xDF" => "\xE7\x9C\xA0", + "\xC3\xE0" => "\xE7\xBB\xB5", + "\xC3\xE1" => "\xE5\x86\x95", + "\xC3\xE2" => "\xE5\x85\x8D", + "\xC3\xE3" => "\xE5\x8B\x89", + "\xC3\xE4" => "\xE5\xA8\xA9", + "\xC3\xE5" => "\xE7\xBC\x85", + "\xC3\xE6" => "\xE9\x9D\xA2", + "\xC3\xE7" => "\xE8\x8B\x97", + "\xC3\xE8" => "\xE6\x8F\x8F", + "\xC3\xE9" => "\xE7\x9E\x84", + "\xC3\xEA" => "\xE8\x97\x90", + "\xC3\xEB" => "\xE7\xA7\x92", + "\xC3\xEC" => "\xE6\xB8\xBA", + "\xC3\xED" => "\xE5\xBA\x99", + "\xC3\xEE" => "\xE5\xA6\x99", + "\xC3\xEF" => "\xE8\x94\x91", + "\xC3\xF0" => "\xE7\x81\xAD", + "\xC3\xF1" => "\xE6\xB0\x91", + "\xC3\xF2" => "\xE6\x8A\xBF", + "\xC3\xF3" => "\xE7\x9A\xBF", + "\xC3\xF4" => "\xE6\x95\x8F", + "\xC3\xF5" => "\xE6\x82\xAF", + "\xC3\xF6" => "\xE9\x97\xBD", + "\xC3\xF7" => "\xE6\x98\x8E", + "\xC3\xF8" => "\xE8\x9E\x9F", + "\xC3\xF9" => "\xE9\xB8\xA3", + "\xC3\xFA" => "\xE9\x93\xAD", + "\xC3\xFB" => "\xE5\x90\x8D", + "\xC3\xFC" => "\xE5\x91\xBD", + "\xC3\xFD" => "\xE8\xB0\xAC", + "\xC3\xFE" => "\xE6\x91\xB8", + "\xC4\xA1" => "\xE6\x91\xB9", + "\xC4\xA2" => "\xE8\x98\x91", + "\xC4\xA3" => "\xE6\xA8\xA1", + "\xC4\xA4" => "\xE8\x86\x9C", + "\xC4\xA5" => "\xE7\xA3\xA8", + "\xC4\xA6" => "\xE6\x91\xA9", + "\xC4\xA7" => "\xE9\xAD\x94", + "\xC4\xA8" => "\xE6\x8A\xB9", + "\xC4\xA9" => "\xE6\x9C\xAB", + "\xC4\xAA" => "\xE8\x8E\xAB", + "\xC4\xAB" => "\xE5\xA2\xA8", + "\xC4\xAC" => "\xE9\xBB\x98", + "\xC4\xAD" => "\xE6\xB2\xAB", + "\xC4\xAE" => "\xE6\xBC\xA0", + "\xC4\xAF" => "\xE5\xAF\x9E", + "\xC4\xB0" => "\xE9\x99\x8C", + "\xC4\xB1" => "\xE8\xB0\x8B", + "\xC4\xB2" => "\xE7\x89\x9F", + "\xC4\xB3" => "\xE6\x9F\x90", + "\xC4\xB4" => "\xE6\x8B\x87", + "\xC4\xB5" => "\xE7\x89\xA1", + "\xC4\xB6" => "\xE4\xBA\xA9", + "\xC4\xB7" => "\xE5\xA7\x86", + "\xC4\xB8" => "\xE6\xAF\x8D", + "\xC4\xB9" => "\xE5\xA2\x93", + "\xC4\xBA" => "\xE6\x9A\xAE", + "\xC4\xBB" => "\xE5\xB9\x95", + "\xC4\xBC" => "\xE5\x8B\x9F", + "\xC4\xBD" => "\xE6\x85\x95", + "\xC4\xBE" => "\xE6\x9C\xA8", + "\xC4\xBF" => "\xE7\x9B\xAE", + "\xC4\xC0" => "\xE7\x9D\xA6", + "\xC4\xC1" => "\xE7\x89\xA7", + "\xC4\xC2" => "\xE7\xA9\x86", + "\xC4\xC3" => "\xE6\x8B\xBF", + "\xC4\xC4" => "\xE5\x93\xAA", + "\xC4\xC5" => "\xE5\x91\x90", + "\xC4\xC6" => "\xE9\x92\xA0", + "\xC4\xC7" => "\xE9\x82\xA3", + "\xC4\xC8" => "\xE5\xA8\x9C", + "\xC4\xC9" => "\xE7\xBA\xB3", + "\xC4\xCA" => "\xE6\xB0\x96", + "\xC4\xCB" => "\xE4\xB9\x83", + "\xC4\xCC" => "\xE5\xA5\xB6", + "\xC4\xCD" => "\xE8\x80\x90", + "\xC4\xCE" => "\xE5\xA5\x88", + "\xC4\xCF" => "\xE5\x8D\x97", + "\xC4\xD0" => "\xE7\x94\xB7", + "\xC4\xD1" => "\xE9\x9A\xBE", + "\xC4\xD2" => "\xE5\x9B\x8A", + "\xC4\xD3" => "\xE6\x8C\xA0", + "\xC4\xD4" => "\xE8\x84\x91", + "\xC4\xD5" => "\xE6\x81\xBC", + "\xC4\xD6" => "\xE9\x97\xB9", + "\xC4\xD7" => "\xE6\xB7\x96", + "\xC4\xD8" => "\xE5\x91\xA2", + "\xC4\xD9" => "\xE9\xA6\x81", + "\xC4\xDA" => "\xE5\x86\x85", + "\xC4\xDB" => "\xE5\xAB\xA9", + "\xC4\xDC" => "\xE8\x83\xBD", + "\xC4\xDD" => "\xE5\xA6\xAE", + "\xC4\xDE" => "\xE9\x9C\x93", + "\xC4\xDF" => "\xE5\x80\xAA", + "\xC4\xE0" => "\xE6\xB3\xA5", + "\xC4\xE1" => "\xE5\xB0\xBC", + "\xC4\xE2" => "\xE6\x8B\x9F", + "\xC4\xE3" => "\xE4\xBD\xA0", + "\xC4\xE4" => "\xE5\x8C\xBF", + "\xC4\xE5" => "\xE8\x85\xBB", + "\xC4\xE6" => "\xE9\x80\x86", + "\xC4\xE7" => "\xE6\xBA\xBA", + "\xC4\xE8" => "\xE8\x94\xAB", + "\xC4\xE9" => "\xE6\x8B\x88", + "\xC4\xEA" => "\xE5\xB9\xB4", + "\xC4\xEB" => "\xE7\xA2\xBE", + "\xC4\xEC" => "\xE6\x92\xB5", + "\xC4\xED" => "\xE6\x8D\xBB", + "\xC4\xEE" => "\xE5\xBF\xB5", + "\xC4\xEF" => "\xE5\xA8\x98", + "\xC4\xF0" => "\xE9\x85\xBF", + "\xC4\xF1" => "\xE9\xB8\x9F", + "\xC4\xF2" => "\xE5\xB0\xBF", + "\xC4\xF3" => "\xE6\x8D\x8F", + "\xC4\xF4" => "\xE8\x81\x82", + "\xC4\xF5" => "\xE5\xAD\xBD", + "\xC4\xF6" => "\xE5\x95\xAE", + "\xC4\xF7" => "\xE9\x95\x8A", + "\xC4\xF8" => "\xE9\x95\x8D", + "\xC4\xF9" => "\xE6\xB6\x85", + "\xC4\xFA" => "\xE6\x82\xA8", + "\xC4\xFB" => "\xE6\x9F\xA0", + "\xC4\xFC" => "\xE7\x8B\x9E", + "\xC4\xFD" => "\xE5\x87\x9D", + "\xC4\xFE" => "\xE5\xAE\x81", + "\xC5\xA1" => "\xE6\x8B\xA7", + "\xC5\xA2" => "\xE6\xB3\x9E", + "\xC5\xA3" => "\xE7\x89\x9B", + "\xC5\xA4" => "\xE6\x89\xAD", + "\xC5\xA5" => "\xE9\x92\xAE", + "\xC5\xA6" => "\xE7\xBA\xBD", + "\xC5\xA7" => "\xE8\x84\x93", + "\xC5\xA8" => "\xE6\xB5\x93", + "\xC5\xA9" => "\xE5\x86\x9C", + "\xC5\xAA" => "\xE5\xBC\x84", + "\xC5\xAB" => "\xE5\xA5\xB4", + "\xC5\xAC" => "\xE5\x8A\xAA", + "\xC5\xAD" => "\xE6\x80\x92", + "\xC5\xAE" => "\xE5\xA5\xB3", + "\xC5\xAF" => "\xE6\x9A\x96", + "\xC5\xB0" => "\xE8\x99\x90", + "\xC5\xB1" => "\xE7\x96\x9F", + "\xC5\xB2" => "\xE6\x8C\xAA", + "\xC5\xB3" => "\xE6\x87\xA6", + "\xC5\xB4" => "\xE7\xB3\xAF", + "\xC5\xB5" => "\xE8\xAF\xBA", + "\xC5\xB6" => "\xE5\x93\xA6", + "\xC5\xB7" => "\xE6\xAC\xA7", + "\xC5\xB8" => "\xE9\xB8\xA5", + "\xC5\xB9" => "\xE6\xAE\xB4", + "\xC5\xBA" => "\xE8\x97\x95", + "\xC5\xBB" => "\xE5\x91\x95", + "\xC5\xBC" => "\xE5\x81\xB6", + "\xC5\xBD" => "\xE6\xB2\xA4", + "\xC5\xBE" => "\xE5\x95\xAA", + "\xC5\xBF" => "\xE8\xB6\xB4", + "\xC5\xC0" => "\xE7\x88\xAC", + "\xC5\xC1" => "\xE5\xB8\x95", + "\xC5\xC2" => "\xE6\x80\x95", + "\xC5\xC3" => "\xE7\x90\xB6", + "\xC5\xC4" => "\xE6\x8B\x8D", + "\xC5\xC5" => "\xE6\x8E\x92", + "\xC5\xC6" => "\xE7\x89\x8C", + "\xC5\xC7" => "\xE5\xBE\x98", + "\xC5\xC8" => "\xE6\xB9\x83", + "\xC5\xC9" => "\xE6\xB4\xBE", + "\xC5\xCA" => "\xE6\x94\x80", + "\xC5\xCB" => "\xE6\xBD\x98", + "\xC5\xCC" => "\xE7\x9B\x98", + "\xC5\xCD" => "\xE7\xA3\x90", + "\xC5\xCE" => "\xE7\x9B\xBC", + "\xC5\xCF" => "\xE7\x95\x94", + "\xC5\xD0" => "\xE5\x88\xA4", + "\xC5\xD1" => "\xE5\x8F\x9B", + "\xC5\xD2" => "\xE4\xB9\x93", + "\xC5\xD3" => "\xE5\xBA\x9E", + "\xC5\xD4" => "\xE6\x97\x81", + "\xC5\xD5" => "\xE8\x80\xAA", + "\xC5\xD6" => "\xE8\x83\x96", + "\xC5\xD7" => "\xE6\x8A\x9B", + "\xC5\xD8" => "\xE5\x92\x86", + "\xC5\xD9" => "\xE5\x88\xA8", + "\xC5\xDA" => "\xE7\x82\xAE", + "\xC5\xDB" => "\xE8\xA2\x8D", + "\xC5\xDC" => "\xE8\xB7\x91", + "\xC5\xDD" => "\xE6\xB3\xA1", + "\xC5\xDE" => "\xE5\x91\xB8", + "\xC5\xDF" => "\xE8\x83\x9A", + "\xC5\xE0" => "\xE5\x9F\xB9", + "\xC5\xE1" => "\xE8\xA3\xB4", + "\xC5\xE2" => "\xE8\xB5\x94", + "\xC5\xE3" => "\xE9\x99\xAA", + "\xC5\xE4" => "\xE9\x85\x8D", + "\xC5\xE5" => "\xE4\xBD\xA9", + "\xC5\xE6" => "\xE6\xB2\x9B", + "\xC5\xE7" => "\xE5\x96\xB7", + "\xC5\xE8" => "\xE7\x9B\x86", + "\xC5\xE9" => "\xE7\xA0\xB0", + "\xC5\xEA" => "\xE6\x8A\xA8", + "\xC5\xEB" => "\xE7\x83\xB9", + "\xC5\xEC" => "\xE6\xBE\x8E", + "\xC5\xED" => "\xE5\xBD\xAD", + "\xC5\xEE" => "\xE8\x93\xAC", + "\xC5\xEF" => "\xE6\xA3\x9A", + "\xC5\xF0" => "\xE7\xA1\xBC", + "\xC5\xF1" => "\xE7\xAF\xB7", + "\xC5\xF2" => "\xE8\x86\xA8", + "\xC5\xF3" => "\xE6\x9C\x8B", + "\xC5\xF4" => "\xE9\xB9\x8F", + "\xC5\xF5" => "\xE6\x8D\xA7", + "\xC5\xF6" => "\xE7\xA2\xB0", + "\xC5\xF7" => "\xE5\x9D\xAF", + "\xC5\xF8" => "\xE7\xA0\x92", + "\xC5\xF9" => "\xE9\x9C\xB9", + "\xC5\xFA" => "\xE6\x89\xB9", + "\xC5\xFB" => "\xE6\x8A\xAB", + "\xC5\xFC" => "\xE5\x8A\x88", + "\xC5\xFD" => "\xE7\x90\xB5", + "\xC5\xFE" => "\xE6\xAF\x97", + "\xC6\xA1" => "\xE5\x95\xA4", + "\xC6\xA2" => "\xE8\x84\xBE", + "\xC6\xA3" => "\xE7\x96\xB2", + "\xC6\xA4" => "\xE7\x9A\xAE", + "\xC6\xA5" => "\xE5\x8C\xB9", + "\xC6\xA6" => "\xE7\x97\x9E", + "\xC6\xA7" => "\xE5\x83\xBB", + "\xC6\xA8" => "\xE5\xB1\x81", + "\xC6\xA9" => "\xE8\xAD\xAC", + "\xC6\xAA" => "\xE7\xAF\x87", + "\xC6\xAB" => "\xE5\x81\x8F", + "\xC6\xAC" => "\xE7\x89\x87", + "\xC6\xAD" => "\xE9\xAA\x97", + "\xC6\xAE" => "\xE9\xA3\x98", + "\xC6\xAF" => "\xE6\xBC\x82", + "\xC6\xB0" => "\xE7\x93\xA2", + "\xC6\xB1" => "\xE7\xA5\xA8", + "\xC6\xB2" => "\xE6\x92\x87", + "\xC6\xB3" => "\xE7\x9E\xA5", + "\xC6\xB4" => "\xE6\x8B\xBC", + "\xC6\xB5" => "\xE9\xA2\x91", + "\xC6\xB6" => "\xE8\xB4\xAB", + "\xC6\xB7" => "\xE5\x93\x81", + "\xC6\xB8" => "\xE8\x81\x98", + "\xC6\xB9" => "\xE4\xB9\x92", + "\xC6\xBA" => "\xE5\x9D\xAA", + "\xC6\xBB" => "\xE8\x8B\xB9", + "\xC6\xBC" => "\xE8\x90\x8D", + "\xC6\xBD" => "\xE5\xB9\xB3", + "\xC6\xBE" => "\xE5\x87\xAD", + "\xC6\xBF" => "\xE7\x93\xB6", + "\xC6\xC0" => "\xE8\xAF\x84", + "\xC6\xC1" => "\xE5\xB1\x8F", + "\xC6\xC2" => "\xE5\x9D\xA1", + "\xC6\xC3" => "\xE6\xB3\xBC", + "\xC6\xC4" => "\xE9\xA2\x87", + "\xC6\xC5" => "\xE5\xA9\x86", + "\xC6\xC6" => "\xE7\xA0\xB4", + "\xC6\xC7" => "\xE9\xAD\x84", + "\xC6\xC8" => "\xE8\xBF\xAB", + "\xC6\xC9" => "\xE7\xB2\x95", + "\xC6\xCA" => "\xE5\x89\x96", + "\xC6\xCB" => "\xE6\x89\x91", + "\xC6\xCC" => "\xE9\x93\xBA", + "\xC6\xCD" => "\xE4\xBB\x86", + "\xC6\xCE" => "\xE8\x8E\x86", + "\xC6\xCF" => "\xE8\x91\xA1", + "\xC6\xD0" => "\xE8\x8F\xA9", + "\xC6\xD1" => "\xE8\x92\xB2", + "\xC6\xD2" => "\xE5\x9F\x94", + "\xC6\xD3" => "\xE6\x9C\xB4", + "\xC6\xD4" => "\xE5\x9C\x83", + "\xC6\xD5" => "\xE6\x99\xAE", + "\xC6\xD6" => "\xE6\xB5\xA6", + "\xC6\xD7" => "\xE8\xB0\xB1", + "\xC6\xD8" => "\xE6\x9B\x9D", + "\xC6\xD9" => "\xE7\x80\x91", + "\xC6\xDA" => "\xE6\x9C\x9F", + "\xC6\xDB" => "\xE6\xAC\xBA", + "\xC6\xDC" => "\xE6\xA0\x96", + "\xC6\xDD" => "\xE6\x88\x9A", + "\xC6\xDE" => "\xE5\xA6\xBB", + "\xC6\xDF" => "\xE4\xB8\x83", + "\xC6\xE0" => "\xE5\x87\x84", + "\xC6\xE1" => "\xE6\xBC\x86", + "\xC6\xE2" => "\xE6\x9F\x92", + "\xC6\xE3" => "\xE6\xB2\x8F", + "\xC6\xE4" => "\xE5\x85\xB6", + "\xC6\xE5" => "\xE6\xA3\x8B", + "\xC6\xE6" => "\xE5\xA5\x87", + "\xC6\xE7" => "\xE6\xAD\xA7", + "\xC6\xE8" => "\xE7\x95\xA6", + "\xC6\xE9" => "\xE5\xB4\x8E", + "\xC6\xEA" => "\xE8\x84\x90", + "\xC6\xEB" => "\xE9\xBD\x90", + "\xC6\xEC" => "\xE6\x97\x97", + "\xC6\xED" => "\xE7\xA5\x88", + "\xC6\xEE" => "\xE7\xA5\x81", + "\xC6\xEF" => "\xE9\xAA\x91", + "\xC6\xF0" => "\xE8\xB5\xB7", + "\xC6\xF1" => "\xE5\xB2\x82", + "\xC6\xF2" => "\xE4\xB9\x9E", + "\xC6\xF3" => "\xE4\xBC\x81", + "\xC6\xF4" => "\xE5\x90\xAF", + "\xC6\xF5" => "\xE5\xA5\x91", + "\xC6\xF6" => "\xE7\xA0\x8C", + "\xC6\xF7" => "\xE5\x99\xA8", + "\xC6\xF8" => "\xE6\xB0\x94", + "\xC6\xF9" => "\xE8\xBF\x84", + "\xC6\xFA" => "\xE5\xBC\x83", + "\xC6\xFB" => "\xE6\xB1\xBD", + "\xC6\xFC" => "\xE6\xB3\xA3", + "\xC6\xFD" => "\xE8\xAE\xAB", + "\xC6\xFE" => "\xE6\x8E\x90", + "\xC7\xA1" => "\xE6\x81\xB0", + "\xC7\xA2" => "\xE6\xB4\xBD", + "\xC7\xA3" => "\xE7\x89\xB5", + "\xC7\xA4" => "\xE6\x89\xA6", + "\xC7\xA5" => "\xE9\x92\x8E", + "\xC7\xA6" => "\xE9\x93\x85", + "\xC7\xA7" => "\xE5\x8D\x83", + "\xC7\xA8" => "\xE8\xBF\x81", + "\xC7\xA9" => "\xE7\xAD\xBE", + "\xC7\xAA" => "\xE4\xBB\x9F", + "\xC7\xAB" => "\xE8\xB0\xA6", + "\xC7\xAC" => "\xE4\xB9\xBE", + "\xC7\xAD" => "\xE9\xBB\x94", + "\xC7\xAE" => "\xE9\x92\xB1", + "\xC7\xAF" => "\xE9\x92\xB3", + "\xC7\xB0" => "\xE5\x89\x8D", + "\xC7\xB1" => "\xE6\xBD\x9C", + "\xC7\xB2" => "\xE9\x81\xA3", + "\xC7\xB3" => "\xE6\xB5\x85", + "\xC7\xB4" => "\xE8\xB0\xB4", + "\xC7\xB5" => "\xE5\xA0\x91", + "\xC7\xB6" => "\xE5\xB5\x8C", + "\xC7\xB7" => "\xE6\xAC\xA0", + "\xC7\xB8" => "\xE6\xAD\x89", + "\xC7\xB9" => "\xE6\x9E\xAA", + "\xC7\xBA" => "\xE5\x91\x9B", + "\xC7\xBB" => "\xE8\x85\x94", + "\xC7\xBC" => "\xE7\xBE\x8C", + "\xC7\xBD" => "\xE5\xA2\x99", + "\xC7\xBE" => "\xE8\x94\xB7", + "\xC7\xBF" => "\xE5\xBC\xBA", + "\xC7\xC0" => "\xE6\x8A\xA2", + "\xC7\xC1" => "\xE6\xA9\x87", + "\xC7\xC2" => "\xE9\x94\xB9", + "\xC7\xC3" => "\xE6\x95\xB2", + "\xC7\xC4" => "\xE6\x82\x84", + "\xC7\xC5" => "\xE6\xA1\xA5", + "\xC7\xC6" => "\xE7\x9E\xA7", + "\xC7\xC7" => "\xE4\xB9\x94", + "\xC7\xC8" => "\xE4\xBE\xA8", + "\xC7\xC9" => "\xE5\xB7\xA7", + "\xC7\xCA" => "\xE9\x9E\x98", + "\xC7\xCB" => "\xE6\x92\xAC", + "\xC7\xCC" => "\xE7\xBF\x98", + "\xC7\xCD" => "\xE5\xB3\xAD", + "\xC7\xCE" => "\xE4\xBF\x8F", + "\xC7\xCF" => "\xE7\xAA\x8D", + "\xC7\xD0" => "\xE5\x88\x87", + "\xC7\xD1" => "\xE8\x8C\x84", + "\xC7\xD2" => "\xE4\xB8\x94", + "\xC7\xD3" => "\xE6\x80\xAF", + "\xC7\xD4" => "\xE7\xAA\x83", + "\xC7\xD5" => "\xE9\x92\xA6", + "\xC7\xD6" => "\xE4\xBE\xB5", + "\xC7\xD7" => "\xE4\xBA\xB2", + "\xC7\xD8" => "\xE7\xA7\xA6", + "\xC7\xD9" => "\xE7\x90\xB4", + "\xC7\xDA" => "\xE5\x8B\xA4", + "\xC7\xDB" => "\xE8\x8A\xB9", + "\xC7\xDC" => "\xE6\x93\x92", + "\xC7\xDD" => "\xE7\xA6\xBD", + "\xC7\xDE" => "\xE5\xAF\x9D", + "\xC7\xDF" => "\xE6\xB2\x81", + "\xC7\xE0" => "\xE9\x9D\x92", + "\xC7\xE1" => "\xE8\xBD\xBB", + "\xC7\xE2" => "\xE6\xB0\xA2", + "\xC7\xE3" => "\xE5\x80\xBE", + "\xC7\xE4" => "\xE5\x8D\xBF", + "\xC7\xE5" => "\xE6\xB8\x85", + "\xC7\xE6" => "\xE6\x93\x8E", + "\xC7\xE7" => "\xE6\x99\xB4", + "\xC7\xE8" => "\xE6\xB0\xB0", + "\xC7\xE9" => "\xE6\x83\x85", + "\xC7\xEA" => "\xE9\xA1\xB7", + "\xC7\xEB" => "\xE8\xAF\xB7", + "\xC7\xEC" => "\xE5\xBA\x86", + "\xC7\xED" => "\xE7\x90\xBC", + "\xC7\xEE" => "\xE7\xA9\xB7", + "\xC7\xEF" => "\xE7\xA7\x8B", + "\xC7\xF0" => "\xE4\xB8\x98", + "\xC7\xF1" => "\xE9\x82\xB1", + "\xC7\xF2" => "\xE7\x90\x83", + "\xC7\xF3" => "\xE6\xB1\x82", + "\xC7\xF4" => "\xE5\x9B\x9A", + "\xC7\xF5" => "\xE9\x85\x8B", + "\xC7\xF6" => "\xE6\xB3\x85", + "\xC7\xF7" => "\xE8\xB6\x8B", + "\xC7\xF8" => "\xE5\x8C\xBA", + "\xC7\xF9" => "\xE8\x9B\x86", + "\xC7\xFA" => "\xE6\x9B\xB2", + "\xC7\xFB" => "\xE8\xBA\xAF", + "\xC7\xFC" => "\xE5\xB1\x88", + "\xC7\xFD" => "\xE9\xA9\xB1", + "\xC7\xFE" => "\xE6\xB8\xA0", + "\xC8\xA1" => "\xE5\x8F\x96", + "\xC8\xA2" => "\xE5\xA8\xB6", + "\xC8\xA3" => "\xE9\xBE\x8B", + "\xC8\xA4" => "\xE8\xB6\xA3", + "\xC8\xA5" => "\xE5\x8E\xBB", + "\xC8\xA6" => "\xE5\x9C\x88", + "\xC8\xA7" => "\xE9\xA2\xA7", + "\xC8\xA8" => "\xE6\x9D\x83", + "\xC8\xA9" => "\xE9\x86\x9B", + "\xC8\xAA" => "\xE6\xB3\x89", + "\xC8\xAB" => "\xE5\x85\xA8", + "\xC8\xAC" => "\xE7\x97\x8A", + "\xC8\xAD" => "\xE6\x8B\xB3", + "\xC8\xAE" => "\xE7\x8A\xAC", + "\xC8\xAF" => "\xE5\x88\xB8", + "\xC8\xB0" => "\xE5\x8A\x9D", + "\xC8\xB1" => "\xE7\xBC\xBA", + "\xC8\xB2" => "\xE7\x82\x94", + "\xC8\xB3" => "\xE7\x98\xB8", + "\xC8\xB4" => "\xE5\x8D\xB4", + "\xC8\xB5" => "\xE9\xB9\x8A", + "\xC8\xB6" => "\xE6\xA6\xB7", + "\xC8\xB7" => "\xE7\xA1\xAE", + "\xC8\xB8" => "\xE9\x9B\x80", + "\xC8\xB9" => "\xE8\xA3\x99", + "\xC8\xBA" => "\xE7\xBE\xA4", + "\xC8\xBB" => "\xE7\x84\xB6", + "\xC8\xBC" => "\xE7\x87\x83", + "\xC8\xBD" => "\xE5\x86\x89", + "\xC8\xBE" => "\xE6\x9F\x93", + "\xC8\xBF" => "\xE7\x93\xA4", + "\xC8\xC0" => "\xE5\xA3\xA4", + "\xC8\xC1" => "\xE6\x94\x98", + "\xC8\xC2" => "\xE5\x9A\xB7", + "\xC8\xC3" => "\xE8\xAE\xA9", + "\xC8\xC4" => "\xE9\xA5\xB6", + "\xC8\xC5" => "\xE6\x89\xB0", + "\xC8\xC6" => "\xE7\xBB\x95", + "\xC8\xC7" => "\xE6\x83\xB9", + "\xC8\xC8" => "\xE7\x83\xAD", + "\xC8\xC9" => "\xE5\xA3\xAC", + "\xC8\xCA" => "\xE4\xBB\x81", + "\xC8\xCB" => "\xE4\xBA\xBA", + "\xC8\xCC" => "\xE5\xBF\x8D", + "\xC8\xCD" => "\xE9\x9F\xA7", + "\xC8\xCE" => "\xE4\xBB\xBB", + "\xC8\xCF" => "\xE8\xAE\xA4", + "\xC8\xD0" => "\xE5\x88\x83", + "\xC8\xD1" => "\xE5\xA6\x8A", + "\xC8\xD2" => "\xE7\xBA\xAB", + "\xC8\xD3" => "\xE6\x89\x94", + "\xC8\xD4" => "\xE4\xBB\x8D", + "\xC8\xD5" => "\xE6\x97\xA5", + "\xC8\xD6" => "\xE6\x88\x8E", + "\xC8\xD7" => "\xE8\x8C\xB8", + "\xC8\xD8" => "\xE8\x93\x89", + "\xC8\xD9" => "\xE8\x8D\xA3", + "\xC8\xDA" => "\xE8\x9E\x8D", + "\xC8\xDB" => "\xE7\x86\x94", + "\xC8\xDC" => "\xE6\xBA\xB6", + "\xC8\xDD" => "\xE5\xAE\xB9", + "\xC8\xDE" => "\xE7\xBB\x92", + "\xC8\xDF" => "\xE5\x86\x97", + "\xC8\xE0" => "\xE6\x8F\x89", + "\xC8\xE1" => "\xE6\x9F\x94", + "\xC8\xE2" => "\xE8\x82\x89", + "\xC8\xE3" => "\xE8\x8C\xB9", + "\xC8\xE4" => "\xE8\xA0\x95", + "\xC8\xE5" => "\xE5\x84\x92", + "\xC8\xE6" => "\xE5\xAD\xBA", + "\xC8\xE7" => "\xE5\xA6\x82", + "\xC8\xE8" => "\xE8\xBE\xB1", + "\xC8\xE9" => "\xE4\xB9\xB3", + "\xC8\xEA" => "\xE6\xB1\x9D", + "\xC8\xEB" => "\xE5\x85\xA5", + "\xC8\xEC" => "\xE8\xA4\xA5", + "\xC8\xED" => "\xE8\xBD\xAF", + "\xC8\xEE" => "\xE9\x98\xAE", + "\xC8\xEF" => "\xE8\x95\x8A", + "\xC8\xF0" => "\xE7\x91\x9E", + "\xC8\xF1" => "\xE9\x94\x90", + "\xC8\xF2" => "\xE9\x97\xB0", + "\xC8\xF3" => "\xE6\xB6\xA6", + "\xC8\xF4" => "\xE8\x8B\xA5", + "\xC8\xF5" => "\xE5\xBC\xB1", + "\xC8\xF6" => "\xE6\x92\x92", + "\xC8\xF7" => "\xE6\xB4\x92", + "\xC8\xF8" => "\xE8\x90\xA8", + "\xC8\xF9" => "\xE8\x85\xAE", + "\xC8\xFA" => "\xE9\xB3\x83", + "\xC8\xFB" => "\xE5\xA1\x9E", + "\xC8\xFC" => "\xE8\xB5\x9B", + "\xC8\xFD" => "\xE4\xB8\x89", + "\xC8\xFE" => "\xE5\x8F\x81", + "\xC9\xA1" => "\xE4\xBC\x9E", + "\xC9\xA2" => "\xE6\x95\xA3", + "\xC9\xA3" => "\xE6\xA1\x91", + "\xC9\xA4" => "\xE5\x97\x93", + "\xC9\xA5" => "\xE4\xB8\xA7", + "\xC9\xA6" => "\xE6\x90\x94", + "\xC9\xA7" => "\xE9\xAA\x9A", + "\xC9\xA8" => "\xE6\x89\xAB", + "\xC9\xA9" => "\xE5\xAB\x82", + "\xC9\xAA" => "\xE7\x91\x9F", + "\xC9\xAB" => "\xE8\x89\xB2", + "\xC9\xAC" => "\xE6\xB6\xA9", + "\xC9\xAD" => "\xE6\xA3\xAE", + "\xC9\xAE" => "\xE5\x83\xA7", + "\xC9\xAF" => "\xE8\x8E\x8E", + "\xC9\xB0" => "\xE7\xA0\x82", + "\xC9\xB1" => "\xE6\x9D\x80", + "\xC9\xB2" => "\xE5\x88\xB9", + "\xC9\xB3" => "\xE6\xB2\x99", + "\xC9\xB4" => "\xE7\xBA\xB1", + "\xC9\xB5" => "\xE5\x82\xBB", + "\xC9\xB6" => "\xE5\x95\xA5", + "\xC9\xB7" => "\xE7\x85\x9E", + "\xC9\xB8" => "\xE7\xAD\x9B", + "\xC9\xB9" => "\xE6\x99\x92", + "\xC9\xBA" => "\xE7\x8F\x8A", + "\xC9\xBB" => "\xE8\x8B\xAB", + "\xC9\xBC" => "\xE6\x9D\x89", + "\xC9\xBD" => "\xE5\xB1\xB1", + "\xC9\xBE" => "\xE5\x88\xA0", + "\xC9\xBF" => "\xE7\x85\xBD", + "\xC9\xC0" => "\xE8\xA1\xAB", + "\xC9\xC1" => "\xE9\x97\xAA", + "\xC9\xC2" => "\xE9\x99\x95", + "\xC9\xC3" => "\xE6\x93\x85", + "\xC9\xC4" => "\xE8\xB5\xA1", + "\xC9\xC5" => "\xE8\x86\xB3", + "\xC9\xC6" => "\xE5\x96\x84", + "\xC9\xC7" => "\xE6\xB1\x95", + "\xC9\xC8" => "\xE6\x89\x87", + "\xC9\xC9" => "\xE7\xBC\xAE", + "\xC9\xCA" => "\xE5\xA2\x92", + "\xC9\xCB" => "\xE4\xBC\xA4", + "\xC9\xCC" => "\xE5\x95\x86", + "\xC9\xCD" => "\xE8\xB5\x8F", + "\xC9\xCE" => "\xE6\x99\x8C", + "\xC9\xCF" => "\xE4\xB8\x8A", + "\xC9\xD0" => "\xE5\xB0\x9A", + "\xC9\xD1" => "\xE8\xA3\xB3", + "\xC9\xD2" => "\xE6\xA2\xA2", + "\xC9\xD3" => "\xE6\x8D\x8E", + "\xC9\xD4" => "\xE7\xA8\x8D", + "\xC9\xD5" => "\xE7\x83\xA7", + "\xC9\xD6" => "\xE8\x8A\x8D", + "\xC9\xD7" => "\xE5\x8B\xBA", + "\xC9\xD8" => "\xE9\x9F\xB6", + "\xC9\xD9" => "\xE5\xB0\x91", + "\xC9\xDA" => "\xE5\x93\xA8", + "\xC9\xDB" => "\xE9\x82\xB5", + "\xC9\xDC" => "\xE7\xBB\x8D", + "\xC9\xDD" => "\xE5\xA5\xA2", + "\xC9\xDE" => "\xE8\xB5\x8A", + "\xC9\xDF" => "\xE8\x9B\x87", + "\xC9\xE0" => "\xE8\x88\x8C", + "\xC9\xE1" => "\xE8\x88\x8D", + "\xC9\xE2" => "\xE8\xB5\xA6", + "\xC9\xE3" => "\xE6\x91\x84", + "\xC9\xE4" => "\xE5\xB0\x84", + "\xC9\xE5" => "\xE6\x85\x91", + "\xC9\xE6" => "\xE6\xB6\x89", + "\xC9\xE7" => "\xE7\xA4\xBE", + "\xC9\xE8" => "\xE8\xAE\xBE", + "\xC9\xE9" => "\xE7\xA0\xB7", + "\xC9\xEA" => "\xE7\x94\xB3", + "\xC9\xEB" => "\xE5\x91\xBB", + "\xC9\xEC" => "\xE4\xBC\xB8", + "\xC9\xED" => "\xE8\xBA\xAB", + "\xC9\xEE" => "\xE6\xB7\xB1", + "\xC9\xEF" => "\xE5\xA8\xA0", + "\xC9\xF0" => "\xE7\xBB\x85", + "\xC9\xF1" => "\xE7\xA5\x9E", + "\xC9\xF2" => "\xE6\xB2\x88", + "\xC9\xF3" => "\xE5\xAE\xA1", + "\xC9\xF4" => "\xE5\xA9\xB6", + "\xC9\xF5" => "\xE7\x94\x9A", + "\xC9\xF6" => "\xE8\x82\xBE", + "\xC9\xF7" => "\xE6\x85\x8E", + "\xC9\xF8" => "\xE6\xB8\x97", + "\xC9\xF9" => "\xE5\xA3\xB0", + "\xC9\xFA" => "\xE7\x94\x9F", + "\xC9\xFB" => "\xE7\x94\xA5", + "\xC9\xFC" => "\xE7\x89\xB2", + "\xC9\xFD" => "\xE5\x8D\x87", + "\xC9\xFE" => "\xE7\xBB\xB3", + "\xCA\xA1" => "\xE7\x9C\x81", + "\xCA\xA2" => "\xE7\x9B\x9B", + "\xCA\xA3" => "\xE5\x89\xA9", + "\xCA\xA4" => "\xE8\x83\x9C", + "\xCA\xA5" => "\xE5\x9C\xA3", + "\xCA\xA6" => "\xE5\xB8\x88", + "\xCA\xA7" => "\xE5\xA4\xB1", + "\xCA\xA8" => "\xE7\x8B\xAE", + "\xCA\xA9" => "\xE6\x96\xBD", + "\xCA\xAA" => "\xE6\xB9\xBF", + "\xCA\xAB" => "\xE8\xAF\x97", + "\xCA\xAC" => "\xE5\xB0\xB8", + "\xCA\xAD" => "\xE8\x99\xB1", + "\xCA\xAE" => "\xE5\x8D\x81", + "\xCA\xAF" => "\xE7\x9F\xB3", + "\xCA\xB0" => "\xE6\x8B\xBE", + "\xCA\xB1" => "\xE6\x97\xB6", + "\xCA\xB2" => "\xE4\xBB\x80", + "\xCA\xB3" => "\xE9\xA3\x9F", + "\xCA\xB4" => "\xE8\x9A\x80", + "\xCA\xB5" => "\xE5\xAE\x9E", + "\xCA\xB6" => "\xE8\xAF\x86", + "\xCA\xB7" => "\xE5\x8F\xB2", + "\xCA\xB8" => "\xE7\x9F\xA2", + "\xCA\xB9" => "\xE4\xBD\xBF", + "\xCA\xBA" => "\xE5\xB1\x8E", + "\xCA\xBB" => "\xE9\xA9\xB6", + "\xCA\xBC" => "\xE5\xA7\x8B", + "\xCA\xBD" => "\xE5\xBC\x8F", + "\xCA\xBE" => "\xE7\xA4\xBA", + "\xCA\xBF" => "\xE5\xA3\xAB", + "\xCA\xC0" => "\xE4\xB8\x96", + "\xCA\xC1" => "\xE6\x9F\xBF", + "\xCA\xC2" => "\xE4\xBA\x8B", + "\xCA\xC3" => "\xE6\x8B\xAD", + "\xCA\xC4" => "\xE8\xAA\x93", + "\xCA\xC5" => "\xE9\x80\x9D", + "\xCA\xC6" => "\xE5\x8A\xBF", + "\xCA\xC7" => "\xE6\x98\xAF", + "\xCA\xC8" => "\xE5\x97\x9C", + "\xCA\xC9" => "\xE5\x99\xAC", + "\xCA\xCA" => "\xE9\x80\x82", + "\xCA\xCB" => "\xE4\xBB\x95", + "\xCA\xCC" => "\xE4\xBE\x8D", + "\xCA\xCD" => "\xE9\x87\x8A", + "\xCA\xCE" => "\xE9\xA5\xB0", + "\xCA\xCF" => "\xE6\xB0\x8F", + "\xCA\xD0" => "\xE5\xB8\x82", + "\xCA\xD1" => "\xE6\x81\x83", + "\xCA\xD2" => "\xE5\xAE\xA4", + "\xCA\xD3" => "\xE8\xA7\x86", + "\xCA\xD4" => "\xE8\xAF\x95", + "\xCA\xD5" => "\xE6\x94\xB6", + "\xCA\xD6" => "\xE6\x89\x8B", + "\xCA\xD7" => "\xE9\xA6\x96", + "\xCA\xD8" => "\xE5\xAE\x88", + "\xCA\xD9" => "\xE5\xAF\xBF", + "\xCA\xDA" => "\xE6\x8E\x88", + "\xCA\xDB" => "\xE5\x94\xAE", + "\xCA\xDC" => "\xE5\x8F\x97", + "\xCA\xDD" => "\xE7\x98\xA6", + "\xCA\xDE" => "\xE5\x85\xBD", + "\xCA\xDF" => "\xE8\x94\xAC", + "\xCA\xE0" => "\xE6\x9E\xA2", + "\xCA\xE1" => "\xE6\xA2\xB3", + "\xCA\xE2" => "\xE6\xAE\x8A", + "\xCA\xE3" => "\xE6\x8A\x92", + "\xCA\xE4" => "\xE8\xBE\x93", + "\xCA\xE5" => "\xE5\x8F\x94", + "\xCA\xE6" => "\xE8\x88\x92", + "\xCA\xE7" => "\xE6\xB7\x91", + "\xCA\xE8" => "\xE7\x96\x8F", + "\xCA\xE9" => "\xE4\xB9\xA6", + "\xCA\xEA" => "\xE8\xB5\x8E", + "\xCA\xEB" => "\xE5\xAD\xB0", + "\xCA\xEC" => "\xE7\x86\x9F", + "\xCA\xED" => "\xE8\x96\xAF", + "\xCA\xEE" => "\xE6\x9A\x91", + "\xCA\xEF" => "\xE6\x9B\x99", + "\xCA\xF0" => "\xE7\xBD\xB2", + "\xCA\xF1" => "\xE8\x9C\x80", + "\xCA\xF2" => "\xE9\xBB\x8D", + "\xCA\xF3" => "\xE9\xBC\xA0", + "\xCA\xF4" => "\xE5\xB1\x9E", + "\xCA\xF5" => "\xE6\x9C\xAF", + "\xCA\xF6" => "\xE8\xBF\xB0", + "\xCA\xF7" => "\xE6\xA0\x91", + "\xCA\xF8" => "\xE6\x9D\x9F", + "\xCA\xF9" => "\xE6\x88\x8D", + "\xCA\xFA" => "\xE7\xAB\x96", + "\xCA\xFB" => "\xE5\xA2\x85", + "\xCA\xFC" => "\xE5\xBA\xB6", + "\xCA\xFD" => "\xE6\x95\xB0", + "\xCA\xFE" => "\xE6\xBC\xB1", + "\xCB\xA1" => "\xE6\x81\x95", + "\xCB\xA2" => "\xE5\x88\xB7", + "\xCB\xA3" => "\xE8\x80\x8D", + "\xCB\xA4" => "\xE6\x91\x94", + "\xCB\xA5" => "\xE8\xA1\xB0", + "\xCB\xA6" => "\xE7\x94\xA9", + "\xCB\xA7" => "\xE5\xB8\x85", + "\xCB\xA8" => "\xE6\xA0\x93", + "\xCB\xA9" => "\xE6\x8B\xB4", + "\xCB\xAA" => "\xE9\x9C\x9C", + "\xCB\xAB" => "\xE5\x8F\x8C", + "\xCB\xAC" => "\xE7\x88\xBD", + "\xCB\xAD" => "\xE8\xB0\x81", + "\xCB\xAE" => "\xE6\xB0\xB4", + "\xCB\xAF" => "\xE7\x9D\xA1", + "\xCB\xB0" => "\xE7\xA8\x8E", + "\xCB\xB1" => "\xE5\x90\xAE", + "\xCB\xB2" => "\xE7\x9E\xAC", + "\xCB\xB3" => "\xE9\xA1\xBA", + "\xCB\xB4" => "\xE8\x88\x9C", + "\xCB\xB5" => "\xE8\xAF\xB4", + "\xCB\xB6" => "\xE7\xA1\x95", + "\xCB\xB7" => "\xE6\x9C\x94", + "\xCB\xB8" => "\xE7\x83\x81", + "\xCB\xB9" => "\xE6\x96\xAF", + "\xCB\xBA" => "\xE6\x92\x95", + "\xCB\xBB" => "\xE5\x98\xB6", + "\xCB\xBC" => "\xE6\x80\x9D", + "\xCB\xBD" => "\xE7\xA7\x81", + "\xCB\xBE" => "\xE5\x8F\xB8", + "\xCB\xBF" => "\xE4\xB8\x9D", + "\xCB\xC0" => "\xE6\xAD\xBB", + "\xCB\xC1" => "\xE8\x82\x86", + "\xCB\xC2" => "\xE5\xAF\xBA", + "\xCB\xC3" => "\xE5\x97\xA3", + "\xCB\xC4" => "\xE5\x9B\x9B", + "\xCB\xC5" => "\xE4\xBC\xBA", + "\xCB\xC6" => "\xE4\xBC\xBC", + "\xCB\xC7" => "\xE9\xA5\xB2", + "\xCB\xC8" => "\xE5\xB7\xB3", + "\xCB\xC9" => "\xE6\x9D\xBE", + "\xCB\xCA" => "\xE8\x80\xB8", + "\xCB\xCB" => "\xE6\x80\x82", + "\xCB\xCC" => "\xE9\xA2\x82", + "\xCB\xCD" => "\xE9\x80\x81", + "\xCB\xCE" => "\xE5\xAE\x8B", + "\xCB\xCF" => "\xE8\xAE\xBC", + "\xCB\xD0" => "\xE8\xAF\xB5", + "\xCB\xD1" => "\xE6\x90\x9C", + "\xCB\xD2" => "\xE8\x89\x98", + "\xCB\xD3" => "\xE6\x93\x9E", + "\xCB\xD4" => "\xE5\x97\xBD", + "\xCB\xD5" => "\xE8\x8B\x8F", + "\xCB\xD6" => "\xE9\x85\xA5", + "\xCB\xD7" => "\xE4\xBF\x97", + "\xCB\xD8" => "\xE7\xB4\xA0", + "\xCB\xD9" => "\xE9\x80\x9F", + "\xCB\xDA" => "\xE7\xB2\x9F", + "\xCB\xDB" => "\xE5\x83\xB3", + "\xCB\xDC" => "\xE5\xA1\x91", + "\xCB\xDD" => "\xE6\xBA\xAF", + "\xCB\xDE" => "\xE5\xAE\xBF", + "\xCB\xDF" => "\xE8\xAF\x89", + "\xCB\xE0" => "\xE8\x82\x83", + "\xCB\xE1" => "\xE9\x85\xB8", + "\xCB\xE2" => "\xE8\x92\x9C", + "\xCB\xE3" => "\xE7\xAE\x97", + "\xCB\xE4" => "\xE8\x99\xBD", + "\xCB\xE5" => "\xE9\x9A\x8B", + "\xCB\xE6" => "\xE9\x9A\x8F", + "\xCB\xE7" => "\xE7\xBB\xA5", + "\xCB\xE8" => "\xE9\xAB\x93", + "\xCB\xE9" => "\xE7\xA2\x8E", + "\xCB\xEA" => "\xE5\xB2\x81", + "\xCB\xEB" => "\xE7\xA9\x97", + "\xCB\xEC" => "\xE9\x81\x82", + "\xCB\xED" => "\xE9\x9A\xA7", + "\xCB\xEE" => "\xE7\xA5\x9F", + "\xCB\xEF" => "\xE5\xAD\x99", + "\xCB\xF0" => "\xE6\x8D\x9F", + "\xCB\xF1" => "\xE7\xAC\x8B", + "\xCB\xF2" => "\xE8\x93\x91", + "\xCB\xF3" => "\xE6\xA2\xAD", + "\xCB\xF4" => "\xE5\x94\x86", + "\xCB\xF5" => "\xE7\xBC\xA9", + "\xCB\xF6" => "\xE7\x90\x90", + "\xCB\xF7" => "\xE7\xB4\xA2", + "\xCB\xF8" => "\xE9\x94\x81", + "\xCB\xF9" => "\xE6\x89\x80", + "\xCB\xFA" => "\xE5\xA1\x8C", + "\xCB\xFB" => "\xE4\xBB\x96", + "\xCB\xFC" => "\xE5\xAE\x83", + "\xCB\xFD" => "\xE5\xA5\xB9", + "\xCB\xFE" => "\xE5\xA1\x94", + "\xCC\xA1" => "\xE7\x8D\xAD", + "\xCC\xA2" => "\xE6\x8C\x9E", + "\xCC\xA3" => "\xE8\xB9\x8B", + "\xCC\xA4" => "\xE8\xB8\x8F", + "\xCC\xA5" => "\xE8\x83\x8E", + "\xCC\xA6" => "\xE8\x8B\x94", + "\xCC\xA7" => "\xE6\x8A\xAC", + "\xCC\xA8" => "\xE5\x8F\xB0", + "\xCC\xA9" => "\xE6\xB3\xB0", + "\xCC\xAA" => "\xE9\x85\x9E", + "\xCC\xAB" => "\xE5\xA4\xAA", + "\xCC\xAC" => "\xE6\x80\x81", + "\xCC\xAD" => "\xE6\xB1\xB0", + "\xCC\xAE" => "\xE5\x9D\x8D", + "\xCC\xAF" => "\xE6\x91\x8A", + "\xCC\xB0" => "\xE8\xB4\xAA", + "\xCC\xB1" => "\xE7\x98\xAB", + "\xCC\xB2" => "\xE6\xBB\xA9", + "\xCC\xB3" => "\xE5\x9D\x9B", + "\xCC\xB4" => "\xE6\xAA\x80", + "\xCC\xB5" => "\xE7\x97\xB0", + "\xCC\xB6" => "\xE6\xBD\xAD", + "\xCC\xB7" => "\xE8\xB0\xAD", + "\xCC\xB8" => "\xE8\xB0\x88", + "\xCC\xB9" => "\xE5\x9D\xA6", + "\xCC\xBA" => "\xE6\xAF\xAF", + "\xCC\xBB" => "\xE8\xA2\x92", + "\xCC\xBC" => "\xE7\xA2\xB3", + "\xCC\xBD" => "\xE6\x8E\xA2", + "\xCC\xBE" => "\xE5\x8F\xB9", + "\xCC\xBF" => "\xE7\x82\xAD", + "\xCC\xC0" => "\xE6\xB1\xA4", + "\xCC\xC1" => "\xE5\xA1\x98", + "\xCC\xC2" => "\xE6\x90\xAA", + "\xCC\xC3" => "\xE5\xA0\x82", + "\xCC\xC4" => "\xE6\xA3\xA0", + "\xCC\xC5" => "\xE8\x86\x9B", + "\xCC\xC6" => "\xE5\x94\x90", + "\xCC\xC7" => "\xE7\xB3\x96", + "\xCC\xC8" => "\xE5\x80\x98", + "\xCC\xC9" => "\xE8\xBA\xBA", + "\xCC\xCA" => "\xE6\xB7\x8C", + "\xCC\xCB" => "\xE8\xB6\x9F", + "\xCC\xCC" => "\xE7\x83\xAB", + "\xCC\xCD" => "\xE6\x8E\x8F", + "\xCC\xCE" => "\xE6\xB6\x9B", + "\xCC\xCF" => "\xE6\xBB\x94", + "\xCC\xD0" => "\xE7\xBB\xA6", + "\xCC\xD1" => "\xE8\x90\x84", + "\xCC\xD2" => "\xE6\xA1\x83", + "\xCC\xD3" => "\xE9\x80\x83", + "\xCC\xD4" => "\xE6\xB7\x98", + "\xCC\xD5" => "\xE9\x99\xB6", + "\xCC\xD6" => "\xE8\xAE\xA8", + "\xCC\xD7" => "\xE5\xA5\x97", + "\xCC\xD8" => "\xE7\x89\xB9", + "\xCC\xD9" => "\xE8\x97\xA4", + "\xCC\xDA" => "\xE8\x85\xBE", + "\xCC\xDB" => "\xE7\x96\xBC", + "\xCC\xDC" => "\xE8\xAA\x8A", + "\xCC\xDD" => "\xE6\xA2\xAF", + "\xCC\xDE" => "\xE5\x89\x94", + "\xCC\xDF" => "\xE8\xB8\xA2", + "\xCC\xE0" => "\xE9\x94\x91", + "\xCC\xE1" => "\xE6\x8F\x90", + "\xCC\xE2" => "\xE9\xA2\x98", + "\xCC\xE3" => "\xE8\xB9\x84", + "\xCC\xE4" => "\xE5\x95\xBC", + "\xCC\xE5" => "\xE4\xBD\x93", + "\xCC\xE6" => "\xE6\x9B\xBF", + "\xCC\xE7" => "\xE5\x9A\x8F", + "\xCC\xE8" => "\xE6\x83\x95", + "\xCC\xE9" => "\xE6\xB6\x95", + "\xCC\xEA" => "\xE5\x89\x83", + "\xCC\xEB" => "\xE5\xB1\x89", + "\xCC\xEC" => "\xE5\xA4\xA9", + "\xCC\xED" => "\xE6\xB7\xBB", + "\xCC\xEE" => "\xE5\xA1\xAB", + "\xCC\xEF" => "\xE7\x94\xB0", + "\xCC\xF0" => "\xE7\x94\x9C", + "\xCC\xF1" => "\xE6\x81\xAC", + "\xCC\xF2" => "\xE8\x88\x94", + "\xCC\xF3" => "\xE8\x85\x86", + "\xCC\xF4" => "\xE6\x8C\x91", + "\xCC\xF5" => "\xE6\x9D\xA1", + "\xCC\xF6" => "\xE8\xBF\xA2", + "\xCC\xF7" => "\xE7\x9C\xBA", + "\xCC\xF8" => "\xE8\xB7\xB3", + "\xCC\xF9" => "\xE8\xB4\xB4", + "\xCC\xFA" => "\xE9\x93\x81", + "\xCC\xFB" => "\xE5\xB8\x96", + "\xCC\xFC" => "\xE5\x8E\x85", + "\xCC\xFD" => "\xE5\x90\xAC", + "\xCC\xFE" => "\xE7\x83\x83", + "\xCD\xA1" => "\xE6\xB1\x80", + "\xCD\xA2" => "\xE5\xBB\xB7", + "\xCD\xA3" => "\xE5\x81\x9C", + "\xCD\xA4" => "\xE4\xBA\xAD", + "\xCD\xA5" => "\xE5\xBA\xAD", + "\xCD\xA6" => "\xE6\x8C\xBA", + "\xCD\xA7" => "\xE8\x89\x87", + "\xCD\xA8" => "\xE9\x80\x9A", + "\xCD\xA9" => "\xE6\xA1\x90", + "\xCD\xAA" => "\xE9\x85\xAE", + "\xCD\xAB" => "\xE7\x9E\xB3", + "\xCD\xAC" => "\xE5\x90\x8C", + "\xCD\xAD" => "\xE9\x93\x9C", + "\xCD\xAE" => "\xE5\xBD\xA4", + "\xCD\xAF" => "\xE7\xAB\xA5", + "\xCD\xB0" => "\xE6\xA1\xB6", + "\xCD\xB1" => "\xE6\x8D\x85", + "\xCD\xB2" => "\xE7\xAD\x92", + "\xCD\xB3" => "\xE7\xBB\x9F", + "\xCD\xB4" => "\xE7\x97\x9B", + "\xCD\xB5" => "\xE5\x81\xB7", + "\xCD\xB6" => "\xE6\x8A\x95", + "\xCD\xB7" => "\xE5\xA4\xB4", + "\xCD\xB8" => "\xE9\x80\x8F", + "\xCD\xB9" => "\xE5\x87\xB8", + "\xCD\xBA" => "\xE7\xA7\x83", + "\xCD\xBB" => "\xE7\xAA\x81", + "\xCD\xBC" => "\xE5\x9B\xBE", + "\xCD\xBD" => "\xE5\xBE\x92", + "\xCD\xBE" => "\xE9\x80\x94", + "\xCD\xBF" => "\xE6\xB6\x82", + "\xCD\xC0" => "\xE5\xB1\xA0", + "\xCD\xC1" => "\xE5\x9C\x9F", + "\xCD\xC2" => "\xE5\x90\x90", + "\xCD\xC3" => "\xE5\x85\x94", + "\xCD\xC4" => "\xE6\xB9\x8D", + "\xCD\xC5" => "\xE5\x9B\xA2", + "\xCD\xC6" => "\xE6\x8E\xA8", + "\xCD\xC7" => "\xE9\xA2\x93", + "\xCD\xC8" => "\xE8\x85\xBF", + "\xCD\xC9" => "\xE8\x9C\x95", + "\xCD\xCA" => "\xE8\xA4\xAA", + "\xCD\xCB" => "\xE9\x80\x80", + "\xCD\xCC" => "\xE5\x90\x9E", + "\xCD\xCD" => "\xE5\xB1\xAF", + "\xCD\xCE" => "\xE8\x87\x80", + "\xCD\xCF" => "\xE6\x8B\x96", + "\xCD\xD0" => "\xE6\x89\x98", + "\xCD\xD1" => "\xE8\x84\xB1", + "\xCD\xD2" => "\xE9\xB8\xB5", + "\xCD\xD3" => "\xE9\x99\x80", + "\xCD\xD4" => "\xE9\xA9\xAE", + "\xCD\xD5" => "\xE9\xA9\xBC", + "\xCD\xD6" => "\xE6\xA4\xAD", + "\xCD\xD7" => "\xE5\xA6\xA5", + "\xCD\xD8" => "\xE6\x8B\x93", + "\xCD\xD9" => "\xE5\x94\xBE", + "\xCD\xDA" => "\xE6\x8C\x96", + "\xCD\xDB" => "\xE5\x93\x87", + "\xCD\xDC" => "\xE8\x9B\x99", + "\xCD\xDD" => "\xE6\xB4\xBC", + "\xCD\xDE" => "\xE5\xA8\x83", + "\xCD\xDF" => "\xE7\x93\xA6", + "\xCD\xE0" => "\xE8\xA2\x9C", + "\xCD\xE1" => "\xE6\xAD\xAA", + "\xCD\xE2" => "\xE5\xA4\x96", + "\xCD\xE3" => "\xE8\xB1\x8C", + "\xCD\xE4" => "\xE5\xBC\xAF", + "\xCD\xE5" => "\xE6\xB9\xBE", + "\xCD\xE6" => "\xE7\x8E\xA9", + "\xCD\xE7" => "\xE9\xA1\xBD", + "\xCD\xE8" => "\xE4\xB8\xB8", + "\xCD\xE9" => "\xE7\x83\xB7", + "\xCD\xEA" => "\xE5\xAE\x8C", + "\xCD\xEB" => "\xE7\xA2\x97", + "\xCD\xEC" => "\xE6\x8C\xBD", + "\xCD\xED" => "\xE6\x99\x9A", + "\xCD\xEE" => "\xE7\x9A\x96", + "\xCD\xEF" => "\xE6\x83\x8B", + "\xCD\xF0" => "\xE5\xAE\x9B", + "\xCD\xF1" => "\xE5\xA9\x89", + "\xCD\xF2" => "\xE4\xB8\x87", + "\xCD\xF3" => "\xE8\x85\x95", + "\xCD\xF4" => "\xE6\xB1\xAA", + "\xCD\xF5" => "\xE7\x8E\x8B", + "\xCD\xF6" => "\xE4\xBA\xA1", + "\xCD\xF7" => "\xE6\x9E\x89", + "\xCD\xF8" => "\xE7\xBD\x91", + "\xCD\xF9" => "\xE5\xBE\x80", + "\xCD\xFA" => "\xE6\x97\xBA", + "\xCD\xFB" => "\xE6\x9C\x9B", + "\xCD\xFC" => "\xE5\xBF\x98", + "\xCD\xFD" => "\xE5\xA6\x84", + "\xCD\xFE" => "\xE5\xA8\x81", + "\xCE\xA1" => "\xE5\xB7\x8D", + "\xCE\xA2" => "\xE5\xBE\xAE", + "\xCE\xA3" => "\xE5\x8D\xB1", + "\xCE\xA4" => "\xE9\x9F\xA6", + "\xCE\xA5" => "\xE8\xBF\x9D", + "\xCE\xA6" => "\xE6\xA1\x85", + "\xCE\xA7" => "\xE5\x9B\xB4", + "\xCE\xA8" => "\xE5\x94\xAF", + "\xCE\xA9" => "\xE6\x83\x9F", + "\xCE\xAA" => "\xE4\xB8\xBA", + "\xCE\xAB" => "\xE6\xBD\x8D", + "\xCE\xAC" => "\xE7\xBB\xB4", + "\xCE\xAD" => "\xE8\x8B\x87", + "\xCE\xAE" => "\xE8\x90\x8E", + "\xCE\xAF" => "\xE5\xA7\x94", + "\xCE\xB0" => "\xE4\xBC\x9F", + "\xCE\xB1" => "\xE4\xBC\xAA", + "\xCE\xB2" => "\xE5\xB0\xBE", + "\xCE\xB3" => "\xE7\xBA\xAC", + "\xCE\xB4" => "\xE6\x9C\xAA", + "\xCE\xB5" => "\xE8\x94\x9A", + "\xCE\xB6" => "\xE5\x91\xB3", + "\xCE\xB7" => "\xE7\x95\x8F", + "\xCE\xB8" => "\xE8\x83\x83", + "\xCE\xB9" => "\xE5\x96\x82", + "\xCE\xBA" => "\xE9\xAD\x8F", + "\xCE\xBB" => "\xE4\xBD\x8D", + "\xCE\xBC" => "\xE6\xB8\xAD", + "\xCE\xBD" => "\xE8\xB0\x93", + "\xCE\xBE" => "\xE5\xB0\x89", + "\xCE\xBF" => "\xE6\x85\xB0", + "\xCE\xC0" => "\xE5\x8D\xAB", + "\xCE\xC1" => "\xE7\x98\x9F", + "\xCE\xC2" => "\xE6\xB8\xA9", + "\xCE\xC3" => "\xE8\x9A\x8A", + "\xCE\xC4" => "\xE6\x96\x87", + "\xCE\xC5" => "\xE9\x97\xBB", + "\xCE\xC6" => "\xE7\xBA\xB9", + "\xCE\xC7" => "\xE5\x90\xBB", + "\xCE\xC8" => "\xE7\xA8\xB3", + "\xCE\xC9" => "\xE7\xB4\x8A", + "\xCE\xCA" => "\xE9\x97\xAE", + "\xCE\xCB" => "\xE5\x97\xA1", + "\xCE\xCC" => "\xE7\xBF\x81", + "\xCE\xCD" => "\xE7\x93\xAE", + "\xCE\xCE" => "\xE6\x8C\x9D", + "\xCE\xCF" => "\xE8\x9C\x97", + "\xCE\xD0" => "\xE6\xB6\xA1", + "\xCE\xD1" => "\xE7\xAA\x9D", + "\xCE\xD2" => "\xE6\x88\x91", + "\xCE\xD3" => "\xE6\x96\xA1", + "\xCE\xD4" => "\xE5\x8D\xA7", + "\xCE\xD5" => "\xE6\x8F\xA1", + "\xCE\xD6" => "\xE6\xB2\x83", + "\xCE\xD7" => "\xE5\xB7\xAB", + "\xCE\xD8" => "\xE5\x91\x9C", + "\xCE\xD9" => "\xE9\x92\xA8", + "\xCE\xDA" => "\xE4\xB9\x8C", + "\xCE\xDB" => "\xE6\xB1\xA1", + "\xCE\xDC" => "\xE8\xAF\xAC", + "\xCE\xDD" => "\xE5\xB1\x8B", + "\xCE\xDE" => "\xE6\x97\xA0", + "\xCE\xDF" => "\xE8\x8A\x9C", + "\xCE\xE0" => "\xE6\xA2\xA7", + "\xCE\xE1" => "\xE5\x90\xBE", + "\xCE\xE2" => "\xE5\x90\xB4", + "\xCE\xE3" => "\xE6\xAF\x8B", + "\xCE\xE4" => "\xE6\xAD\xA6", + "\xCE\xE5" => "\xE4\xBA\x94", + "\xCE\xE6" => "\xE6\x8D\x82", + "\xCE\xE7" => "\xE5\x8D\x88", + "\xCE\xE8" => "\xE8\x88\x9E", + "\xCE\xE9" => "\xE4\xBC\x8D", + "\xCE\xEA" => "\xE4\xBE\xAE", + "\xCE\xEB" => "\xE5\x9D\x9E", + "\xCE\xEC" => "\xE6\x88\x8A", + "\xCE\xED" => "\xE9\x9B\xBE", + "\xCE\xEE" => "\xE6\x99\xA4", + "\xCE\xEF" => "\xE7\x89\xA9", + "\xCE\xF0" => "\xE5\x8B\xBF", + "\xCE\xF1" => "\xE5\x8A\xA1", + "\xCE\xF2" => "\xE6\x82\x9F", + "\xCE\xF3" => "\xE8\xAF\xAF", + "\xCE\xF4" => "\xE6\x98\x94", + "\xCE\xF5" => "\xE7\x86\x99", + "\xCE\xF6" => "\xE6\x9E\x90", + "\xCE\xF7" => "\xE8\xA5\xBF", + "\xCE\xF8" => "\xE7\xA1\x92", + "\xCE\xF9" => "\xE7\x9F\xBD", + "\xCE\xFA" => "\xE6\x99\xB0", + "\xCE\xFB" => "\xE5\x98\xBB", + "\xCE\xFC" => "\xE5\x90\xB8", + "\xCE\xFD" => "\xE9\x94\xA1", + "\xCE\xFE" => "\xE7\x89\xBA", + "\xCF\xA1" => "\xE7\xA8\x80", + "\xCF\xA2" => "\xE6\x81\xAF", + "\xCF\xA3" => "\xE5\xB8\x8C", + "\xCF\xA4" => "\xE6\x82\x89", + "\xCF\xA5" => "\xE8\x86\x9D", + "\xCF\xA6" => "\xE5\xA4\x95", + "\xCF\xA7" => "\xE6\x83\x9C", + "\xCF\xA8" => "\xE7\x86\x84", + "\xCF\xA9" => "\xE7\x83\xAF", + "\xCF\xAA" => "\xE6\xBA\xAA", + "\xCF\xAB" => "\xE6\xB1\x90", + "\xCF\xAC" => "\xE7\x8A\x80", + "\xCF\xAD" => "\xE6\xAA\x84", + "\xCF\xAE" => "\xE8\xA2\xAD", + "\xCF\xAF" => "\xE5\xB8\xAD", + "\xCF\xB0" => "\xE4\xB9\xA0", + "\xCF\xB1" => "\xE5\xAA\xB3", + "\xCF\xB2" => "\xE5\x96\x9C", + "\xCF\xB3" => "\xE9\x93\xA3", + "\xCF\xB4" => "\xE6\xB4\x97", + "\xCF\xB5" => "\xE7\xB3\xBB", + "\xCF\xB6" => "\xE9\x9A\x99", + "\xCF\xB7" => "\xE6\x88\x8F", + "\xCF\xB8" => "\xE7\xBB\x86", + "\xCF\xB9" => "\xE7\x9E\x8E", + "\xCF\xBA" => "\xE8\x99\xBE", + "\xCF\xBB" => "\xE5\x8C\xA3", + "\xCF\xBC" => "\xE9\x9C\x9E", + "\xCF\xBD" => "\xE8\xBE\x96", + "\xCF\xBE" => "\xE6\x9A\x87", + "\xCF\xBF" => "\xE5\xB3\xA1", + "\xCF\xC0" => "\xE4\xBE\xA0", + "\xCF\xC1" => "\xE7\x8B\xAD", + "\xCF\xC2" => "\xE4\xB8\x8B", + "\xCF\xC3" => "\xE5\x8E\xA6", + "\xCF\xC4" => "\xE5\xA4\x8F", + "\xCF\xC5" => "\xE5\x90\x93", + "\xCF\xC6" => "\xE6\x8E\x80", + "\xCF\xC7" => "\xE9\x94\xA8", + "\xCF\xC8" => "\xE5\x85\x88", + "\xCF\xC9" => "\xE4\xBB\x99", + "\xCF\xCA" => "\xE9\xB2\x9C", + "\xCF\xCB" => "\xE7\xBA\xA4", + "\xCF\xCC" => "\xE5\x92\xB8", + "\xCF\xCD" => "\xE8\xB4\xA4", + "\xCF\xCE" => "\xE8\xA1\x94", + "\xCF\xCF" => "\xE8\x88\xB7", + "\xCF\xD0" => "\xE9\x97\xB2", + "\xCF\xD1" => "\xE6\xB6\x8E", + "\xCF\xD2" => "\xE5\xBC\xA6", + "\xCF\xD3" => "\xE5\xAB\x8C", + "\xCF\xD4" => "\xE6\x98\xBE", + "\xCF\xD5" => "\xE9\x99\xA9", + "\xCF\xD6" => "\xE7\x8E\xB0", + "\xCF\xD7" => "\xE7\x8C\xAE", + "\xCF\xD8" => "\xE5\x8E\xBF", + "\xCF\xD9" => "\xE8\x85\xBA", + "\xCF\xDA" => "\xE9\xA6\x85", + "\xCF\xDB" => "\xE7\xBE\xA1", + "\xCF\xDC" => "\xE5\xAE\xAA", + "\xCF\xDD" => "\xE9\x99\xB7", + "\xCF\xDE" => "\xE9\x99\x90", + "\xCF\xDF" => "\xE7\xBA\xBF", + "\xCF\xE0" => "\xE7\x9B\xB8", + "\xCF\xE1" => "\xE5\x8E\xA2", + "\xCF\xE2" => "\xE9\x95\xB6", + "\xCF\xE3" => "\xE9\xA6\x99", + "\xCF\xE4" => "\xE7\xAE\xB1", + "\xCF\xE5" => "\xE8\xA5\x84", + "\xCF\xE6" => "\xE6\xB9\x98", + "\xCF\xE7" => "\xE4\xB9\xA1", + "\xCF\xE8" => "\xE7\xBF\x94", + "\xCF\xE9" => "\xE7\xA5\xA5", + "\xCF\xEA" => "\xE8\xAF\xA6", + "\xCF\xEB" => "\xE6\x83\xB3", + "\xCF\xEC" => "\xE5\x93\x8D", + "\xCF\xED" => "\xE4\xBA\xAB", + "\xCF\xEE" => "\xE9\xA1\xB9", + "\xCF\xEF" => "\xE5\xB7\xB7", + "\xCF\xF0" => "\xE6\xA9\xA1", + "\xCF\xF1" => "\xE5\x83\x8F", + "\xCF\xF2" => "\xE5\x90\x91", + "\xCF\xF3" => "\xE8\xB1\xA1", + "\xCF\xF4" => "\xE8\x90\xA7", + "\xCF\xF5" => "\xE7\xA1\x9D", + "\xCF\xF6" => "\xE9\x9C\x84", + "\xCF\xF7" => "\xE5\x89\x8A", + "\xCF\xF8" => "\xE5\x93\xAE", + "\xCF\xF9" => "\xE5\x9A\xA3", + "\xCF\xFA" => "\xE9\x94\x80", + "\xCF\xFB" => "\xE6\xB6\x88", + "\xCF\xFC" => "\xE5\xAE\xB5", + "\xCF\xFD" => "\xE6\xB7\x86", + "\xCF\xFE" => "\xE6\x99\x93", + "\xD0\xA1" => "\xE5\xB0\x8F", + "\xD0\xA2" => "\xE5\xAD\x9D", + "\xD0\xA3" => "\xE6\xA0\xA1", + "\xD0\xA4" => "\xE8\x82\x96", + "\xD0\xA5" => "\xE5\x95\xB8", + "\xD0\xA6" => "\xE7\xAC\x91", + "\xD0\xA7" => "\xE6\x95\x88", + "\xD0\xA8" => "\xE6\xA5\x94", + "\xD0\xA9" => "\xE4\xBA\x9B", + "\xD0\xAA" => "\xE6\xAD\x87", + "\xD0\xAB" => "\xE8\x9D\x8E", + "\xD0\xAC" => "\xE9\x9E\x8B", + "\xD0\xAD" => "\xE5\x8D\x8F", + "\xD0\xAE" => "\xE6\x8C\x9F", + "\xD0\xAF" => "\xE6\x90\xBA", + "\xD0\xB0" => "\xE9\x82\xAA", + "\xD0\xB1" => "\xE6\x96\x9C", + "\xD0\xB2" => "\xE8\x83\x81", + "\xD0\xB3" => "\xE8\xB0\x90", + "\xD0\xB4" => "\xE5\x86\x99", + "\xD0\xB5" => "\xE6\xA2\xB0", + "\xD0\xB6" => "\xE5\x8D\xB8", + "\xD0\xB7" => "\xE8\x9F\xB9", + "\xD0\xB8" => "\xE6\x87\x88", + "\xD0\xB9" => "\xE6\xB3\x84", + "\xD0\xBA" => "\xE6\xB3\xBB", + "\xD0\xBB" => "\xE8\xB0\xA2", + "\xD0\xBC" => "\xE5\xB1\x91", + "\xD0\xBD" => "\xE8\x96\xAA", + "\xD0\xBE" => "\xE8\x8A\xAF", + "\xD0\xBF" => "\xE9\x94\x8C", + "\xD0\xC0" => "\xE6\xAC\xA3", + "\xD0\xC1" => "\xE8\xBE\x9B", + "\xD0\xC2" => "\xE6\x96\xB0", + "\xD0\xC3" => "\xE5\xBF\xBB", + "\xD0\xC4" => "\xE5\xBF\x83", + "\xD0\xC5" => "\xE4\xBF\xA1", + "\xD0\xC6" => "\xE8\xA1\x85", + "\xD0\xC7" => "\xE6\x98\x9F", + "\xD0\xC8" => "\xE8\x85\xA5", + "\xD0\xC9" => "\xE7\x8C\xA9", + "\xD0\xCA" => "\xE6\x83\xBA", + "\xD0\xCB" => "\xE5\x85\xB4", + "\xD0\xCC" => "\xE5\x88\x91", + "\xD0\xCD" => "\xE5\x9E\x8B", + "\xD0\xCE" => "\xE5\xBD\xA2", + "\xD0\xCF" => "\xE9\x82\xA2", + "\xD0\xD0" => "\xE8\xA1\x8C", + "\xD0\xD1" => "\xE9\x86\x92", + "\xD0\xD2" => "\xE5\xB9\xB8", + "\xD0\xD3" => "\xE6\x9D\x8F", + "\xD0\xD4" => "\xE6\x80\xA7", + "\xD0\xD5" => "\xE5\xA7\x93", + "\xD0\xD6" => "\xE5\x85\x84", + "\xD0\xD7" => "\xE5\x87\xB6", + "\xD0\xD8" => "\xE8\x83\xB8", + "\xD0\xD9" => "\xE5\x8C\x88", + "\xD0\xDA" => "\xE6\xB1\xB9", + "\xD0\xDB" => "\xE9\x9B\x84", + "\xD0\xDC" => "\xE7\x86\x8A", + "\xD0\xDD" => "\xE4\xBC\x91", + "\xD0\xDE" => "\xE4\xBF\xAE", + "\xD0\xDF" => "\xE7\xBE\x9E", + "\xD0\xE0" => "\xE6\x9C\xBD", + "\xD0\xE1" => "\xE5\x97\x85", + "\xD0\xE2" => "\xE9\x94\x88", + "\xD0\xE3" => "\xE7\xA7\x80", + "\xD0\xE4" => "\xE8\xA2\x96", + "\xD0\xE5" => "\xE7\xBB\xA3", + "\xD0\xE6" => "\xE5\xA2\x9F", + "\xD0\xE7" => "\xE6\x88\x8C", + "\xD0\xE8" => "\xE9\x9C\x80", + "\xD0\xE9" => "\xE8\x99\x9A", + "\xD0\xEA" => "\xE5\x98\x98", + "\xD0\xEB" => "\xE9\xA1\xBB", + "\xD0\xEC" => "\xE5\xBE\x90", + "\xD0\xED" => "\xE8\xAE\xB8", + "\xD0\xEE" => "\xE8\x93\x84", + "\xD0\xEF" => "\xE9\x85\x97", + "\xD0\xF0" => "\xE5\x8F\x99", + "\xD0\xF1" => "\xE6\x97\xAD", + "\xD0\xF2" => "\xE5\xBA\x8F", + "\xD0\xF3" => "\xE7\x95\x9C", + "\xD0\xF4" => "\xE6\x81\xA4", + "\xD0\xF5" => "\xE7\xB5\xAE", + "\xD0\xF6" => "\xE5\xA9\xBF", + "\xD0\xF7" => "\xE7\xBB\xAA", + "\xD0\xF8" => "\xE7\xBB\xAD", + "\xD0\xF9" => "\xE8\xBD\xA9", + "\xD0\xFA" => "\xE5\x96\xA7", + "\xD0\xFB" => "\xE5\xAE\xA3", + "\xD0\xFC" => "\xE6\x82\xAC", + "\xD0\xFD" => "\xE6\x97\x8B", + "\xD0\xFE" => "\xE7\x8E\x84", + "\xD1\xA1" => "\xE9\x80\x89", + "\xD1\xA2" => "\xE7\x99\xA3", + "\xD1\xA3" => "\xE7\x9C\xA9", + "\xD1\xA4" => "\xE7\xBB\x9A", + "\xD1\xA5" => "\xE9\x9D\xB4", + "\xD1\xA6" => "\xE8\x96\x9B", + "\xD1\xA7" => "\xE5\xAD\xA6", + "\xD1\xA8" => "\xE7\xA9\xB4", + "\xD1\xA9" => "\xE9\x9B\xAA", + "\xD1\xAA" => "\xE8\xA1\x80", + "\xD1\xAB" => "\xE5\x8B\x8B", + "\xD1\xAC" => "\xE7\x86\x8F", + "\xD1\xAD" => "\xE5\xBE\xAA", + "\xD1\xAE" => "\xE6\x97\xAC", + "\xD1\xAF" => "\xE8\xAF\xA2", + "\xD1\xB0" => "\xE5\xAF\xBB", + "\xD1\xB1" => "\xE9\xA9\xAF", + "\xD1\xB2" => "\xE5\xB7\xA1", + "\xD1\xB3" => "\xE6\xAE\x89", + "\xD1\xB4" => "\xE6\xB1\x9B", + "\xD1\xB5" => "\xE8\xAE\xAD", + "\xD1\xB6" => "\xE8\xAE\xAF", + "\xD1\xB7" => "\xE9\x80\x8A", + "\xD1\xB8" => "\xE8\xBF\x85", + "\xD1\xB9" => "\xE5\x8E\x8B", + "\xD1\xBA" => "\xE6\x8A\xBC", + "\xD1\xBB" => "\xE9\xB8\xA6", + "\xD1\xBC" => "\xE9\xB8\xAD", + "\xD1\xBD" => "\xE5\x91\x80", + "\xD1\xBE" => "\xE4\xB8\xAB", + "\xD1\xBF" => "\xE8\x8A\xBD", + "\xD1\xC0" => "\xE7\x89\x99", + "\xD1\xC1" => "\xE8\x9A\x9C", + "\xD1\xC2" => "\xE5\xB4\x96", + "\xD1\xC3" => "\xE8\xA1\x99", + "\xD1\xC4" => "\xE6\xB6\xAF", + "\xD1\xC5" => "\xE9\x9B\x85", + "\xD1\xC6" => "\xE5\x93\x91", + "\xD1\xC7" => "\xE4\xBA\x9A", + "\xD1\xC8" => "\xE8\xAE\xB6", + "\xD1\xC9" => "\xE7\x84\x89", + "\xD1\xCA" => "\xE5\x92\xBD", + "\xD1\xCB" => "\xE9\x98\x89", + "\xD1\xCC" => "\xE7\x83\x9F", + "\xD1\xCD" => "\xE6\xB7\xB9", + "\xD1\xCE" => "\xE7\x9B\x90", + "\xD1\xCF" => "\xE4\xB8\xA5", + "\xD1\xD0" => "\xE7\xA0\x94", + "\xD1\xD1" => "\xE8\x9C\x92", + "\xD1\xD2" => "\xE5\xB2\xA9", + "\xD1\xD3" => "\xE5\xBB\xB6", + "\xD1\xD4" => "\xE8\xA8\x80", + "\xD1\xD5" => "\xE9\xA2\x9C", + "\xD1\xD6" => "\xE9\x98\x8E", + "\xD1\xD7" => "\xE7\x82\x8E", + "\xD1\xD8" => "\xE6\xB2\xBF", + "\xD1\xD9" => "\xE5\xA5\x84", + "\xD1\xDA" => "\xE6\x8E\xA9", + "\xD1\xDB" => "\xE7\x9C\xBC", + "\xD1\xDC" => "\xE8\xA1\x8D", + "\xD1\xDD" => "\xE6\xBC\x94", + "\xD1\xDE" => "\xE8\x89\xB3", + "\xD1\xDF" => "\xE5\xA0\xB0", + "\xD1\xE0" => "\xE7\x87\x95", + "\xD1\xE1" => "\xE5\x8E\x8C", + "\xD1\xE2" => "\xE7\xA0\x9A", + "\xD1\xE3" => "\xE9\x9B\x81", + "\xD1\xE4" => "\xE5\x94\x81", + "\xD1\xE5" => "\xE5\xBD\xA6", + "\xD1\xE6" => "\xE7\x84\xB0", + "\xD1\xE7" => "\xE5\xAE\xB4", + "\xD1\xE8" => "\xE8\xB0\x9A", + "\xD1\xE9" => "\xE9\xAA\x8C", + "\xD1\xEA" => "\xE6\xAE\x83", + "\xD1\xEB" => "\xE5\xA4\xAE", + "\xD1\xEC" => "\xE9\xB8\xAF", + "\xD1\xED" => "\xE7\xA7\xA7", + "\xD1\xEE" => "\xE6\x9D\xA8", + "\xD1\xEF" => "\xE6\x89\xAC", + "\xD1\xF0" => "\xE4\xBD\xAF", + "\xD1\xF1" => "\xE7\x96\xA1", + "\xD1\xF2" => "\xE7\xBE\x8A", + "\xD1\xF3" => "\xE6\xB4\x8B", + "\xD1\xF4" => "\xE9\x98\xB3", + "\xD1\xF5" => "\xE6\xB0\xA7", + "\xD1\xF6" => "\xE4\xBB\xB0", + "\xD1\xF7" => "\xE7\x97\x92", + "\xD1\xF8" => "\xE5\x85\xBB", + "\xD1\xF9" => "\xE6\xA0\xB7", + "\xD1\xFA" => "\xE6\xBC\xBE", + "\xD1\xFB" => "\xE9\x82\x80", + "\xD1\xFC" => "\xE8\x85\xB0", + "\xD1\xFD" => "\xE5\xA6\x96", + "\xD1\xFE" => "\xE7\x91\xB6", + "\xD2\xA1" => "\xE6\x91\x87", + "\xD2\xA2" => "\xE5\xB0\xA7", + "\xD2\xA3" => "\xE9\x81\xA5", + "\xD2\xA4" => "\xE7\xAA\x91", + "\xD2\xA5" => "\xE8\xB0\xA3", + "\xD2\xA6" => "\xE5\xA7\x9A", + "\xD2\xA7" => "\xE5\x92\xAC", + "\xD2\xA8" => "\xE8\x88\x80", + "\xD2\xA9" => "\xE8\x8D\xAF", + "\xD2\xAA" => "\xE8\xA6\x81", + "\xD2\xAB" => "\xE8\x80\x80", + "\xD2\xAC" => "\xE6\xA4\xB0", + "\xD2\xAD" => "\xE5\x99\x8E", + "\xD2\xAE" => "\xE8\x80\xB6", + "\xD2\xAF" => "\xE7\x88\xB7", + "\xD2\xB0" => "\xE9\x87\x8E", + "\xD2\xB1" => "\xE5\x86\xB6", + "\xD2\xB2" => "\xE4\xB9\x9F", + "\xD2\xB3" => "\xE9\xA1\xB5", + "\xD2\xB4" => "\xE6\x8E\x96", + "\xD2\xB5" => "\xE4\xB8\x9A", + "\xD2\xB6" => "\xE5\x8F\xB6", + "\xD2\xB7" => "\xE6\x9B\xB3", + "\xD2\xB8" => "\xE8\x85\x8B", + "\xD2\xB9" => "\xE5\xA4\x9C", + "\xD2\xBA" => "\xE6\xB6\xB2", + "\xD2\xBB" => "\xE4\xB8\x80", + "\xD2\xBC" => "\xE5\xA3\xB9", + "\xD2\xBD" => "\xE5\x8C\xBB", + "\xD2\xBE" => "\xE6\x8F\x96", + "\xD2\xBF" => "\xE9\x93\xB1", + "\xD2\xC0" => "\xE4\xBE\x9D", + "\xD2\xC1" => "\xE4\xBC\x8A", + "\xD2\xC2" => "\xE8\xA1\xA3", + "\xD2\xC3" => "\xE9\xA2\x90", + "\xD2\xC4" => "\xE5\xA4\xB7", + "\xD2\xC5" => "\xE9\x81\x97", + "\xD2\xC6" => "\xE7\xA7\xBB", + "\xD2\xC7" => "\xE4\xBB\xAA", + "\xD2\xC8" => "\xE8\x83\xB0", + "\xD2\xC9" => "\xE7\x96\x91", + "\xD2\xCA" => "\xE6\xB2\x82", + "\xD2\xCB" => "\xE5\xAE\x9C", + "\xD2\xCC" => "\xE5\xA7\xA8", + "\xD2\xCD" => "\xE5\xBD\x9D", + "\xD2\xCE" => "\xE6\xA4\x85", + "\xD2\xCF" => "\xE8\x9A\x81", + "\xD2\xD0" => "\xE5\x80\x9A", + "\xD2\xD1" => "\xE5\xB7\xB2", + "\xD2\xD2" => "\xE4\xB9\x99", + "\xD2\xD3" => "\xE7\x9F\xA3", + "\xD2\xD4" => "\xE4\xBB\xA5", + "\xD2\xD5" => "\xE8\x89\xBA", + "\xD2\xD6" => "\xE6\x8A\x91", + "\xD2\xD7" => "\xE6\x98\x93", + "\xD2\xD8" => "\xE9\x82\x91", + "\xD2\xD9" => "\xE5\xB1\xB9", + "\xD2\xDA" => "\xE4\xBA\xBF", + "\xD2\xDB" => "\xE5\xBD\xB9", + "\xD2\xDC" => "\xE8\x87\x86", + "\xD2\xDD" => "\xE9\x80\xB8", + "\xD2\xDE" => "\xE8\x82\x84", + "\xD2\xDF" => "\xE7\x96\xAB", + "\xD2\xE0" => "\xE4\xBA\xA6", + "\xD2\xE1" => "\xE8\xA3\x94", + "\xD2\xE2" => "\xE6\x84\x8F", + "\xD2\xE3" => "\xE6\xAF\x85", + "\xD2\xE4" => "\xE5\xBF\x86", + "\xD2\xE5" => "\xE4\xB9\x89", + "\xD2\xE6" => "\xE7\x9B\x8A", + "\xD2\xE7" => "\xE6\xBA\xA2", + "\xD2\xE8" => "\xE8\xAF\xA3", + "\xD2\xE9" => "\xE8\xAE\xAE", + "\xD2\xEA" => "\xE8\xB0\x8A", + "\xD2\xEB" => "\xE8\xAF\x91", + "\xD2\xEC" => "\xE5\xBC\x82", + "\xD2\xED" => "\xE7\xBF\xBC", + "\xD2\xEE" => "\xE7\xBF\x8C", + "\xD2\xEF" => "\xE7\xBB\x8E", + "\xD2\xF0" => "\xE8\x8C\xB5", + "\xD2\xF1" => "\xE8\x8D\xAB", + "\xD2\xF2" => "\xE5\x9B\xA0", + "\xD2\xF3" => "\xE6\xAE\xB7", + "\xD2\xF4" => "\xE9\x9F\xB3", + "\xD2\xF5" => "\xE9\x98\xB4", + "\xD2\xF6" => "\xE5\xA7\xBB", + "\xD2\xF7" => "\xE5\x90\x9F", + "\xD2\xF8" => "\xE9\x93\xB6", + "\xD2\xF9" => "\xE6\xB7\xAB", + "\xD2\xFA" => "\xE5\xAF\x85", + "\xD2\xFB" => "\xE9\xA5\xAE", + "\xD2\xFC" => "\xE5\xB0\xB9", + "\xD2\xFD" => "\xE5\xBC\x95", + "\xD2\xFE" => "\xE9\x9A\x90", + "\xD3\xA1" => "\xE5\x8D\xB0", + "\xD3\xA2" => "\xE8\x8B\xB1", + "\xD3\xA3" => "\xE6\xA8\xB1", + "\xD3\xA4" => "\xE5\xA9\xB4", + "\xD3\xA5" => "\xE9\xB9\xB0", + "\xD3\xA6" => "\xE5\xBA\x94", + "\xD3\xA7" => "\xE7\xBC\xA8", + "\xD3\xA8" => "\xE8\x8E\xB9", + "\xD3\xA9" => "\xE8\x90\xA4", + "\xD3\xAA" => "\xE8\x90\xA5", + "\xD3\xAB" => "\xE8\x8D\xA7", + "\xD3\xAC" => "\xE8\x9D\x87", + "\xD3\xAD" => "\xE8\xBF\x8E", + "\xD3\xAE" => "\xE8\xB5\xA2", + "\xD3\xAF" => "\xE7\x9B\x88", + "\xD3\xB0" => "\xE5\xBD\xB1", + "\xD3\xB1" => "\xE9\xA2\x96", + "\xD3\xB2" => "\xE7\xA1\xAC", + "\xD3\xB3" => "\xE6\x98\xA0", + "\xD3\xB4" => "\xE5\x93\x9F", + "\xD3\xB5" => "\xE6\x8B\xA5", + "\xD3\xB6" => "\xE4\xBD\xA3", + "\xD3\xB7" => "\xE8\x87\x83", + "\xD3\xB8" => "\xE7\x97\x88", + "\xD3\xB9" => "\xE5\xBA\xB8", + "\xD3\xBA" => "\xE9\x9B\x8D", + "\xD3\xBB" => "\xE8\xB8\x8A", + "\xD3\xBC" => "\xE8\x9B\xB9", + "\xD3\xBD" => "\xE5\x92\x8F", + "\xD3\xBE" => "\xE6\xB3\xB3", + "\xD3\xBF" => "\xE6\xB6\x8C", + "\xD3\xC0" => "\xE6\xB0\xB8", + "\xD3\xC1" => "\xE6\x81\xBF", + "\xD3\xC2" => "\xE5\x8B\x87", + "\xD3\xC3" => "\xE7\x94\xA8", + "\xD3\xC4" => "\xE5\xB9\xBD", + "\xD3\xC5" => "\xE4\xBC\x98", + "\xD3\xC6" => "\xE6\x82\xA0", + "\xD3\xC7" => "\xE5\xBF\xA7", + "\xD3\xC8" => "\xE5\xB0\xA4", + "\xD3\xC9" => "\xE7\x94\xB1", + "\xD3\xCA" => "\xE9\x82\xAE", + "\xD3\xCB" => "\xE9\x93\x80", + "\xD3\xCC" => "\xE7\x8A\xB9", + "\xD3\xCD" => "\xE6\xB2\xB9", + "\xD3\xCE" => "\xE6\xB8\xB8", + "\xD3\xCF" => "\xE9\x85\x89", + "\xD3\xD0" => "\xE6\x9C\x89", + "\xD3\xD1" => "\xE5\x8F\x8B", + "\xD3\xD2" => "\xE5\x8F\xB3", + "\xD3\xD3" => "\xE4\xBD\x91", + "\xD3\xD4" => "\xE9\x87\x89", + "\xD3\xD5" => "\xE8\xAF\xB1", + "\xD3\xD6" => "\xE5\x8F\x88", + "\xD3\xD7" => "\xE5\xB9\xBC", + "\xD3\xD8" => "\xE8\xBF\x82", + "\xD3\xD9" => "\xE6\xB7\xA4", + "\xD3\xDA" => "\xE4\xBA\x8E", + "\xD3\xDB" => "\xE7\x9B\x82", + "\xD3\xDC" => "\xE6\xA6\x86", + "\xD3\xDD" => "\xE8\x99\x9E", + "\xD3\xDE" => "\xE6\x84\x9A", + "\xD3\xDF" => "\xE8\x88\x86", + "\xD3\xE0" => "\xE4\xBD\x99", + "\xD3\xE1" => "\xE4\xBF\x9E", + "\xD3\xE2" => "\xE9\x80\xBE", + "\xD3\xE3" => "\xE9\xB1\xBC", + "\xD3\xE4" => "\xE6\x84\x89", + "\xD3\xE5" => "\xE6\xB8\x9D", + "\xD3\xE6" => "\xE6\xB8\x94", + "\xD3\xE7" => "\xE9\x9A\x85", + "\xD3\xE8" => "\xE4\xBA\x88", + "\xD3\xE9" => "\xE5\xA8\xB1", + "\xD3\xEA" => "\xE9\x9B\xA8", + "\xD3\xEB" => "\xE4\xB8\x8E", + "\xD3\xEC" => "\xE5\xB1\xBF", + "\xD3\xED" => "\xE7\xA6\xB9", + "\xD3\xEE" => "\xE5\xAE\x87", + "\xD3\xEF" => "\xE8\xAF\xAD", + "\xD3\xF0" => "\xE7\xBE\xBD", + "\xD3\xF1" => "\xE7\x8E\x89", + "\xD3\xF2" => "\xE5\x9F\x9F", + "\xD3\xF3" => "\xE8\x8A\x8B", + "\xD3\xF4" => "\xE9\x83\x81", + "\xD3\xF5" => "\xE5\x90\x81", + "\xD3\xF6" => "\xE9\x81\x87", + "\xD3\xF7" => "\xE5\x96\xBB", + "\xD3\xF8" => "\xE5\xB3\xAA", + "\xD3\xF9" => "\xE5\xBE\xA1", + "\xD3\xFA" => "\xE6\x84\x88", + "\xD3\xFB" => "\xE6\xAC\xB2", + "\xD3\xFC" => "\xE7\x8B\xB1", + "\xD3\xFD" => "\xE8\x82\xB2", + "\xD3\xFE" => "\xE8\xAA\x89", + "\xD4\xA1" => "\xE6\xB5\xB4", + "\xD4\xA2" => "\xE5\xAF\x93", + "\xD4\xA3" => "\xE8\xA3\x95", + "\xD4\xA4" => "\xE9\xA2\x84", + "\xD4\xA5" => "\xE8\xB1\xAB", + "\xD4\xA6" => "\xE9\xA9\xAD", + "\xD4\xA7" => "\xE9\xB8\xB3", + "\xD4\xA8" => "\xE6\xB8\x8A", + "\xD4\xA9" => "\xE5\x86\xA4", + "\xD4\xAA" => "\xE5\x85\x83", + "\xD4\xAB" => "\xE5\x9E\xA3", + "\xD4\xAC" => "\xE8\xA2\x81", + "\xD4\xAD" => "\xE5\x8E\x9F", + "\xD4\xAE" => "\xE6\x8F\xB4", + "\xD4\xAF" => "\xE8\xBE\x95", + "\xD4\xB0" => "\xE5\x9B\xAD", + "\xD4\xB1" => "\xE5\x91\x98", + "\xD4\xB2" => "\xE5\x9C\x86", + "\xD4\xB3" => "\xE7\x8C\xBF", + "\xD4\xB4" => "\xE6\xBA\x90", + "\xD4\xB5" => "\xE7\xBC\x98", + "\xD4\xB6" => "\xE8\xBF\x9C", + "\xD4\xB7" => "\xE8\x8B\x91", + "\xD4\xB8" => "\xE6\x84\xBF", + "\xD4\xB9" => "\xE6\x80\xA8", + "\xD4\xBA" => "\xE9\x99\xA2", + "\xD4\xBB" => "\xE6\x9B\xB0", + "\xD4\xBC" => "\xE7\xBA\xA6", + "\xD4\xBD" => "\xE8\xB6\x8A", + "\xD4\xBE" => "\xE8\xB7\x83", + "\xD4\xBF" => "\xE9\x92\xA5", + "\xD4\xC0" => "\xE5\xB2\xB3", + "\xD4\xC1" => "\xE7\xB2\xA4", + "\xD4\xC2" => "\xE6\x9C\x88", + "\xD4\xC3" => "\xE6\x82\xA6", + "\xD4\xC4" => "\xE9\x98\x85", + "\xD4\xC5" => "\xE8\x80\x98", + "\xD4\xC6" => "\xE4\xBA\x91", + "\xD4\xC7" => "\xE9\x83\xA7", + "\xD4\xC8" => "\xE5\x8C\x80", + "\xD4\xC9" => "\xE9\x99\xA8", + "\xD4\xCA" => "\xE5\x85\x81", + "\xD4\xCB" => "\xE8\xBF\x90", + "\xD4\xCC" => "\xE8\x95\xB4", + "\xD4\xCD" => "\xE9\x85\x9D", + "\xD4\xCE" => "\xE6\x99\x95", + "\xD4\xCF" => "\xE9\x9F\xB5", + "\xD4\xD0" => "\xE5\xAD\x95", + "\xD4\xD1" => "\xE5\x8C\x9D", + "\xD4\xD2" => "\xE7\xA0\xB8", + "\xD4\xD3" => "\xE6\x9D\x82", + "\xD4\xD4" => "\xE6\xA0\xBD", + "\xD4\xD5" => "\xE5\x93\x89", + "\xD4\xD6" => "\xE7\x81\xBE", + "\xD4\xD7" => "\xE5\xAE\xB0", + "\xD4\xD8" => "\xE8\xBD\xBD", + "\xD4\xD9" => "\xE5\x86\x8D", + "\xD4\xDA" => "\xE5\x9C\xA8", + "\xD4\xDB" => "\xE5\x92\xB1", + "\xD4\xDC" => "\xE6\x94\x92", + "\xD4\xDD" => "\xE6\x9A\x82", + "\xD4\xDE" => "\xE8\xB5\x9E", + "\xD4\xDF" => "\xE8\xB5\x83", + "\xD4\xE0" => "\xE8\x84\x8F", + "\xD4\xE1" => "\xE8\x91\xAC", + "\xD4\xE2" => "\xE9\x81\xAD", + "\xD4\xE3" => "\xE7\xB3\x9F", + "\xD4\xE4" => "\xE5\x87\xBF", + "\xD4\xE5" => "\xE8\x97\xBB", + "\xD4\xE6" => "\xE6\x9E\xA3", + "\xD4\xE7" => "\xE6\x97\xA9", + "\xD4\xE8" => "\xE6\xBE\xA1", + "\xD4\xE9" => "\xE8\x9A\xA4", + "\xD4\xEA" => "\xE8\xBA\x81", + "\xD4\xEB" => "\xE5\x99\xAA", + "\xD4\xEC" => "\xE9\x80\xA0", + "\xD4\xED" => "\xE7\x9A\x82", + "\xD4\xEE" => "\xE7\x81\xB6", + "\xD4\xEF" => "\xE7\x87\xA5", + "\xD4\xF0" => "\xE8\xB4\xA3", + "\xD4\xF1" => "\xE6\x8B\xA9", + "\xD4\xF2" => "\xE5\x88\x99", + "\xD4\xF3" => "\xE6\xB3\xBD", + "\xD4\xF4" => "\xE8\xB4\xBC", + "\xD4\xF5" => "\xE6\x80\x8E", + "\xD4\xF6" => "\xE5\xA2\x9E", + "\xD4\xF7" => "\xE6\x86\x8E", + "\xD4\xF8" => "\xE6\x9B\xBE", + "\xD4\xF9" => "\xE8\xB5\xA0", + "\xD4\xFA" => "\xE6\x89\x8E", + "\xD4\xFB" => "\xE5\x96\xB3", + "\xD4\xFC" => "\xE6\xB8\xA3", + "\xD4\xFD" => "\xE6\x9C\xAD", + "\xD4\xFE" => "\xE8\xBD\xA7", + "\xD5\xA1" => "\xE9\x93\xA1", + "\xD5\xA2" => "\xE9\x97\xB8", + "\xD5\xA3" => "\xE7\x9C\xA8", + "\xD5\xA4" => "\xE6\xA0\x85", + "\xD5\xA5" => "\xE6\xA6\xA8", + "\xD5\xA6" => "\xE5\x92\x8B", + "\xD5\xA7" => "\xE4\xB9\x8D", + "\xD5\xA8" => "\xE7\x82\xB8", + "\xD5\xA9" => "\xE8\xAF\x88", + "\xD5\xAA" => "\xE6\x91\x98", + "\xD5\xAB" => "\xE6\x96\x8B", + "\xD5\xAC" => "\xE5\xAE\x85", + "\xD5\xAD" => "\xE7\xAA\x84", + "\xD5\xAE" => "\xE5\x80\xBA", + "\xD5\xAF" => "\xE5\xAF\xA8", + "\xD5\xB0" => "\xE7\x9E\xBB", + "\xD5\xB1" => "\xE6\xAF\xA1", + "\xD5\xB2" => "\xE8\xA9\xB9", + "\xD5\xB3" => "\xE7\xB2\x98", + "\xD5\xB4" => "\xE6\xB2\xBE", + "\xD5\xB5" => "\xE7\x9B\x8F", + "\xD5\xB6" => "\xE6\x96\xA9", + "\xD5\xB7" => "\xE8\xBE\x97", + "\xD5\xB8" => "\xE5\xB4\xAD", + "\xD5\xB9" => "\xE5\xB1\x95", + "\xD5\xBA" => "\xE8\x98\xB8", + "\xD5\xBB" => "\xE6\xA0\x88", + "\xD5\xBC" => "\xE5\x8D\xA0", + "\xD5\xBD" => "\xE6\x88\x98", + "\xD5\xBE" => "\xE7\xAB\x99", + "\xD5\xBF" => "\xE6\xB9\x9B", + "\xD5\xC0" => "\xE7\xBB\xBD", + "\xD5\xC1" => "\xE6\xA8\x9F", + "\xD5\xC2" => "\xE7\xAB\xA0", + "\xD5\xC3" => "\xE5\xBD\xB0", + "\xD5\xC4" => "\xE6\xBC\xB3", + "\xD5\xC5" => "\xE5\xBC\xA0", + "\xD5\xC6" => "\xE6\x8E\x8C", + "\xD5\xC7" => "\xE6\xB6\xA8", + "\xD5\xC8" => "\xE6\x9D\x96", + "\xD5\xC9" => "\xE4\xB8\x88", + "\xD5\xCA" => "\xE5\xB8\x90", + "\xD5\xCB" => "\xE8\xB4\xA6", + "\xD5\xCC" => "\xE4\xBB\x97", + "\xD5\xCD" => "\xE8\x83\x80", + "\xD5\xCE" => "\xE7\x98\xB4", + "\xD5\xCF" => "\xE9\x9A\x9C", + "\xD5\xD0" => "\xE6\x8B\x9B", + "\xD5\xD1" => "\xE6\x98\xAD", + "\xD5\xD2" => "\xE6\x89\xBE", + "\xD5\xD3" => "\xE6\xB2\xBC", + "\xD5\xD4" => "\xE8\xB5\xB5", + "\xD5\xD5" => "\xE7\x85\xA7", + "\xD5\xD6" => "\xE7\xBD\xA9", + "\xD5\xD7" => "\xE5\x85\x86", + "\xD5\xD8" => "\xE8\x82\x87", + "\xD5\xD9" => "\xE5\x8F\xAC", + "\xD5\xDA" => "\xE9\x81\xAE", + "\xD5\xDB" => "\xE6\x8A\x98", + "\xD5\xDC" => "\xE5\x93\xB2", + "\xD5\xDD" => "\xE8\x9B\xB0", + "\xD5\xDE" => "\xE8\xBE\x99", + "\xD5\xDF" => "\xE8\x80\x85", + "\xD5\xE0" => "\xE9\x94\x97", + "\xD5\xE1" => "\xE8\x94\x97", + "\xD5\xE2" => "\xE8\xBF\x99", + "\xD5\xE3" => "\xE6\xB5\x99", + "\xD5\xE4" => "\xE7\x8F\x8D", + "\xD5\xE5" => "\xE6\x96\x9F", + "\xD5\xE6" => "\xE7\x9C\x9F", + "\xD5\xE7" => "\xE7\x94\x84", + "\xD5\xE8" => "\xE7\xA0\xA7", + "\xD5\xE9" => "\xE8\x87\xBB", + "\xD5\xEA" => "\xE8\xB4\x9E", + "\xD5\xEB" => "\xE9\x92\x88", + "\xD5\xEC" => "\xE4\xBE\xA6", + "\xD5\xED" => "\xE6\x9E\x95", + "\xD5\xEE" => "\xE7\x96\xB9", + "\xD5\xEF" => "\xE8\xAF\x8A", + "\xD5\xF0" => "\xE9\x9C\x87", + "\xD5\xF1" => "\xE6\x8C\xAF", + "\xD5\xF2" => "\xE9\x95\x87", + "\xD5\xF3" => "\xE9\x98\xB5", + "\xD5\xF4" => "\xE8\x92\xB8", + "\xD5\xF5" => "\xE6\x8C\xA3", + "\xD5\xF6" => "\xE7\x9D\x81", + "\xD5\xF7" => "\xE5\xBE\x81", + "\xD5\xF8" => "\xE7\x8B\xB0", + "\xD5\xF9" => "\xE4\xBA\x89", + "\xD5\xFA" => "\xE6\x80\x94", + "\xD5\xFB" => "\xE6\x95\xB4", + "\xD5\xFC" => "\xE6\x8B\xAF", + "\xD5\xFD" => "\xE6\xAD\xA3", + "\xD5\xFE" => "\xE6\x94\xBF", + "\xD6\xA1" => "\xE5\xB8\xA7", + "\xD6\xA2" => "\xE7\x97\x87", + "\xD6\xA3" => "\xE9\x83\x91", + "\xD6\xA4" => "\xE8\xAF\x81", + "\xD6\xA5" => "\xE8\x8A\x9D", + "\xD6\xA6" => "\xE6\x9E\x9D", + "\xD6\xA7" => "\xE6\x94\xAF", + "\xD6\xA8" => "\xE5\x90\xB1", + "\xD6\xA9" => "\xE8\x9C\x98", + "\xD6\xAA" => "\xE7\x9F\xA5", + "\xD6\xAB" => "\xE8\x82\xA2", + "\xD6\xAC" => "\xE8\x84\x82", + "\xD6\xAD" => "\xE6\xB1\x81", + "\xD6\xAE" => "\xE4\xB9\x8B", + "\xD6\xAF" => "\xE7\xBB\x87", + "\xD6\xB0" => "\xE8\x81\x8C", + "\xD6\xB1" => "\xE7\x9B\xB4", + "\xD6\xB2" => "\xE6\xA4\x8D", + "\xD6\xB3" => "\xE6\xAE\x96", + "\xD6\xB4" => "\xE6\x89\xA7", + "\xD6\xB5" => "\xE5\x80\xBC", + "\xD6\xB6" => "\xE4\xBE\x84", + "\xD6\xB7" => "\xE5\x9D\x80", + "\xD6\xB8" => "\xE6\x8C\x87", + "\xD6\xB9" => "\xE6\xAD\xA2", + "\xD6\xBA" => "\xE8\xB6\xBE", + "\xD6\xBB" => "\xE5\x8F\xAA", + "\xD6\xBC" => "\xE6\x97\xA8", + "\xD6\xBD" => "\xE7\xBA\xB8", + "\xD6\xBE" => "\xE5\xBF\x97", + "\xD6\xBF" => "\xE6\x8C\x9A", + "\xD6\xC0" => "\xE6\x8E\xB7", + "\xD6\xC1" => "\xE8\x87\xB3", + "\xD6\xC2" => "\xE8\x87\xB4", + "\xD6\xC3" => "\xE7\xBD\xAE", + "\xD6\xC4" => "\xE5\xB8\x9C", + "\xD6\xC5" => "\xE5\xB3\x99", + "\xD6\xC6" => "\xE5\x88\xB6", + "\xD6\xC7" => "\xE6\x99\xBA", + "\xD6\xC8" => "\xE7\xA7\xA9", + "\xD6\xC9" => "\xE7\xA8\x9A", + "\xD6\xCA" => "\xE8\xB4\xA8", + "\xD6\xCB" => "\xE7\x82\x99", + "\xD6\xCC" => "\xE7\x97\x94", + "\xD6\xCD" => "\xE6\xBB\x9E", + "\xD6\xCE" => "\xE6\xB2\xBB", + "\xD6\xCF" => "\xE7\xAA\x92", + "\xD6\xD0" => "\xE4\xB8\xAD", + "\xD6\xD1" => "\xE7\x9B\x85", + "\xD6\xD2" => "\xE5\xBF\xA0", + "\xD6\xD3" => "\xE9\x92\x9F", + "\xD6\xD4" => "\xE8\xA1\xB7", + "\xD6\xD5" => "\xE7\xBB\x88", + "\xD6\xD6" => "\xE7\xA7\x8D", + "\xD6\xD7" => "\xE8\x82\xBF", + "\xD6\xD8" => "\xE9\x87\x8D", + "\xD6\xD9" => "\xE4\xBB\xB2", + "\xD6\xDA" => "\xE4\xBC\x97", + "\xD6\xDB" => "\xE8\x88\x9F", + "\xD6\xDC" => "\xE5\x91\xA8", + "\xD6\xDD" => "\xE5\xB7\x9E", + "\xD6\xDE" => "\xE6\xB4\xB2", + "\xD6\xDF" => "\xE8\xAF\x8C", + "\xD6\xE0" => "\xE7\xB2\xA5", + "\xD6\xE1" => "\xE8\xBD\xB4", + "\xD6\xE2" => "\xE8\x82\x98", + "\xD6\xE3" => "\xE5\xB8\x9A", + "\xD6\xE4" => "\xE5\x92\x92", + "\xD6\xE5" => "\xE7\x9A\xB1", + "\xD6\xE6" => "\xE5\xAE\x99", + "\xD6\xE7" => "\xE6\x98\xBC", + "\xD6\xE8" => "\xE9\xAA\xA4", + "\xD6\xE9" => "\xE7\x8F\xA0", + "\xD6\xEA" => "\xE6\xA0\xAA", + "\xD6\xEB" => "\xE8\x9B\x9B", + "\xD6\xEC" => "\xE6\x9C\xB1", + "\xD6\xED" => "\xE7\x8C\xAA", + "\xD6\xEE" => "\xE8\xAF\xB8", + "\xD6\xEF" => "\xE8\xAF\x9B", + "\xD6\xF0" => "\xE9\x80\x90", + "\xD6\xF1" => "\xE7\xAB\xB9", + "\xD6\xF2" => "\xE7\x83\x9B", + "\xD6\xF3" => "\xE7\x85\xAE", + "\xD6\xF4" => "\xE6\x8B\x84", + "\xD6\xF5" => "\xE7\x9E\xA9", + "\xD6\xF6" => "\xE5\x98\xB1", + "\xD6\xF7" => "\xE4\xB8\xBB", + "\xD6\xF8" => "\xE8\x91\x97", + "\xD6\xF9" => "\xE6\x9F\xB1", + "\xD6\xFA" => "\xE5\x8A\xA9", + "\xD6\xFB" => "\xE8\x9B\x80", + "\xD6\xFC" => "\xE8\xB4\xAE", + "\xD6\xFD" => "\xE9\x93\xB8", + "\xD6\xFE" => "\xE7\xAD\x91", + "\xD7\xA1" => "\xE4\xBD\x8F", + "\xD7\xA2" => "\xE6\xB3\xA8", + "\xD7\xA3" => "\xE7\xA5\x9D", + "\xD7\xA4" => "\xE9\xA9\xBB", + "\xD7\xA5" => "\xE6\x8A\x93", + "\xD7\xA6" => "\xE7\x88\xAA", + "\xD7\xA7" => "\xE6\x8B\xBD", + "\xD7\xA8" => "\xE4\xB8\x93", + "\xD7\xA9" => "\xE7\xA0\x96", + "\xD7\xAA" => "\xE8\xBD\xAC", + "\xD7\xAB" => "\xE6\x92\xB0", + "\xD7\xAC" => "\xE8\xB5\x9A", + "\xD7\xAD" => "\xE7\xAF\x86", + "\xD7\xAE" => "\xE6\xA1\xA9", + "\xD7\xAF" => "\xE5\xBA\x84", + "\xD7\xB0" => "\xE8\xA3\x85", + "\xD7\xB1" => "\xE5\xA6\x86", + "\xD7\xB2" => "\xE6\x92\x9E", + "\xD7\xB3" => "\xE5\xA3\xAE", + "\xD7\xB4" => "\xE7\x8A\xB6", + "\xD7\xB5" => "\xE6\xA4\x8E", + "\xD7\xB6" => "\xE9\x94\xA5", + "\xD7\xB7" => "\xE8\xBF\xBD", + "\xD7\xB8" => "\xE8\xB5\x98", + "\xD7\xB9" => "\xE5\x9D\xA0", + "\xD7\xBA" => "\xE7\xBC\x80", + "\xD7\xBB" => "\xE8\xB0\x86", + "\xD7\xBC" => "\xE5\x87\x86", + "\xD7\xBD" => "\xE6\x8D\x89", + "\xD7\xBE" => "\xE6\x8B\x99", + "\xD7\xBF" => "\xE5\x8D\x93", + "\xD7\xC0" => "\xE6\xA1\x8C", + "\xD7\xC1" => "\xE7\x90\xA2", + "\xD7\xC2" => "\xE8\x8C\x81", + "\xD7\xC3" => "\xE9\x85\x8C", + "\xD7\xC4" => "\xE5\x95\x84", + "\xD7\xC5" => "\xE7\x9D\x80", + "\xD7\xC6" => "\xE7\x81\xBC", + "\xD7\xC7" => "\xE6\xB5\x8A", + "\xD7\xC8" => "\xE5\x85\xB9", + "\xD7\xC9" => "\xE5\x92\xA8", + "\xD7\xCA" => "\xE8\xB5\x84", + "\xD7\xCB" => "\xE5\xA7\xBF", + "\xD7\xCC" => "\xE6\xBB\x8B", + "\xD7\xCD" => "\xE6\xB7\x84", + "\xD7\xCE" => "\xE5\xAD\x9C", + "\xD7\xCF" => "\xE7\xB4\xAB", + "\xD7\xD0" => "\xE4\xBB\x94", + "\xD7\xD1" => "\xE7\xB1\xBD", + "\xD7\xD2" => "\xE6\xBB\x93", + "\xD7\xD3" => "\xE5\xAD\x90", + "\xD7\xD4" => "\xE8\x87\xAA", + "\xD7\xD5" => "\xE6\xB8\x8D", + "\xD7\xD6" => "\xE5\xAD\x97", + "\xD7\xD7" => "\xE9\xAC\x83", + "\xD7\xD8" => "\xE6\xA3\x95", + "\xD7\xD9" => "\xE8\xB8\xAA", + "\xD7\xDA" => "\xE5\xAE\x97", + "\xD7\xDB" => "\xE7\xBB\xBC", + "\xD7\xDC" => "\xE6\x80\xBB", + "\xD7\xDD" => "\xE7\xBA\xB5", + "\xD7\xDE" => "\xE9\x82\xB9", + "\xD7\xDF" => "\xE8\xB5\xB0", + "\xD7\xE0" => "\xE5\xA5\x8F", + "\xD7\xE1" => "\xE6\x8F\x8D", + "\xD7\xE2" => "\xE7\xA7\x9F", + "\xD7\xE3" => "\xE8\xB6\xB3", + "\xD7\xE4" => "\xE5\x8D\x92", + "\xD7\xE5" => "\xE6\x97\x8F", + "\xD7\xE6" => "\xE7\xA5\x96", + "\xD7\xE7" => "\xE8\xAF\x85", + "\xD7\xE8" => "\xE9\x98\xBB", + "\xD7\xE9" => "\xE7\xBB\x84", + "\xD7\xEA" => "\xE9\x92\xBB", + "\xD7\xEB" => "\xE7\xBA\x82", + "\xD7\xEC" => "\xE5\x98\xB4", + "\xD7\xED" => "\xE9\x86\x89", + "\xD7\xEE" => "\xE6\x9C\x80", + "\xD7\xEF" => "\xE7\xBD\xAA", + "\xD7\xF0" => "\xE5\xB0\x8A", + "\xD7\xF1" => "\xE9\x81\xB5", + "\xD7\xF2" => "\xE6\x98\xA8", + "\xD7\xF3" => "\xE5\xB7\xA6", + "\xD7\xF4" => "\xE4\xBD\x90", + "\xD7\xF5" => "\xE6\x9F\x9E", + "\xD7\xF6" => "\xE5\x81\x9A", + "\xD7\xF7" => "\xE4\xBD\x9C", + "\xD7\xF8" => "\xE5\x9D\x90", + "\xD7\xF9" => "\xE5\xBA\xA7", + "\xD8\xA1" => "\xE4\xBA\x8D", + "\xD8\xA2" => "\xE4\xB8\x8C", + "\xD8\xA3" => "\xE5\x85\x80", + "\xD8\xA4" => "\xE4\xB8\x90", + "\xD8\xA5" => "\xE5\xBB\xBF", + "\xD8\xA6" => "\xE5\x8D\x85", + "\xD8\xA7" => "\xE4\xB8\x95", + "\xD8\xA8" => "\xE4\xBA\x98", + "\xD8\xA9" => "\xE4\xB8\x9E", + "\xD8\xAA" => "\xE9\xAC\xB2", + "\xD8\xAB" => "\xE5\xAD\xAC", + "\xD8\xAC" => "\xE5\x99\xA9", + "\xD8\xAD" => "\xE4\xB8\xA8", + "\xD8\xAE" => "\xE7\xA6\xBA", + "\xD8\xAF" => "\xE4\xB8\xBF", + "\xD8\xB0" => "\xE5\x8C\x95", + "\xD8\xB1" => "\xE4\xB9\x87", + "\xD8\xB2" => "\xE5\xA4\xAD", + "\xD8\xB3" => "\xE7\x88\xBB", + "\xD8\xB4" => "\xE5\x8D\xAE", + "\xD8\xB5" => "\xE6\xB0\x90", + "\xD8\xB6" => "\xE5\x9B\x9F", + "\xD8\xB7" => "\xE8\x83\xA4", + "\xD8\xB8" => "\xE9\xA6\x97", + "\xD8\xB9" => "\xE6\xAF\x93", + "\xD8\xBA" => "\xE7\x9D\xBE", + "\xD8\xBB" => "\xE9\xBC\x97", + "\xD8\xBC" => "\xE4\xB8\xB6", + "\xD8\xBD" => "\xE4\xBA\x9F", + "\xD8\xBE" => "\xE9\xBC\x90", + "\xD8\xBF" => "\xE4\xB9\x9C", + "\xD8\xC0" => "\xE4\xB9\xA9", + "\xD8\xC1" => "\xE4\xBA\x93", + "\xD8\xC2" => "\xE8\x8A\x88", + "\xD8\xC3" => "\xE5\xAD\x9B", + "\xD8\xC4" => "\xE5\x95\xAC", + "\xD8\xC5" => "\xE5\x98\x8F", + "\xD8\xC6" => "\xE4\xBB\x84", + "\xD8\xC7" => "\xE5\x8E\x8D", + "\xD8\xC8" => "\xE5\x8E\x9D", + "\xD8\xC9" => "\xE5\x8E\xA3", + "\xD8\xCA" => "\xE5\x8E\xA5", + "\xD8\xCB" => "\xE5\x8E\xAE", + "\xD8\xCC" => "\xE9\x9D\xA5", + "\xD8\xCD" => "\xE8\xB5\x9D", + "\xD8\xCE" => "\xE5\x8C\x9A", + "\xD8\xCF" => "\xE5\x8F\xB5", + "\xD8\xD0" => "\xE5\x8C\xA6", + "\xD8\xD1" => "\xE5\x8C\xAE", + "\xD8\xD2" => "\xE5\x8C\xBE", + "\xD8\xD3" => "\xE8\xB5\x9C", + "\xD8\xD4" => "\xE5\x8D\xA6", + "\xD8\xD5" => "\xE5\x8D\xA3", + "\xD8\xD6" => "\xE5\x88\x82", + "\xD8\xD7" => "\xE5\x88\x88", + "\xD8\xD8" => "\xE5\x88\x8E", + "\xD8\xD9" => "\xE5\x88\xAD", + "\xD8\xDA" => "\xE5\x88\xB3", + "\xD8\xDB" => "\xE5\x88\xBF", + "\xD8\xDC" => "\xE5\x89\x80", + "\xD8\xDD" => "\xE5\x89\x8C", + "\xD8\xDE" => "\xE5\x89\x9E", + "\xD8\xDF" => "\xE5\x89\xA1", + "\xD8\xE0" => "\xE5\x89\x9C", + "\xD8\xE1" => "\xE8\x92\xAF", + "\xD8\xE2" => "\xE5\x89\xBD", + "\xD8\xE3" => "\xE5\x8A\x82", + "\xD8\xE4" => "\xE5\x8A\x81", + "\xD8\xE5" => "\xE5\x8A\x90", + "\xD8\xE6" => "\xE5\x8A\x93", + "\xD8\xE7" => "\xE5\x86\x82", + "\xD8\xE8" => "\xE7\xBD\x94", + "\xD8\xE9" => "\xE4\xBA\xBB", + "\xD8\xEA" => "\xE4\xBB\x83", + "\xD8\xEB" => "\xE4\xBB\x89", + "\xD8\xEC" => "\xE4\xBB\x82", + "\xD8\xED" => "\xE4\xBB\xA8", + "\xD8\xEE" => "\xE4\xBB\xA1", + "\xD8\xEF" => "\xE4\xBB\xAB", + "\xD8\xF0" => "\xE4\xBB\x9E", + "\xD8\xF1" => "\xE4\xBC\x9B", + "\xD8\xF2" => "\xE4\xBB\xB3", + "\xD8\xF3" => "\xE4\xBC\xA2", + "\xD8\xF4" => "\xE4\xBD\xA4", + "\xD8\xF5" => "\xE4\xBB\xB5", + "\xD8\xF6" => "\xE4\xBC\xA5", + "\xD8\xF7" => "\xE4\xBC\xA7", + "\xD8\xF8" => "\xE4\xBC\x89", + "\xD8\xF9" => "\xE4\xBC\xAB", + "\xD8\xFA" => "\xE4\xBD\x9E", + "\xD8\xFB" => "\xE4\xBD\xA7", + "\xD8\xFC" => "\xE6\x94\xB8", + "\xD8\xFD" => "\xE4\xBD\x9A", + "\xD8\xFE" => "\xE4\xBD\x9D", + "\xD9\xA1" => "\xE4\xBD\x9F", + "\xD9\xA2" => "\xE4\xBD\x97", + "\xD9\xA3" => "\xE4\xBC\xB2", + "\xD9\xA4" => "\xE4\xBC\xBD", + "\xD9\xA5" => "\xE4\xBD\xB6", + "\xD9\xA6" => "\xE4\xBD\xB4", + "\xD9\xA7" => "\xE4\xBE\x91", + "\xD9\xA8" => "\xE4\xBE\x89", + "\xD9\xA9" => "\xE4\xBE\x83", + "\xD9\xAA" => "\xE4\xBE\x8F", + "\xD9\xAB" => "\xE4\xBD\xBE", + "\xD9\xAC" => "\xE4\xBD\xBB", + "\xD9\xAD" => "\xE4\xBE\xAA", + "\xD9\xAE" => "\xE4\xBD\xBC", + "\xD9\xAF" => "\xE4\xBE\xAC", + "\xD9\xB0" => "\xE4\xBE\x94", + "\xD9\xB1" => "\xE4\xBF\xA6", + "\xD9\xB2" => "\xE4\xBF\xA8", + "\xD9\xB3" => "\xE4\xBF\xAA", + "\xD9\xB4" => "\xE4\xBF\x85", + "\xD9\xB5" => "\xE4\xBF\x9A", + "\xD9\xB6" => "\xE4\xBF\xA3", + "\xD9\xB7" => "\xE4\xBF\x9C", + "\xD9\xB8" => "\xE4\xBF\x91", + "\xD9\xB9" => "\xE4\xBF\x9F", + "\xD9\xBA" => "\xE4\xBF\xB8", + "\xD9\xBB" => "\xE5\x80\xA9", + "\xD9\xBC" => "\xE5\x81\x8C", + "\xD9\xBD" => "\xE4\xBF\xB3", + "\xD9\xBE" => "\xE5\x80\xAC", + "\xD9\xBF" => "\xE5\x80\x8F", + "\xD9\xC0" => "\xE5\x80\xAE", + "\xD9\xC1" => "\xE5\x80\xAD", + "\xD9\xC2" => "\xE4\xBF\xBE", + "\xD9\xC3" => "\xE5\x80\x9C", + "\xD9\xC4" => "\xE5\x80\x8C", + "\xD9\xC5" => "\xE5\x80\xA5", + "\xD9\xC6" => "\xE5\x80\xA8", + "\xD9\xC7" => "\xE5\x81\xBE", + "\xD9\xC8" => "\xE5\x81\x83", + "\xD9\xC9" => "\xE5\x81\x95", + "\xD9\xCA" => "\xE5\x81\x88", + "\xD9\xCB" => "\xE5\x81\x8E", + "\xD9\xCC" => "\xE5\x81\xAC", + "\xD9\xCD" => "\xE5\x81\xBB", + "\xD9\xCE" => "\xE5\x82\xA5", + "\xD9\xCF" => "\xE5\x82\xA7", + "\xD9\xD0" => "\xE5\x82\xA9", + "\xD9\xD1" => "\xE5\x82\xBA", + "\xD9\xD2" => "\xE5\x83\x96", + "\xD9\xD3" => "\xE5\x84\x86", + "\xD9\xD4" => "\xE5\x83\xAD", + "\xD9\xD5" => "\xE5\x83\xAC", + "\xD9\xD6" => "\xE5\x83\xA6", + "\xD9\xD7" => "\xE5\x83\xAE", + "\xD9\xD8" => "\xE5\x84\x87", + "\xD9\xD9" => "\xE5\x84\x8B", + "\xD9\xDA" => "\xE4\xBB\x9D", + "\xD9\xDB" => "\xE6\xB0\xBD", + "\xD9\xDC" => "\xE4\xBD\x98", + "\xD9\xDD" => "\xE4\xBD\xA5", + "\xD9\xDE" => "\xE4\xBF\x8E", + "\xD9\xDF" => "\xE9\xBE\xA0", + "\xD9\xE0" => "\xE6\xB1\x86", + "\xD9\xE1" => "\xE7\xB1\xB4", + "\xD9\xE2" => "\xE5\x85\xAE", + "\xD9\xE3" => "\xE5\xB7\xBD", + "\xD9\xE4" => "\xE9\xBB\x89", + "\xD9\xE5" => "\xE9\xA6\x98", + "\xD9\xE6" => "\xE5\x86\x81", + "\xD9\xE7" => "\xE5\xA4\x94", + "\xD9\xE8" => "\xE5\x8B\xB9", + "\xD9\xE9" => "\xE5\x8C\x8D", + "\xD9\xEA" => "\xE8\xA8\x87", + "\xD9\xEB" => "\xE5\x8C\x90", + "\xD9\xEC" => "\xE5\x87\xAB", + "\xD9\xED" => "\xE5\xA4\x99", + "\xD9\xEE" => "\xE5\x85\x95", + "\xD9\xEF" => "\xE4\xBA\xA0", + "\xD9\xF0" => "\xE5\x85\x96", + "\xD9\xF1" => "\xE4\xBA\xB3", + "\xD9\xF2" => "\xE8\xA1\xAE", + "\xD9\xF3" => "\xE8\xA2\xA4", + "\xD9\xF4" => "\xE4\xBA\xB5", + "\xD9\xF5" => "\xE8\x84\x94", + "\xD9\xF6" => "\xE8\xA3\x92", + "\xD9\xF7" => "\xE7\xA6\x80", + "\xD9\xF8" => "\xE5\xAC\xB4", + "\xD9\xF9" => "\xE8\xA0\x83", + "\xD9\xFA" => "\xE7\xBE\xB8", + "\xD9\xFB" => "\xE5\x86\xAB", + "\xD9\xFC" => "\xE5\x86\xB1", + "\xD9\xFD" => "\xE5\x86\xBD", + "\xD9\xFE" => "\xE5\x86\xBC", + "\xDA\xA1" => "\xE5\x87\x87", + "\xDA\xA2" => "\xE5\x86\x96", + "\xDA\xA3" => "\xE5\x86\xA2", + "\xDA\xA4" => "\xE5\x86\xA5", + "\xDA\xA5" => "\xE8\xAE\xA0", + "\xDA\xA6" => "\xE8\xAE\xA6", + "\xDA\xA7" => "\xE8\xAE\xA7", + "\xDA\xA8" => "\xE8\xAE\xAA", + "\xDA\xA9" => "\xE8\xAE\xB4", + "\xDA\xAA" => "\xE8\xAE\xB5", + "\xDA\xAB" => "\xE8\xAE\xB7", + "\xDA\xAC" => "\xE8\xAF\x82", + "\xDA\xAD" => "\xE8\xAF\x83", + "\xDA\xAE" => "\xE8\xAF\x8B", + "\xDA\xAF" => "\xE8\xAF\x8F", + "\xDA\xB0" => "\xE8\xAF\x8E", + "\xDA\xB1" => "\xE8\xAF\x92", + "\xDA\xB2" => "\xE8\xAF\x93", + "\xDA\xB3" => "\xE8\xAF\x94", + "\xDA\xB4" => "\xE8\xAF\x96", + "\xDA\xB5" => "\xE8\xAF\x98", + "\xDA\xB6" => "\xE8\xAF\x99", + "\xDA\xB7" => "\xE8\xAF\x9C", + "\xDA\xB8" => "\xE8\xAF\x9F", + "\xDA\xB9" => "\xE8\xAF\xA0", + "\xDA\xBA" => "\xE8\xAF\xA4", + "\xDA\xBB" => "\xE8\xAF\xA8", + "\xDA\xBC" => "\xE8\xAF\xA9", + "\xDA\xBD" => "\xE8\xAF\xAE", + "\xDA\xBE" => "\xE8\xAF\xB0", + "\xDA\xBF" => "\xE8\xAF\xB3", + "\xDA\xC0" => "\xE8\xAF\xB6", + "\xDA\xC1" => "\xE8\xAF\xB9", + "\xDA\xC2" => "\xE8\xAF\xBC", + "\xDA\xC3" => "\xE8\xAF\xBF", + "\xDA\xC4" => "\xE8\xB0\x80", + "\xDA\xC5" => "\xE8\xB0\x82", + "\xDA\xC6" => "\xE8\xB0\x84", + "\xDA\xC7" => "\xE8\xB0\x87", + "\xDA\xC8" => "\xE8\xB0\x8C", + "\xDA\xC9" => "\xE8\xB0\x8F", + "\xDA\xCA" => "\xE8\xB0\x91", + "\xDA\xCB" => "\xE8\xB0\x92", + "\xDA\xCC" => "\xE8\xB0\x94", + "\xDA\xCD" => "\xE8\xB0\x95", + "\xDA\xCE" => "\xE8\xB0\x96", + "\xDA\xCF" => "\xE8\xB0\x99", + "\xDA\xD0" => "\xE8\xB0\x9B", + "\xDA\xD1" => "\xE8\xB0\x98", + "\xDA\xD2" => "\xE8\xB0\x9D", + "\xDA\xD3" => "\xE8\xB0\x9F", + "\xDA\xD4" => "\xE8\xB0\xA0", + "\xDA\xD5" => "\xE8\xB0\xA1", + "\xDA\xD6" => "\xE8\xB0\xA5", + "\xDA\xD7" => "\xE8\xB0\xA7", + "\xDA\xD8" => "\xE8\xB0\xAA", + "\xDA\xD9" => "\xE8\xB0\xAB", + "\xDA\xDA" => "\xE8\xB0\xAE", + "\xDA\xDB" => "\xE8\xB0\xAF", + "\xDA\xDC" => "\xE8\xB0\xB2", + "\xDA\xDD" => "\xE8\xB0\xB3", + "\xDA\xDE" => "\xE8\xB0\xB5", + "\xDA\xDF" => "\xE8\xB0\xB6", + "\xDA\xE0" => "\xE5\x8D\xA9", + "\xDA\xE1" => "\xE5\x8D\xBA", + "\xDA\xE2" => "\xE9\x98\x9D", + "\xDA\xE3" => "\xE9\x98\xA2", + "\xDA\xE4" => "\xE9\x98\xA1", + "\xDA\xE5" => "\xE9\x98\xB1", + "\xDA\xE6" => "\xE9\x98\xAA", + "\xDA\xE7" => "\xE9\x98\xBD", + "\xDA\xE8" => "\xE9\x98\xBC", + "\xDA\xE9" => "\xE9\x99\x82", + "\xDA\xEA" => "\xE9\x99\x89", + "\xDA\xEB" => "\xE9\x99\x94", + "\xDA\xEC" => "\xE9\x99\x9F", + "\xDA\xED" => "\xE9\x99\xA7", + "\xDA\xEE" => "\xE9\x99\xAC", + "\xDA\xEF" => "\xE9\x99\xB2", + "\xDA\xF0" => "\xE9\x99\xB4", + "\xDA\xF1" => "\xE9\x9A\x88", + "\xDA\xF2" => "\xE9\x9A\x8D", + "\xDA\xF3" => "\xE9\x9A\x97", + "\xDA\xF4" => "\xE9\x9A\xB0", + "\xDA\xF5" => "\xE9\x82\x97", + "\xDA\xF6" => "\xE9\x82\x9B", + "\xDA\xF7" => "\xE9\x82\x9D", + "\xDA\xF8" => "\xE9\x82\x99", + "\xDA\xF9" => "\xE9\x82\xAC", + "\xDA\xFA" => "\xE9\x82\xA1", + "\xDA\xFB" => "\xE9\x82\xB4", + "\xDA\xFC" => "\xE9\x82\xB3", + "\xDA\xFD" => "\xE9\x82\xB6", + "\xDA\xFE" => "\xE9\x82\xBA", + "\xDB\xA1" => "\xE9\x82\xB8", + "\xDB\xA2" => "\xE9\x82\xB0", + "\xDB\xA3" => "\xE9\x83\x8F", + "\xDB\xA4" => "\xE9\x83\x85", + "\xDB\xA5" => "\xE9\x82\xBE", + "\xDB\xA6" => "\xE9\x83\x90", + "\xDB\xA7" => "\xE9\x83\x84", + "\xDB\xA8" => "\xE9\x83\x87", + "\xDB\xA9" => "\xE9\x83\x93", + "\xDB\xAA" => "\xE9\x83\xA6", + "\xDB\xAB" => "\xE9\x83\xA2", + "\xDB\xAC" => "\xE9\x83\x9C", + "\xDB\xAD" => "\xE9\x83\x97", + "\xDB\xAE" => "\xE9\x83\x9B", + "\xDB\xAF" => "\xE9\x83\xAB", + "\xDB\xB0" => "\xE9\x83\xAF", + "\xDB\xB1" => "\xE9\x83\xBE", + "\xDB\xB2" => "\xE9\x84\x84", + "\xDB\xB3" => "\xE9\x84\xA2", + "\xDB\xB4" => "\xE9\x84\x9E", + "\xDB\xB5" => "\xE9\x84\xA3", + "\xDB\xB6" => "\xE9\x84\xB1", + "\xDB\xB7" => "\xE9\x84\xAF", + "\xDB\xB8" => "\xE9\x84\xB9", + "\xDB\xB9" => "\xE9\x85\x83", + "\xDB\xBA" => "\xE9\x85\x86", + "\xDB\xBB" => "\xE5\x88\x8D", + "\xDB\xBC" => "\xE5\xA5\x82", + "\xDB\xBD" => "\xE5\x8A\xA2", + "\xDB\xBE" => "\xE5\x8A\xAC", + "\xDB\xBF" => "\xE5\x8A\xAD", + "\xDB\xC0" => "\xE5\x8A\xBE", + "\xDB\xC1" => "\xE5\x93\xBF", + "\xDB\xC2" => "\xE5\x8B\x90", + "\xDB\xC3" => "\xE5\x8B\x96", + "\xDB\xC4" => "\xE5\x8B\xB0", + "\xDB\xC5" => "\xE5\x8F\x9F", + "\xDB\xC6" => "\xE7\x87\xAE", + "\xDB\xC7" => "\xE7\x9F\x8D", + "\xDB\xC8" => "\xE5\xBB\xB4", + "\xDB\xC9" => "\xE5\x87\xB5", + "\xDB\xCA" => "\xE5\x87\xBC", + "\xDB\xCB" => "\xE9\xAC\xAF", + "\xDB\xCC" => "\xE5\x8E\xB6", + "\xDB\xCD" => "\xE5\xBC\x81", + "\xDB\xCE" => "\xE7\x95\x9A", + "\xDB\xCF" => "\xE5\xB7\xAF", + "\xDB\xD0" => "\xE5\x9D\x8C", + "\xDB\xD1" => "\xE5\x9E\xA9", + "\xDB\xD2" => "\xE5\x9E\xA1", + "\xDB\xD3" => "\xE5\xA1\xBE", + "\xDB\xD4" => "\xE5\xA2\xBC", + "\xDB\xD5" => "\xE5\xA3\x85", + "\xDB\xD6" => "\xE5\xA3\x91", + "\xDB\xD7" => "\xE5\x9C\xA9", + "\xDB\xD8" => "\xE5\x9C\xAC", + "\xDB\xD9" => "\xE5\x9C\xAA", + "\xDB\xDA" => "\xE5\x9C\xB3", + "\xDB\xDB" => "\xE5\x9C\xB9", + "\xDB\xDC" => "\xE5\x9C\xAE", + "\xDB\xDD" => "\xE5\x9C\xAF", + "\xDB\xDE" => "\xE5\x9D\x9C", + "\xDB\xDF" => "\xE5\x9C\xBB", + "\xDB\xE0" => "\xE5\x9D\x82", + "\xDB\xE1" => "\xE5\x9D\xA9", + "\xDB\xE2" => "\xE5\x9E\x85", + "\xDB\xE3" => "\xE5\x9D\xAB", + "\xDB\xE4" => "\xE5\x9E\x86", + "\xDB\xE5" => "\xE5\x9D\xBC", + "\xDB\xE6" => "\xE5\x9D\xBB", + "\xDB\xE7" => "\xE5\x9D\xA8", + "\xDB\xE8" => "\xE5\x9D\xAD", + "\xDB\xE9" => "\xE5\x9D\xB6", + "\xDB\xEA" => "\xE5\x9D\xB3", + "\xDB\xEB" => "\xE5\x9E\xAD", + "\xDB\xEC" => "\xE5\x9E\xA4", + "\xDB\xED" => "\xE5\x9E\x8C", + "\xDB\xEE" => "\xE5\x9E\xB2", + "\xDB\xEF" => "\xE5\x9F\x8F", + "\xDB\xF0" => "\xE5\x9E\xA7", + "\xDB\xF1" => "\xE5\x9E\xB4", + "\xDB\xF2" => "\xE5\x9E\x93", + "\xDB\xF3" => "\xE5\x9E\xA0", + "\xDB\xF4" => "\xE5\x9F\x95", + "\xDB\xF5" => "\xE5\x9F\x98", + "\xDB\xF6" => "\xE5\x9F\x9A", + "\xDB\xF7" => "\xE5\x9F\x99", + "\xDB\xF8" => "\xE5\x9F\x92", + "\xDB\xF9" => "\xE5\x9E\xB8", + "\xDB\xFA" => "\xE5\x9F\xB4", + "\xDB\xFB" => "\xE5\x9F\xAF", + "\xDB\xFC" => "\xE5\x9F\xB8", + "\xDB\xFD" => "\xE5\x9F\xA4", + "\xDB\xFE" => "\xE5\x9F\x9D", + "\xDC\xA1" => "\xE5\xA0\x8B", + "\xDC\xA2" => "\xE5\xA0\x8D", + "\xDC\xA3" => "\xE5\x9F\xBD", + "\xDC\xA4" => "\xE5\x9F\xAD", + "\xDC\xA5" => "\xE5\xA0\x80", + "\xDC\xA6" => "\xE5\xA0\x9E", + "\xDC\xA7" => "\xE5\xA0\x99", + "\xDC\xA8" => "\xE5\xA1\x84", + "\xDC\xA9" => "\xE5\xA0\xA0", + "\xDC\xAA" => "\xE5\xA1\xA5", + "\xDC\xAB" => "\xE5\xA1\xAC", + "\xDC\xAC" => "\xE5\xA2\x81", + "\xDC\xAD" => "\xE5\xA2\x89", + "\xDC\xAE" => "\xE5\xA2\x9A", + "\xDC\xAF" => "\xE5\xA2\x80", + "\xDC\xB0" => "\xE9\xA6\xA8", + "\xDC\xB1" => "\xE9\xBC\x99", + "\xDC\xB2" => "\xE6\x87\xBF", + "\xDC\xB3" => "\xE8\x89\xB9", + "\xDC\xB4" => "\xE8\x89\xBD", + "\xDC\xB5" => "\xE8\x89\xBF", + "\xDC\xB6" => "\xE8\x8A\x8F", + "\xDC\xB7" => "\xE8\x8A\x8A", + "\xDC\xB8" => "\xE8\x8A\xA8", + "\xDC\xB9" => "\xE8\x8A\x84", + "\xDC\xBA" => "\xE8\x8A\x8E", + "\xDC\xBB" => "\xE8\x8A\x91", + "\xDC\xBC" => "\xE8\x8A\x97", + "\xDC\xBD" => "\xE8\x8A\x99", + "\xDC\xBE" => "\xE8\x8A\xAB", + "\xDC\xBF" => "\xE8\x8A\xB8", + "\xDC\xC0" => "\xE8\x8A\xBE", + "\xDC\xC1" => "\xE8\x8A\xB0", + "\xDC\xC2" => "\xE8\x8B\x88", + "\xDC\xC3" => "\xE8\x8B\x8A", + "\xDC\xC4" => "\xE8\x8B\xA3", + "\xDC\xC5" => "\xE8\x8A\x98", + "\xDC\xC6" => "\xE8\x8A\xB7", + "\xDC\xC7" => "\xE8\x8A\xAE", + "\xDC\xC8" => "\xE8\x8B\x8B", + "\xDC\xC9" => "\xE8\x8B\x8C", + "\xDC\xCA" => "\xE8\x8B\x81", + "\xDC\xCB" => "\xE8\x8A\xA9", + "\xDC\xCC" => "\xE8\x8A\xB4", + "\xDC\xCD" => "\xE8\x8A\xA1", + "\xDC\xCE" => "\xE8\x8A\xAA", + "\xDC\xCF" => "\xE8\x8A\x9F", + "\xDC\xD0" => "\xE8\x8B\x84", + "\xDC\xD1" => "\xE8\x8B\x8E", + "\xDC\xD2" => "\xE8\x8A\xA4", + "\xDC\xD3" => "\xE8\x8B\xA1", + "\xDC\xD4" => "\xE8\x8C\x89", + "\xDC\xD5" => "\xE8\x8B\xB7", + "\xDC\xD6" => "\xE8\x8B\xA4", + "\xDC\xD7" => "\xE8\x8C\x8F", + "\xDC\xD8" => "\xE8\x8C\x87", + "\xDC\xD9" => "\xE8\x8B\x9C", + "\xDC\xDA" => "\xE8\x8B\xB4", + "\xDC\xDB" => "\xE8\x8B\x92", + "\xDC\xDC" => "\xE8\x8B\x98", + "\xDC\xDD" => "\xE8\x8C\x8C", + "\xDC\xDE" => "\xE8\x8B\xBB", + "\xDC\xDF" => "\xE8\x8B\x93", + "\xDC\xE0" => "\xE8\x8C\x91", + "\xDC\xE1" => "\xE8\x8C\x9A", + "\xDC\xE2" => "\xE8\x8C\x86", + "\xDC\xE3" => "\xE8\x8C\x94", + "\xDC\xE4" => "\xE8\x8C\x95", + "\xDC\xE5" => "\xE8\x8B\xA0", + "\xDC\xE6" => "\xE8\x8B\x95", + "\xDC\xE7" => "\xE8\x8C\x9C", + "\xDC\xE8" => "\xE8\x8D\x91", + "\xDC\xE9" => "\xE8\x8D\x9B", + "\xDC\xEA" => "\xE8\x8D\x9C", + "\xDC\xEB" => "\xE8\x8C\x88", + "\xDC\xEC" => "\xE8\x8E\x92", + "\xDC\xED" => "\xE8\x8C\xBC", + "\xDC\xEE" => "\xE8\x8C\xB4", + "\xDC\xEF" => "\xE8\x8C\xB1", + "\xDC\xF0" => "\xE8\x8E\x9B", + "\xDC\xF1" => "\xE8\x8D\x9E", + "\xDC\xF2" => "\xE8\x8C\xAF", + "\xDC\xF3" => "\xE8\x8D\x8F", + "\xDC\xF4" => "\xE8\x8D\x87", + "\xDC\xF5" => "\xE8\x8D\x83", + "\xDC\xF6" => "\xE8\x8D\x9F", + "\xDC\xF7" => "\xE8\x8D\x80", + "\xDC\xF8" => "\xE8\x8C\x97", + "\xDC\xF9" => "\xE8\x8D\xA0", + "\xDC\xFA" => "\xE8\x8C\xAD", + "\xDC\xFB" => "\xE8\x8C\xBA", + "\xDC\xFC" => "\xE8\x8C\xB3", + "\xDC\xFD" => "\xE8\x8D\xA6", + "\xDC\xFE" => "\xE8\x8D\xA5", + "\xDD\xA1" => "\xE8\x8D\xA8", + "\xDD\xA2" => "\xE8\x8C\x9B", + "\xDD\xA3" => "\xE8\x8D\xA9", + "\xDD\xA4" => "\xE8\x8D\xAC", + "\xDD\xA5" => "\xE8\x8D\xAA", + "\xDD\xA6" => "\xE8\x8D\xAD", + "\xDD\xA7" => "\xE8\x8D\xAE", + "\xDD\xA8" => "\xE8\x8E\xB0", + "\xDD\xA9" => "\xE8\x8D\xB8", + "\xDD\xAA" => "\xE8\x8E\xB3", + "\xDD\xAB" => "\xE8\x8E\xB4", + "\xDD\xAC" => "\xE8\x8E\xA0", + "\xDD\xAD" => "\xE8\x8E\xAA", + "\xDD\xAE" => "\xE8\x8E\x93", + "\xDD\xAF" => "\xE8\x8E\x9C", + "\xDD\xB0" => "\xE8\x8E\x85", + "\xDD\xB1" => "\xE8\x8D\xBC", + "\xDD\xB2" => "\xE8\x8E\xB6", + "\xDD\xB3" => "\xE8\x8E\xA9", + "\xDD\xB4" => "\xE8\x8D\xBD", + "\xDD\xB5" => "\xE8\x8E\xB8", + "\xDD\xB6" => "\xE8\x8D\xBB", + "\xDD\xB7" => "\xE8\x8E\x98", + "\xDD\xB8" => "\xE8\x8E\x9E", + "\xDD\xB9" => "\xE8\x8E\xA8", + "\xDD\xBA" => "\xE8\x8E\xBA", + "\xDD\xBB" => "\xE8\x8E\xBC", + "\xDD\xBC" => "\xE8\x8F\x81", + "\xDD\xBD" => "\xE8\x90\x81", + "\xDD\xBE" => "\xE8\x8F\xA5", + "\xDD\xBF" => "\xE8\x8F\x98", + "\xDD\xC0" => "\xE5\xA0\x87", + "\xDD\xC1" => "\xE8\x90\x98", + "\xDD\xC2" => "\xE8\x90\x8B", + "\xDD\xC3" => "\xE8\x8F\x9D", + "\xDD\xC4" => "\xE8\x8F\xBD", + "\xDD\xC5" => "\xE8\x8F\x96", + "\xDD\xC6" => "\xE8\x90\x9C", + "\xDD\xC7" => "\xE8\x90\xB8", + "\xDD\xC8" => "\xE8\x90\x91", + "\xDD\xC9" => "\xE8\x90\x86", + "\xDD\xCA" => "\xE8\x8F\x94", + "\xDD\xCB" => "\xE8\x8F\x9F", + "\xDD\xCC" => "\xE8\x90\x8F", + "\xDD\xCD" => "\xE8\x90\x83", + "\xDD\xCE" => "\xE8\x8F\xB8", + "\xDD\xCF" => "\xE8\x8F\xB9", + "\xDD\xD0" => "\xE8\x8F\xAA", + "\xDD\xD1" => "\xE8\x8F\x85", + "\xDD\xD2" => "\xE8\x8F\x80", + "\xDD\xD3" => "\xE8\x90\xA6", + "\xDD\xD4" => "\xE8\x8F\xB0", + "\xDD\xD5" => "\xE8\x8F\xA1", + "\xDD\xD6" => "\xE8\x91\x9C", + "\xDD\xD7" => "\xE8\x91\x91", + "\xDD\xD8" => "\xE8\x91\x9A", + "\xDD\xD9" => "\xE8\x91\x99", + "\xDD\xDA" => "\xE8\x91\xB3", + "\xDD\xDB" => "\xE8\x92\x87", + "\xDD\xDC" => "\xE8\x92\x88", + "\xDD\xDD" => "\xE8\x91\xBA", + "\xDD\xDE" => "\xE8\x92\x89", + "\xDD\xDF" => "\xE8\x91\xB8", + "\xDD\xE0" => "\xE8\x90\xBC", + "\xDD\xE1" => "\xE8\x91\x86", + "\xDD\xE2" => "\xE8\x91\xA9", + "\xDD\xE3" => "\xE8\x91\xB6", + "\xDD\xE4" => "\xE8\x92\x8C", + "\xDD\xE5" => "\xE8\x92\x8E", + "\xDD\xE6" => "\xE8\x90\xB1", + "\xDD\xE7" => "\xE8\x91\xAD", + "\xDD\xE8" => "\xE8\x93\x81", + "\xDD\xE9" => "\xE8\x93\x8D", + "\xDD\xEA" => "\xE8\x93\x90", + "\xDD\xEB" => "\xE8\x93\xA6", + "\xDD\xEC" => "\xE8\x92\xBD", + "\xDD\xED" => "\xE8\x93\x93", + "\xDD\xEE" => "\xE8\x93\x8A", + "\xDD\xEF" => "\xE8\x92\xBF", + "\xDD\xF0" => "\xE8\x92\xBA", + "\xDD\xF1" => "\xE8\x93\xA0", + "\xDD\xF2" => "\xE8\x92\xA1", + "\xDD\xF3" => "\xE8\x92\xB9", + "\xDD\xF4" => "\xE8\x92\xB4", + "\xDD\xF5" => "\xE8\x92\x97", + "\xDD\xF6" => "\xE8\x93\xA5", + "\xDD\xF7" => "\xE8\x93\xA3", + "\xDD\xF8" => "\xE8\x94\x8C", + "\xDD\xF9" => "\xE7\x94\x8D", + "\xDD\xFA" => "\xE8\x94\xB8", + "\xDD\xFB" => "\xE8\x93\xB0", + "\xDD\xFC" => "\xE8\x94\xB9", + "\xDD\xFD" => "\xE8\x94\x9F", + "\xDD\xFE" => "\xE8\x94\xBA", + "\xDE\xA1" => "\xE8\x95\x96", + "\xDE\xA2" => "\xE8\x94\xBB", + "\xDE\xA3" => "\xE8\x93\xBF", + "\xDE\xA4" => "\xE8\x93\xBC", + "\xDE\xA5" => "\xE8\x95\x99", + "\xDE\xA6" => "\xE8\x95\x88", + "\xDE\xA7" => "\xE8\x95\xA8", + "\xDE\xA8" => "\xE8\x95\xA4", + "\xDE\xA9" => "\xE8\x95\x9E", + "\xDE\xAA" => "\xE8\x95\xBA", + "\xDE\xAB" => "\xE7\x9E\xA2", + "\xDE\xAC" => "\xE8\x95\x83", + "\xDE\xAD" => "\xE8\x95\xB2", + "\xDE\xAE" => "\xE8\x95\xBB", + "\xDE\xAF" => "\xE8\x96\xA4", + "\xDE\xB0" => "\xE8\x96\xA8", + "\xDE\xB1" => "\xE8\x96\x87", + "\xDE\xB2" => "\xE8\x96\x8F", + "\xDE\xB3" => "\xE8\x95\xB9", + "\xDE\xB4" => "\xE8\x96\xAE", + "\xDE\xB5" => "\xE8\x96\x9C", + "\xDE\xB6" => "\xE8\x96\x85", + "\xDE\xB7" => "\xE8\x96\xB9", + "\xDE\xB8" => "\xE8\x96\xB7", + "\xDE\xB9" => "\xE8\x96\xB0", + "\xDE\xBA" => "\xE8\x97\x93", + "\xDE\xBB" => "\xE8\x97\x81", + "\xDE\xBC" => "\xE8\x97\x9C", + "\xDE\xBD" => "\xE8\x97\xBF", + "\xDE\xBE" => "\xE8\x98\xA7", + "\xDE\xBF" => "\xE8\x98\x85", + "\xDE\xC0" => "\xE8\x98\xA9", + "\xDE\xC1" => "\xE8\x98\x96", + "\xDE\xC2" => "\xE8\x98\xBC", + "\xDE\xC3" => "\xE5\xBB\xBE", + "\xDE\xC4" => "\xE5\xBC\x88", + "\xDE\xC5" => "\xE5\xA4\xBC", + "\xDE\xC6" => "\xE5\xA5\x81", + "\xDE\xC7" => "\xE8\x80\xB7", + "\xDE\xC8" => "\xE5\xA5\x95", + "\xDE\xC9" => "\xE5\xA5\x9A", + "\xDE\xCA" => "\xE5\xA5\x98", + "\xDE\xCB" => "\xE5\x8C\x8F", + "\xDE\xCC" => "\xE5\xB0\xA2", + "\xDE\xCD" => "\xE5\xB0\xA5", + "\xDE\xCE" => "\xE5\xB0\xAC", + "\xDE\xCF" => "\xE5\xB0\xB4", + "\xDE\xD0" => "\xE6\x89\x8C", + "\xDE\xD1" => "\xE6\x89\xAA", + "\xDE\xD2" => "\xE6\x8A\x9F", + "\xDE\xD3" => "\xE6\x8A\xBB", + "\xDE\xD4" => "\xE6\x8B\x8A", + "\xDE\xD5" => "\xE6\x8B\x9A", + "\xDE\xD6" => "\xE6\x8B\x97", + "\xDE\xD7" => "\xE6\x8B\xAE", + "\xDE\xD8" => "\xE6\x8C\xA2", + "\xDE\xD9" => "\xE6\x8B\xB6", + "\xDE\xDA" => "\xE6\x8C\xB9", + "\xDE\xDB" => "\xE6\x8D\x8B", + "\xDE\xDC" => "\xE6\x8D\x83", + "\xDE\xDD" => "\xE6\x8E\xAD", + "\xDE\xDE" => "\xE6\x8F\xB6", + "\xDE\xDF" => "\xE6\x8D\xB1", + "\xDE\xE0" => "\xE6\x8D\xBA", + "\xDE\xE1" => "\xE6\x8E\x8E", + "\xDE\xE2" => "\xE6\x8E\xB4", + "\xDE\xE3" => "\xE6\x8D\xAD", + "\xDE\xE4" => "\xE6\x8E\xAC", + "\xDE\xE5" => "\xE6\x8E\x8A", + "\xDE\xE6" => "\xE6\x8D\xA9", + "\xDE\xE7" => "\xE6\x8E\xAE", + "\xDE\xE8" => "\xE6\x8E\xBC", + "\xDE\xE9" => "\xE6\x8F\xB2", + "\xDE\xEA" => "\xE6\x8F\xB8", + "\xDE\xEB" => "\xE6\x8F\xA0", + "\xDE\xEC" => "\xE6\x8F\xBF", + "\xDE\xED" => "\xE6\x8F\x84", + "\xDE\xEE" => "\xE6\x8F\x9E", + "\xDE\xEF" => "\xE6\x8F\x8E", + "\xDE\xF0" => "\xE6\x91\x92", + "\xDE\xF1" => "\xE6\x8F\x86", + "\xDE\xF2" => "\xE6\x8E\xBE", + "\xDE\xF3" => "\xE6\x91\x85", + "\xDE\xF4" => "\xE6\x91\x81", + "\xDE\xF5" => "\xE6\x90\x8B", + "\xDE\xF6" => "\xE6\x90\x9B", + "\xDE\xF7" => "\xE6\x90\xA0", + "\xDE\xF8" => "\xE6\x90\x8C", + "\xDE\xF9" => "\xE6\x90\xA6", + "\xDE\xFA" => "\xE6\x90\xA1", + "\xDE\xFB" => "\xE6\x91\x9E", + "\xDE\xFC" => "\xE6\x92\x84", + "\xDE\xFD" => "\xE6\x91\xAD", + "\xDE\xFE" => "\xE6\x92\x96", + "\xDF\xA1" => "\xE6\x91\xBA", + "\xDF\xA2" => "\xE6\x92\xB7", + "\xDF\xA3" => "\xE6\x92\xB8", + "\xDF\xA4" => "\xE6\x92\x99", + "\xDF\xA5" => "\xE6\x92\xBA", + "\xDF\xA6" => "\xE6\x93\x80", + "\xDF\xA7" => "\xE6\x93\x90", + "\xDF\xA8" => "\xE6\x93\x97", + "\xDF\xA9" => "\xE6\x93\xA4", + "\xDF\xAA" => "\xE6\x93\xA2", + "\xDF\xAB" => "\xE6\x94\x89", + "\xDF\xAC" => "\xE6\x94\xA5", + "\xDF\xAD" => "\xE6\x94\xAE", + "\xDF\xAE" => "\xE5\xBC\x8B", + "\xDF\xAF" => "\xE5\xBF\x92", + "\xDF\xB0" => "\xE7\x94\x99", + "\xDF\xB1" => "\xE5\xBC\x91", + "\xDF\xB2" => "\xE5\x8D\x9F", + "\xDF\xB3" => "\xE5\x8F\xB1", + "\xDF\xB4" => "\xE5\x8F\xBD", + "\xDF\xB5" => "\xE5\x8F\xA9", + "\xDF\xB6" => "\xE5\x8F\xA8", + "\xDF\xB7" => "\xE5\x8F\xBB", + "\xDF\xB8" => "\xE5\x90\x92", + "\xDF\xB9" => "\xE5\x90\x96", + "\xDF\xBA" => "\xE5\x90\x86", + "\xDF\xBB" => "\xE5\x91\x8B", + "\xDF\xBC" => "\xE5\x91\x92", + "\xDF\xBD" => "\xE5\x91\x93", + "\xDF\xBE" => "\xE5\x91\x94", + "\xDF\xBF" => "\xE5\x91\x96", + "\xDF\xC0" => "\xE5\x91\x83", + "\xDF\xC1" => "\xE5\x90\xA1", + "\xDF\xC2" => "\xE5\x91\x97", + "\xDF\xC3" => "\xE5\x91\x99", + "\xDF\xC4" => "\xE5\x90\xA3", + "\xDF\xC5" => "\xE5\x90\xB2", + "\xDF\xC6" => "\xE5\x92\x82", + "\xDF\xC7" => "\xE5\x92\x94", + "\xDF\xC8" => "\xE5\x91\xB7", + "\xDF\xC9" => "\xE5\x91\xB1", + "\xDF\xCA" => "\xE5\x91\xA4", + "\xDF\xCB" => "\xE5\x92\x9A", + "\xDF\xCC" => "\xE5\x92\x9B", + "\xDF\xCD" => "\xE5\x92\x84", + "\xDF\xCE" => "\xE5\x91\xB6", + "\xDF\xCF" => "\xE5\x91\xA6", + "\xDF\xD0" => "\xE5\x92\x9D", + "\xDF\xD1" => "\xE5\x93\x90", + "\xDF\xD2" => "\xE5\x92\xAD", + "\xDF\xD3" => "\xE5\x93\x82", + "\xDF\xD4" => "\xE5\x92\xB4", + "\xDF\xD5" => "\xE5\x93\x92", + "\xDF\xD6" => "\xE5\x92\xA7", + "\xDF\xD7" => "\xE5\x92\xA6", + "\xDF\xD8" => "\xE5\x93\x93", + "\xDF\xD9" => "\xE5\x93\x94", + "\xDF\xDA" => "\xE5\x91\xB2", + "\xDF\xDB" => "\xE5\x92\xA3", + "\xDF\xDC" => "\xE5\x93\x95", + "\xDF\xDD" => "\xE5\x92\xBB", + "\xDF\xDE" => "\xE5\x92\xBF", + "\xDF\xDF" => "\xE5\x93\x8C", + "\xDF\xE0" => "\xE5\x93\x99", + "\xDF\xE1" => "\xE5\x93\x9A", + "\xDF\xE2" => "\xE5\x93\x9C", + "\xDF\xE3" => "\xE5\x92\xA9", + "\xDF\xE4" => "\xE5\x92\xAA", + "\xDF\xE5" => "\xE5\x92\xA4", + "\xDF\xE6" => "\xE5\x93\x9D", + "\xDF\xE7" => "\xE5\x93\x8F", + "\xDF\xE8" => "\xE5\x93\x9E", + "\xDF\xE9" => "\xE5\x94\x9B", + "\xDF\xEA" => "\xE5\x93\xA7", + "\xDF\xEB" => "\xE5\x94\xA0", + "\xDF\xEC" => "\xE5\x93\xBD", + "\xDF\xED" => "\xE5\x94\x94", + "\xDF\xEE" => "\xE5\x93\xB3", + "\xDF\xEF" => "\xE5\x94\xA2", + "\xDF\xF0" => "\xE5\x94\xA3", + "\xDF\xF1" => "\xE5\x94\x8F", + "\xDF\xF2" => "\xE5\x94\x91", + "\xDF\xF3" => "\xE5\x94\xA7", + "\xDF\xF4" => "\xE5\x94\xAA", + "\xDF\xF5" => "\xE5\x95\xA7", + "\xDF\xF6" => "\xE5\x96\x8F", + "\xDF\xF7" => "\xE5\x96\xB5", + "\xDF\xF8" => "\xE5\x95\x89", + "\xDF\xF9" => "\xE5\x95\xAD", + "\xDF\xFA" => "\xE5\x95\x81", + "\xDF\xFB" => "\xE5\x95\x95", + "\xDF\xFC" => "\xE5\x94\xBF", + "\xDF\xFD" => "\xE5\x95\x90", + "\xDF\xFE" => "\xE5\x94\xBC", + "\xE0\xA1" => "\xE5\x94\xB7", + "\xE0\xA2" => "\xE5\x95\x96", + "\xE0\xA3" => "\xE5\x95\xB5", + "\xE0\xA4" => "\xE5\x95\xB6", + "\xE0\xA5" => "\xE5\x95\xB7", + "\xE0\xA6" => "\xE5\x94\xB3", + "\xE0\xA7" => "\xE5\x94\xB0", + "\xE0\xA8" => "\xE5\x95\x9C", + "\xE0\xA9" => "\xE5\x96\x8B", + "\xE0\xAA" => "\xE5\x97\x92", + "\xE0\xAB" => "\xE5\x96\x83", + "\xE0\xAC" => "\xE5\x96\xB1", + "\xE0\xAD" => "\xE5\x96\xB9", + "\xE0\xAE" => "\xE5\x96\x88", + "\xE0\xAF" => "\xE5\x96\x81", + "\xE0\xB0" => "\xE5\x96\x9F", + "\xE0\xB1" => "\xE5\x95\xBE", + "\xE0\xB2" => "\xE5\x97\x96", + "\xE0\xB3" => "\xE5\x96\x91", + "\xE0\xB4" => "\xE5\x95\xBB", + "\xE0\xB5" => "\xE5\x97\x9F", + "\xE0\xB6" => "\xE5\x96\xBD", + "\xE0\xB7" => "\xE5\x96\xBE", + "\xE0\xB8" => "\xE5\x96\x94", + "\xE0\xB9" => "\xE5\x96\x99", + "\xE0\xBA" => "\xE5\x97\xAA", + "\xE0\xBB" => "\xE5\x97\xB7", + "\xE0\xBC" => "\xE5\x97\x89", + "\xE0\xBD" => "\xE5\x98\x9F", + "\xE0\xBE" => "\xE5\x97\x91", + "\xE0\xBF" => "\xE5\x97\xAB", + "\xE0\xC0" => "\xE5\x97\xAC", + "\xE0\xC1" => "\xE5\x97\x94", + "\xE0\xC2" => "\xE5\x97\xA6", + "\xE0\xC3" => "\xE5\x97\x9D", + "\xE0\xC4" => "\xE5\x97\x84", + "\xE0\xC5" => "\xE5\x97\xAF", + "\xE0\xC6" => "\xE5\x97\xA5", + "\xE0\xC7" => "\xE5\x97\xB2", + "\xE0\xC8" => "\xE5\x97\xB3", + "\xE0\xC9" => "\xE5\x97\x8C", + "\xE0\xCA" => "\xE5\x97\x8D", + "\xE0\xCB" => "\xE5\x97\xA8", + "\xE0\xCC" => "\xE5\x97\xB5", + "\xE0\xCD" => "\xE5\x97\xA4", + "\xE0\xCE" => "\xE8\xBE\x94", + "\xE0\xCF" => "\xE5\x98\x9E", + "\xE0\xD0" => "\xE5\x98\x88", + "\xE0\xD1" => "\xE5\x98\x8C", + "\xE0\xD2" => "\xE5\x98\x81", + "\xE0\xD3" => "\xE5\x98\xA4", + "\xE0\xD4" => "\xE5\x98\xA3", + "\xE0\xD5" => "\xE5\x97\xBE", + "\xE0\xD6" => "\xE5\x98\x80", + "\xE0\xD7" => "\xE5\x98\xA7", + "\xE0\xD8" => "\xE5\x98\xAD", + "\xE0\xD9" => "\xE5\x99\x98", + "\xE0\xDA" => "\xE5\x98\xB9", + "\xE0\xDB" => "\xE5\x99\x97", + "\xE0\xDC" => "\xE5\x98\xAC", + "\xE0\xDD" => "\xE5\x99\x8D", + "\xE0\xDE" => "\xE5\x99\xA2", + "\xE0\xDF" => "\xE5\x99\x99", + "\xE0\xE0" => "\xE5\x99\x9C", + "\xE0\xE1" => "\xE5\x99\x8C", + "\xE0\xE2" => "\xE5\x99\x94", + "\xE0\xE3" => "\xE5\x9A\x86", + "\xE0\xE4" => "\xE5\x99\xA4", + "\xE0\xE5" => "\xE5\x99\xB1", + "\xE0\xE6" => "\xE5\x99\xAB", + "\xE0\xE7" => "\xE5\x99\xBB", + "\xE0\xE8" => "\xE5\x99\xBC", + "\xE0\xE9" => "\xE5\x9A\x85", + "\xE0\xEA" => "\xE5\x9A\x93", + "\xE0\xEB" => "\xE5\x9A\xAF", + "\xE0\xEC" => "\xE5\x9B\x94", + "\xE0\xED" => "\xE5\x9B\x97", + "\xE0\xEE" => "\xE5\x9B\x9D", + "\xE0\xEF" => "\xE5\x9B\xA1", + "\xE0\xF0" => "\xE5\x9B\xB5", + "\xE0\xF1" => "\xE5\x9B\xAB", + "\xE0\xF2" => "\xE5\x9B\xB9", + "\xE0\xF3" => "\xE5\x9B\xBF", + "\xE0\xF4" => "\xE5\x9C\x84", + "\xE0\xF5" => "\xE5\x9C\x8A", + "\xE0\xF6" => "\xE5\x9C\x89", + "\xE0\xF7" => "\xE5\x9C\x9C", + "\xE0\xF8" => "\xE5\xB8\x8F", + "\xE0\xF9" => "\xE5\xB8\x99", + "\xE0\xFA" => "\xE5\xB8\x94", + "\xE0\xFB" => "\xE5\xB8\x91", + "\xE0\xFC" => "\xE5\xB8\xB1", + "\xE0\xFD" => "\xE5\xB8\xBB", + "\xE0\xFE" => "\xE5\xB8\xBC", + "\xE1\xA1" => "\xE5\xB8\xB7", + "\xE1\xA2" => "\xE5\xB9\x84", + "\xE1\xA3" => "\xE5\xB9\x94", + "\xE1\xA4" => "\xE5\xB9\x9B", + "\xE1\xA5" => "\xE5\xB9\x9E", + "\xE1\xA6" => "\xE5\xB9\xA1", + "\xE1\xA7" => "\xE5\xB2\x8C", + "\xE1\xA8" => "\xE5\xB1\xBA", + "\xE1\xA9" => "\xE5\xB2\x8D", + "\xE1\xAA" => "\xE5\xB2\x90", + "\xE1\xAB" => "\xE5\xB2\x96", + "\xE1\xAC" => "\xE5\xB2\x88", + "\xE1\xAD" => "\xE5\xB2\x98", + "\xE1\xAE" => "\xE5\xB2\x99", + "\xE1\xAF" => "\xE5\xB2\x91", + "\xE1\xB0" => "\xE5\xB2\x9A", + "\xE1\xB1" => "\xE5\xB2\x9C", + "\xE1\xB2" => "\xE5\xB2\xB5", + "\xE1\xB3" => "\xE5\xB2\xA2", + "\xE1\xB4" => "\xE5\xB2\xBD", + "\xE1\xB5" => "\xE5\xB2\xAC", + "\xE1\xB6" => "\xE5\xB2\xAB", + "\xE1\xB7" => "\xE5\xB2\xB1", + "\xE1\xB8" => "\xE5\xB2\xA3", + "\xE1\xB9" => "\xE5\xB3\x81", + "\xE1\xBA" => "\xE5\xB2\xB7", + "\xE1\xBB" => "\xE5\xB3\x84", + "\xE1\xBC" => "\xE5\xB3\x92", + "\xE1\xBD" => "\xE5\xB3\xA4", + "\xE1\xBE" => "\xE5\xB3\x8B", + "\xE1\xBF" => "\xE5\xB3\xA5", + "\xE1\xC0" => "\xE5\xB4\x82", + "\xE1\xC1" => "\xE5\xB4\x83", + "\xE1\xC2" => "\xE5\xB4\xA7", + "\xE1\xC3" => "\xE5\xB4\xA6", + "\xE1\xC4" => "\xE5\xB4\xAE", + "\xE1\xC5" => "\xE5\xB4\xA4", + "\xE1\xC6" => "\xE5\xB4\x9E", + "\xE1\xC7" => "\xE5\xB4\x86", + "\xE1\xC8" => "\xE5\xB4\x9B", + "\xE1\xC9" => "\xE5\xB5\x98", + "\xE1\xCA" => "\xE5\xB4\xBE", + "\xE1\xCB" => "\xE5\xB4\xB4", + "\xE1\xCC" => "\xE5\xB4\xBD", + "\xE1\xCD" => "\xE5\xB5\xAC", + "\xE1\xCE" => "\xE5\xB5\x9B", + "\xE1\xCF" => "\xE5\xB5\xAF", + "\xE1\xD0" => "\xE5\xB5\x9D", + "\xE1\xD1" => "\xE5\xB5\xAB", + "\xE1\xD2" => "\xE5\xB5\x8B", + "\xE1\xD3" => "\xE5\xB5\x8A", + "\xE1\xD4" => "\xE5\xB5\xA9", + "\xE1\xD5" => "\xE5\xB5\xB4", + "\xE1\xD6" => "\xE5\xB6\x82", + "\xE1\xD7" => "\xE5\xB6\x99", + "\xE1\xD8" => "\xE5\xB6\x9D", + "\xE1\xD9" => "\xE8\xB1\xB3", + "\xE1\xDA" => "\xE5\xB6\xB7", + "\xE1\xDB" => "\xE5\xB7\x85", + "\xE1\xDC" => "\xE5\xBD\xB3", + "\xE1\xDD" => "\xE5\xBD\xB7", + "\xE1\xDE" => "\xE5\xBE\x82", + "\xE1\xDF" => "\xE5\xBE\x87", + "\xE1\xE0" => "\xE5\xBE\x89", + "\xE1\xE1" => "\xE5\xBE\x8C", + "\xE1\xE2" => "\xE5\xBE\x95", + "\xE1\xE3" => "\xE5\xBE\x99", + "\xE1\xE4" => "\xE5\xBE\x9C", + "\xE1\xE5" => "\xE5\xBE\xA8", + "\xE1\xE6" => "\xE5\xBE\xAD", + "\xE1\xE7" => "\xE5\xBE\xB5", + "\xE1\xE8" => "\xE5\xBE\xBC", + "\xE1\xE9" => "\xE8\xA1\xA2", + "\xE1\xEA" => "\xE5\xBD\xA1", + "\xE1\xEB" => "\xE7\x8A\xAD", + "\xE1\xEC" => "\xE7\x8A\xB0", + "\xE1\xED" => "\xE7\x8A\xB4", + "\xE1\xEE" => "\xE7\x8A\xB7", + "\xE1\xEF" => "\xE7\x8A\xB8", + "\xE1\xF0" => "\xE7\x8B\x83", + "\xE1\xF1" => "\xE7\x8B\x81", + "\xE1\xF2" => "\xE7\x8B\x8E", + "\xE1\xF3" => "\xE7\x8B\x8D", + "\xE1\xF4" => "\xE7\x8B\x92", + "\xE1\xF5" => "\xE7\x8B\xA8", + "\xE1\xF6" => "\xE7\x8B\xAF", + "\xE1\xF7" => "\xE7\x8B\xA9", + "\xE1\xF8" => "\xE7\x8B\xB2", + "\xE1\xF9" => "\xE7\x8B\xB4", + "\xE1\xFA" => "\xE7\x8B\xB7", + "\xE1\xFB" => "\xE7\x8C\x81", + "\xE1\xFC" => "\xE7\x8B\xB3", + "\xE1\xFD" => "\xE7\x8C\x83", + "\xE1\xFE" => "\xE7\x8B\xBA", + "\xE2\xA1" => "\xE7\x8B\xBB", + "\xE2\xA2" => "\xE7\x8C\x97", + "\xE2\xA3" => "\xE7\x8C\x93", + "\xE2\xA4" => "\xE7\x8C\xA1", + "\xE2\xA5" => "\xE7\x8C\x8A", + "\xE2\xA6" => "\xE7\x8C\x9E", + "\xE2\xA7" => "\xE7\x8C\x9D", + "\xE2\xA8" => "\xE7\x8C\x95", + "\xE2\xA9" => "\xE7\x8C\xA2", + "\xE2\xAA" => "\xE7\x8C\xB9", + "\xE2\xAB" => "\xE7\x8C\xA5", + "\xE2\xAC" => "\xE7\x8C\xAC", + "\xE2\xAD" => "\xE7\x8C\xB8", + "\xE2\xAE" => "\xE7\x8C\xB1", + "\xE2\xAF" => "\xE7\x8D\x90", + "\xE2\xB0" => "\xE7\x8D\x8D", + "\xE2\xB1" => "\xE7\x8D\x97", + "\xE2\xB2" => "\xE7\x8D\xA0", + "\xE2\xB3" => "\xE7\x8D\xAC", + "\xE2\xB4" => "\xE7\x8D\xAF", + "\xE2\xB5" => "\xE7\x8D\xBE", + "\xE2\xB6" => "\xE8\x88\x9B", + "\xE2\xB7" => "\xE5\xA4\xA5", + "\xE2\xB8" => "\xE9\xA3\xA7", + "\xE2\xB9" => "\xE5\xA4\xA4", + "\xE2\xBA" => "\xE5\xA4\x82", + "\xE2\xBB" => "\xE9\xA5\xA3", + "\xE2\xBC" => "\xE9\xA5\xA7", + "\xE2\xBD" => "\xE9\xA5\xA8", + "\xE2\xBE" => "\xE9\xA5\xA9", + "\xE2\xBF" => "\xE9\xA5\xAA", + "\xE2\xC0" => "\xE9\xA5\xAB", + "\xE2\xC1" => "\xE9\xA5\xAC", + "\xE2\xC2" => "\xE9\xA5\xB4", + "\xE2\xC3" => "\xE9\xA5\xB7", + "\xE2\xC4" => "\xE9\xA5\xBD", + "\xE2\xC5" => "\xE9\xA6\x80", + "\xE2\xC6" => "\xE9\xA6\x84", + "\xE2\xC7" => "\xE9\xA6\x87", + "\xE2\xC8" => "\xE9\xA6\x8A", + "\xE2\xC9" => "\xE9\xA6\x8D", + "\xE2\xCA" => "\xE9\xA6\x90", + "\xE2\xCB" => "\xE9\xA6\x91", + "\xE2\xCC" => "\xE9\xA6\x93", + "\xE2\xCD" => "\xE9\xA6\x94", + "\xE2\xCE" => "\xE9\xA6\x95", + "\xE2\xCF" => "\xE5\xBA\x80", + "\xE2\xD0" => "\xE5\xBA\x91", + "\xE2\xD1" => "\xE5\xBA\x8B", + "\xE2\xD2" => "\xE5\xBA\x96", + "\xE2\xD3" => "\xE5\xBA\xA5", + "\xE2\xD4" => "\xE5\xBA\xA0", + "\xE2\xD5" => "\xE5\xBA\xB9", + "\xE2\xD6" => "\xE5\xBA\xB5", + "\xE2\xD7" => "\xE5\xBA\xBE", + "\xE2\xD8" => "\xE5\xBA\xB3", + "\xE2\xD9" => "\xE8\xB5\x93", + "\xE2\xDA" => "\xE5\xBB\x92", + "\xE2\xDB" => "\xE5\xBB\x91", + "\xE2\xDC" => "\xE5\xBB\x9B", + "\xE2\xDD" => "\xE5\xBB\xA8", + "\xE2\xDE" => "\xE5\xBB\xAA", + "\xE2\xDF" => "\xE8\x86\xBA", + "\xE2\xE0" => "\xE5\xBF\x84", + "\xE2\xE1" => "\xE5\xBF\x89", + "\xE2\xE2" => "\xE5\xBF\x96", + "\xE2\xE3" => "\xE5\xBF\x8F", + "\xE2\xE4" => "\xE6\x80\x83", + "\xE2\xE5" => "\xE5\xBF\xAE", + "\xE2\xE6" => "\xE6\x80\x84", + "\xE2\xE7" => "\xE5\xBF\xA1", + "\xE2\xE8" => "\xE5\xBF\xA4", + "\xE2\xE9" => "\xE5\xBF\xBE", + "\xE2\xEA" => "\xE6\x80\x85", + "\xE2\xEB" => "\xE6\x80\x86", + "\xE2\xEC" => "\xE5\xBF\xAA", + "\xE2\xED" => "\xE5\xBF\xAD", + "\xE2\xEE" => "\xE5\xBF\xB8", + "\xE2\xEF" => "\xE6\x80\x99", + "\xE2\xF0" => "\xE6\x80\xB5", + "\xE2\xF1" => "\xE6\x80\xA6", + "\xE2\xF2" => "\xE6\x80\x9B", + "\xE2\xF3" => "\xE6\x80\x8F", + "\xE2\xF4" => "\xE6\x80\x8D", + "\xE2\xF5" => "\xE6\x80\xA9", + "\xE2\xF6" => "\xE6\x80\xAB", + "\xE2\xF7" => "\xE6\x80\x8A", + "\xE2\xF8" => "\xE6\x80\xBF", + "\xE2\xF9" => "\xE6\x80\xA1", + "\xE2\xFA" => "\xE6\x81\xB8", + "\xE2\xFB" => "\xE6\x81\xB9", + "\xE2\xFC" => "\xE6\x81\xBB", + "\xE2\xFD" => "\xE6\x81\xBA", + "\xE2\xFE" => "\xE6\x81\x82", + "\xE3\xA1" => "\xE6\x81\xAA", + "\xE3\xA2" => "\xE6\x81\xBD", + "\xE3\xA3" => "\xE6\x82\x96", + "\xE3\xA4" => "\xE6\x82\x9A", + "\xE3\xA5" => "\xE6\x82\xAD", + "\xE3\xA6" => "\xE6\x82\x9D", + "\xE3\xA7" => "\xE6\x82\x83", + "\xE3\xA8" => "\xE6\x82\x92", + "\xE3\xA9" => "\xE6\x82\x8C", + "\xE3\xAA" => "\xE6\x82\x9B", + "\xE3\xAB" => "\xE6\x83\xAC", + "\xE3\xAC" => "\xE6\x82\xBB", + "\xE3\xAD" => "\xE6\x82\xB1", + "\xE3\xAE" => "\xE6\x83\x9D", + "\xE3\xAF" => "\xE6\x83\x98", + "\xE3\xB0" => "\xE6\x83\x86", + "\xE3\xB1" => "\xE6\x83\x9A", + "\xE3\xB2" => "\xE6\x82\xB4", + "\xE3\xB3" => "\xE6\x84\xA0", + "\xE3\xB4" => "\xE6\x84\xA6", + "\xE3\xB5" => "\xE6\x84\x95", + "\xE3\xB6" => "\xE6\x84\xA3", + "\xE3\xB7" => "\xE6\x83\xB4", + "\xE3\xB8" => "\xE6\x84\x80", + "\xE3\xB9" => "\xE6\x84\x8E", + "\xE3\xBA" => "\xE6\x84\xAB", + "\xE3\xBB" => "\xE6\x85\x8A", + "\xE3\xBC" => "\xE6\x85\xB5", + "\xE3\xBD" => "\xE6\x86\xAC", + "\xE3\xBE" => "\xE6\x86\x94", + "\xE3\xBF" => "\xE6\x86\xA7", + "\xE3\xC0" => "\xE6\x86\xB7", + "\xE3\xC1" => "\xE6\x87\x94", + "\xE3\xC2" => "\xE6\x87\xB5", + "\xE3\xC3" => "\xE5\xBF\x9D", + "\xE3\xC4" => "\xE9\x9A\xB3", + "\xE3\xC5" => "\xE9\x97\xA9", + "\xE3\xC6" => "\xE9\x97\xAB", + "\xE3\xC7" => "\xE9\x97\xB1", + "\xE3\xC8" => "\xE9\x97\xB3", + "\xE3\xC9" => "\xE9\x97\xB5", + "\xE3\xCA" => "\xE9\x97\xB6", + "\xE3\xCB" => "\xE9\x97\xBC", + "\xE3\xCC" => "\xE9\x97\xBE", + "\xE3\xCD" => "\xE9\x98\x83", + "\xE3\xCE" => "\xE9\x98\x84", + "\xE3\xCF" => "\xE9\x98\x86", + "\xE3\xD0" => "\xE9\x98\x88", + "\xE3\xD1" => "\xE9\x98\x8A", + "\xE3\xD2" => "\xE9\x98\x8B", + "\xE3\xD3" => "\xE9\x98\x8C", + "\xE3\xD4" => "\xE9\x98\x8D", + "\xE3\xD5" => "\xE9\x98\x8F", + "\xE3\xD6" => "\xE9\x98\x92", + "\xE3\xD7" => "\xE9\x98\x95", + "\xE3\xD8" => "\xE9\x98\x96", + "\xE3\xD9" => "\xE9\x98\x97", + "\xE3\xDA" => "\xE9\x98\x99", + "\xE3\xDB" => "\xE9\x98\x9A", + "\xE3\xDC" => "\xE4\xB8\xAC", + "\xE3\xDD" => "\xE7\x88\xBF", + "\xE3\xDE" => "\xE6\x88\x95", + "\xE3\xDF" => "\xE6\xB0\xB5", + "\xE3\xE0" => "\xE6\xB1\x94", + "\xE3\xE1" => "\xE6\xB1\x9C", + "\xE3\xE2" => "\xE6\xB1\x8A", + "\xE3\xE3" => "\xE6\xB2\xA3", + "\xE3\xE4" => "\xE6\xB2\x85", + "\xE3\xE5" => "\xE6\xB2\x90", + "\xE3\xE6" => "\xE6\xB2\x94", + "\xE3\xE7" => "\xE6\xB2\x8C", + "\xE3\xE8" => "\xE6\xB1\xA8", + "\xE3\xE9" => "\xE6\xB1\xA9", + "\xE3\xEA" => "\xE6\xB1\xB4", + "\xE3\xEB" => "\xE6\xB1\xB6", + "\xE3\xEC" => "\xE6\xB2\x86", + "\xE3\xED" => "\xE6\xB2\xA9", + "\xE3\xEE" => "\xE6\xB3\x90", + "\xE3\xEF" => "\xE6\xB3\x94", + "\xE3\xF0" => "\xE6\xB2\xAD", + "\xE3\xF1" => "\xE6\xB3\xB7", + "\xE3\xF2" => "\xE6\xB3\xB8", + "\xE3\xF3" => "\xE6\xB3\xB1", + "\xE3\xF4" => "\xE6\xB3\x97", + "\xE3\xF5" => "\xE6\xB2\xB2", + "\xE3\xF6" => "\xE6\xB3\xA0", + "\xE3\xF7" => "\xE6\xB3\x96", + "\xE3\xF8" => "\xE6\xB3\xBA", + "\xE3\xF9" => "\xE6\xB3\xAB", + "\xE3\xFA" => "\xE6\xB3\xAE", + "\xE3\xFB" => "\xE6\xB2\xB1", + "\xE3\xFC" => "\xE6\xB3\x93", + "\xE3\xFD" => "\xE6\xB3\xAF", + "\xE3\xFE" => "\xE6\xB3\xBE", + "\xE4\xA1" => "\xE6\xB4\xB9", + "\xE4\xA2" => "\xE6\xB4\xA7", + "\xE4\xA3" => "\xE6\xB4\x8C", + "\xE4\xA4" => "\xE6\xB5\x83", + "\xE4\xA5" => "\xE6\xB5\x88", + "\xE4\xA6" => "\xE6\xB4\x87", + "\xE4\xA7" => "\xE6\xB4\x84", + "\xE4\xA8" => "\xE6\xB4\x99", + "\xE4\xA9" => "\xE6\xB4\x8E", + "\xE4\xAA" => "\xE6\xB4\xAB", + "\xE4\xAB" => "\xE6\xB5\x8D", + "\xE4\xAC" => "\xE6\xB4\xAE", + "\xE4\xAD" => "\xE6\xB4\xB5", + "\xE4\xAE" => "\xE6\xB4\x9A", + "\xE4\xAF" => "\xE6\xB5\x8F", + "\xE4\xB0" => "\xE6\xB5\x92", + "\xE4\xB1" => "\xE6\xB5\x94", + "\xE4\xB2" => "\xE6\xB4\xB3", + "\xE4\xB3" => "\xE6\xB6\x91", + "\xE4\xB4" => "\xE6\xB5\xAF", + "\xE4\xB5" => "\xE6\xB6\x9E", + "\xE4\xB6" => "\xE6\xB6\xA0", + "\xE4\xB7" => "\xE6\xB5\x9E", + "\xE4\xB8" => "\xE6\xB6\x93", + "\xE4\xB9" => "\xE6\xB6\x94", + "\xE4\xBA" => "\xE6\xB5\x9C", + "\xE4\xBB" => "\xE6\xB5\xA0", + "\xE4\xBC" => "\xE6\xB5\xBC", + "\xE4\xBD" => "\xE6\xB5\xA3", + "\xE4\xBE" => "\xE6\xB8\x9A", + "\xE4\xBF" => "\xE6\xB7\x87", + "\xE4\xC0" => "\xE6\xB7\x85", + "\xE4\xC1" => "\xE6\xB7\x9E", + "\xE4\xC2" => "\xE6\xB8\x8E", + "\xE4\xC3" => "\xE6\xB6\xBF", + "\xE4\xC4" => "\xE6\xB7\xA0", + "\xE4\xC5" => "\xE6\xB8\x91", + "\xE4\xC6" => "\xE6\xB7\xA6", + "\xE4\xC7" => "\xE6\xB7\x9D", + "\xE4\xC8" => "\xE6\xB7\x99", + "\xE4\xC9" => "\xE6\xB8\x96", + "\xE4\xCA" => "\xE6\xB6\xAB", + "\xE4\xCB" => "\xE6\xB8\x8C", + "\xE4\xCC" => "\xE6\xB6\xAE", + "\xE4\xCD" => "\xE6\xB8\xAB", + "\xE4\xCE" => "\xE6\xB9\xAE", + "\xE4\xCF" => "\xE6\xB9\x8E", + "\xE4\xD0" => "\xE6\xB9\xAB", + "\xE4\xD1" => "\xE6\xBA\xB2", + "\xE4\xD2" => "\xE6\xB9\x9F", + "\xE4\xD3" => "\xE6\xBA\x86", + "\xE4\xD4" => "\xE6\xB9\x93", + "\xE4\xD5" => "\xE6\xB9\x94", + "\xE4\xD6" => "\xE6\xB8\xB2", + "\xE4\xD7" => "\xE6\xB8\xA5", + "\xE4\xD8" => "\xE6\xB9\x84", + "\xE4\xD9" => "\xE6\xBB\x9F", + "\xE4\xDA" => "\xE6\xBA\xB1", + "\xE4\xDB" => "\xE6\xBA\x98", + "\xE4\xDC" => "\xE6\xBB\xA0", + "\xE4\xDD" => "\xE6\xBC\xAD", + "\xE4\xDE" => "\xE6\xBB\xA2", + "\xE4\xDF" => "\xE6\xBA\xA5", + "\xE4\xE0" => "\xE6\xBA\xA7", + "\xE4\xE1" => "\xE6\xBA\xBD", + "\xE4\xE2" => "\xE6\xBA\xBB", + "\xE4\xE3" => "\xE6\xBA\xB7", + "\xE4\xE4" => "\xE6\xBB\x97", + "\xE4\xE5" => "\xE6\xBA\xB4", + "\xE4\xE6" => "\xE6\xBB\x8F", + "\xE4\xE7" => "\xE6\xBA\x8F", + "\xE4\xE8" => "\xE6\xBB\x82", + "\xE4\xE9" => "\xE6\xBA\x9F", + "\xE4\xEA" => "\xE6\xBD\xA2", + "\xE4\xEB" => "\xE6\xBD\x86", + "\xE4\xEC" => "\xE6\xBD\x87", + "\xE4\xED" => "\xE6\xBC\xA4", + "\xE4\xEE" => "\xE6\xBC\x95", + "\xE4\xEF" => "\xE6\xBB\xB9", + "\xE4\xF0" => "\xE6\xBC\xAF", + "\xE4\xF1" => "\xE6\xBC\xB6", + "\xE4\xF2" => "\xE6\xBD\x8B", + "\xE4\xF3" => "\xE6\xBD\xB4", + "\xE4\xF4" => "\xE6\xBC\xAA", + "\xE4\xF5" => "\xE6\xBC\x89", + "\xE4\xF6" => "\xE6\xBC\xA9", + "\xE4\xF7" => "\xE6\xBE\x89", + "\xE4\xF8" => "\xE6\xBE\x8D", + "\xE4\xF9" => "\xE6\xBE\x8C", + "\xE4\xFA" => "\xE6\xBD\xB8", + "\xE4\xFB" => "\xE6\xBD\xB2", + "\xE4\xFC" => "\xE6\xBD\xBC", + "\xE4\xFD" => "\xE6\xBD\xBA", + "\xE4\xFE" => "\xE6\xBF\x91", + "\xE5\xA1" => "\xE6\xBF\x89", + "\xE5\xA2" => "\xE6\xBE\xA7", + "\xE5\xA3" => "\xE6\xBE\xB9", + "\xE5\xA4" => "\xE6\xBE\xB6", + "\xE5\xA5" => "\xE6\xBF\x82", + "\xE5\xA6" => "\xE6\xBF\xA1", + "\xE5\xA7" => "\xE6\xBF\xAE", + "\xE5\xA8" => "\xE6\xBF\x9E", + "\xE5\xA9" => "\xE6\xBF\xA0", + "\xE5\xAA" => "\xE6\xBF\xAF", + "\xE5\xAB" => "\xE7\x80\x9A", + "\xE5\xAC" => "\xE7\x80\xA3", + "\xE5\xAD" => "\xE7\x80\x9B", + "\xE5\xAE" => "\xE7\x80\xB9", + "\xE5\xAF" => "\xE7\x80\xB5", + "\xE5\xB0" => "\xE7\x81\x8F", + "\xE5\xB1" => "\xE7\x81\x9E", + "\xE5\xB2" => "\xE5\xAE\x80", + "\xE5\xB3" => "\xE5\xAE\x84", + "\xE5\xB4" => "\xE5\xAE\x95", + "\xE5\xB5" => "\xE5\xAE\x93", + "\xE5\xB6" => "\xE5\xAE\xA5", + "\xE5\xB7" => "\xE5\xAE\xB8", + "\xE5\xB8" => "\xE7\x94\xAF", + "\xE5\xB9" => "\xE9\xAA\x9E", + "\xE5\xBA" => "\xE6\x90\xB4", + "\xE5\xBB" => "\xE5\xAF\xA4", + "\xE5\xBC" => "\xE5\xAF\xAE", + "\xE5\xBD" => "\xE8\xA4\xB0", + "\xE5\xBE" => "\xE5\xAF\xB0", + "\xE5\xBF" => "\xE8\xB9\x87", + "\xE5\xC0" => "\xE8\xAC\x87", + "\xE5\xC1" => "\xE8\xBE\xB6", + "\xE5\xC2" => "\xE8\xBF\x93", + "\xE5\xC3" => "\xE8\xBF\x95", + "\xE5\xC4" => "\xE8\xBF\xA5", + "\xE5\xC5" => "\xE8\xBF\xAE", + "\xE5\xC6" => "\xE8\xBF\xA4", + "\xE5\xC7" => "\xE8\xBF\xA9", + "\xE5\xC8" => "\xE8\xBF\xA6", + "\xE5\xC9" => "\xE8\xBF\xB3", + "\xE5\xCA" => "\xE8\xBF\xA8", + "\xE5\xCB" => "\xE9\x80\x85", + "\xE5\xCC" => "\xE9\x80\x84", + "\xE5\xCD" => "\xE9\x80\x8B", + "\xE5\xCE" => "\xE9\x80\xA6", + "\xE5\xCF" => "\xE9\x80\x91", + "\xE5\xD0" => "\xE9\x80\x8D", + "\xE5\xD1" => "\xE9\x80\x96", + "\xE5\xD2" => "\xE9\x80\xA1", + "\xE5\xD3" => "\xE9\x80\xB5", + "\xE5\xD4" => "\xE9\x80\xB6", + "\xE5\xD5" => "\xE9\x80\xAD", + "\xE5\xD6" => "\xE9\x80\xAF", + "\xE5\xD7" => "\xE9\x81\x84", + "\xE5\xD8" => "\xE9\x81\x91", + "\xE5\xD9" => "\xE9\x81\x92", + "\xE5\xDA" => "\xE9\x81\x90", + "\xE5\xDB" => "\xE9\x81\xA8", + "\xE5\xDC" => "\xE9\x81\x98", + "\xE5\xDD" => "\xE9\x81\xA2", + "\xE5\xDE" => "\xE9\x81\x9B", + "\xE5\xDF" => "\xE6\x9A\xB9", + "\xE5\xE0" => "\xE9\x81\xB4", + "\xE5\xE1" => "\xE9\x81\xBD", + "\xE5\xE2" => "\xE9\x82\x82", + "\xE5\xE3" => "\xE9\x82\x88", + "\xE5\xE4" => "\xE9\x82\x83", + "\xE5\xE5" => "\xE9\x82\x8B", + "\xE5\xE6" => "\xE5\xBD\x90", + "\xE5\xE7" => "\xE5\xBD\x97", + "\xE5\xE8" => "\xE5\xBD\x96", + "\xE5\xE9" => "\xE5\xBD\x98", + "\xE5\xEA" => "\xE5\xB0\xBB", + "\xE5\xEB" => "\xE5\x92\xAB", + "\xE5\xEC" => "\xE5\xB1\x90", + "\xE5\xED" => "\xE5\xB1\x99", + "\xE5\xEE" => "\xE5\xAD\xB1", + "\xE5\xEF" => "\xE5\xB1\xA3", + "\xE5\xF0" => "\xE5\xB1\xA6", + "\xE5\xF1" => "\xE7\xBE\xBC", + "\xE5\xF2" => "\xE5\xBC\xAA", + "\xE5\xF3" => "\xE5\xBC\xA9", + "\xE5\xF4" => "\xE5\xBC\xAD", + "\xE5\xF5" => "\xE8\x89\xB4", + "\xE5\xF6" => "\xE5\xBC\xBC", + "\xE5\xF7" => "\xE9\xAC\xBB", + "\xE5\xF8" => "\xE5\xB1\xAE", + "\xE5\xF9" => "\xE5\xA6\x81", + "\xE5\xFA" => "\xE5\xA6\x83", + "\xE5\xFB" => "\xE5\xA6\x8D", + "\xE5\xFC" => "\xE5\xA6\xA9", + "\xE5\xFD" => "\xE5\xA6\xAA", + "\xE5\xFE" => "\xE5\xA6\xA3", + "\xE6\xA1" => "\xE5\xA6\x97", + "\xE6\xA2" => "\xE5\xA7\x8A", + "\xE6\xA3" => "\xE5\xA6\xAB", + "\xE6\xA4" => "\xE5\xA6\x9E", + "\xE6\xA5" => "\xE5\xA6\xA4", + "\xE6\xA6" => "\xE5\xA7\x92", + "\xE6\xA7" => "\xE5\xA6\xB2", + "\xE6\xA8" => "\xE5\xA6\xAF", + "\xE6\xA9" => "\xE5\xA7\x97", + "\xE6\xAA" => "\xE5\xA6\xBE", + "\xE6\xAB" => "\xE5\xA8\x85", + "\xE6\xAC" => "\xE5\xA8\x86", + "\xE6\xAD" => "\xE5\xA7\x9D", + "\xE6\xAE" => "\xE5\xA8\x88", + "\xE6\xAF" => "\xE5\xA7\xA3", + "\xE6\xB0" => "\xE5\xA7\x98", + "\xE6\xB1" => "\xE5\xA7\xB9", + "\xE6\xB2" => "\xE5\xA8\x8C", + "\xE6\xB3" => "\xE5\xA8\x89", + "\xE6\xB4" => "\xE5\xA8\xB2", + "\xE6\xB5" => "\xE5\xA8\xB4", + "\xE6\xB6" => "\xE5\xA8\x91", + "\xE6\xB7" => "\xE5\xA8\xA3", + "\xE6\xB8" => "\xE5\xA8\x93", + "\xE6\xB9" => "\xE5\xA9\x80", + "\xE6\xBA" => "\xE5\xA9\xA7", + "\xE6\xBB" => "\xE5\xA9\x8A", + "\xE6\xBC" => "\xE5\xA9\x95", + "\xE6\xBD" => "\xE5\xA8\xBC", + "\xE6\xBE" => "\xE5\xA9\xA2", + "\xE6\xBF" => "\xE5\xA9\xB5", + "\xE6\xC0" => "\xE8\x83\xAC", + "\xE6\xC1" => "\xE5\xAA\xAA", + "\xE6\xC2" => "\xE5\xAA\x9B", + "\xE6\xC3" => "\xE5\xA9\xB7", + "\xE6\xC4" => "\xE5\xA9\xBA", + "\xE6\xC5" => "\xE5\xAA\xBE", + "\xE6\xC6" => "\xE5\xAB\xAB", + "\xE6\xC7" => "\xE5\xAA\xB2", + "\xE6\xC8" => "\xE5\xAB\x92", + "\xE6\xC9" => "\xE5\xAB\x94", + "\xE6\xCA" => "\xE5\xAA\xB8", + "\xE6\xCB" => "\xE5\xAB\xA0", + "\xE6\xCC" => "\xE5\xAB\xA3", + "\xE6\xCD" => "\xE5\xAB\xB1", + "\xE6\xCE" => "\xE5\xAB\x96", + "\xE6\xCF" => "\xE5\xAB\xA6", + "\xE6\xD0" => "\xE5\xAB\x98", + "\xE6\xD1" => "\xE5\xAB\x9C", + "\xE6\xD2" => "\xE5\xAC\x89", + "\xE6\xD3" => "\xE5\xAC\x97", + "\xE6\xD4" => "\xE5\xAC\x96", + "\xE6\xD5" => "\xE5\xAC\xB2", + "\xE6\xD6" => "\xE5\xAC\xB7", + "\xE6\xD7" => "\xE5\xAD\x80", + "\xE6\xD8" => "\xE5\xB0\x95", + "\xE6\xD9" => "\xE5\xB0\x9C", + "\xE6\xDA" => "\xE5\xAD\x9A", + "\xE6\xDB" => "\xE5\xAD\xA5", + "\xE6\xDC" => "\xE5\xAD\xB3", + "\xE6\xDD" => "\xE5\xAD\x91", + "\xE6\xDE" => "\xE5\xAD\x93", + "\xE6\xDF" => "\xE5\xAD\xA2", + "\xE6\xE0" => "\xE9\xA9\xB5", + "\xE6\xE1" => "\xE9\xA9\xB7", + "\xE6\xE2" => "\xE9\xA9\xB8", + "\xE6\xE3" => "\xE9\xA9\xBA", + "\xE6\xE4" => "\xE9\xA9\xBF", + "\xE6\xE5" => "\xE9\xA9\xBD", + "\xE6\xE6" => "\xE9\xAA\x80", + "\xE6\xE7" => "\xE9\xAA\x81", + "\xE6\xE8" => "\xE9\xAA\x85", + "\xE6\xE9" => "\xE9\xAA\x88", + "\xE6\xEA" => "\xE9\xAA\x8A", + "\xE6\xEB" => "\xE9\xAA\x90", + "\xE6\xEC" => "\xE9\xAA\x92", + "\xE6\xED" => "\xE9\xAA\x93", + "\xE6\xEE" => "\xE9\xAA\x96", + "\xE6\xEF" => "\xE9\xAA\x98", + "\xE6\xF0" => "\xE9\xAA\x9B", + "\xE6\xF1" => "\xE9\xAA\x9C", + "\xE6\xF2" => "\xE9\xAA\x9D", + "\xE6\xF3" => "\xE9\xAA\x9F", + "\xE6\xF4" => "\xE9\xAA\xA0", + "\xE6\xF5" => "\xE9\xAA\xA2", + "\xE6\xF6" => "\xE9\xAA\xA3", + "\xE6\xF7" => "\xE9\xAA\xA5", + "\xE6\xF8" => "\xE9\xAA\xA7", + "\xE6\xF9" => "\xE7\xBA\x9F", + "\xE6\xFA" => "\xE7\xBA\xA1", + "\xE6\xFB" => "\xE7\xBA\xA3", + "\xE6\xFC" => "\xE7\xBA\xA5", + "\xE6\xFD" => "\xE7\xBA\xA8", + "\xE6\xFE" => "\xE7\xBA\xA9", + "\xE7\xA1" => "\xE7\xBA\xAD", + "\xE7\xA2" => "\xE7\xBA\xB0", + "\xE7\xA3" => "\xE7\xBA\xBE", + "\xE7\xA4" => "\xE7\xBB\x80", + "\xE7\xA5" => "\xE7\xBB\x81", + "\xE7\xA6" => "\xE7\xBB\x82", + "\xE7\xA7" => "\xE7\xBB\x89", + "\xE7\xA8" => "\xE7\xBB\x8B", + "\xE7\xA9" => "\xE7\xBB\x8C", + "\xE7\xAA" => "\xE7\xBB\x90", + "\xE7\xAB" => "\xE7\xBB\x94", + "\xE7\xAC" => "\xE7\xBB\x97", + "\xE7\xAD" => "\xE7\xBB\x9B", + "\xE7\xAE" => "\xE7\xBB\xA0", + "\xE7\xAF" => "\xE7\xBB\xA1", + "\xE7\xB0" => "\xE7\xBB\xA8", + "\xE7\xB1" => "\xE7\xBB\xAB", + "\xE7\xB2" => "\xE7\xBB\xAE", + "\xE7\xB3" => "\xE7\xBB\xAF", + "\xE7\xB4" => "\xE7\xBB\xB1", + "\xE7\xB5" => "\xE7\xBB\xB2", + "\xE7\xB6" => "\xE7\xBC\x8D", + "\xE7\xB7" => "\xE7\xBB\xB6", + "\xE7\xB8" => "\xE7\xBB\xBA", + "\xE7\xB9" => "\xE7\xBB\xBB", + "\xE7\xBA" => "\xE7\xBB\xBE", + "\xE7\xBB" => "\xE7\xBC\x81", + "\xE7\xBC" => "\xE7\xBC\x82", + "\xE7\xBD" => "\xE7\xBC\x83", + "\xE7\xBE" => "\xE7\xBC\x87", + "\xE7\xBF" => "\xE7\xBC\x88", + "\xE7\xC0" => "\xE7\xBC\x8B", + "\xE7\xC1" => "\xE7\xBC\x8C", + "\xE7\xC2" => "\xE7\xBC\x8F", + "\xE7\xC3" => "\xE7\xBC\x91", + "\xE7\xC4" => "\xE7\xBC\x92", + "\xE7\xC5" => "\xE7\xBC\x97", + "\xE7\xC6" => "\xE7\xBC\x99", + "\xE7\xC7" => "\xE7\xBC\x9C", + "\xE7\xC8" => "\xE7\xBC\x9B", + "\xE7\xC9" => "\xE7\xBC\x9F", + "\xE7\xCA" => "\xE7\xBC\xA1", + "\xE7\xCB" => "\xE7\xBC\xA2", + "\xE7\xCC" => "\xE7\xBC\xA3", + "\xE7\xCD" => "\xE7\xBC\xA4", + "\xE7\xCE" => "\xE7\xBC\xA5", + "\xE7\xCF" => "\xE7\xBC\xA6", + "\xE7\xD0" => "\xE7\xBC\xA7", + "\xE7\xD1" => "\xE7\xBC\xAA", + "\xE7\xD2" => "\xE7\xBC\xAB", + "\xE7\xD3" => "\xE7\xBC\xAC", + "\xE7\xD4" => "\xE7\xBC\xAD", + "\xE7\xD5" => "\xE7\xBC\xAF", + "\xE7\xD6" => "\xE7\xBC\xB0", + "\xE7\xD7" => "\xE7\xBC\xB1", + "\xE7\xD8" => "\xE7\xBC\xB2", + "\xE7\xD9" => "\xE7\xBC\xB3", + "\xE7\xDA" => "\xE7\xBC\xB5", + "\xE7\xDB" => "\xE5\xB9\xBA", + "\xE7\xDC" => "\xE7\x95\xBF", + "\xE7\xDD" => "\xE5\xB7\x9B", + "\xE7\xDE" => "\xE7\x94\xBE", + "\xE7\xDF" => "\xE9\x82\x95", + "\xE7\xE0" => "\xE7\x8E\x8E", + "\xE7\xE1" => "\xE7\x8E\x91", + "\xE7\xE2" => "\xE7\x8E\xAE", + "\xE7\xE3" => "\xE7\x8E\xA2", + "\xE7\xE4" => "\xE7\x8E\x9F", + "\xE7\xE5" => "\xE7\x8F\x8F", + "\xE7\xE6" => "\xE7\x8F\x82", + "\xE7\xE7" => "\xE7\x8F\x91", + "\xE7\xE8" => "\xE7\x8E\xB7", + "\xE7\xE9" => "\xE7\x8E\xB3", + "\xE7\xEA" => "\xE7\x8F\x80", + "\xE7\xEB" => "\xE7\x8F\x89", + "\xE7\xEC" => "\xE7\x8F\x88", + "\xE7\xED" => "\xE7\x8F\xA5", + "\xE7\xEE" => "\xE7\x8F\x99", + "\xE7\xEF" => "\xE9\xA1\xBC", + "\xE7\xF0" => "\xE7\x90\x8A", + "\xE7\xF1" => "\xE7\x8F\xA9", + "\xE7\xF2" => "\xE7\x8F\xA7", + "\xE7\xF3" => "\xE7\x8F\x9E", + "\xE7\xF4" => "\xE7\x8E\xBA", + "\xE7\xF5" => "\xE7\x8F\xB2", + "\xE7\xF6" => "\xE7\x90\x8F", + "\xE7\xF7" => "\xE7\x90\xAA", + "\xE7\xF8" => "\xE7\x91\x9B", + "\xE7\xF9" => "\xE7\x90\xA6", + "\xE7\xFA" => "\xE7\x90\xA5", + "\xE7\xFB" => "\xE7\x90\xA8", + "\xE7\xFC" => "\xE7\x90\xB0", + "\xE7\xFD" => "\xE7\x90\xAE", + "\xE7\xFE" => "\xE7\x90\xAC", + "\xE8\xA1" => "\xE7\x90\x9B", + "\xE8\xA2" => "\xE7\x90\x9A", + "\xE8\xA3" => "\xE7\x91\x81", + "\xE8\xA4" => "\xE7\x91\x9C", + "\xE8\xA5" => "\xE7\x91\x97", + "\xE8\xA6" => "\xE7\x91\x95", + "\xE8\xA7" => "\xE7\x91\x99", + "\xE8\xA8" => "\xE7\x91\xB7", + "\xE8\xA9" => "\xE7\x91\xAD", + "\xE8\xAA" => "\xE7\x91\xBE", + "\xE8\xAB" => "\xE7\x92\x9C", + "\xE8\xAC" => "\xE7\x92\x8E", + "\xE8\xAD" => "\xE7\x92\x80", + "\xE8\xAE" => "\xE7\x92\x81", + "\xE8\xAF" => "\xE7\x92\x87", + "\xE8\xB0" => "\xE7\x92\x8B", + "\xE8\xB1" => "\xE7\x92\x9E", + "\xE8\xB2" => "\xE7\x92\xA8", + "\xE8\xB3" => "\xE7\x92\xA9", + "\xE8\xB4" => "\xE7\x92\x90", + "\xE8\xB5" => "\xE7\x92\xA7", + "\xE8\xB6" => "\xE7\x93\x92", + "\xE8\xB7" => "\xE7\x92\xBA", + "\xE8\xB8" => "\xE9\x9F\xAA", + "\xE8\xB9" => "\xE9\x9F\xAB", + "\xE8\xBA" => "\xE9\x9F\xAC", + "\xE8\xBB" => "\xE6\x9D\x8C", + "\xE8\xBC" => "\xE6\x9D\x93", + "\xE8\xBD" => "\xE6\x9D\x9E", + "\xE8\xBE" => "\xE6\x9D\x88", + "\xE8\xBF" => "\xE6\x9D\xA9", + "\xE8\xC0" => "\xE6\x9E\xA5", + "\xE8\xC1" => "\xE6\x9E\x87", + "\xE8\xC2" => "\xE6\x9D\xAA", + "\xE8\xC3" => "\xE6\x9D\xB3", + "\xE8\xC4" => "\xE6\x9E\x98", + "\xE8\xC5" => "\xE6\x9E\xA7", + "\xE8\xC6" => "\xE6\x9D\xB5", + "\xE8\xC7" => "\xE6\x9E\xA8", + "\xE8\xC8" => "\xE6\x9E\x9E", + "\xE8\xC9" => "\xE6\x9E\xAD", + "\xE8\xCA" => "\xE6\x9E\x8B", + "\xE8\xCB" => "\xE6\x9D\xB7", + "\xE8\xCC" => "\xE6\x9D\xBC", + "\xE8\xCD" => "\xE6\x9F\xB0", + "\xE8\xCE" => "\xE6\xA0\x89", + "\xE8\xCF" => "\xE6\x9F\x98", + "\xE8\xD0" => "\xE6\xA0\x8A", + "\xE8\xD1" => "\xE6\x9F\xA9", + "\xE8\xD2" => "\xE6\x9E\xB0", + "\xE8\xD3" => "\xE6\xA0\x8C", + "\xE8\xD4" => "\xE6\x9F\x99", + "\xE8\xD5" => "\xE6\x9E\xB5", + "\xE8\xD6" => "\xE6\x9F\x9A", + "\xE8\xD7" => "\xE6\x9E\xB3", + "\xE8\xD8" => "\xE6\x9F\x9D", + "\xE8\xD9" => "\xE6\xA0\x80", + "\xE8\xDA" => "\xE6\x9F\x83", + "\xE8\xDB" => "\xE6\x9E\xB8", + "\xE8\xDC" => "\xE6\x9F\xA2", + "\xE8\xDD" => "\xE6\xA0\x8E", + "\xE8\xDE" => "\xE6\x9F\x81", + "\xE8\xDF" => "\xE6\x9F\xBD", + "\xE8\xE0" => "\xE6\xA0\xB2", + "\xE8\xE1" => "\xE6\xA0\xB3", + "\xE8\xE2" => "\xE6\xA1\xA0", + "\xE8\xE3" => "\xE6\xA1\xA1", + "\xE8\xE4" => "\xE6\xA1\x8E", + "\xE8\xE5" => "\xE6\xA1\xA2", + "\xE8\xE6" => "\xE6\xA1\x84", + "\xE8\xE7" => "\xE6\xA1\xA4", + "\xE8\xE8" => "\xE6\xA2\x83", + "\xE8\xE9" => "\xE6\xA0\x9D", + "\xE8\xEA" => "\xE6\xA1\x95", + "\xE8\xEB" => "\xE6\xA1\xA6", + "\xE8\xEC" => "\xE6\xA1\x81", + "\xE8\xED" => "\xE6\xA1\xA7", + "\xE8\xEE" => "\xE6\xA1\x80", + "\xE8\xEF" => "\xE6\xA0\xBE", + "\xE8\xF0" => "\xE6\xA1\x8A", + "\xE8\xF1" => "\xE6\xA1\x89", + "\xE8\xF2" => "\xE6\xA0\xA9", + "\xE8\xF3" => "\xE6\xA2\xB5", + "\xE8\xF4" => "\xE6\xA2\x8F", + "\xE8\xF5" => "\xE6\xA1\xB4", + "\xE8\xF6" => "\xE6\xA1\xB7", + "\xE8\xF7" => "\xE6\xA2\x93", + "\xE8\xF8" => "\xE6\xA1\xAB", + "\xE8\xF9" => "\xE6\xA3\x82", + "\xE8\xFA" => "\xE6\xA5\xAE", + "\xE8\xFB" => "\xE6\xA3\xBC", + "\xE8\xFC" => "\xE6\xA4\x9F", + "\xE8\xFD" => "\xE6\xA4\xA0", + "\xE8\xFE" => "\xE6\xA3\xB9", + "\xE9\xA1" => "\xE6\xA4\xA4", + "\xE9\xA2" => "\xE6\xA3\xB0", + "\xE9\xA3" => "\xE6\xA4\x8B", + "\xE9\xA4" => "\xE6\xA4\x81", + "\xE9\xA5" => "\xE6\xA5\x97", + "\xE9\xA6" => "\xE6\xA3\xA3", + "\xE9\xA7" => "\xE6\xA4\x90", + "\xE9\xA8" => "\xE6\xA5\xB1", + "\xE9\xA9" => "\xE6\xA4\xB9", + "\xE9\xAA" => "\xE6\xA5\xA0", + "\xE9\xAB" => "\xE6\xA5\x82", + "\xE9\xAC" => "\xE6\xA5\x9D", + "\xE9\xAD" => "\xE6\xA6\x84", + "\xE9\xAE" => "\xE6\xA5\xAB", + "\xE9\xAF" => "\xE6\xA6\x80", + "\xE9\xB0" => "\xE6\xA6\x98", + "\xE9\xB1" => "\xE6\xA5\xB8", + "\xE9\xB2" => "\xE6\xA4\xB4", + "\xE9\xB3" => "\xE6\xA7\x8C", + "\xE9\xB4" => "\xE6\xA6\x87", + "\xE9\xB5" => "\xE6\xA6\x88", + "\xE9\xB6" => "\xE6\xA7\x8E", + "\xE9\xB7" => "\xE6\xA6\x89", + "\xE9\xB8" => "\xE6\xA5\xA6", + "\xE9\xB9" => "\xE6\xA5\xA3", + "\xE9\xBA" => "\xE6\xA5\xB9", + "\xE9\xBB" => "\xE6\xA6\x9B", + "\xE9\xBC" => "\xE6\xA6\xA7", + "\xE9\xBD" => "\xE6\xA6\xBB", + "\xE9\xBE" => "\xE6\xA6\xAB", + "\xE9\xBF" => "\xE6\xA6\xAD", + "\xE9\xC0" => "\xE6\xA7\x94", + "\xE9\xC1" => "\xE6\xA6\xB1", + "\xE9\xC2" => "\xE6\xA7\x81", + "\xE9\xC3" => "\xE6\xA7\x8A", + "\xE9\xC4" => "\xE6\xA7\x9F", + "\xE9\xC5" => "\xE6\xA6\x95", + "\xE9\xC6" => "\xE6\xA7\xA0", + "\xE9\xC7" => "\xE6\xA6\x8D", + "\xE9\xC8" => "\xE6\xA7\xBF", + "\xE9\xC9" => "\xE6\xA8\xAF", + "\xE9\xCA" => "\xE6\xA7\xAD", + "\xE9\xCB" => "\xE6\xA8\x97", + "\xE9\xCC" => "\xE6\xA8\x98", + "\xE9\xCD" => "\xE6\xA9\xA5", + "\xE9\xCE" => "\xE6\xA7\xB2", + "\xE9\xCF" => "\xE6\xA9\x84", + "\xE9\xD0" => "\xE6\xA8\xBE", + "\xE9\xD1" => "\xE6\xAA\xA0", + "\xE9\xD2" => "\xE6\xA9\x90", + "\xE9\xD3" => "\xE6\xA9\x9B", + "\xE9\xD4" => "\xE6\xA8\xB5", + "\xE9\xD5" => "\xE6\xAA\x8E", + "\xE9\xD6" => "\xE6\xA9\xB9", + "\xE9\xD7" => "\xE6\xA8\xBD", + "\xE9\xD8" => "\xE6\xA8\xA8", + "\xE9\xD9" => "\xE6\xA9\x98", + "\xE9\xDA" => "\xE6\xA9\xBC", + "\xE9\xDB" => "\xE6\xAA\x91", + "\xE9\xDC" => "\xE6\xAA\x90", + "\xE9\xDD" => "\xE6\xAA\xA9", + "\xE9\xDE" => "\xE6\xAA\x97", + "\xE9\xDF" => "\xE6\xAA\xAB", + "\xE9\xE0" => "\xE7\x8C\xB7", + "\xE9\xE1" => "\xE7\x8D\x92", + "\xE9\xE2" => "\xE6\xAE\x81", + "\xE9\xE3" => "\xE6\xAE\x82", + "\xE9\xE4" => "\xE6\xAE\x87", + "\xE9\xE5" => "\xE6\xAE\x84", + "\xE9\xE6" => "\xE6\xAE\x92", + "\xE9\xE7" => "\xE6\xAE\x93", + "\xE9\xE8" => "\xE6\xAE\x8D", + "\xE9\xE9" => "\xE6\xAE\x9A", + "\xE9\xEA" => "\xE6\xAE\x9B", + "\xE9\xEB" => "\xE6\xAE\xA1", + "\xE9\xEC" => "\xE6\xAE\xAA", + "\xE9\xED" => "\xE8\xBD\xAB", + "\xE9\xEE" => "\xE8\xBD\xAD", + "\xE9\xEF" => "\xE8\xBD\xB1", + "\xE9\xF0" => "\xE8\xBD\xB2", + "\xE9\xF1" => "\xE8\xBD\xB3", + "\xE9\xF2" => "\xE8\xBD\xB5", + "\xE9\xF3" => "\xE8\xBD\xB6", + "\xE9\xF4" => "\xE8\xBD\xB8", + "\xE9\xF5" => "\xE8\xBD\xB7", + "\xE9\xF6" => "\xE8\xBD\xB9", + "\xE9\xF7" => "\xE8\xBD\xBA", + "\xE9\xF8" => "\xE8\xBD\xBC", + "\xE9\xF9" => "\xE8\xBD\xBE", + "\xE9\xFA" => "\xE8\xBE\x81", + "\xE9\xFB" => "\xE8\xBE\x82", + "\xE9\xFC" => "\xE8\xBE\x84", + "\xE9\xFD" => "\xE8\xBE\x87", + "\xE9\xFE" => "\xE8\xBE\x8B", + "\xEA\xA1" => "\xE8\xBE\x8D", + "\xEA\xA2" => "\xE8\xBE\x8E", + "\xEA\xA3" => "\xE8\xBE\x8F", + "\xEA\xA4" => "\xE8\xBE\x98", + "\xEA\xA5" => "\xE8\xBE\x9A", + "\xEA\xA6" => "\xE8\xBB\x8E", + "\xEA\xA7" => "\xE6\x88\x8B", + "\xEA\xA8" => "\xE6\x88\x97", + "\xEA\xA9" => "\xE6\x88\x9B", + "\xEA\xAA" => "\xE6\x88\x9F", + "\xEA\xAB" => "\xE6\x88\xA2", + "\xEA\xAC" => "\xE6\x88\xA1", + "\xEA\xAD" => "\xE6\x88\xA5", + "\xEA\xAE" => "\xE6\x88\xA4", + "\xEA\xAF" => "\xE6\x88\xAC", + "\xEA\xB0" => "\xE8\x87\xA7", + "\xEA\xB1" => "\xE7\x93\xAF", + "\xEA\xB2" => "\xE7\x93\xB4", + "\xEA\xB3" => "\xE7\x93\xBF", + "\xEA\xB4" => "\xE7\x94\x8F", + "\xEA\xB5" => "\xE7\x94\x91", + "\xEA\xB6" => "\xE7\x94\x93", + "\xEA\xB7" => "\xE6\x94\xB4", + "\xEA\xB8" => "\xE6\x97\xAE", + "\xEA\xB9" => "\xE6\x97\xAF", + "\xEA\xBA" => "\xE6\x97\xB0", + "\xEA\xBB" => "\xE6\x98\x8A", + "\xEA\xBC" => "\xE6\x98\x99", + "\xEA\xBD" => "\xE6\x9D\xB2", + "\xEA\xBE" => "\xE6\x98\x83", + "\xEA\xBF" => "\xE6\x98\x95", + "\xEA\xC0" => "\xE6\x98\x80", + "\xEA\xC1" => "\xE7\x82\x85", + "\xEA\xC2" => "\xE6\x9B\xB7", + "\xEA\xC3" => "\xE6\x98\x9D", + "\xEA\xC4" => "\xE6\x98\xB4", + "\xEA\xC5" => "\xE6\x98\xB1", + "\xEA\xC6" => "\xE6\x98\xB6", + "\xEA\xC7" => "\xE6\x98\xB5", + "\xEA\xC8" => "\xE8\x80\x86", + "\xEA\xC9" => "\xE6\x99\x9F", + "\xEA\xCA" => "\xE6\x99\x94", + "\xEA\xCB" => "\xE6\x99\x81", + "\xEA\xCC" => "\xE6\x99\x8F", + "\xEA\xCD" => "\xE6\x99\x96", + "\xEA\xCE" => "\xE6\x99\xA1", + "\xEA\xCF" => "\xE6\x99\x97", + "\xEA\xD0" => "\xE6\x99\xB7", + "\xEA\xD1" => "\xE6\x9A\x84", + "\xEA\xD2" => "\xE6\x9A\x8C", + "\xEA\xD3" => "\xE6\x9A\xA7", + "\xEA\xD4" => "\xE6\x9A\x9D", + "\xEA\xD5" => "\xE6\x9A\xBE", + "\xEA\xD6" => "\xE6\x9B\x9B", + "\xEA\xD7" => "\xE6\x9B\x9C", + "\xEA\xD8" => "\xE6\x9B\xA6", + "\xEA\xD9" => "\xE6\x9B\xA9", + "\xEA\xDA" => "\xE8\xB4\xB2", + "\xEA\xDB" => "\xE8\xB4\xB3", + "\xEA\xDC" => "\xE8\xB4\xB6", + "\xEA\xDD" => "\xE8\xB4\xBB", + "\xEA\xDE" => "\xE8\xB4\xBD", + "\xEA\xDF" => "\xE8\xB5\x80", + "\xEA\xE0" => "\xE8\xB5\x85", + "\xEA\xE1" => "\xE8\xB5\x86", + "\xEA\xE2" => "\xE8\xB5\x88", + "\xEA\xE3" => "\xE8\xB5\x89", + "\xEA\xE4" => "\xE8\xB5\x87", + "\xEA\xE5" => "\xE8\xB5\x8D", + "\xEA\xE6" => "\xE8\xB5\x95", + "\xEA\xE7" => "\xE8\xB5\x99", + "\xEA\xE8" => "\xE8\xA7\x87", + "\xEA\xE9" => "\xE8\xA7\x8A", + "\xEA\xEA" => "\xE8\xA7\x8B", + "\xEA\xEB" => "\xE8\xA7\x8C", + "\xEA\xEC" => "\xE8\xA7\x8E", + "\xEA\xED" => "\xE8\xA7\x8F", + "\xEA\xEE" => "\xE8\xA7\x90", + "\xEA\xEF" => "\xE8\xA7\x91", + "\xEA\xF0" => "\xE7\x89\xAE", + "\xEA\xF1" => "\xE7\x8A\x9F", + "\xEA\xF2" => "\xE7\x89\x9D", + "\xEA\xF3" => "\xE7\x89\xA6", + "\xEA\xF4" => "\xE7\x89\xAF", + "\xEA\xF5" => "\xE7\x89\xBE", + "\xEA\xF6" => "\xE7\x89\xBF", + "\xEA\xF7" => "\xE7\x8A\x84", + "\xEA\xF8" => "\xE7\x8A\x8B", + "\xEA\xF9" => "\xE7\x8A\x8D", + "\xEA\xFA" => "\xE7\x8A\x8F", + "\xEA\xFB" => "\xE7\x8A\x92", + "\xEA\xFC" => "\xE6\x8C\x88", + "\xEA\xFD" => "\xE6\x8C\xB2", + "\xEA\xFE" => "\xE6\x8E\xB0", + "\xEB\xA1" => "\xE6\x90\xBF", + "\xEB\xA2" => "\xE6\x93\x98", + "\xEB\xA3" => "\xE8\x80\x84", + "\xEB\xA4" => "\xE6\xAF\xAA", + "\xEB\xA5" => "\xE6\xAF\xB3", + "\xEB\xA6" => "\xE6\xAF\xBD", + "\xEB\xA7" => "\xE6\xAF\xB5", + "\xEB\xA8" => "\xE6\xAF\xB9", + "\xEB\xA9" => "\xE6\xB0\x85", + "\xEB\xAA" => "\xE6\xB0\x87", + "\xEB\xAB" => "\xE6\xB0\x86", + "\xEB\xAC" => "\xE6\xB0\x8D", + "\xEB\xAD" => "\xE6\xB0\x95", + "\xEB\xAE" => "\xE6\xB0\x98", + "\xEB\xAF" => "\xE6\xB0\x99", + "\xEB\xB0" => "\xE6\xB0\x9A", + "\xEB\xB1" => "\xE6\xB0\xA1", + "\xEB\xB2" => "\xE6\xB0\xA9", + "\xEB\xB3" => "\xE6\xB0\xA4", + "\xEB\xB4" => "\xE6\xB0\xAA", + "\xEB\xB5" => "\xE6\xB0\xB2", + "\xEB\xB6" => "\xE6\x94\xB5", + "\xEB\xB7" => "\xE6\x95\x95", + "\xEB\xB8" => "\xE6\x95\xAB", + "\xEB\xB9" => "\xE7\x89\x8D", + "\xEB\xBA" => "\xE7\x89\x92", + "\xEB\xBB" => "\xE7\x89\x96", + "\xEB\xBC" => "\xE7\x88\xB0", + "\xEB\xBD" => "\xE8\x99\xA2", + "\xEB\xBE" => "\xE5\x88\x96", + "\xEB\xBF" => "\xE8\x82\x9F", + "\xEB\xC0" => "\xE8\x82\x9C", + "\xEB\xC1" => "\xE8\x82\x93", + "\xEB\xC2" => "\xE8\x82\xBC", + "\xEB\xC3" => "\xE6\x9C\x8A", + "\xEB\xC4" => "\xE8\x82\xBD", + "\xEB\xC5" => "\xE8\x82\xB1", + "\xEB\xC6" => "\xE8\x82\xAB", + "\xEB\xC7" => "\xE8\x82\xAD", + "\xEB\xC8" => "\xE8\x82\xB4", + "\xEB\xC9" => "\xE8\x82\xB7", + "\xEB\xCA" => "\xE8\x83\xA7", + "\xEB\xCB" => "\xE8\x83\xA8", + "\xEB\xCC" => "\xE8\x83\xA9", + "\xEB\xCD" => "\xE8\x83\xAA", + "\xEB\xCE" => "\xE8\x83\x9B", + "\xEB\xCF" => "\xE8\x83\x82", + "\xEB\xD0" => "\xE8\x83\x84", + "\xEB\xD1" => "\xE8\x83\x99", + "\xEB\xD2" => "\xE8\x83\x8D", + "\xEB\xD3" => "\xE8\x83\x97", + "\xEB\xD4" => "\xE6\x9C\x90", + "\xEB\xD5" => "\xE8\x83\x9D", + "\xEB\xD6" => "\xE8\x83\xAB", + "\xEB\xD7" => "\xE8\x83\xB1", + "\xEB\xD8" => "\xE8\x83\xB4", + "\xEB\xD9" => "\xE8\x83\xAD", + "\xEB\xDA" => "\xE8\x84\x8D", + "\xEB\xDB" => "\xE8\x84\x8E", + "\xEB\xDC" => "\xE8\x83\xB2", + "\xEB\xDD" => "\xE8\x83\xBC", + "\xEB\xDE" => "\xE6\x9C\x95", + "\xEB\xDF" => "\xE8\x84\x92", + "\xEB\xE0" => "\xE8\xB1\x9A", + "\xEB\xE1" => "\xE8\x84\xB6", + "\xEB\xE2" => "\xE8\x84\x9E", + "\xEB\xE3" => "\xE8\x84\xAC", + "\xEB\xE4" => "\xE8\x84\x98", + "\xEB\xE5" => "\xE8\x84\xB2", + "\xEB\xE6" => "\xE8\x85\x88", + "\xEB\xE7" => "\xE8\x85\x8C", + "\xEB\xE8" => "\xE8\x85\x93", + "\xEB\xE9" => "\xE8\x85\xB4", + "\xEB\xEA" => "\xE8\x85\x99", + "\xEB\xEB" => "\xE8\x85\x9A", + "\xEB\xEC" => "\xE8\x85\xB1", + "\xEB\xED" => "\xE8\x85\xA0", + "\xEB\xEE" => "\xE8\x85\xA9", + "\xEB\xEF" => "\xE8\x85\xBC", + "\xEB\xF0" => "\xE8\x85\xBD", + "\xEB\xF1" => "\xE8\x85\xAD", + "\xEB\xF2" => "\xE8\x85\xA7", + "\xEB\xF3" => "\xE5\xA1\x8D", + "\xEB\xF4" => "\xE5\xAA\xB5", + "\xEB\xF5" => "\xE8\x86\x88", + "\xEB\xF6" => "\xE8\x86\x82", + "\xEB\xF7" => "\xE8\x86\x91", + "\xEB\xF8" => "\xE6\xBB\x95", + "\xEB\xF9" => "\xE8\x86\xA3", + "\xEB\xFA" => "\xE8\x86\xAA", + "\xEB\xFB" => "\xE8\x87\x8C", + "\xEB\xFC" => "\xE6\x9C\xA6", + "\xEB\xFD" => "\xE8\x87\x8A", + "\xEB\xFE" => "\xE8\x86\xBB", + "\xEC\xA1" => "\xE8\x87\x81", + "\xEC\xA2" => "\xE8\x86\xA6", + "\xEC\xA3" => "\xE6\xAC\xA4", + "\xEC\xA4" => "\xE6\xAC\xB7", + "\xEC\xA5" => "\xE6\xAC\xB9", + "\xEC\xA6" => "\xE6\xAD\x83", + "\xEC\xA7" => "\xE6\xAD\x86", + "\xEC\xA8" => "\xE6\xAD\x99", + "\xEC\xA9" => "\xE9\xA3\x91", + "\xEC\xAA" => "\xE9\xA3\x92", + "\xEC\xAB" => "\xE9\xA3\x93", + "\xEC\xAC" => "\xE9\xA3\x95", + "\xEC\xAD" => "\xE9\xA3\x99", + "\xEC\xAE" => "\xE9\xA3\x9A", + "\xEC\xAF" => "\xE6\xAE\xB3", + "\xEC\xB0" => "\xE5\xBD\x80", + "\xEC\xB1" => "\xE6\xAF\x82", + "\xEC\xB2" => "\xE8\xA7\xB3", + "\xEC\xB3" => "\xE6\x96\x90", + "\xEC\xB4" => "\xE9\xBD\x91", + "\xEC\xB5" => "\xE6\x96\x93", + "\xEC\xB6" => "\xE6\x96\xBC", + "\xEC\xB7" => "\xE6\x97\x86", + "\xEC\xB8" => "\xE6\x97\x84", + "\xEC\xB9" => "\xE6\x97\x83", + "\xEC\xBA" => "\xE6\x97\x8C", + "\xEC\xBB" => "\xE6\x97\x8E", + "\xEC\xBC" => "\xE6\x97\x92", + "\xEC\xBD" => "\xE6\x97\x96", + "\xEC\xBE" => "\xE7\x82\x80", + "\xEC\xBF" => "\xE7\x82\x9C", + "\xEC\xC0" => "\xE7\x82\x96", + "\xEC\xC1" => "\xE7\x82\x9D", + "\xEC\xC2" => "\xE7\x82\xBB", + "\xEC\xC3" => "\xE7\x83\x80", + "\xEC\xC4" => "\xE7\x82\xB7", + "\xEC\xC5" => "\xE7\x82\xAB", + "\xEC\xC6" => "\xE7\x82\xB1", + "\xEC\xC7" => "\xE7\x83\xA8", + "\xEC\xC8" => "\xE7\x83\x8A", + "\xEC\xC9" => "\xE7\x84\x90", + "\xEC\xCA" => "\xE7\x84\x93", + "\xEC\xCB" => "\xE7\x84\x96", + "\xEC\xCC" => "\xE7\x84\xAF", + "\xEC\xCD" => "\xE7\x84\xB1", + "\xEC\xCE" => "\xE7\x85\xB3", + "\xEC\xCF" => "\xE7\x85\x9C", + "\xEC\xD0" => "\xE7\x85\xA8", + "\xEC\xD1" => "\xE7\x85\x85", + "\xEC\xD2" => "\xE7\x85\xB2", + "\xEC\xD3" => "\xE7\x85\x8A", + "\xEC\xD4" => "\xE7\x85\xB8", + "\xEC\xD5" => "\xE7\x85\xBA", + "\xEC\xD6" => "\xE7\x86\x98", + "\xEC\xD7" => "\xE7\x86\xB3", + "\xEC\xD8" => "\xE7\x86\xB5", + "\xEC\xD9" => "\xE7\x86\xA8", + "\xEC\xDA" => "\xE7\x86\xA0", + "\xEC\xDB" => "\xE7\x87\xA0", + "\xEC\xDC" => "\xE7\x87\x94", + "\xEC\xDD" => "\xE7\x87\xA7", + "\xEC\xDE" => "\xE7\x87\xB9", + "\xEC\xDF" => "\xE7\x88\x9D", + "\xEC\xE0" => "\xE7\x88\xA8", + "\xEC\xE1" => "\xE7\x81\xAC", + "\xEC\xE2" => "\xE7\x84\x98", + "\xEC\xE3" => "\xE7\x85\xA6", + "\xEC\xE4" => "\xE7\x86\xB9", + "\xEC\xE5" => "\xE6\x88\xBE", + "\xEC\xE6" => "\xE6\x88\xBD", + "\xEC\xE7" => "\xE6\x89\x83", + "\xEC\xE8" => "\xE6\x89\x88", + "\xEC\xE9" => "\xE6\x89\x89", + "\xEC\xEA" => "\xE7\xA4\xBB", + "\xEC\xEB" => "\xE7\xA5\x80", + "\xEC\xEC" => "\xE7\xA5\x86", + "\xEC\xED" => "\xE7\xA5\x89", + "\xEC\xEE" => "\xE7\xA5\x9B", + "\xEC\xEF" => "\xE7\xA5\x9C", + "\xEC\xF0" => "\xE7\xA5\x93", + "\xEC\xF1" => "\xE7\xA5\x9A", + "\xEC\xF2" => "\xE7\xA5\xA2", + "\xEC\xF3" => "\xE7\xA5\x97", + "\xEC\xF4" => "\xE7\xA5\xA0", + "\xEC\xF5" => "\xE7\xA5\xAF", + "\xEC\xF6" => "\xE7\xA5\xA7", + "\xEC\xF7" => "\xE7\xA5\xBA", + "\xEC\xF8" => "\xE7\xA6\x85", + "\xEC\xF9" => "\xE7\xA6\x8A", + "\xEC\xFA" => "\xE7\xA6\x9A", + "\xEC\xFB" => "\xE7\xA6\xA7", + "\xEC\xFC" => "\xE7\xA6\xB3", + "\xEC\xFD" => "\xE5\xBF\x91", + "\xEC\xFE" => "\xE5\xBF\x90", + "\xED\xA1" => "\xE6\x80\xBC", + "\xED\xA2" => "\xE6\x81\x9D", + "\xED\xA3" => "\xE6\x81\x9A", + "\xED\xA4" => "\xE6\x81\xA7", + "\xED\xA5" => "\xE6\x81\x81", + "\xED\xA6" => "\xE6\x81\x99", + "\xED\xA7" => "\xE6\x81\xA3", + "\xED\xA8" => "\xE6\x82\xAB", + "\xED\xA9" => "\xE6\x84\x86", + "\xED\xAA" => "\xE6\x84\x8D", + "\xED\xAB" => "\xE6\x85\x9D", + "\xED\xAC" => "\xE6\x86\xA9", + "\xED\xAD" => "\xE6\x86\x9D", + "\xED\xAE" => "\xE6\x87\x8B", + "\xED\xAF" => "\xE6\x87\x91", + "\xED\xB0" => "\xE6\x88\x86", + "\xED\xB1" => "\xE8\x82\x80", + "\xED\xB2" => "\xE8\x81\xBF", + "\xED\xB3" => "\xE6\xB2\x93", + "\xED\xB4" => "\xE6\xB3\xB6", + "\xED\xB5" => "\xE6\xB7\xBC", + "\xED\xB6" => "\xE7\x9F\xB6", + "\xED\xB7" => "\xE7\x9F\xB8", + "\xED\xB8" => "\xE7\xA0\x80", + "\xED\xB9" => "\xE7\xA0\x89", + "\xED\xBA" => "\xE7\xA0\x97", + "\xED\xBB" => "\xE7\xA0\x98", + "\xED\xBC" => "\xE7\xA0\x91", + "\xED\xBD" => "\xE6\x96\xAB", + "\xED\xBE" => "\xE7\xA0\xAD", + "\xED\xBF" => "\xE7\xA0\x9C", + "\xED\xC0" => "\xE7\xA0\x9D", + "\xED\xC1" => "\xE7\xA0\xB9", + "\xED\xC2" => "\xE7\xA0\xBA", + "\xED\xC3" => "\xE7\xA0\xBB", + "\xED\xC4" => "\xE7\xA0\x9F", + "\xED\xC5" => "\xE7\xA0\xBC", + "\xED\xC6" => "\xE7\xA0\xA5", + "\xED\xC7" => "\xE7\xA0\xAC", + "\xED\xC8" => "\xE7\xA0\xA3", + "\xED\xC9" => "\xE7\xA0\xA9", + "\xED\xCA" => "\xE7\xA1\x8E", + "\xED\xCB" => "\xE7\xA1\xAD", + "\xED\xCC" => "\xE7\xA1\x96", + "\xED\xCD" => "\xE7\xA1\x97", + "\xED\xCE" => "\xE7\xA0\xA6", + "\xED\xCF" => "\xE7\xA1\x90", + "\xED\xD0" => "\xE7\xA1\x87", + "\xED\xD1" => "\xE7\xA1\x8C", + "\xED\xD2" => "\xE7\xA1\xAA", + "\xED\xD3" => "\xE7\xA2\x9B", + "\xED\xD4" => "\xE7\xA2\x93", + "\xED\xD5" => "\xE7\xA2\x9A", + "\xED\xD6" => "\xE7\xA2\x87", + "\xED\xD7" => "\xE7\xA2\x9C", + "\xED\xD8" => "\xE7\xA2\xA1", + "\xED\xD9" => "\xE7\xA2\xA3", + "\xED\xDA" => "\xE7\xA2\xB2", + "\xED\xDB" => "\xE7\xA2\xB9", + "\xED\xDC" => "\xE7\xA2\xA5", + "\xED\xDD" => "\xE7\xA3\x94", + "\xED\xDE" => "\xE7\xA3\x99", + "\xED\xDF" => "\xE7\xA3\x89", + "\xED\xE0" => "\xE7\xA3\xAC", + "\xED\xE1" => "\xE7\xA3\xB2", + "\xED\xE2" => "\xE7\xA4\x85", + "\xED\xE3" => "\xE7\xA3\xB4", + "\xED\xE4" => "\xE7\xA4\x93", + "\xED\xE5" => "\xE7\xA4\xA4", + "\xED\xE6" => "\xE7\xA4\x9E", + "\xED\xE7" => "\xE7\xA4\xB4", + "\xED\xE8" => "\xE9\xBE\x9B", + "\xED\xE9" => "\xE9\xBB\xB9", + "\xED\xEA" => "\xE9\xBB\xBB", + "\xED\xEB" => "\xE9\xBB\xBC", + "\xED\xEC" => "\xE7\x9B\xB1", + "\xED\xED" => "\xE7\x9C\x84", + "\xED\xEE" => "\xE7\x9C\x8D", + "\xED\xEF" => "\xE7\x9B\xB9", + "\xED\xF0" => "\xE7\x9C\x87", + "\xED\xF1" => "\xE7\x9C\x88", + "\xED\xF2" => "\xE7\x9C\x9A", + "\xED\xF3" => "\xE7\x9C\xA2", + "\xED\xF4" => "\xE7\x9C\x99", + "\xED\xF5" => "\xE7\x9C\xAD", + "\xED\xF6" => "\xE7\x9C\xA6", + "\xED\xF7" => "\xE7\x9C\xB5", + "\xED\xF8" => "\xE7\x9C\xB8", + "\xED\xF9" => "\xE7\x9D\x90", + "\xED\xFA" => "\xE7\x9D\x91", + "\xED\xFB" => "\xE7\x9D\x87", + "\xED\xFC" => "\xE7\x9D\x83", + "\xED\xFD" => "\xE7\x9D\x9A", + "\xED\xFE" => "\xE7\x9D\xA8", + "\xEE\xA1" => "\xE7\x9D\xA2", + "\xEE\xA2" => "\xE7\x9D\xA5", + "\xEE\xA3" => "\xE7\x9D\xBF", + "\xEE\xA4" => "\xE7\x9E\x8D", + "\xEE\xA5" => "\xE7\x9D\xBD", + "\xEE\xA6" => "\xE7\x9E\x80", + "\xEE\xA7" => "\xE7\x9E\x8C", + "\xEE\xA8" => "\xE7\x9E\x91", + "\xEE\xA9" => "\xE7\x9E\x9F", + "\xEE\xAA" => "\xE7\x9E\xA0", + "\xEE\xAB" => "\xE7\x9E\xB0", + "\xEE\xAC" => "\xE7\x9E\xB5", + "\xEE\xAD" => "\xE7\x9E\xBD", + "\xEE\xAE" => "\xE7\x94\xBA", + "\xEE\xAF" => "\xE7\x95\x80", + "\xEE\xB0" => "\xE7\x95\x8E", + "\xEE\xB1" => "\xE7\x95\x8B", + "\xEE\xB2" => "\xE7\x95\x88", + "\xEE\xB3" => "\xE7\x95\x9B", + "\xEE\xB4" => "\xE7\x95\xB2", + "\xEE\xB5" => "\xE7\x95\xB9", + "\xEE\xB6" => "\xE7\x96\x83", + "\xEE\xB7" => "\xE7\xBD\x98", + "\xEE\xB8" => "\xE7\xBD\xA1", + "\xEE\xB9" => "\xE7\xBD\x9F", + "\xEE\xBA" => "\xE8\xA9\x88", + "\xEE\xBB" => "\xE7\xBD\xA8", + "\xEE\xBC" => "\xE7\xBD\xB4", + "\xEE\xBD" => "\xE7\xBD\xB1", + "\xEE\xBE" => "\xE7\xBD\xB9", + "\xEE\xBF" => "\xE7\xBE\x81", + "\xEE\xC0" => "\xE7\xBD\xBE", + "\xEE\xC1" => "\xE7\x9B\x8D", + "\xEE\xC2" => "\xE7\x9B\xA5", + "\xEE\xC3" => "\xE8\xA0\xB2", + "\xEE\xC4" => "\xE9\x92\x85", + "\xEE\xC5" => "\xE9\x92\x86", + "\xEE\xC6" => "\xE9\x92\x87", + "\xEE\xC7" => "\xE9\x92\x8B", + "\xEE\xC8" => "\xE9\x92\x8A", + "\xEE\xC9" => "\xE9\x92\x8C", + "\xEE\xCA" => "\xE9\x92\x8D", + "\xEE\xCB" => "\xE9\x92\x8F", + "\xEE\xCC" => "\xE9\x92\x90", + "\xEE\xCD" => "\xE9\x92\x94", + "\xEE\xCE" => "\xE9\x92\x97", + "\xEE\xCF" => "\xE9\x92\x95", + "\xEE\xD0" => "\xE9\x92\x9A", + "\xEE\xD1" => "\xE9\x92\x9B", + "\xEE\xD2" => "\xE9\x92\x9C", + "\xEE\xD3" => "\xE9\x92\xA3", + "\xEE\xD4" => "\xE9\x92\xA4", + "\xEE\xD5" => "\xE9\x92\xAB", + "\xEE\xD6" => "\xE9\x92\xAA", + "\xEE\xD7" => "\xE9\x92\xAD", + "\xEE\xD8" => "\xE9\x92\xAC", + "\xEE\xD9" => "\xE9\x92\xAF", + "\xEE\xDA" => "\xE9\x92\xB0", + "\xEE\xDB" => "\xE9\x92\xB2", + "\xEE\xDC" => "\xE9\x92\xB4", + "\xEE\xDD" => "\xE9\x92\xB6", + "\xEE\xDE" => "\xE9\x92\xB7", + "\xEE\xDF" => "\xE9\x92\xB8", + "\xEE\xE0" => "\xE9\x92\xB9", + "\xEE\xE1" => "\xE9\x92\xBA", + "\xEE\xE2" => "\xE9\x92\xBC", + "\xEE\xE3" => "\xE9\x92\xBD", + "\xEE\xE4" => "\xE9\x92\xBF", + "\xEE\xE5" => "\xE9\x93\x84", + "\xEE\xE6" => "\xE9\x93\x88", + "\xEE\xE7" => "\xE9\x93\x89", + "\xEE\xE8" => "\xE9\x93\x8A", + "\xEE\xE9" => "\xE9\x93\x8B", + "\xEE\xEA" => "\xE9\x93\x8C", + "\xEE\xEB" => "\xE9\x93\x8D", + "\xEE\xEC" => "\xE9\x93\x8E", + "\xEE\xED" => "\xE9\x93\x90", + "\xEE\xEE" => "\xE9\x93\x91", + "\xEE\xEF" => "\xE9\x93\x92", + "\xEE\xF0" => "\xE9\x93\x95", + "\xEE\xF1" => "\xE9\x93\x96", + "\xEE\xF2" => "\xE9\x93\x97", + "\xEE\xF3" => "\xE9\x93\x99", + "\xEE\xF4" => "\xE9\x93\x98", + "\xEE\xF5" => "\xE9\x93\x9B", + "\xEE\xF6" => "\xE9\x93\x9E", + "\xEE\xF7" => "\xE9\x93\x9F", + "\xEE\xF8" => "\xE9\x93\xA0", + "\xEE\xF9" => "\xE9\x93\xA2", + "\xEE\xFA" => "\xE9\x93\xA4", + "\xEE\xFB" => "\xE9\x93\xA5", + "\xEE\xFC" => "\xE9\x93\xA7", + "\xEE\xFD" => "\xE9\x93\xA8", + "\xEE\xFE" => "\xE9\x93\xAA", + "\xEF\xA1" => "\xE9\x93\xA9", + "\xEF\xA2" => "\xE9\x93\xAB", + "\xEF\xA3" => "\xE9\x93\xAE", + "\xEF\xA4" => "\xE9\x93\xAF", + "\xEF\xA5" => "\xE9\x93\xB3", + "\xEF\xA6" => "\xE9\x93\xB4", + "\xEF\xA7" => "\xE9\x93\xB5", + "\xEF\xA8" => "\xE9\x93\xB7", + "\xEF\xA9" => "\xE9\x93\xB9", + "\xEF\xAA" => "\xE9\x93\xBC", + "\xEF\xAB" => "\xE9\x93\xBD", + "\xEF\xAC" => "\xE9\x93\xBF", + "\xEF\xAD" => "\xE9\x94\x83", + "\xEF\xAE" => "\xE9\x94\x82", + "\xEF\xAF" => "\xE9\x94\x86", + "\xEF\xB0" => "\xE9\x94\x87", + "\xEF\xB1" => "\xE9\x94\x89", + "\xEF\xB2" => "\xE9\x94\x8A", + "\xEF\xB3" => "\xE9\x94\x8D", + "\xEF\xB4" => "\xE9\x94\x8E", + "\xEF\xB5" => "\xE9\x94\x8F", + "\xEF\xB6" => "\xE9\x94\x92", + "\xEF\xB7" => "\xE9\x94\x93", + "\xEF\xB8" => "\xE9\x94\x94", + "\xEF\xB9" => "\xE9\x94\x95", + "\xEF\xBA" => "\xE9\x94\x96", + "\xEF\xBB" => "\xE9\x94\x98", + "\xEF\xBC" => "\xE9\x94\x9B", + "\xEF\xBD" => "\xE9\x94\x9D", + "\xEF\xBE" => "\xE9\x94\x9E", + "\xEF\xBF" => "\xE9\x94\x9F", + "\xEF\xC0" => "\xE9\x94\xA2", + "\xEF\xC1" => "\xE9\x94\xAA", + "\xEF\xC2" => "\xE9\x94\xAB", + "\xEF\xC3" => "\xE9\x94\xA9", + "\xEF\xC4" => "\xE9\x94\xAC", + "\xEF\xC5" => "\xE9\x94\xB1", + "\xEF\xC6" => "\xE9\x94\xB2", + "\xEF\xC7" => "\xE9\x94\xB4", + "\xEF\xC8" => "\xE9\x94\xB6", + "\xEF\xC9" => "\xE9\x94\xB7", + "\xEF\xCA" => "\xE9\x94\xB8", + "\xEF\xCB" => "\xE9\x94\xBC", + "\xEF\xCC" => "\xE9\x94\xBE", + "\xEF\xCD" => "\xE9\x94\xBF", + "\xEF\xCE" => "\xE9\x95\x82", + "\xEF\xCF" => "\xE9\x94\xB5", + "\xEF\xD0" => "\xE9\x95\x84", + "\xEF\xD1" => "\xE9\x95\x85", + "\xEF\xD2" => "\xE9\x95\x86", + "\xEF\xD3" => "\xE9\x95\x89", + "\xEF\xD4" => "\xE9\x95\x8C", + "\xEF\xD5" => "\xE9\x95\x8E", + "\xEF\xD6" => "\xE9\x95\x8F", + "\xEF\xD7" => "\xE9\x95\x92", + "\xEF\xD8" => "\xE9\x95\x93", + "\xEF\xD9" => "\xE9\x95\x94", + "\xEF\xDA" => "\xE9\x95\x96", + "\xEF\xDB" => "\xE9\x95\x97", + "\xEF\xDC" => "\xE9\x95\x98", + "\xEF\xDD" => "\xE9\x95\x99", + "\xEF\xDE" => "\xE9\x95\x9B", + "\xEF\xDF" => "\xE9\x95\x9E", + "\xEF\xE0" => "\xE9\x95\x9F", + "\xEF\xE1" => "\xE9\x95\x9D", + "\xEF\xE2" => "\xE9\x95\xA1", + "\xEF\xE3" => "\xE9\x95\xA2", + "\xEF\xE4" => "\xE9\x95\xA4", + "\xEF\xE5" => "\xE9\x95\xA5", + "\xEF\xE6" => "\xE9\x95\xA6", + "\xEF\xE7" => "\xE9\x95\xA7", + "\xEF\xE8" => "\xE9\x95\xA8", + "\xEF\xE9" => "\xE9\x95\xA9", + "\xEF\xEA" => "\xE9\x95\xAA", + "\xEF\xEB" => "\xE9\x95\xAB", + "\xEF\xEC" => "\xE9\x95\xAC", + "\xEF\xED" => "\xE9\x95\xAF", + "\xEF\xEE" => "\xE9\x95\xB1", + "\xEF\xEF" => "\xE9\x95\xB2", + "\xEF\xF0" => "\xE9\x95\xB3", + "\xEF\xF1" => "\xE9\x94\xBA", + "\xEF\xF2" => "\xE7\x9F\xA7", + "\xEF\xF3" => "\xE7\x9F\xAC", + "\xEF\xF4" => "\xE9\x9B\x89", + "\xEF\xF5" => "\xE7\xA7\x95", + "\xEF\xF6" => "\xE7\xA7\xAD", + "\xEF\xF7" => "\xE7\xA7\xA3", + "\xEF\xF8" => "\xE7\xA7\xAB", + "\xEF\xF9" => "\xE7\xA8\x86", + "\xEF\xFA" => "\xE5\xB5\x87", + "\xEF\xFB" => "\xE7\xA8\x83", + "\xEF\xFC" => "\xE7\xA8\x82", + "\xEF\xFD" => "\xE7\xA8\x9E", + "\xEF\xFE" => "\xE7\xA8\x94", + "\xF0\xA1" => "\xE7\xA8\xB9", + "\xF0\xA2" => "\xE7\xA8\xB7", + "\xF0\xA3" => "\xE7\xA9\x91", + "\xF0\xA4" => "\xE9\xBB\x8F", + "\xF0\xA5" => "\xE9\xA6\xA5", + "\xF0\xA6" => "\xE7\xA9\xB0", + "\xF0\xA7" => "\xE7\x9A\x88", + "\xF0\xA8" => "\xE7\x9A\x8E", + "\xF0\xA9" => "\xE7\x9A\x93", + "\xF0\xAA" => "\xE7\x9A\x99", + "\xF0\xAB" => "\xE7\x9A\xA4", + "\xF0\xAC" => "\xE7\x93\x9E", + "\xF0\xAD" => "\xE7\x93\xA0", + "\xF0\xAE" => "\xE7\x94\xAC", + "\xF0\xAF" => "\xE9\xB8\xA0", + "\xF0\xB0" => "\xE9\xB8\xA2", + "\xF0\xB1" => "\xE9\xB8\xA8", + "\xF0\xB2" => "\xE9\xB8\xA9", + "\xF0\xB3" => "\xE9\xB8\xAA", + "\xF0\xB4" => "\xE9\xB8\xAB", + "\xF0\xB5" => "\xE9\xB8\xAC", + "\xF0\xB6" => "\xE9\xB8\xB2", + "\xF0\xB7" => "\xE9\xB8\xB1", + "\xF0\xB8" => "\xE9\xB8\xB6", + "\xF0\xB9" => "\xE9\xB8\xB8", + "\xF0\xBA" => "\xE9\xB8\xB7", + "\xF0\xBB" => "\xE9\xB8\xB9", + "\xF0\xBC" => "\xE9\xB8\xBA", + "\xF0\xBD" => "\xE9\xB8\xBE", + "\xF0\xBE" => "\xE9\xB9\x81", + "\xF0\xBF" => "\xE9\xB9\x82", + "\xF0\xC0" => "\xE9\xB9\x84", + "\xF0\xC1" => "\xE9\xB9\x86", + "\xF0\xC2" => "\xE9\xB9\x87", + "\xF0\xC3" => "\xE9\xB9\x88", + "\xF0\xC4" => "\xE9\xB9\x89", + "\xF0\xC5" => "\xE9\xB9\x8B", + "\xF0\xC6" => "\xE9\xB9\x8C", + "\xF0\xC7" => "\xE9\xB9\x8E", + "\xF0\xC8" => "\xE9\xB9\x91", + "\xF0\xC9" => "\xE9\xB9\x95", + "\xF0\xCA" => "\xE9\xB9\x97", + "\xF0\xCB" => "\xE9\xB9\x9A", + "\xF0\xCC" => "\xE9\xB9\x9B", + "\xF0\xCD" => "\xE9\xB9\x9C", + "\xF0\xCE" => "\xE9\xB9\x9E", + "\xF0\xCF" => "\xE9\xB9\xA3", + "\xF0\xD0" => "\xE9\xB9\xA6", + "\xF0\xD1" => "\xE9\xB9\xA7", + "\xF0\xD2" => "\xE9\xB9\xA8", + "\xF0\xD3" => "\xE9\xB9\xA9", + "\xF0\xD4" => "\xE9\xB9\xAA", + "\xF0\xD5" => "\xE9\xB9\xAB", + "\xF0\xD6" => "\xE9\xB9\xAC", + "\xF0\xD7" => "\xE9\xB9\xB1", + "\xF0\xD8" => "\xE9\xB9\xAD", + "\xF0\xD9" => "\xE9\xB9\xB3", + "\xF0\xDA" => "\xE7\x96\x92", + "\xF0\xDB" => "\xE7\x96\x94", + "\xF0\xDC" => "\xE7\x96\x96", + "\xF0\xDD" => "\xE7\x96\xA0", + "\xF0\xDE" => "\xE7\x96\x9D", + "\xF0\xDF" => "\xE7\x96\xAC", + "\xF0\xE0" => "\xE7\x96\xA3", + "\xF0\xE1" => "\xE7\x96\xB3", + "\xF0\xE2" => "\xE7\x96\xB4", + "\xF0\xE3" => "\xE7\x96\xB8", + "\xF0\xE4" => "\xE7\x97\x84", + "\xF0\xE5" => "\xE7\x96\xB1", + "\xF0\xE6" => "\xE7\x96\xB0", + "\xF0\xE7" => "\xE7\x97\x83", + "\xF0\xE8" => "\xE7\x97\x82", + "\xF0\xE9" => "\xE7\x97\x96", + "\xF0\xEA" => "\xE7\x97\x8D", + "\xF0\xEB" => "\xE7\x97\xA3", + "\xF0\xEC" => "\xE7\x97\xA8", + "\xF0\xED" => "\xE7\x97\xA6", + "\xF0\xEE" => "\xE7\x97\xA4", + "\xF0\xEF" => "\xE7\x97\xAB", + "\xF0\xF0" => "\xE7\x97\xA7", + "\xF0\xF1" => "\xE7\x98\x83", + "\xF0\xF2" => "\xE7\x97\xB1", + "\xF0\xF3" => "\xE7\x97\xBC", + "\xF0\xF4" => "\xE7\x97\xBF", + "\xF0\xF5" => "\xE7\x98\x90", + "\xF0\xF6" => "\xE7\x98\x80", + "\xF0\xF7" => "\xE7\x98\x85", + "\xF0\xF8" => "\xE7\x98\x8C", + "\xF0\xF9" => "\xE7\x98\x97", + "\xF0\xFA" => "\xE7\x98\x8A", + "\xF0\xFB" => "\xE7\x98\xA5", + "\xF0\xFC" => "\xE7\x98\x98", + "\xF0\xFD" => "\xE7\x98\x95", + "\xF0\xFE" => "\xE7\x98\x99", + "\xF1\xA1" => "\xE7\x98\x9B", + "\xF1\xA2" => "\xE7\x98\xBC", + "\xF1\xA3" => "\xE7\x98\xA2", + "\xF1\xA4" => "\xE7\x98\xA0", + "\xF1\xA5" => "\xE7\x99\x80", + "\xF1\xA6" => "\xE7\x98\xAD", + "\xF1\xA7" => "\xE7\x98\xB0", + "\xF1\xA8" => "\xE7\x98\xBF", + "\xF1\xA9" => "\xE7\x98\xB5", + "\xF1\xAA" => "\xE7\x99\x83", + "\xF1\xAB" => "\xE7\x98\xBE", + "\xF1\xAC" => "\xE7\x98\xB3", + "\xF1\xAD" => "\xE7\x99\x8D", + "\xF1\xAE" => "\xE7\x99\x9E", + "\xF1\xAF" => "\xE7\x99\x94", + "\xF1\xB0" => "\xE7\x99\x9C", + "\xF1\xB1" => "\xE7\x99\x96", + "\xF1\xB2" => "\xE7\x99\xAB", + "\xF1\xB3" => "\xE7\x99\xAF", + "\xF1\xB4" => "\xE7\xBF\x8A", + "\xF1\xB5" => "\xE7\xAB\xA6", + "\xF1\xB6" => "\xE7\xA9\xB8", + "\xF1\xB7" => "\xE7\xA9\xB9", + "\xF1\xB8" => "\xE7\xAA\x80", + "\xF1\xB9" => "\xE7\xAA\x86", + "\xF1\xBA" => "\xE7\xAA\x88", + "\xF1\xBB" => "\xE7\xAA\x95", + "\xF1\xBC" => "\xE7\xAA\xA6", + "\xF1\xBD" => "\xE7\xAA\xA0", + "\xF1\xBE" => "\xE7\xAA\xAC", + "\xF1\xBF" => "\xE7\xAA\xA8", + "\xF1\xC0" => "\xE7\xAA\xAD", + "\xF1\xC1" => "\xE7\xAA\xB3", + "\xF1\xC2" => "\xE8\xA1\xA4", + "\xF1\xC3" => "\xE8\xA1\xA9", + "\xF1\xC4" => "\xE8\xA1\xB2", + "\xF1\xC5" => "\xE8\xA1\xBD", + "\xF1\xC6" => "\xE8\xA1\xBF", + "\xF1\xC7" => "\xE8\xA2\x82", + "\xF1\xC8" => "\xE8\xA2\xA2", + "\xF1\xC9" => "\xE8\xA3\x86", + "\xF1\xCA" => "\xE8\xA2\xB7", + "\xF1\xCB" => "\xE8\xA2\xBC", + "\xF1\xCC" => "\xE8\xA3\x89", + "\xF1\xCD" => "\xE8\xA3\xA2", + "\xF1\xCE" => "\xE8\xA3\x8E", + "\xF1\xCF" => "\xE8\xA3\xA3", + "\xF1\xD0" => "\xE8\xA3\xA5", + "\xF1\xD1" => "\xE8\xA3\xB1", + "\xF1\xD2" => "\xE8\xA4\x9A", + "\xF1\xD3" => "\xE8\xA3\xBC", + "\xF1\xD4" => "\xE8\xA3\xA8", + "\xF1\xD5" => "\xE8\xA3\xBE", + "\xF1\xD6" => "\xE8\xA3\xB0", + "\xF1\xD7" => "\xE8\xA4\xA1", + "\xF1\xD8" => "\xE8\xA4\x99", + "\xF1\xD9" => "\xE8\xA4\x93", + "\xF1\xDA" => "\xE8\xA4\x9B", + "\xF1\xDB" => "\xE8\xA4\x8A", + "\xF1\xDC" => "\xE8\xA4\xB4", + "\xF1\xDD" => "\xE8\xA4\xAB", + "\xF1\xDE" => "\xE8\xA4\xB6", + "\xF1\xDF" => "\xE8\xA5\x81", + "\xF1\xE0" => "\xE8\xA5\xA6", + "\xF1\xE1" => "\xE8\xA5\xBB", + "\xF1\xE2" => "\xE7\x96\x8B", + "\xF1\xE3" => "\xE8\x83\xA5", + "\xF1\xE4" => "\xE7\x9A\xB2", + "\xF1\xE5" => "\xE7\x9A\xB4", + "\xF1\xE6" => "\xE7\x9F\x9C", + "\xF1\xE7" => "\xE8\x80\x92", + "\xF1\xE8" => "\xE8\x80\x94", + "\xF1\xE9" => "\xE8\x80\x96", + "\xF1\xEA" => "\xE8\x80\x9C", + "\xF1\xEB" => "\xE8\x80\xA0", + "\xF1\xEC" => "\xE8\x80\xA2", + "\xF1\xED" => "\xE8\x80\xA5", + "\xF1\xEE" => "\xE8\x80\xA6", + "\xF1\xEF" => "\xE8\x80\xA7", + "\xF1\xF0" => "\xE8\x80\xA9", + "\xF1\xF1" => "\xE8\x80\xA8", + "\xF1\xF2" => "\xE8\x80\xB1", + "\xF1\xF3" => "\xE8\x80\x8B", + "\xF1\xF4" => "\xE8\x80\xB5", + "\xF1\xF5" => "\xE8\x81\x83", + "\xF1\xF6" => "\xE8\x81\x86", + "\xF1\xF7" => "\xE8\x81\x8D", + "\xF1\xF8" => "\xE8\x81\x92", + "\xF1\xF9" => "\xE8\x81\xA9", + "\xF1\xFA" => "\xE8\x81\xB1", + "\xF1\xFB" => "\xE8\xA6\x83", + "\xF1\xFC" => "\xE9\xA1\xB8", + "\xF1\xFD" => "\xE9\xA2\x80", + "\xF1\xFE" => "\xE9\xA2\x83", + "\xF2\xA1" => "\xE9\xA2\x89", + "\xF2\xA2" => "\xE9\xA2\x8C", + "\xF2\xA3" => "\xE9\xA2\x8D", + "\xF2\xA4" => "\xE9\xA2\x8F", + "\xF2\xA5" => "\xE9\xA2\x94", + "\xF2\xA6" => "\xE9\xA2\x9A", + "\xF2\xA7" => "\xE9\xA2\x9B", + "\xF2\xA8" => "\xE9\xA2\x9E", + "\xF2\xA9" => "\xE9\xA2\x9F", + "\xF2\xAA" => "\xE9\xA2\xA1", + "\xF2\xAB" => "\xE9\xA2\xA2", + "\xF2\xAC" => "\xE9\xA2\xA5", + "\xF2\xAD" => "\xE9\xA2\xA6", + "\xF2\xAE" => "\xE8\x99\x8D", + "\xF2\xAF" => "\xE8\x99\x94", + "\xF2\xB0" => "\xE8\x99\xAC", + "\xF2\xB1" => "\xE8\x99\xAE", + "\xF2\xB2" => "\xE8\x99\xBF", + "\xF2\xB3" => "\xE8\x99\xBA", + "\xF2\xB4" => "\xE8\x99\xBC", + "\xF2\xB5" => "\xE8\x99\xBB", + "\xF2\xB6" => "\xE8\x9A\xA8", + "\xF2\xB7" => "\xE8\x9A\x8D", + "\xF2\xB8" => "\xE8\x9A\x8B", + "\xF2\xB9" => "\xE8\x9A\xAC", + "\xF2\xBA" => "\xE8\x9A\x9D", + "\xF2\xBB" => "\xE8\x9A\xA7", + "\xF2\xBC" => "\xE8\x9A\xA3", + "\xF2\xBD" => "\xE8\x9A\xAA", + "\xF2\xBE" => "\xE8\x9A\x93", + "\xF2\xBF" => "\xE8\x9A\xA9", + "\xF2\xC0" => "\xE8\x9A\xB6", + "\xF2\xC1" => "\xE8\x9B\x84", + "\xF2\xC2" => "\xE8\x9A\xB5", + "\xF2\xC3" => "\xE8\x9B\x8E", + "\xF2\xC4" => "\xE8\x9A\xB0", + "\xF2\xC5" => "\xE8\x9A\xBA", + "\xF2\xC6" => "\xE8\x9A\xB1", + "\xF2\xC7" => "\xE8\x9A\xAF", + "\xF2\xC8" => "\xE8\x9B\x89", + "\xF2\xC9" => "\xE8\x9B\x8F", + "\xF2\xCA" => "\xE8\x9A\xB4", + "\xF2\xCB" => "\xE8\x9B\xA9", + "\xF2\xCC" => "\xE8\x9B\xB1", + "\xF2\xCD" => "\xE8\x9B\xB2", + "\xF2\xCE" => "\xE8\x9B\xAD", + "\xF2\xCF" => "\xE8\x9B\xB3", + "\xF2\xD0" => "\xE8\x9B\x90", + "\xF2\xD1" => "\xE8\x9C\x93", + "\xF2\xD2" => "\xE8\x9B\x9E", + "\xF2\xD3" => "\xE8\x9B\xB4", + "\xF2\xD4" => "\xE8\x9B\x9F", + "\xF2\xD5" => "\xE8\x9B\x98", + "\xF2\xD6" => "\xE8\x9B\x91", + "\xF2\xD7" => "\xE8\x9C\x83", + "\xF2\xD8" => "\xE8\x9C\x87", + "\xF2\xD9" => "\xE8\x9B\xB8", + "\xF2\xDA" => "\xE8\x9C\x88", + "\xF2\xDB" => "\xE8\x9C\x8A", + "\xF2\xDC" => "\xE8\x9C\x8D", + "\xF2\xDD" => "\xE8\x9C\x89", + "\xF2\xDE" => "\xE8\x9C\xA3", + "\xF2\xDF" => "\xE8\x9C\xBB", + "\xF2\xE0" => "\xE8\x9C\x9E", + "\xF2\xE1" => "\xE8\x9C\xA5", + "\xF2\xE2" => "\xE8\x9C\xAE", + "\xF2\xE3" => "\xE8\x9C\x9A", + "\xF2\xE4" => "\xE8\x9C\xBE", + "\xF2\xE5" => "\xE8\x9D\x88", + "\xF2\xE6" => "\xE8\x9C\xB4", + "\xF2\xE7" => "\xE8\x9C\xB1", + "\xF2\xE8" => "\xE8\x9C\xA9", + "\xF2\xE9" => "\xE8\x9C\xB7", + "\xF2\xEA" => "\xE8\x9C\xBF", + "\xF2\xEB" => "\xE8\x9E\x82", + "\xF2\xEC" => "\xE8\x9C\xA2", + "\xF2\xED" => "\xE8\x9D\xBD", + "\xF2\xEE" => "\xE8\x9D\xBE", + "\xF2\xEF" => "\xE8\x9D\xBB", + "\xF2\xF0" => "\xE8\x9D\xA0", + "\xF2\xF1" => "\xE8\x9D\xB0", + "\xF2\xF2" => "\xE8\x9D\x8C", + "\xF2\xF3" => "\xE8\x9D\xAE", + "\xF2\xF4" => "\xE8\x9E\x8B", + "\xF2\xF5" => "\xE8\x9D\x93", + "\xF2\xF6" => "\xE8\x9D\xA3", + "\xF2\xF7" => "\xE8\x9D\xBC", + "\xF2\xF8" => "\xE8\x9D\xA4", + "\xF2\xF9" => "\xE8\x9D\x99", + "\xF2\xFA" => "\xE8\x9D\xA5", + "\xF2\xFB" => "\xE8\x9E\x93", + "\xF2\xFC" => "\xE8\x9E\xAF", + "\xF2\xFD" => "\xE8\x9E\xA8", + "\xF2\xFE" => "\xE8\x9F\x92", + "\xF3\xA1" => "\xE8\x9F\x86", + "\xF3\xA2" => "\xE8\x9E\x88", + "\xF3\xA3" => "\xE8\x9E\x85", + "\xF3\xA4" => "\xE8\x9E\xAD", + "\xF3\xA5" => "\xE8\x9E\x97", + "\xF3\xA6" => "\xE8\x9E\x83", + "\xF3\xA7" => "\xE8\x9E\xAB", + "\xF3\xA8" => "\xE8\x9F\xA5", + "\xF3\xA9" => "\xE8\x9E\xAC", + "\xF3\xAA" => "\xE8\x9E\xB5", + "\xF3\xAB" => "\xE8\x9E\xB3", + "\xF3\xAC" => "\xE8\x9F\x8B", + "\xF3\xAD" => "\xE8\x9F\x93", + "\xF3\xAE" => "\xE8\x9E\xBD", + "\xF3\xAF" => "\xE8\x9F\x91", + "\xF3\xB0" => "\xE8\x9F\x80", + "\xF3\xB1" => "\xE8\x9F\x8A", + "\xF3\xB2" => "\xE8\x9F\x9B", + "\xF3\xB3" => "\xE8\x9F\xAA", + "\xF3\xB4" => "\xE8\x9F\xA0", + "\xF3\xB5" => "\xE8\x9F\xAE", + "\xF3\xB6" => "\xE8\xA0\x96", + "\xF3\xB7" => "\xE8\xA0\x93", + "\xF3\xB8" => "\xE8\x9F\xBE", + "\xF3\xB9" => "\xE8\xA0\x8A", + "\xF3\xBA" => "\xE8\xA0\x9B", + "\xF3\xBB" => "\xE8\xA0\xA1", + "\xF3\xBC" => "\xE8\xA0\xB9", + "\xF3\xBD" => "\xE8\xA0\xBC", + "\xF3\xBE" => "\xE7\xBC\xB6", + "\xF3\xBF" => "\xE7\xBD\x82", + "\xF3\xC0" => "\xE7\xBD\x84", + "\xF3\xC1" => "\xE7\xBD\x85", + "\xF3\xC2" => "\xE8\x88\x90", + "\xF3\xC3" => "\xE7\xAB\xBA", + "\xF3\xC4" => "\xE7\xAB\xBD", + "\xF3\xC5" => "\xE7\xAC\x88", + "\xF3\xC6" => "\xE7\xAC\x83", + "\xF3\xC7" => "\xE7\xAC\x84", + "\xF3\xC8" => "\xE7\xAC\x95", + "\xF3\xC9" => "\xE7\xAC\x8A", + "\xF3\xCA" => "\xE7\xAC\xAB", + "\xF3\xCB" => "\xE7\xAC\x8F", + "\xF3\xCC" => "\xE7\xAD\x87", + "\xF3\xCD" => "\xE7\xAC\xB8", + "\xF3\xCE" => "\xE7\xAC\xAA", + "\xF3\xCF" => "\xE7\xAC\x99", + "\xF3\xD0" => "\xE7\xAC\xAE", + "\xF3\xD1" => "\xE7\xAC\xB1", + "\xF3\xD2" => "\xE7\xAC\xA0", + "\xF3\xD3" => "\xE7\xAC\xA5", + "\xF3\xD4" => "\xE7\xAC\xA4", + "\xF3\xD5" => "\xE7\xAC\xB3", + "\xF3\xD6" => "\xE7\xAC\xBE", + "\xF3\xD7" => "\xE7\xAC\x9E", + "\xF3\xD8" => "\xE7\xAD\x98", + "\xF3\xD9" => "\xE7\xAD\x9A", + "\xF3\xDA" => "\xE7\xAD\x85", + "\xF3\xDB" => "\xE7\xAD\xB5", + "\xF3\xDC" => "\xE7\xAD\x8C", + "\xF3\xDD" => "\xE7\xAD\x9D", + "\xF3\xDE" => "\xE7\xAD\xA0", + "\xF3\xDF" => "\xE7\xAD\xAE", + "\xF3\xE0" => "\xE7\xAD\xBB", + "\xF3\xE1" => "\xE7\xAD\xA2", + "\xF3\xE2" => "\xE7\xAD\xB2", + "\xF3\xE3" => "\xE7\xAD\xB1", + "\xF3\xE4" => "\xE7\xAE\x90", + "\xF3\xE5" => "\xE7\xAE\xA6", + "\xF3\xE6" => "\xE7\xAE\xA7", + "\xF3\xE7" => "\xE7\xAE\xB8", + "\xF3\xE8" => "\xE7\xAE\xAC", + "\xF3\xE9" => "\xE7\xAE\x9D", + "\xF3\xEA" => "\xE7\xAE\xA8", + "\xF3\xEB" => "\xE7\xAE\x85", + "\xF3\xEC" => "\xE7\xAE\xAA", + "\xF3\xED" => "\xE7\xAE\x9C", + "\xF3\xEE" => "\xE7\xAE\xA2", + "\xF3\xEF" => "\xE7\xAE\xAB", + "\xF3\xF0" => "\xE7\xAE\xB4", + "\xF3\xF1" => "\xE7\xAF\x91", + "\xF3\xF2" => "\xE7\xAF\x81", + "\xF3\xF3" => "\xE7\xAF\x8C", + "\xF3\xF4" => "\xE7\xAF\x9D", + "\xF3\xF5" => "\xE7\xAF\x9A", + "\xF3\xF6" => "\xE7\xAF\xA5", + "\xF3\xF7" => "\xE7\xAF\xA6", + "\xF3\xF8" => "\xE7\xAF\xAA", + "\xF3\xF9" => "\xE7\xB0\x8C", + "\xF3\xFA" => "\xE7\xAF\xBE", + "\xF3\xFB" => "\xE7\xAF\xBC", + "\xF3\xFC" => "\xE7\xB0\x8F", + "\xF3\xFD" => "\xE7\xB0\x96", + "\xF3\xFE" => "\xE7\xB0\x8B", + "\xF4\xA1" => "\xE7\xB0\x9F", + "\xF4\xA2" => "\xE7\xB0\xAA", + "\xF4\xA3" => "\xE7\xB0\xA6", + "\xF4\xA4" => "\xE7\xB0\xB8", + "\xF4\xA5" => "\xE7\xB1\x81", + "\xF4\xA6" => "\xE7\xB1\x80", + "\xF4\xA7" => "\xE8\x87\xBE", + "\xF4\xA8" => "\xE8\x88\x81", + "\xF4\xA9" => "\xE8\x88\x82", + "\xF4\xAA" => "\xE8\x88\x84", + "\xF4\xAB" => "\xE8\x87\xAC", + "\xF4\xAC" => "\xE8\xA1\x84", + "\xF4\xAD" => "\xE8\x88\xA1", + "\xF4\xAE" => "\xE8\x88\xA2", + "\xF4\xAF" => "\xE8\x88\xA3", + "\xF4\xB0" => "\xE8\x88\xAD", + "\xF4\xB1" => "\xE8\x88\xAF", + "\xF4\xB2" => "\xE8\x88\xA8", + "\xF4\xB3" => "\xE8\x88\xAB", + "\xF4\xB4" => "\xE8\x88\xB8", + "\xF4\xB5" => "\xE8\x88\xBB", + "\xF4\xB6" => "\xE8\x88\xB3", + "\xF4\xB7" => "\xE8\x88\xB4", + "\xF4\xB8" => "\xE8\x88\xBE", + "\xF4\xB9" => "\xE8\x89\x84", + "\xF4\xBA" => "\xE8\x89\x89", + "\xF4\xBB" => "\xE8\x89\x8B", + "\xF4\xBC" => "\xE8\x89\x8F", + "\xF4\xBD" => "\xE8\x89\x9A", + "\xF4\xBE" => "\xE8\x89\x9F", + "\xF4\xBF" => "\xE8\x89\xA8", + "\xF4\xC0" => "\xE8\xA1\xBE", + "\xF4\xC1" => "\xE8\xA2\x85", + "\xF4\xC2" => "\xE8\xA2\x88", + "\xF4\xC3" => "\xE8\xA3\x98", + "\xF4\xC4" => "\xE8\xA3\x9F", + "\xF4\xC5" => "\xE8\xA5\x9E", + "\xF4\xC6" => "\xE7\xBE\x9D", + "\xF4\xC7" => "\xE7\xBE\x9F", + "\xF4\xC8" => "\xE7\xBE\xA7", + "\xF4\xC9" => "\xE7\xBE\xAF", + "\xF4\xCA" => "\xE7\xBE\xB0", + "\xF4\xCB" => "\xE7\xBE\xB2", + "\xF4\xCC" => "\xE7\xB1\xBC", + "\xF4\xCD" => "\xE6\x95\x89", + "\xF4\xCE" => "\xE7\xB2\x91", + "\xF4\xCF" => "\xE7\xB2\x9D", + "\xF4\xD0" => "\xE7\xB2\x9C", + "\xF4\xD1" => "\xE7\xB2\x9E", + "\xF4\xD2" => "\xE7\xB2\xA2", + "\xF4\xD3" => "\xE7\xB2\xB2", + "\xF4\xD4" => "\xE7\xB2\xBC", + "\xF4\xD5" => "\xE7\xB2\xBD", + "\xF4\xD6" => "\xE7\xB3\x81", + "\xF4\xD7" => "\xE7\xB3\x87", + "\xF4\xD8" => "\xE7\xB3\x8C", + "\xF4\xD9" => "\xE7\xB3\x8D", + "\xF4\xDA" => "\xE7\xB3\x88", + "\xF4\xDB" => "\xE7\xB3\x85", + "\xF4\xDC" => "\xE7\xB3\x97", + "\xF4\xDD" => "\xE7\xB3\xA8", + "\xF4\xDE" => "\xE8\x89\xAE", + "\xF4\xDF" => "\xE6\x9A\xA8", + "\xF4\xE0" => "\xE7\xBE\xBF", + "\xF4\xE1" => "\xE7\xBF\x8E", + "\xF4\xE2" => "\xE7\xBF\x95", + "\xF4\xE3" => "\xE7\xBF\xA5", + "\xF4\xE4" => "\xE7\xBF\xA1", + "\xF4\xE5" => "\xE7\xBF\xA6", + "\xF4\xE6" => "\xE7\xBF\xA9", + "\xF4\xE7" => "\xE7\xBF\xAE", + "\xF4\xE8" => "\xE7\xBF\xB3", + "\xF4\xE9" => "\xE7\xB3\xB8", + "\xF4\xEA" => "\xE7\xB5\xB7", + "\xF4\xEB" => "\xE7\xB6\xA6", + "\xF4\xEC" => "\xE7\xB6\xAE", + "\xF4\xED" => "\xE7\xB9\x87", + "\xF4\xEE" => "\xE7\xBA\x9B", + "\xF4\xEF" => "\xE9\xBA\xB8", + "\xF4\xF0" => "\xE9\xBA\xB4", + "\xF4\xF1" => "\xE8\xB5\xB3", + "\xF4\xF2" => "\xE8\xB6\x84", + "\xF4\xF3" => "\xE8\xB6\x94", + "\xF4\xF4" => "\xE8\xB6\x91", + "\xF4\xF5" => "\xE8\xB6\xB1", + "\xF4\xF6" => "\xE8\xB5\xA7", + "\xF4\xF7" => "\xE8\xB5\xAD", + "\xF4\xF8" => "\xE8\xB1\x87", + "\xF4\xF9" => "\xE8\xB1\x89", + "\xF4\xFA" => "\xE9\x85\x8A", + "\xF4\xFB" => "\xE9\x85\x90", + "\xF4\xFC" => "\xE9\x85\x8E", + "\xF4\xFD" => "\xE9\x85\x8F", + "\xF4\xFE" => "\xE9\x85\xA4", + "\xF5\xA1" => "\xE9\x85\xA2", + "\xF5\xA2" => "\xE9\x85\xA1", + "\xF5\xA3" => "\xE9\x85\xB0", + "\xF5\xA4" => "\xE9\x85\xA9", + "\xF5\xA5" => "\xE9\x85\xAF", + "\xF5\xA6" => "\xE9\x85\xBD", + "\xF5\xA7" => "\xE9\x85\xBE", + "\xF5\xA8" => "\xE9\x85\xB2", + "\xF5\xA9" => "\xE9\x85\xB4", + "\xF5\xAA" => "\xE9\x85\xB9", + "\xF5\xAB" => "\xE9\x86\x8C", + "\xF5\xAC" => "\xE9\x86\x85", + "\xF5\xAD" => "\xE9\x86\x90", + "\xF5\xAE" => "\xE9\x86\x8D", + "\xF5\xAF" => "\xE9\x86\x91", + "\xF5\xB0" => "\xE9\x86\xA2", + "\xF5\xB1" => "\xE9\x86\xA3", + "\xF5\xB2" => "\xE9\x86\xAA", + "\xF5\xB3" => "\xE9\x86\xAD", + "\xF5\xB4" => "\xE9\x86\xAE", + "\xF5\xB5" => "\xE9\x86\xAF", + "\xF5\xB6" => "\xE9\x86\xB5", + "\xF5\xB7" => "\xE9\x86\xB4", + "\xF5\xB8" => "\xE9\x86\xBA", + "\xF5\xB9" => "\xE8\xB1\x95", + "\xF5\xBA" => "\xE9\xB9\xBE", + "\xF5\xBB" => "\xE8\xB6\xB8", + "\xF5\xBC" => "\xE8\xB7\xAB", + "\xF5\xBD" => "\xE8\xB8\x85", + "\xF5\xBE" => "\xE8\xB9\x99", + "\xF5\xBF" => "\xE8\xB9\xA9", + "\xF5\xC0" => "\xE8\xB6\xB5", + "\xF5\xC1" => "\xE8\xB6\xBF", + "\xF5\xC2" => "\xE8\xB6\xBC", + "\xF5\xC3" => "\xE8\xB6\xBA", + "\xF5\xC4" => "\xE8\xB7\x84", + "\xF5\xC5" => "\xE8\xB7\x96", + "\xF5\xC6" => "\xE8\xB7\x97", + "\xF5\xC7" => "\xE8\xB7\x9A", + "\xF5\xC8" => "\xE8\xB7\x9E", + "\xF5\xC9" => "\xE8\xB7\x8E", + "\xF5\xCA" => "\xE8\xB7\x8F", + "\xF5\xCB" => "\xE8\xB7\x9B", + "\xF5\xCC" => "\xE8\xB7\x86", + "\xF5\xCD" => "\xE8\xB7\xAC", + "\xF5\xCE" => "\xE8\xB7\xB7", + "\xF5\xCF" => "\xE8\xB7\xB8", + "\xF5\xD0" => "\xE8\xB7\xA3", + "\xF5\xD1" => "\xE8\xB7\xB9", + "\xF5\xD2" => "\xE8\xB7\xBB", + "\xF5\xD3" => "\xE8\xB7\xA4", + "\xF5\xD4" => "\xE8\xB8\x89", + "\xF5\xD5" => "\xE8\xB7\xBD", + "\xF5\xD6" => "\xE8\xB8\x94", + "\xF5\xD7" => "\xE8\xB8\x9D", + "\xF5\xD8" => "\xE8\xB8\x9F", + "\xF5\xD9" => "\xE8\xB8\xAC", + "\xF5\xDA" => "\xE8\xB8\xAE", + "\xF5\xDB" => "\xE8\xB8\xA3", + "\xF5\xDC" => "\xE8\xB8\xAF", + "\xF5\xDD" => "\xE8\xB8\xBA", + "\xF5\xDE" => "\xE8\xB9\x80", + "\xF5\xDF" => "\xE8\xB8\xB9", + "\xF5\xE0" => "\xE8\xB8\xB5", + "\xF5\xE1" => "\xE8\xB8\xBD", + "\xF5\xE2" => "\xE8\xB8\xB1", + "\xF5\xE3" => "\xE8\xB9\x89", + "\xF5\xE4" => "\xE8\xB9\x81", + "\xF5\xE5" => "\xE8\xB9\x82", + "\xF5\xE6" => "\xE8\xB9\x91", + "\xF5\xE7" => "\xE8\xB9\x92", + "\xF5\xE8" => "\xE8\xB9\x8A", + "\xF5\xE9" => "\xE8\xB9\xB0", + "\xF5\xEA" => "\xE8\xB9\xB6", + "\xF5\xEB" => "\xE8\xB9\xBC", + "\xF5\xEC" => "\xE8\xB9\xAF", + "\xF5\xED" => "\xE8\xB9\xB4", + "\xF5\xEE" => "\xE8\xBA\x85", + "\xF5\xEF" => "\xE8\xBA\x8F", + "\xF5\xF0" => "\xE8\xBA\x94", + "\xF5\xF1" => "\xE8\xBA\x90", + "\xF5\xF2" => "\xE8\xBA\x9C", + "\xF5\xF3" => "\xE8\xBA\x9E", + "\xF5\xF4" => "\xE8\xB1\xB8", + "\xF5\xF5" => "\xE8\xB2\x82", + "\xF5\xF6" => "\xE8\xB2\x8A", + "\xF5\xF7" => "\xE8\xB2\x85", + "\xF5\xF8" => "\xE8\xB2\x98", + "\xF5\xF9" => "\xE8\xB2\x94", + "\xF5\xFA" => "\xE6\x96\x9B", + "\xF5\xFB" => "\xE8\xA7\x96", + "\xF5\xFC" => "\xE8\xA7\x9E", + "\xF5\xFD" => "\xE8\xA7\x9A", + "\xF5\xFE" => "\xE8\xA7\x9C", + "\xF6\xA1" => "\xE8\xA7\xA5", + "\xF6\xA2" => "\xE8\xA7\xAB", + "\xF6\xA3" => "\xE8\xA7\xAF", + "\xF6\xA4" => "\xE8\xA8\xBE", + "\xF6\xA5" => "\xE8\xAC\xA6", + "\xF6\xA6" => "\xE9\x9D\x93", + "\xF6\xA7" => "\xE9\x9B\xA9", + "\xF6\xA8" => "\xE9\x9B\xB3", + "\xF6\xA9" => "\xE9\x9B\xAF", + "\xF6\xAA" => "\xE9\x9C\x86", + "\xF6\xAB" => "\xE9\x9C\x81", + "\xF6\xAC" => "\xE9\x9C\x88", + "\xF6\xAD" => "\xE9\x9C\x8F", + "\xF6\xAE" => "\xE9\x9C\x8E", + "\xF6\xAF" => "\xE9\x9C\xAA", + "\xF6\xB0" => "\xE9\x9C\xAD", + "\xF6\xB1" => "\xE9\x9C\xB0", + "\xF6\xB2" => "\xE9\x9C\xBE", + "\xF6\xB3" => "\xE9\xBE\x80", + "\xF6\xB4" => "\xE9\xBE\x83", + "\xF6\xB5" => "\xE9\xBE\x85", + "\xF6\xB6" => "\xE9\xBE\x86", + "\xF6\xB7" => "\xE9\xBE\x87", + "\xF6\xB8" => "\xE9\xBE\x88", + "\xF6\xB9" => "\xE9\xBE\x89", + "\xF6\xBA" => "\xE9\xBE\x8A", + "\xF6\xBB" => "\xE9\xBE\x8C", + "\xF6\xBC" => "\xE9\xBB\xBE", + "\xF6\xBD" => "\xE9\xBC\x8B", + "\xF6\xBE" => "\xE9\xBC\x8D", + "\xF6\xBF" => "\xE9\x9A\xB9", + "\xF6\xC0" => "\xE9\x9A\xBC", + "\xF6\xC1" => "\xE9\x9A\xBD", + "\xF6\xC2" => "\xE9\x9B\x8E", + "\xF6\xC3" => "\xE9\x9B\x92", + "\xF6\xC4" => "\xE7\x9E\xBF", + "\xF6\xC5" => "\xE9\x9B\xA0", + "\xF6\xC6" => "\xE9\x8A\x8E", + "\xF6\xC7" => "\xE9\x8A\xAE", + "\xF6\xC8" => "\xE9\x8B\x88", + "\xF6\xC9" => "\xE9\x8C\xBE", + "\xF6\xCA" => "\xE9\x8D\xAA", + "\xF6\xCB" => "\xE9\x8F\x8A", + "\xF6\xCC" => "\xE9\x8E\x8F", + "\xF6\xCD" => "\xE9\x90\xBE", + "\xF6\xCE" => "\xE9\x91\xAB", + "\xF6\xCF" => "\xE9\xB1\xBF", + "\xF6\xD0" => "\xE9\xB2\x82", + "\xF6\xD1" => "\xE9\xB2\x85", + "\xF6\xD2" => "\xE9\xB2\x86", + "\xF6\xD3" => "\xE9\xB2\x87", + "\xF6\xD4" => "\xE9\xB2\x88", + "\xF6\xD5" => "\xE7\xA8\xA3", + "\xF6\xD6" => "\xE9\xB2\x8B", + "\xF6\xD7" => "\xE9\xB2\x8E", + "\xF6\xD8" => "\xE9\xB2\x90", + "\xF6\xD9" => "\xE9\xB2\x91", + "\xF6\xDA" => "\xE9\xB2\x92", + "\xF6\xDB" => "\xE9\xB2\x94", + "\xF6\xDC" => "\xE9\xB2\x95", + "\xF6\xDD" => "\xE9\xB2\x9A", + "\xF6\xDE" => "\xE9\xB2\x9B", + "\xF6\xDF" => "\xE9\xB2\x9E", + "\xF6\xE0" => "\xE9\xB2\x9F", + "\xF6\xE1" => "\xE9\xB2\xA0", + "\xF6\xE2" => "\xE9\xB2\xA1", + "\xF6\xE3" => "\xE9\xB2\xA2", + "\xF6\xE4" => "\xE9\xB2\xA3", + "\xF6\xE5" => "\xE9\xB2\xA5", + "\xF6\xE6" => "\xE9\xB2\xA6", + "\xF6\xE7" => "\xE9\xB2\xA7", + "\xF6\xE8" => "\xE9\xB2\xA8", + "\xF6\xE9" => "\xE9\xB2\xA9", + "\xF6\xEA" => "\xE9\xB2\xAB", + "\xF6\xEB" => "\xE9\xB2\xAD", + "\xF6\xEC" => "\xE9\xB2\xAE", + "\xF6\xED" => "\xE9\xB2\xB0", + "\xF6\xEE" => "\xE9\xB2\xB1", + "\xF6\xEF" => "\xE9\xB2\xB2", + "\xF6\xF0" => "\xE9\xB2\xB3", + "\xF6\xF1" => "\xE9\xB2\xB4", + "\xF6\xF2" => "\xE9\xB2\xB5", + "\xF6\xF3" => "\xE9\xB2\xB6", + "\xF6\xF4" => "\xE9\xB2\xB7", + "\xF6\xF5" => "\xE9\xB2\xBA", + "\xF6\xF6" => "\xE9\xB2\xBB", + "\xF6\xF7" => "\xE9\xB2\xBC", + "\xF6\xF8" => "\xE9\xB2\xBD", + "\xF6\xF9" => "\xE9\xB3\x84", + "\xF6\xFA" => "\xE9\xB3\x85", + "\xF6\xFB" => "\xE9\xB3\x86", + "\xF6\xFC" => "\xE9\xB3\x87", + "\xF6\xFD" => "\xE9\xB3\x8A", + "\xF6\xFE" => "\xE9\xB3\x8B", + "\xF7\xA1" => "\xE9\xB3\x8C", + "\xF7\xA2" => "\xE9\xB3\x8D", + "\xF7\xA3" => "\xE9\xB3\x8E", + "\xF7\xA4" => "\xE9\xB3\x8F", + "\xF7\xA5" => "\xE9\xB3\x90", + "\xF7\xA6" => "\xE9\xB3\x93", + "\xF7\xA7" => "\xE9\xB3\x94", + "\xF7\xA8" => "\xE9\xB3\x95", + "\xF7\xA9" => "\xE9\xB3\x97", + "\xF7\xAA" => "\xE9\xB3\x98", + "\xF7\xAB" => "\xE9\xB3\x99", + "\xF7\xAC" => "\xE9\xB3\x9C", + "\xF7\xAD" => "\xE9\xB3\x9D", + "\xF7\xAE" => "\xE9\xB3\x9F", + "\xF7\xAF" => "\xE9\xB3\xA2", + "\xF7\xB0" => "\xE9\x9D\xBC", + "\xF7\xB1" => "\xE9\x9E\x85", + "\xF7\xB2" => "\xE9\x9E\x91", + "\xF7\xB3" => "\xE9\x9E\x92", + "\xF7\xB4" => "\xE9\x9E\x94", + "\xF7\xB5" => "\xE9\x9E\xAF", + "\xF7\xB6" => "\xE9\x9E\xAB", + "\xF7\xB7" => "\xE9\x9E\xA3", + "\xF7\xB8" => "\xE9\x9E\xB2", + "\xF7\xB9" => "\xE9\x9E\xB4", + "\xF7\xBA" => "\xE9\xAA\xB1", + "\xF7\xBB" => "\xE9\xAA\xB0", + "\xF7\xBC" => "\xE9\xAA\xB7", + "\xF7\xBD" => "\xE9\xB9\x98", + "\xF7\xBE" => "\xE9\xAA\xB6", + "\xF7\xBF" => "\xE9\xAA\xBA", + "\xF7\xC0" => "\xE9\xAA\xBC", + "\xF7\xC1" => "\xE9\xAB\x81", + "\xF7\xC2" => "\xE9\xAB\x80", + "\xF7\xC3" => "\xE9\xAB\x85", + "\xF7\xC4" => "\xE9\xAB\x82", + "\xF7\xC5" => "\xE9\xAB\x8B", + "\xF7\xC6" => "\xE9\xAB\x8C", + "\xF7\xC7" => "\xE9\xAB\x91", + "\xF7\xC8" => "\xE9\xAD\x85", + "\xF7\xC9" => "\xE9\xAD\x83", + "\xF7\xCA" => "\xE9\xAD\x87", + "\xF7\xCB" => "\xE9\xAD\x89", + "\xF7\xCC" => "\xE9\xAD\x88", + "\xF7\xCD" => "\xE9\xAD\x8D", + "\xF7\xCE" => "\xE9\xAD\x91", + "\xF7\xCF" => "\xE9\xA3\xA8", + "\xF7\xD0" => "\xE9\xA4\x8D", + "\xF7\xD1" => "\xE9\xA4\xAE", + "\xF7\xD2" => "\xE9\xA5\x95", + "\xF7\xD3" => "\xE9\xA5\x94", + "\xF7\xD4" => "\xE9\xAB\x9F", + "\xF7\xD5" => "\xE9\xAB\xA1", + "\xF7\xD6" => "\xE9\xAB\xA6", + "\xF7\xD7" => "\xE9\xAB\xAF", + "\xF7\xD8" => "\xE9\xAB\xAB", + "\xF7\xD9" => "\xE9\xAB\xBB", + "\xF7\xDA" => "\xE9\xAB\xAD", + "\xF7\xDB" => "\xE9\xAB\xB9", + "\xF7\xDC" => "\xE9\xAC\x88", + "\xF7\xDD" => "\xE9\xAC\x8F", + "\xF7\xDE" => "\xE9\xAC\x93", + "\xF7\xDF" => "\xE9\xAC\x9F", + "\xF7\xE0" => "\xE9\xAC\xA3", + "\xF7\xE1" => "\xE9\xBA\xBD", + "\xF7\xE2" => "\xE9\xBA\xBE", + "\xF7\xE3" => "\xE7\xB8\xBB", + "\xF7\xE4" => "\xE9\xBA\x82", + "\xF7\xE5" => "\xE9\xBA\x87", + "\xF7\xE6" => "\xE9\xBA\x88", + "\xF7\xE7" => "\xE9\xBA\x8B", + "\xF7\xE8" => "\xE9\xBA\x92", + "\xF7\xE9" => "\xE9\x8F\x96", + "\xF7\xEA" => "\xE9\xBA\x9D", + "\xF7\xEB" => "\xE9\xBA\x9F", + "\xF7\xEC" => "\xE9\xBB\x9B", + "\xF7\xED" => "\xE9\xBB\x9C", + "\xF7\xEE" => "\xE9\xBB\x9D", + "\xF7\xEF" => "\xE9\xBB\xA0", + "\xF7\xF0" => "\xE9\xBB\x9F", + "\xF7\xF1" => "\xE9\xBB\xA2", + "\xF7\xF2" => "\xE9\xBB\xA9", + "\xF7\xF3" => "\xE9\xBB\xA7", + "\xF7\xF4" => "\xE9\xBB\xA5", + "\xF7\xF5" => "\xE9\xBB\xAA", + "\xF7\xF6" => "\xE9\xBB\xAF", + "\xF7\xF7" => "\xE9\xBC\xA2", + "\xF7\xF8" => "\xE9\xBC\xAC", + "\xF7\xF9" => "\xE9\xBC\xAF", + "\xF7\xFA" => "\xE9\xBC\xB9", + "\xF7\xFB" => "\xE9\xBC\xB7", + "\xF7\xFC" => "\xE9\xBC\xBD", + "\xF7\xFD" => "\xE9\xBC\xBE", + "\xF7\xFE" => "\xE9\xBD\x84", + ); + return strtr($string, $transform); +} + +function sjis($string) +{ + static $transform = array( + "\x5C"=>"\xC2\xA5", + "\x7E"=>"\xE2\x80\xBE", + "\x81\x40"=>"\xE3\x80\x80", + "\x81\x41"=>"\xE3\x80\x81", + "\x81\x42"=>"\xE3\x80\x82", + "\x81\x43"=>"\xEF\xBC\x8C", + "\x81\x44"=>"\xEF\xBC\x8E", + "\x81\x45"=>"\xE3\x83\xBB", + "\x81\x46"=>"\xEF\xBC\x9A", + "\x81\x47"=>"\xEF\xBC\x9B", + "\x81\x48"=>"\xEF\xBC\x9F", + "\x81\x49"=>"\xEF\xBC\x81", + "\x81\x4A"=>"\xE3\x82\x9B", + "\x81\x4B"=>"\xE3\x82\x9C", + "\x81\x4C"=>"\xC2\xB4", + "\x81\x4D"=>"\xEF\xBD\x80", + "\x81\x4E"=>"\xC2\xA8", + "\x81\x4F"=>"\xEF\xBC\xBE", + "\x81\x50"=>"\xEF\xBF\xA3", + "\x81\x51"=>"\xEF\xBC\xBF", + "\x81\x52"=>"\xE3\x83\xBD", + "\x81\x53"=>"\xE3\x83\xBE", + "\x81\x54"=>"\xE3\x82\x9D", + "\x81\x55"=>"\xE3\x82\x9E", + "\x81\x56"=>"\xE3\x80\x83", + "\x81\x57"=>"\xE4\xBB\x9D", + "\x81\x58"=>"\xE3\x80\x85", + "\x81\x59"=>"\xE3\x80\x86", + "\x81\x5A"=>"\xE3\x80\x87", + "\x81\x5B"=>"\xE3\x83\xBC", + "\x81\x5C"=>"\xE2\x80\x95", // set as U+2015 but could be U+2014 + "\x81\x5D"=>"\xE2\x80\x90", + "\x81\x5E"=>"\xEF\xBC\x8F", + "\x81\x5F"=>"\xEF\xBC\xBC", // or U+005C + "\x81\x60"=>"\xE3\x80\x9C", + "\x81\x61"=>"\xE2\x80\x96", + "\x81\x62"=>"\xEF\xBD\x9C", + "\x81\x63"=>"\xE2\x80\xA6", + "\x81\x64"=>"\xE2\x80\xA5", + "\x81\x65"=>"\xE2\x80\x98", + "\x81\x66"=>"\xE2\x80\x99", + "\x81\x67"=>"\xE2\x80\x9C", + "\x81\x68"=>"\xE2\x80\x9D", + "\x81\x69"=>"\xEF\xBC\x88", + "\x81\x6A"=>"\xEF\xBC\x89", + "\x81\x6B"=>"\xE3\x80\x94", + "\x81\x6C"=>"\xE3\x80\x95", + "\x81\x6D"=>"\xEF\xBC\xBB", + "\x81\x6E"=>"\xEF\xBC\xBD", + "\x81\x6F"=>"\xEF\xBD\x9B", + "\x81\x70"=>"\xEF\xBD\x9D", + "\x81\x71"=>"\xE3\x80\x88", + "\x81\x72"=>"\xE3\x80\x89", + "\x81\x73"=>"\xE3\x80\x8A", + "\x81\x74"=>"\xE3\x80\x8B", + "\x81\x75"=>"\xE3\x80\x8C", + "\x81\x76"=>"\xE3\x80\x8D", + "\x81\x77"=>"\xE3\x80\x8E", + "\x81\x78"=>"\xE3\x80\x8F", + "\x81\x79"=>"\xE3\x80\x90", + "\x81\x7A"=>"\xE3\x80\x91", + "\x81\x7B"=>"\xEF\xBC\x8B", + "\x81\x7C"=>"\xE2\x88\x92", + "\x81\x7D"=>"\xC2\xB1", + "\x81\x7E"=>"\xC3\x97", + "\x81\x80"=>"\xC3\xB7", + "\x81\x81"=>"\xEF\xBC\x9D", + "\x81\x82"=>"\xE2\x89\xA0", + "\x81\x83"=>"\xEF\xBC\x9C", + "\x81\x84"=>"\xEF\xBC\x9E", + "\x81\x85"=>"\xE2\x89\xA6", + "\x81\x86"=>"\xE2\x89\xA7", + "\x81\x87"=>"\xE2\x88\x9E", + "\x81\x88"=>"\xE2\x88\xB4", + "\x81\x89"=>"\xE2\x99\x82", + "\x81\x8A"=>"\xE2\x99\x80", + "\x81\x8B"=>"\xC2\xB0", + "\x81\x8C"=>"\xE2\x80\xB2", + "\x81\x8D"=>"\xE2\x80\xB3", + "\x81\x8E"=>"\xE2\x84\x83", + "\x81\x8F"=>"\xEF\xBF\xA5", + "\x81\x90"=>"\xEF\xBC\x84", + "\x81\x91"=>"\xC2\xA2", + "\x81\x92"=>"\xC2\xA3", + "\x81\x93"=>"\xEF\xBC\x85", + "\x81\x94"=>"\xEF\xBC\x83", + "\x81\x95"=>"\xEF\xBC\x86", + "\x81\x96"=>"\xEF\xBC\x8A", + "\x81\x97"=>"\xEF\xBC\xA0", + "\x81\x98"=>"\xC2\xA7", + "\x81\x99"=>"\xE2\x98\x86", + "\x81\x9A"=>"\xE2\x98\x85", + "\x81\x9B"=>"\xE2\x97\x8B", + "\x81\x9C"=>"\xE2\x97\x8F", + "\x81\x9D"=>"\xE2\x97\x8E", + "\x81\x9E"=>"\xE2\x97\x87", + "\x81\x9F"=>"\xE2\x97\x86", + "\x81\xA0"=>"\xE2\x96\xA1", + "\x81\xA1"=>"\xE2\x96\xA0", + "\x81\xA2"=>"\xE2\x96\xB3", + "\x81\xA3"=>"\xE2\x96\xB2", + "\x81\xA4"=>"\xE2\x96\xBD", + "\x81\xA5"=>"\xE2\x96\xBC", + "\x81\xA6"=>"\xE2\x80\xBB", + "\x81\xA7"=>"\xE3\x80\x92", + "\x81\xA8"=>"\xE2\x86\x92", + "\x81\xA9"=>"\xE2\x86\x90", + "\x81\xAA"=>"\xE2\x86\x91", + "\x81\xAB"=>"\xE2\x86\x93", + "\x81\xAC"=>"\xE3\x80\x93", + "\x81\xAD"=>"\xEF\xBC\x87", // extra?! + "\x81\xB8"=>"\xE2\x88\x88", + "\x81\xB9"=>"\xE2\x88\x8B", + "\x81\xBA"=>"\xE2\x8A\x86", + "\x81\xBB"=>"\xE2\x8A\x87", + "\x81\xBC"=>"\xE2\x8A\x82", + "\x81\xBD"=>"\xE2\x8A\x83", + "\x81\xBE"=>"\xE2\x88\xAA", + "\x81\xBF"=>"\xE2\x88\xA9", + "\x81\xC8"=>"\xE2\x88\xA7", + "\x81\xC9"=>"\xE2\x88\xA8", + "\x81\xCA"=>"\xC2\xAC", + "\x81\xCB"=>"\xE2\x87\x92", + "\x81\xCC"=>"\xE2\x87\x94", + "\x81\xCD"=>"\xE2\x88\x80", + "\x81\xCE"=>"\xE2\x88\x83", + "\x81\xDA"=>"\xE2\x88\xA0", + "\x81\xDB"=>"\xE2\x8A\xA5", + "\x81\xDC"=>"\xE2\x8C\x92", + "\x81\xDD"=>"\xE2\x88\x82", + "\x81\xDE"=>"\xE2\x88\x87", + "\x81\xDF"=>"\xE2\x89\xA1", + "\x81\xE0"=>"\xE2\x89\x92", + "\x81\xE1"=>"\xE2\x89\xAA", + "\x81\xE2"=>"\xE2\x89\xAB", + "\x81\xE3"=>"\xE2\x88\x9A", + "\x81\xE4"=>"\xE2\x88\xBD", + "\x81\xE5"=>"\xE2\x88\x9D", + "\x81\xE6"=>"\xE2\x88\xB5", + "\x81\xE7"=>"\xE2\x88\xAB", + "\x81\xE8"=>"\xE2\x88\xAC", + "\x81\xF0"=>"\xE2\x84\xAB", + "\x81\xF1"=>"\xE2\x80\xB0", + "\x81\xF2"=>"\xE2\x99\xAF", + "\x81\xF3"=>"\xE2\x99\xAD", + "\x81\xF4"=>"\xE2\x99\xAA", + "\x81\xF5"=>"\xE2\x80\xA0", + "\x81\xF6"=>"\xE2\x80\xA1", + "\x81\xF7"=>"\xC2\xB6", + "\x81\xFC"=>"\xE2\x97\xAF", + "\x82\x4F"=>"\xEF\xBC\x90", + "\x82\x50"=>"\xEF\xBC\x91", + "\x82\x51"=>"\xEF\xBC\x92", + "\x82\x52"=>"\xEF\xBC\x93", + "\x82\x53"=>"\xEF\xBC\x94", + "\x82\x54"=>"\xEF\xBC\x95", + "\x82\x55"=>"\xEF\xBC\x96", + "\x82\x56"=>"\xEF\xBC\x97", + "\x82\x57"=>"\xEF\xBC\x98", + "\x82\x58"=>"\xEF\xBC\x99", + "\x82\x60"=>"\xEF\xBC\xA1", + "\x82\x61"=>"\xEF\xBC\xA2", + "\x82\x62"=>"\xEF\xBC\xA3", + "\x82\x63"=>"\xEF\xBC\xA4", + "\x82\x64"=>"\xEF\xBC\xA5", + "\x82\x65"=>"\xEF\xBC\xA6", + "\x82\x66"=>"\xEF\xBC\xA7", + "\x82\x67"=>"\xEF\xBC\xA8", + "\x82\x68"=>"\xEF\xBC\xA9", + "\x82\x69"=>"\xEF\xBC\xAA", + "\x82\x6A"=>"\xEF\xBC\xAB", + "\x82\x6B"=>"\xEF\xBC\xAC", + "\x82\x6C"=>"\xEF\xBC\xAD", + "\x82\x6D"=>"\xEF\xBC\xAE", + "\x82\x6E"=>"\xEF\xBC\xAF", + "\x82\x6F"=>"\xEF\xBC\xB0", + "\x82\x70"=>"\xEF\xBC\xB1", + "\x82\x71"=>"\xEF\xBC\xB2", + "\x82\x72"=>"\xEF\xBC\xB3", + "\x82\x73"=>"\xEF\xBC\xB4", + "\x82\x74"=>"\xEF\xBC\xB5", + "\x82\x75"=>"\xEF\xBC\xB6", + "\x82\x76"=>"\xEF\xBC\xB7", + "\x82\x77"=>"\xEF\xBC\xB8", + "\x82\x78"=>"\xEF\xBC\xB9", + "\x82\x79"=>"\xEF\xBC\xBA", + "\x82\x81"=>"\xEF\xBD\x81", + "\x82\x82"=>"\xEF\xBD\x82", + "\x82\x83"=>"\xEF\xBD\x83", + "\x82\x84"=>"\xEF\xBD\x84", + "\x82\x85"=>"\xEF\xBD\x85", + "\x82\x86"=>"\xEF\xBD\x86", + "\x82\x87"=>"\xEF\xBD\x87", + "\x82\x88"=>"\xEF\xBD\x88", + "\x82\x89"=>"\xEF\xBD\x89", + "\x82\x8A"=>"\xEF\xBD\x8A", + "\x82\x8B"=>"\xEF\xBD\x8B", + "\x82\x8C"=>"\xEF\xBD\x8C", + "\x82\x8D"=>"\xEF\xBD\x8D", + "\x82\x8E"=>"\xEF\xBD\x8E", + "\x82\x8F"=>"\xEF\xBD\x8F", + "\x82\x90"=>"\xEF\xBD\x90", + "\x82\x91"=>"\xEF\xBD\x91", + "\x82\x92"=>"\xEF\xBD\x92", + "\x82\x93"=>"\xEF\xBD\x93", + "\x82\x94"=>"\xEF\xBD\x94", + "\x82\x95"=>"\xEF\xBD\x95", + "\x82\x96"=>"\xEF\xBD\x96", + "\x82\x97"=>"\xEF\xBD\x97", + "\x82\x98"=>"\xEF\xBD\x98", + "\x82\x99"=>"\xEF\xBD\x99", + "\x82\x9A"=>"\xEF\xBD\x9A", + "\x82\x9F"=>"\xE3\x81\x81", + "\x82\xA0"=>"\xE3\x81\x82", + "\x82\xA1"=>"\xE3\x81\x83", + "\x82\xA2"=>"\xE3\x81\x84", + "\x82\xA3"=>"\xE3\x81\x85", + "\x82\xA4"=>"\xE3\x81\x86", + "\x82\xA5"=>"\xE3\x81\x87", + "\x82\xA6"=>"\xE3\x81\x88", + "\x82\xA7"=>"\xE3\x81\x89", + "\x82\xA8"=>"\xE3\x81\x8A", + "\x82\xA9"=>"\xE3\x81\x8B", + "\x82\xAA"=>"\xE3\x81\x8C", + "\x82\xAB"=>"\xE3\x81\x8D", + "\x82\xAC"=>"\xE3\x81\x8E", + "\x82\xAD"=>"\xE3\x81\x8F", + "\x82\xAE"=>"\xE3\x81\x90", + "\x82\xAF"=>"\xE3\x81\x91", + "\x82\xB0"=>"\xE3\x81\x92", + "\x82\xB1"=>"\xE3\x81\x93", + "\x82\xB2"=>"\xE3\x81\x94", + "\x82\xB3"=>"\xE3\x81\x95", + "\x82\xB4"=>"\xE3\x81\x96", + "\x82\xB5"=>"\xE3\x81\x97", + "\x82\xB6"=>"\xE3\x81\x98", + "\x82\xB7"=>"\xE3\x81\x99", + "\x82\xB8"=>"\xE3\x81\x9A", + "\x82\xB9"=>"\xE3\x81\x9B", + "\x82\xBA"=>"\xE3\x81\x9C", + "\x82\xBB"=>"\xE3\x81\x9D", + "\x82\xBC"=>"\xE3\x81\x9E", + "\x82\xBD"=>"\xE3\x81\x9F", + "\x82\xBE"=>"\xE3\x81\xA0", + "\x82\xBF"=>"\xE3\x81\xA1", + "\x82\xC0"=>"\xE3\x81\xA2", + "\x82\xC1"=>"\xE3\x81\xA3", + "\x82\xC2"=>"\xE3\x81\xA4", + "\x82\xC3"=>"\xE3\x81\xA5", + "\x82\xC4"=>"\xE3\x81\xA6", + "\x82\xC5"=>"\xE3\x81\xA7", + "\x82\xC6"=>"\xE3\x81\xA8", + "\x82\xC7"=>"\xE3\x81\xA9", + "\x82\xC8"=>"\xE3\x81\xAA", + "\x82\xC9"=>"\xE3\x81\xAB", + "\x82\xCA"=>"\xE3\x81\xAC", + "\x82\xCB"=>"\xE3\x81\xAD", + "\x82\xCC"=>"\xE3\x81\xAE", + "\x82\xCD"=>"\xE3\x81\xAF", + "\x82\xCE"=>"\xE3\x81\xB0", + "\x82\xCF"=>"\xE3\x81\xB1", + "\x82\xD0"=>"\xE3\x81\xB2", + "\x82\xD1"=>"\xE3\x81\xB3", + "\x82\xD2"=>"\xE3\x81\xB4", + "\x82\xD3"=>"\xE3\x81\xB5", + "\x82\xD4"=>"\xE3\x81\xB6", + "\x82\xD5"=>"\xE3\x81\xB7", + "\x82\xD6"=>"\xE3\x81\xB8", + "\x82\xD7"=>"\xE3\x81\xB9", + "\x82\xD8"=>"\xE3\x81\xBA", + "\x82\xD9"=>"\xE3\x81\xBB", + "\x82\xDA"=>"\xE3\x81\xBC", + "\x82\xDB"=>"\xE3\x81\xBD", + "\x82\xDC"=>"\xE3\x81\xBE", + "\x82\xDD"=>"\xE3\x81\xBF", + "\x82\xDE"=>"\xE3\x82\x80", + "\x82\xDF"=>"\xE3\x82\x81", + "\x82\xE0"=>"\xE3\x82\x82", + "\x82\xE1"=>"\xE3\x82\x83", + "\x82\xE2"=>"\xE3\x82\x84", + "\x82\xE3"=>"\xE3\x82\x85", + "\x82\xE4"=>"\xE3\x82\x86", + "\x82\xE5"=>"\xE3\x82\x87", + "\x82\xE6"=>"\xE3\x82\x88", + "\x82\xE7"=>"\xE3\x82\x89", + "\x82\xE8"=>"\xE3\x82\x8A", + "\x82\xE9"=>"\xE3\x82\x8B", + "\x82\xEA"=>"\xE3\x82\x8C", + "\x82\xEB"=>"\xE3\x82\x8D", + "\x82\xEC"=>"\xE3\x82\x8E", + "\x82\xED"=>"\xE3\x82\x8F", + "\x82\xEE"=>"\xE3\x82\x90", + "\x82\xEF"=>"\xE3\x82\x91", + "\x82\xF0"=>"\xE3\x82\x92", + "\x82\xF1"=>"\xE3\x82\x93", + "\x83\x40"=>"\xE3\x82\xA1", + "\x83\x41"=>"\xE3\x82\xA2", + "\x83\x42"=>"\xE3\x82\xA3", + "\x83\x43"=>"\xE3\x82\xA4", + "\x83\x44"=>"\xE3\x82\xA5", + "\x83\x45"=>"\xE3\x82\xA6", + "\x83\x46"=>"\xE3\x82\xA7", + "\x83\x47"=>"\xE3\x82\xA8", + "\x83\x48"=>"\xE3\x82\xA9", + "\x83\x49"=>"\xE3\x82\xAA", + "\x83\x4A"=>"\xE3\x82\xAB", + "\x83\x4B"=>"\xE3\x82\xAC", + "\x83\x4C"=>"\xE3\x82\xAD", + "\x83\x4D"=>"\xE3\x82\xAE", + "\x83\x4E"=>"\xE3\x82\xAF", + "\x83\x4F"=>"\xE3\x82\xB0", + "\x83\x50"=>"\xE3\x82\xB1", + "\x83\x51"=>"\xE3\x82\xB2", + "\x83\x52"=>"\xE3\x82\xB3", + "\x83\x53"=>"\xE3\x82\xB4", + "\x83\x54"=>"\xE3\x82\xB5", + "\x83\x55"=>"\xE3\x82\xB6", + "\x83\x56"=>"\xE3\x82\xB7", + "\x83\x57"=>"\xE3\x82\xB8", + "\x83\x58"=>"\xE3\x82\xB9", + "\x83\x59"=>"\xE3\x82\xBA", + "\x83\x5A"=>"\xE3\x82\xBB", + "\x83\x5B"=>"\xE3\x82\xBC", + "\x83\x5C"=>"\xE3\x82\xBD", + "\x83\x5D"=>"\xE3\x82\xBE", + "\x83\x5E"=>"\xE3\x82\xBF", + "\x83\x5F"=>"\xE3\x83\x80", + "\x83\x60"=>"\xE3\x83\x81", + "\x83\x61"=>"\xE3\x83\x82", + "\x83\x62"=>"\xE3\x83\x83", + "\x83\x63"=>"\xE3\x83\x84", + "\x83\x64"=>"\xE3\x83\x85", + "\x83\x65"=>"\xE3\x83\x86", + "\x83\x66"=>"\xE3\x83\x87", + "\x83\x67"=>"\xE3\x83\x88", + "\x83\x68"=>"\xE3\x83\x89", + "\x83\x69"=>"\xE3\x83\x8A", + "\x83\x6A"=>"\xE3\x83\x8B", + "\x83\x6B"=>"\xE3\x83\x8C", + "\x83\x6C"=>"\xE3\x83\x8D", + "\x83\x6D"=>"\xE3\x83\x8E", + "\x83\x6E"=>"\xE3\x83\x8F", + "\x83\x6F"=>"\xE3\x83\x90", + "\x83\x70"=>"\xE3\x83\x91", + "\x83\x71"=>"\xE3\x83\x92", + "\x83\x72"=>"\xE3\x83\x93", + "\x83\x73"=>"\xE3\x83\x94", + "\x83\x74"=>"\xE3\x83\x95", + "\x83\x75"=>"\xE3\x83\x96", + "\x83\x76"=>"\xE3\x83\x97", + "\x83\x77"=>"\xE3\x83\x98", + "\x83\x78"=>"\xE3\x83\x99", + "\x83\x79"=>"\xE3\x83\x9A", + "\x83\x7A"=>"\xE3\x83\x9B", + "\x83\x7B"=>"\xE3\x83\x9C", + "\x83\x7C"=>"\xE3\x83\x9D", + "\x83\x7D"=>"\xE3\x83\x9E", + "\x83\x7E"=>"\xE3\x83\x9F", + "\x83\x80"=>"\xE3\x83\xA0", + "\x83\x81"=>"\xE3\x83\xA1", + "\x83\x82"=>"\xE3\x83\xA2", + "\x83\x83"=>"\xE3\x83\xA3", + "\x83\x84"=>"\xE3\x83\xA4", + "\x83\x85"=>"\xE3\x83\xA5", + "\x83\x86"=>"\xE3\x83\xA6", + "\x83\x87"=>"\xE3\x83\xA7", + "\x83\x88"=>"\xE3\x83\xA8", + "\x83\x89"=>"\xE3\x83\xA9", + "\x83\x8A"=>"\xE3\x83\xAA", + "\x83\x8B"=>"\xE3\x83\xAB", + "\x83\x8C"=>"\xE3\x83\xAC", + "\x83\x8D"=>"\xE3\x83\xAD", + "\x83\x8E"=>"\xE3\x83\xAE", + "\x83\x8F"=>"\xE3\x83\xAF", + "\x83\x90"=>"\xE3\x83\xB0", + "\x83\x91"=>"\xE3\x83\xB1", + "\x83\x92"=>"\xE3\x83\xB2", + "\x83\x93"=>"\xE3\x83\xB3", + "\x83\x94"=>"\xE3\x83\xB4", + "\x83\x95"=>"\xE3\x83\xB5", + "\x83\x96"=>"\xE3\x83\xB6", + "\x83\x9F"=>"\xCE\x91", + "\x83\xA0"=>"\xCE\x92", + "\x83\xA1"=>"\xCE\x93", + "\x83\xA2"=>"\xCE\x94", + "\x83\xA3"=>"\xCE\x95", + "\x83\xA4"=>"\xCE\x96", + "\x83\xA5"=>"\xCE\x97", + "\x83\xA6"=>"\xCE\x98", + "\x83\xA7"=>"\xCE\x99", + "\x83\xA8"=>"\xCE\x9A", + "\x83\xA9"=>"\xCE\x9B", + "\x83\xAA"=>"\xCE\x9C", + "\x83\xAB"=>"\xCE\x9D", + "\x83\xAC"=>"\xCE\x9E", + "\x83\xAD"=>"\xCE\x9F", + "\x83\xAE"=>"\xCE\xA0", + "\x83\xAF"=>"\xCE\xA1", + "\x83\xB0"=>"\xCE\xA3", + "\x83\xB1"=>"\xCE\xA4", + "\x83\xB2"=>"\xCE\xA5", + "\x83\xB3"=>"\xCE\xA6", + "\x83\xB4"=>"\xCE\xA7", + "\x83\xB5"=>"\xCE\xA8", + "\x83\xB6"=>"\xCE\xA9", + "\x83\xBF"=>"\xCE\xB1", + "\x83\xC0"=>"\xCE\xB2", + "\x83\xC1"=>"\xCE\xB3", + "\x83\xC2"=>"\xCE\xB4", + "\x83\xC3"=>"\xCE\xB5", + "\x83\xC4"=>"\xCE\xB6", + "\x83\xC5"=>"\xCE\xB7", + "\x83\xC6"=>"\xCE\xB8", + "\x83\xC7"=>"\xCE\xB9", + "\x83\xC8"=>"\xCE\xBA", + "\x83\xC9"=>"\xCE\xBB", + "\x83\xCA"=>"\xCE\xBC", + "\x83\xCB"=>"\xCE\xBD", + "\x83\xCC"=>"\xCE\xBE", + "\x83\xCD"=>"\xCE\xBF", + "\x83\xCE"=>"\xCF\x80", + "\x83\xCF"=>"\xCF\x81", + "\x83\xD0"=>"\xCF\x83", + "\x83\xD1"=>"\xCF\x84", + "\x83\xD2"=>"\xCF\x85", + "\x83\xD3"=>"\xCF\x86", + "\x83\xD4"=>"\xCF\x87", + "\x83\xD5"=>"\xCF\x88", + "\x83\xD6"=>"\xCF\x89", + "\x84\x40"=>"\xD0\x90", + "\x84\x41"=>"\xD0\x91", + "\x84\x42"=>"\xD0\x92", + "\x84\x43"=>"\xD0\x93", + "\x84\x44"=>"\xD0\x94", + "\x84\x45"=>"\xD0\x95", + "\x84\x46"=>"\xD0\x81", + "\x84\x47"=>"\xD0\x96", + "\x84\x48"=>"\xD0\x97", + "\x84\x49"=>"\xD0\x98", + "\x84\x4A"=>"\xD0\x99", + "\x84\x4B"=>"\xD0\x9A", + "\x84\x4C"=>"\xD0\x9B", + "\x84\x4D"=>"\xD0\x9C", + "\x84\x4E"=>"\xD0\x9D", + "\x84\x4F"=>"\xD0\x9E", + "\x84\x50"=>"\xD0\x9F", + "\x84\x51"=>"\xD0\xA0", + "\x84\x52"=>"\xD0\xA1", + "\x84\x53"=>"\xD0\xA2", + "\x84\x54"=>"\xD0\xA3", + "\x84\x55"=>"\xD0\xA4", + "\x84\x56"=>"\xD0\xA5", + "\x84\x57"=>"\xD0\xA6", + "\x84\x58"=>"\xD0\xA7", + "\x84\x59"=>"\xD0\xA8", + "\x84\x5A"=>"\xD0\xA9", + "\x84\x5B"=>"\xD0\xAA", + "\x84\x5C"=>"\xD0\xAB", + "\x84\x5D"=>"\xD0\xAC", + "\x84\x5E"=>"\xD0\xAD", + "\x84\x5F"=>"\xD0\xAE", + "\x84\x60"=>"\xD0\xAF", + "\x84\x70"=>"\xD0\xB0", + "\x84\x71"=>"\xD0\xB1", + "\x84\x72"=>"\xD0\xB2", + "\x84\x73"=>"\xD0\xB3", + "\x84\x74"=>"\xD0\xB4", + "\x84\x75"=>"\xD0\xB5", + "\x84\x76"=>"\xD1\x91", + "\x84\x77"=>"\xD0\xB6", + "\x84\x78"=>"\xD0\xB7", + "\x84\x79"=>"\xD0\xB8", + "\x84\x7A"=>"\xD0\xB9", + "\x84\x7B"=>"\xD0\xBA", + "\x84\x7C"=>"\xD0\xBB", + "\x84\x7D"=>"\xD0\xBC", + "\x84\x7E"=>"\xD0\xBD", + "\x84\x80"=>"\xD0\xBE", + "\x84\x81"=>"\xD0\xBF", + "\x84\x82"=>"\xD1\x80", + "\x84\x83"=>"\xD1\x81", + "\x84\x84"=>"\xD1\x82", + "\x84\x85"=>"\xD1\x83", + "\x84\x86"=>"\xD1\x84", + "\x84\x87"=>"\xD1\x85", + "\x84\x88"=>"\xD1\x86", + "\x84\x89"=>"\xD1\x87", + "\x84\x8A"=>"\xD1\x88", + "\x84\x8B"=>"\xD1\x89", + "\x84\x8C"=>"\xD1\x8A", + "\x84\x8D"=>"\xD1\x8B", + "\x84\x8E"=>"\xD1\x8C", + "\x84\x8F"=>"\xD1\x8D", + "\x84\x90"=>"\xD1\x8E", + "\x84\x91"=>"\xD1\x8F", + "\x84\x9F"=>"\xE2\x94\x80", + "\x84\xA0"=>"\xE2\x94\x82", + "\x84\xA1"=>"\xE2\x94\x8C", + "\x84\xA2"=>"\xE2\x94\x90", + "\x84\xA3"=>"\xE2\x94\x98", + "\x84\xA4"=>"\xE2\x94\x94", + "\x84\xA5"=>"\xE2\x94\x9C", + "\x84\xA6"=>"\xE2\x94\xAC", + "\x84\xA7"=>"\xE2\x94\xA4", + "\x84\xA8"=>"\xE2\x94\xB4", + "\x84\xA9"=>"\xE2\x94\xBC", + "\x84\xAA"=>"\xE2\x94\x81", + "\x84\xAB"=>"\xE2\x94\x83", + "\x84\xAC"=>"\xE2\x94\x8F", + "\x84\xAD"=>"\xE2\x94\x93", + "\x84\xAE"=>"\xE2\x94\x9B", + "\x84\xAF"=>"\xE2\x94\x97", + "\x84\xB0"=>"\xE2\x94\xA3", + "\x84\xB1"=>"\xE2\x94\xB3", + "\x84\xB2"=>"\xE2\x94\xAB", + "\x84\xB3"=>"\xE2\x94\xBB", + "\x84\xB4"=>"\xE2\x95\x8B", + "\x84\xB5"=>"\xE2\x94\xA0", + "\x84\xB6"=>"\xE2\x94\xAF", + "\x84\xB7"=>"\xE2\x94\xA8", + "\x84\xB8"=>"\xE2\x94\xB7", + "\x84\xB9"=>"\xE2\x94\xBF", + "\x84\xBA"=>"\xE2\x94\x9D", + "\x84\xBB"=>"\xE2\x94\xB0", + "\x84\xBC"=>"\xE2\x94\xA5", + "\x84\xBD"=>"\xE2\x94\xB8", + "\x84\xBE"=>"\xE2\x95\x82", + "\x88\x9F"=>"\xE4\xBA\x9C", + "\x88\xA0"=>"\xE5\x94\x96", + "\x88\xA1"=>"\xE5\xA8\x83", + "\x88\xA2"=>"\xE9\x98\xBF", + "\x88\xA3"=>"\xE5\x93\x80", + "\x88\xA4"=>"\xE6\x84\x9B", + "\x88\xA5"=>"\xE6\x8C\xA8", + "\x88\xA6"=>"\xE5\xA7\xB6", + "\x88\xA7"=>"\xE9\x80\xA2", + "\x88\xA8"=>"\xE8\x91\xB5", + "\x88\xA9"=>"\xE8\x8C\x9C", + "\x88\xAA"=>"\xE7\xA9\x90", + "\x88\xAB"=>"\xE6\x82\xAA", + "\x88\xAC"=>"\xE6\x8F\xA1", + "\x88\xAD"=>"\xE6\xB8\xA5", + "\x88\xAE"=>"\xE6\x97\xAD", + "\x88\xAF"=>"\xE8\x91\xA6", + "\x88\xB0"=>"\xE8\x8A\xA6", + "\x88\xB1"=>"\xE9\xAF\xB5", + "\x88\xB2"=>"\xE6\xA2\x93", + "\x88\xB3"=>"\xE5\x9C\xA7", + "\x88\xB4"=>"\xE6\x96\xA1", + "\x88\xB5"=>"\xE6\x89\xB1", + "\x88\xB6"=>"\xE5\xAE\x9B", + "\x88\xB7"=>"\xE5\xA7\x90", + "\x88\xB8"=>"\xE8\x99\xBB", + "\x88\xB9"=>"\xE9\xA3\xB4", + "\x88\xBA"=>"\xE7\xB5\xA2", + "\x88\xBB"=>"\xE7\xB6\xBE", + "\x88\xBC"=>"\xE9\xAE\x8E", + "\x88\xBD"=>"\xE6\x88\x96", + "\x88\xBE"=>"\xE7\xB2\x9F", + "\x88\xBF"=>"\xE8\xA2\xB7", + "\x88\xC0"=>"\xE5\xAE\x89", + "\x88\xC1"=>"\xE5\xBA\xB5", + "\x88\xC2"=>"\xE6\x8C\x89", + "\x88\xC3"=>"\xE6\x9A\x97", + "\x88\xC4"=>"\xE6\xA1\x88", + "\x88\xC5"=>"\xE9\x97\x87", + "\x88\xC6"=>"\xE9\x9E\x8D", + "\x88\xC7"=>"\xE6\x9D\x8F", + "\x88\xC8"=>"\xE4\xBB\xA5", + "\x88\xC9"=>"\xE4\xBC\x8A", + "\x88\xCA"=>"\xE4\xBD\x8D", + "\x88\xCB"=>"\xE4\xBE\x9D", + "\x88\xCC"=>"\xE5\x81\x89", + "\x88\xCD"=>"\xE5\x9B\xB2", + "\x88\xCE"=>"\xE5\xA4\xB7", + "\x88\xCF"=>"\xE5\xA7\x94", + "\x88\xD0"=>"\xE5\xA8\x81", + "\x88\xD1"=>"\xE5\xB0\x89", + "\x88\xD2"=>"\xE6\x83\x9F", + "\x88\xD3"=>"\xE6\x84\x8F", + "\x88\xD4"=>"\xE6\x85\xB0", + "\x88\xD5"=>"\xE6\x98\x93", + "\x88\xD6"=>"\xE6\xA4\x85", + "\x88\xD7"=>"\xE7\x82\xBA", + "\x88\xD8"=>"\xE7\x95\x8F", + "\x88\xD9"=>"\xE7\x95\xB0", + "\x88\xDA"=>"\xE7\xA7\xBB", + "\x88\xDB"=>"\xE7\xB6\xAD", + "\x88\xDC"=>"\xE7\xB7\xAF", + "\x88\xDD"=>"\xE8\x83\x83", + "\x88\xDE"=>"\xE8\x90\x8E", + "\x88\xDF"=>"\xE8\xA1\xA3", + "\x88\xE0"=>"\xE8\xAC\x82", + "\x88\xE1"=>"\xE9\x81\x95", + "\x88\xE2"=>"\xE9\x81\xBA", + "\x88\xE3"=>"\xE5\x8C\xBB", + "\x88\xE4"=>"\xE4\xBA\x95", + "\x88\xE5"=>"\xE4\xBA\xA5", + "\x88\xE6"=>"\xE5\x9F\x9F", + "\x88\xE7"=>"\xE8\x82\xB2", + "\x88\xE8"=>"\xE9\x83\x81", + "\x88\xE9"=>"\xE7\xA3\xAF", + "\x88\xEA"=>"\xE4\xB8\x80", + "\x88\xEB"=>"\xE5\xA3\xB1", + "\x88\xEC"=>"\xE6\xBA\xA2", + "\x88\xED"=>"\xE9\x80\xB8", + "\x88\xEE"=>"\xE7\xA8\xB2", + "\x88\xEF"=>"\xE8\x8C\xA8", + "\x88\xF0"=>"\xE8\x8A\x8B", + "\x88\xF1"=>"\xE9\xB0\xAF", + "\x88\xF2"=>"\xE5\x85\x81", + "\x88\xF3"=>"\xE5\x8D\xB0", + "\x88\xF4"=>"\xE5\x92\xBD", + "\x88\xF5"=>"\xE5\x93\xA1", + "\x88\xF6"=>"\xE5\x9B\xA0", + "\x88\xF7"=>"\xE5\xA7\xBB", + "\x88\xF8"=>"\xE5\xBC\x95", + "\x88\xF9"=>"\xE9\xA3\xB2", + "\x88\xFA"=>"\xE6\xB7\xAB", + "\x88\xFB"=>"\xE8\x83\xA4", + "\x88\xFC"=>"\xE8\x94\xAD", + "\x89\x40"=>"\xE9\x99\xA2", + "\x89\x41"=>"\xE9\x99\xB0", + "\x89\x42"=>"\xE9\x9A\xA0", + "\x89\x43"=>"\xE9\x9F\xBB", + "\x89\x44"=>"\xE5\x90\x8B", + "\x89\x45"=>"\xE5\x8F\xB3", + "\x89\x46"=>"\xE5\xAE\x87", + "\x89\x47"=>"\xE7\x83\x8F", + "\x89\x48"=>"\xE7\xBE\xBD", + "\x89\x49"=>"\xE8\xBF\x82", + "\x89\x4A"=>"\xE9\x9B\xA8", + "\x89\x4B"=>"\xE5\x8D\xAF", + "\x89\x4C"=>"\xE9\xB5\x9C", + "\x89\x4D"=>"\xE7\xAA\xBA", + "\x89\x4E"=>"\xE4\xB8\x91", + "\x89\x4F"=>"\xE7\xA2\x93", + "\x89\x50"=>"\xE8\x87\xBC", + "\x89\x51"=>"\xE6\xB8\xA6", + "\x89\x52"=>"\xE5\x98\x98", + "\x89\x53"=>"\xE5\x94\x84", + "\x89\x54"=>"\xE6\xAC\x9D", + "\x89\x55"=>"\xE8\x94\x9A", + "\x89\x56"=>"\xE9\xB0\xBB", + "\x89\x57"=>"\xE5\xA7\xA5", + "\x89\x58"=>"\xE5\x8E\xA9", + "\x89\x59"=>"\xE6\xB5\xA6", + "\x89\x5A"=>"\xE7\x93\x9C", + "\x89\x5B"=>"\xE9\x96\x8F", + "\x89\x5C"=>"\xE5\x99\x82", + "\x89\x5D"=>"\xE4\xBA\x91", + "\x89\x5E"=>"\xE9\x81\x8B", + "\x89\x5F"=>"\xE9\x9B\xB2", + "\x89\x60"=>"\xE8\x8D\x8F", + "\x89\x61"=>"\xE9\xA4\x8C", + "\x89\x62"=>"\xE5\x8F\xA1", + "\x89\x63"=>"\xE5\x96\xB6", + "\x89\x64"=>"\xE5\xAC\xB0", + "\x89\x65"=>"\xE5\xBD\xB1", + "\x89\x66"=>"\xE6\x98\xA0", + "\x89\x67"=>"\xE6\x9B\xB3", + "\x89\x68"=>"\xE6\xA0\x84", + "\x89\x69"=>"\xE6\xB0\xB8", + "\x89\x6A"=>"\xE6\xB3\xB3", + "\x89\x6B"=>"\xE6\xB4\xA9", + "\x89\x6C"=>"\xE7\x91\x9B", + "\x89\x6D"=>"\xE7\x9B\x88", + "\x89\x6E"=>"\xE7\xA9\x8E", + "\x89\x6F"=>"\xE9\xA0\xB4", + "\x89\x70"=>"\xE8\x8B\xB1", + "\x89\x71"=>"\xE8\xA1\x9B", + "\x89\x72"=>"\xE8\xA9\xA0", + "\x89\x73"=>"\xE9\x8B\xAD", + "\x89\x74"=>"\xE6\xB6\xB2", + "\x89\x75"=>"\xE7\x96\xAB", + "\x89\x76"=>"\xE7\x9B\x8A", + "\x89\x77"=>"\xE9\xA7\x85", + "\x89\x78"=>"\xE6\x82\xA6", + "\x89\x79"=>"\xE8\xAC\x81", + "\x89\x7A"=>"\xE8\xB6\x8A", + "\x89\x7B"=>"\xE9\x96\xB2", + "\x89\x7C"=>"\xE6\xA6\x8E", + "\x89\x7D"=>"\xE5\x8E\xAD", + "\x89\x7E"=>"\xE5\x86\x86", + "\x89\x80"=>"\xE5\x9C\x92", + "\x89\x81"=>"\xE5\xA0\xB0", + "\x89\x82"=>"\xE5\xA5\x84", + "\x89\x83"=>"\xE5\xAE\xB4", + "\x89\x84"=>"\xE5\xBB\xB6", + "\x89\x85"=>"\xE6\x80\xA8", + "\x89\x86"=>"\xE6\x8E\xA9", + "\x89\x87"=>"\xE6\x8F\xB4", + "\x89\x88"=>"\xE6\xB2\xBF", + "\x89\x89"=>"\xE6\xBC\x94", + "\x89\x8A"=>"\xE7\x82\x8E", + "\x89\x8B"=>"\xE7\x84\x94", + "\x89\x8C"=>"\xE7\x85\x99", + "\x89\x8D"=>"\xE7\x87\x95", + "\x89\x8E"=>"\xE7\x8C\xBF", + "\x89\x8F"=>"\xE7\xB8\x81", + "\x89\x90"=>"\xE8\x89\xB6", + "\x89\x91"=>"\xE8\x8B\x91", + "\x89\x92"=>"\xE8\x96\x97", + "\x89\x93"=>"\xE9\x81\xA0", + "\x89\x94"=>"\xE9\x89\x9B", + "\x89\x95"=>"\xE9\xB4\x9B", + "\x89\x96"=>"\xE5\xA1\xA9", + "\x89\x97"=>"\xE6\x96\xBC", + "\x89\x98"=>"\xE6\xB1\x9A", + "\x89\x99"=>"\xE7\x94\xA5", + "\x89\x9A"=>"\xE5\x87\xB9", + "\x89\x9B"=>"\xE5\xA4\xAE", + "\x89\x9C"=>"\xE5\xA5\xA5", + "\x89\x9D"=>"\xE5\xBE\x80", + "\x89\x9E"=>"\xE5\xBF\x9C", + "\x89\x9F"=>"\xE6\x8A\xBC", + "\x89\xA0"=>"\xE6\x97\xBA", + "\x89\xA1"=>"\xE6\xA8\xAA", + "\x89\xA2"=>"\xE6\xAC\xA7", + "\x89\xA3"=>"\xE6\xAE\xB4", + "\x89\xA4"=>"\xE7\x8E\x8B", + "\x89\xA5"=>"\xE7\xBF\x81", + "\x89\xA6"=>"\xE8\xA5\x96", + "\x89\xA7"=>"\xE9\xB4\xAC", + "\x89\xA8"=>"\xE9\xB4\x8E", + "\x89\xA9"=>"\xE9\xBB\x84", + "\x89\xAA"=>"\xE5\xB2\xA1", + "\x89\xAB"=>"\xE6\xB2\x96", + "\x89\xAC"=>"\xE8\x8D\xBB", + "\x89\xAD"=>"\xE5\x84\x84", + "\x89\xAE"=>"\xE5\xB1\x8B", + "\x89\xAF"=>"\xE6\x86\xB6", + "\x89\xB0"=>"\xE8\x87\x86", + "\x89\xB1"=>"\xE6\xA1\xB6", + "\x89\xB2"=>"\xE7\x89\xA1", + "\x89\xB3"=>"\xE4\xB9\x99", + "\x89\xB4"=>"\xE4\xBF\xBA", + "\x89\xB5"=>"\xE5\x8D\xB8", + "\x89\xB6"=>"\xE6\x81\xA9", + "\x89\xB7"=>"\xE6\xB8\xA9", + "\x89\xB8"=>"\xE7\xA9\x8F", + "\x89\xB9"=>"\xE9\x9F\xB3", + "\x89\xBA"=>"\xE4\xB8\x8B", + "\x89\xBB"=>"\xE5\x8C\x96", + "\x89\xBC"=>"\xE4\xBB\xAE", + "\x89\xBD"=>"\xE4\xBD\x95", + "\x89\xBE"=>"\xE4\xBC\xBD", + "\x89\xBF"=>"\xE4\xBE\xA1", + "\x89\xC0"=>"\xE4\xBD\xB3", + "\x89\xC1"=>"\xE5\x8A\xA0", + "\x89\xC2"=>"\xE5\x8F\xAF", + "\x89\xC3"=>"\xE5\x98\x89", + "\x89\xC4"=>"\xE5\xA4\x8F", + "\x89\xC5"=>"\xE5\xAB\x81", + "\x89\xC6"=>"\xE5\xAE\xB6", + "\x89\xC7"=>"\xE5\xAF\xA1", + "\x89\xC8"=>"\xE7\xA7\x91", + "\x89\xC9"=>"\xE6\x9A\x87", + "\x89\xCA"=>"\xE6\x9E\x9C", + "\x89\xCB"=>"\xE6\x9E\xB6", + "\x89\xCC"=>"\xE6\xAD\x8C", + "\x89\xCD"=>"\xE6\xB2\xB3", + "\x89\xCE"=>"\xE7\x81\xAB", + "\x89\xCF"=>"\xE7\x8F\x82", + "\x89\xD0"=>"\xE7\xA6\x8D", + "\x89\xD1"=>"\xE7\xA6\xBE", + "\x89\xD2"=>"\xE7\xA8\xBC", + "\x89\xD3"=>"\xE7\xAE\x87", + "\x89\xD4"=>"\xE8\x8A\xB1", + "\x89\xD5"=>"\xE8\x8B\x9B", + "\x89\xD6"=>"\xE8\x8C\x84", + "\x89\xD7"=>"\xE8\x8D\xB7", + "\x89\xD8"=>"\xE8\x8F\xAF", + "\x89\xD9"=>"\xE8\x8F\x93", + "\x89\xDA"=>"\xE8\x9D\xA6", + "\x89\xDB"=>"\xE8\xAA\xB2", + "\x89\xDC"=>"\xE5\x98\xA9", + "\x89\xDD"=>"\xE8\xB2\xA8", + "\x89\xDE"=>"\xE8\xBF\xA6", + "\x89\xDF"=>"\xE9\x81\x8E", + "\x89\xE0"=>"\xE9\x9C\x9E", + "\x89\xE1"=>"\xE8\x9A\x8A", + "\x89\xE2"=>"\xE4\xBF\x84", + "\x89\xE3"=>"\xE5\xB3\xA8", + "\x89\xE4"=>"\xE6\x88\x91", + "\x89\xE5"=>"\xE7\x89\x99", + "\x89\xE6"=>"\xE7\x94\xBB", + "\x89\xE7"=>"\xE8\x87\xA5", + "\x89\xE8"=>"\xE8\x8A\xBD", + "\x89\xE9"=>"\xE8\x9B\xBE", + "\x89\xEA"=>"\xE8\xB3\x80", + "\x89\xEB"=>"\xE9\x9B\x85", + "\x89\xEC"=>"\xE9\xA4\x93", + "\x89\xED"=>"\xE9\xA7\x95", + "\x89\xEE"=>"\xE4\xBB\x8B", + "\x89\xEF"=>"\xE4\xBC\x9A", + "\x89\xF0"=>"\xE8\xA7\xA3", + "\x89\xF1"=>"\xE5\x9B\x9E", + "\x89\xF2"=>"\xE5\xA1\x8A", + "\x89\xF3"=>"\xE5\xA3\x8A", + "\x89\xF4"=>"\xE5\xBB\xBB", + "\x89\xF5"=>"\xE5\xBF\xAB", + "\x89\xF6"=>"\xE6\x80\xAA", + "\x89\xF7"=>"\xE6\x82\x94", + "\x89\xF8"=>"\xE6\x81\xA2", + "\x89\xF9"=>"\xE6\x87\x90", + "\x89\xFA"=>"\xE6\x88\x92", + "\x89\xFB"=>"\xE6\x8B\x90", + "\x89\xFC"=>"\xE6\x94\xB9", + "\x8A\x40"=>"\xE9\xAD\x81", + "\x8A\x41"=>"\xE6\x99\xA6", + "\x8A\x42"=>"\xE6\xA2\xB0", + "\x8A\x43"=>"\xE6\xB5\xB7", + "\x8A\x44"=>"\xE7\x81\xB0", + "\x8A\x45"=>"\xE7\x95\x8C", + "\x8A\x46"=>"\xE7\x9A\x86", + "\x8A\x47"=>"\xE7\xB5\xB5", + "\x8A\x48"=>"\xE8\x8A\xA5", + "\x8A\x49"=>"\xE8\x9F\xB9", + "\x8A\x4A"=>"\xE9\x96\x8B", + "\x8A\x4B"=>"\xE9\x9A\x8E", + "\x8A\x4C"=>"\xE8\xB2\x9D", + "\x8A\x4D"=>"\xE5\x87\xB1", + "\x8A\x4E"=>"\xE5\x8A\xBE", + "\x8A\x4F"=>"\xE5\xA4\x96", + "\x8A\x50"=>"\xE5\x92\xB3", + "\x8A\x51"=>"\xE5\xAE\xB3", + "\x8A\x52"=>"\xE5\xB4\x96", + "\x8A\x53"=>"\xE6\x85\xA8", + "\x8A\x54"=>"\xE6\xA6\x82", + "\x8A\x55"=>"\xE6\xB6\xAF", + "\x8A\x56"=>"\xE7\xA2\x8D", + "\x8A\x57"=>"\xE8\x93\x8B", + "\x8A\x58"=>"\xE8\xA1\x97", + "\x8A\x59"=>"\xE8\xA9\xB2", + "\x8A\x5A"=>"\xE9\x8E\xA7", + "\x8A\x5B"=>"\xE9\xAA\xB8", + "\x8A\x5C"=>"\xE6\xB5\xAC", + "\x8A\x5D"=>"\xE9\xA6\xA8", + "\x8A\x5E"=>"\xE8\x9B\x99", + "\x8A\x5F"=>"\xE5\x9E\xA3", + "\x8A\x60"=>"\xE6\x9F\xBF", + "\x8A\x61"=>"\xE8\x9B\x8E", + "\x8A\x62"=>"\xE9\x88\x8E", + "\x8A\x63"=>"\xE5\x8A\x83", + "\x8A\x64"=>"\xE5\x9A\x87", + "\x8A\x65"=>"\xE5\x90\x84", + "\x8A\x66"=>"\xE5\xBB\x93", + "\x8A\x67"=>"\xE6\x8B\xA1", + "\x8A\x68"=>"\xE6\x92\xB9", + "\x8A\x69"=>"\xE6\xA0\xBC", + "\x8A\x6A"=>"\xE6\xA0\xB8", + "\x8A\x6B"=>"\xE6\xAE\xBB", + "\x8A\x6C"=>"\xE7\x8D\xB2", + "\x8A\x6D"=>"\xE7\xA2\xBA", + "\x8A\x6E"=>"\xE7\xA9\xAB", + "\x8A\x6F"=>"\xE8\xA6\x9A", + "\x8A\x70"=>"\xE8\xA7\x92", + "\x8A\x71"=>"\xE8\xB5\xAB", + "\x8A\x72"=>"\xE8\xBC\x83", + "\x8A\x73"=>"\xE9\x83\xAD", + "\x8A\x74"=>"\xE9\x96\xA3", + "\x8A\x75"=>"\xE9\x9A\x94", + "\x8A\x76"=>"\xE9\x9D\xA9", + "\x8A\x77"=>"\xE5\xAD\xA6", + "\x8A\x78"=>"\xE5\xB2\xB3", + "\x8A\x79"=>"\xE6\xA5\xBD", + "\x8A\x7A"=>"\xE9\xA1\x8D", + "\x8A\x7B"=>"\xE9\xA1\x8E", + "\x8A\x7C"=>"\xE6\x8E\x9B", + "\x8A\x7D"=>"\xE7\xAC\xA0", + "\x8A\x7E"=>"\xE6\xA8\xAB", + "\x8A\x80"=>"\xE6\xA9\xBF", + "\x8A\x81"=>"\xE6\xA2\xB6", + "\x8A\x82"=>"\xE9\xB0\x8D", + "\x8A\x83"=>"\xE6\xBD\x9F", + "\x8A\x84"=>"\xE5\x89\xB2", + "\x8A\x85"=>"\xE5\x96\x9D", + "\x8A\x86"=>"\xE6\x81\xB0", + "\x8A\x87"=>"\xE6\x8B\xAC", + "\x8A\x88"=>"\xE6\xB4\xBB", + "\x8A\x89"=>"\xE6\xB8\x87", + "\x8A\x8A"=>"\xE6\xBB\x91", + "\x8A\x8B"=>"\xE8\x91\x9B", + "\x8A\x8C"=>"\xE8\xA4\x90", + "\x8A\x8D"=>"\xE8\xBD\x84", + "\x8A\x8E"=>"\xE4\xB8\x94", + "\x8A\x8F"=>"\xE9\xB0\xB9", + "\x8A\x90"=>"\xE5\x8F\xB6", + "\x8A\x91"=>"\xE6\xA4\x9B", + "\x8A\x92"=>"\xE6\xA8\xBA", + "\x8A\x93"=>"\xE9\x9E\x84", + "\x8A\x94"=>"\xE6\xA0\xAA", + "\x8A\x95"=>"\xE5\x85\x9C", + "\x8A\x96"=>"\xE7\xAB\x83", + "\x8A\x97"=>"\xE8\x92\xB2", + "\x8A\x98"=>"\xE9\x87\x9C", + "\x8A\x99"=>"\xE9\x8E\x8C", + "\x8A\x9A"=>"\xE5\x99\x9B", + "\x8A\x9B"=>"\xE9\xB4\xA8", + "\x8A\x9C"=>"\xE6\xA0\xA2", + "\x8A\x9D"=>"\xE8\x8C\x85", + "\x8A\x9E"=>"\xE8\x90\xB1", + "\x8A\x9F"=>"\xE7\xB2\xA5", + "\x8A\xA0"=>"\xE5\x88\x88", + "\x8A\xA1"=>"\xE8\x8B\x85", + "\x8A\xA2"=>"\xE7\x93\xA6", + "\x8A\xA3"=>"\xE4\xB9\xBE", + "\x8A\xA4"=>"\xE4\xBE\x83", + "\x8A\xA5"=>"\xE5\x86\xA0", + "\x8A\xA6"=>"\xE5\xAF\x92", + "\x8A\xA7"=>"\xE5\x88\x8A", + "\x8A\xA8"=>"\xE5\x8B\x98", + "\x8A\xA9"=>"\xE5\x8B\xA7", + "\x8A\xAA"=>"\xE5\xB7\xBB", + "\x8A\xAB"=>"\xE5\x96\x9A", + "\x8A\xAC"=>"\xE5\xA0\xAA", + "\x8A\xAD"=>"\xE5\xA7\xA6", + "\x8A\xAE"=>"\xE5\xAE\x8C", + "\x8A\xAF"=>"\xE5\xAE\x98", + "\x8A\xB0"=>"\xE5\xAF\x9B", + "\x8A\xB1"=>"\xE5\xB9\xB2", + "\x8A\xB2"=>"\xE5\xB9\xB9", + "\x8A\xB3"=>"\xE6\x82\xA3", + "\x8A\xB4"=>"\xE6\x84\x9F", + "\x8A\xB5"=>"\xE6\x85\xA3", + "\x8A\xB6"=>"\xE6\x86\xBE", + "\x8A\xB7"=>"\xE6\x8F\x9B", + "\x8A\xB8"=>"\xE6\x95\xA2", + "\x8A\xB9"=>"\xE6\x9F\x91", + "\x8A\xBA"=>"\xE6\xA1\x93", + "\x8A\xBB"=>"\xE6\xA3\xBA", + "\x8A\xBC"=>"\xE6\xAC\xBE", + "\x8A\xBD"=>"\xE6\xAD\x93", + "\x8A\xBE"=>"\xE6\xB1\x97", + "\x8A\xBF"=>"\xE6\xBC\xA2", + "\x8A\xC0"=>"\xE6\xBE\x97", + "\x8A\xC1"=>"\xE6\xBD\x85", + "\x8A\xC2"=>"\xE7\x92\xB0", + "\x8A\xC3"=>"\xE7\x94\x98", + "\x8A\xC4"=>"\xE7\x9B\xA3", + "\x8A\xC5"=>"\xE7\x9C\x8B", + "\x8A\xC6"=>"\xE7\xAB\xBF", + "\x8A\xC7"=>"\xE7\xAE\xA1", + "\x8A\xC8"=>"\xE7\xB0\xA1", + "\x8A\xC9"=>"\xE7\xB7\xA9", + "\x8A\xCA"=>"\xE7\xBC\xB6", + "\x8A\xCB"=>"\xE7\xBF\xB0", + "\x8A\xCC"=>"\xE8\x82\x9D", + "\x8A\xCD"=>"\xE8\x89\xA6", + "\x8A\xCE"=>"\xE8\x8E\x9E", + "\x8A\xCF"=>"\xE8\xA6\xB3", + "\x8A\xD0"=>"\xE8\xAB\x8C", + "\x8A\xD1"=>"\xE8\xB2\xAB", + "\x8A\xD2"=>"\xE9\x82\x84", + "\x8A\xD3"=>"\xE9\x91\x91", + "\x8A\xD4"=>"\xE9\x96\x93", + "\x8A\xD5"=>"\xE9\x96\x91", + "\x8A\xD6"=>"\xE9\x96\xA2", + "\x8A\xD7"=>"\xE9\x99\xA5", + "\x8A\xD8"=>"\xE9\x9F\x93", + "\x8A\xD9"=>"\xE9\xA4\xA8", + "\x8A\xDA"=>"\xE8\x88\x98", + "\x8A\xDB"=>"\xE4\xB8\xB8", + "\x8A\xDC"=>"\xE5\x90\xAB", + "\x8A\xDD"=>"\xE5\xB2\xB8", + "\x8A\xDE"=>"\xE5\xB7\x8C", + "\x8A\xDF"=>"\xE7\x8E\xA9", + "\x8A\xE0"=>"\xE7\x99\x8C", + "\x8A\xE1"=>"\xE7\x9C\xBC", + "\x8A\xE2"=>"\xE5\xB2\xA9", + "\x8A\xE3"=>"\xE7\xBF\xAB", + "\x8A\xE4"=>"\xE8\xB4\x8B", + "\x8A\xE5"=>"\xE9\x9B\x81", + "\x8A\xE6"=>"\xE9\xA0\x91", + "\x8A\xE7"=>"\xE9\xA1\x94", + "\x8A\xE8"=>"\xE9\xA1\x98", + "\x8A\xE9"=>"\xE4\xBC\x81", + "\x8A\xEA"=>"\xE4\xBC\x8E", + "\x8A\xEB"=>"\xE5\x8D\xB1", + "\x8A\xEC"=>"\xE5\x96\x9C", + "\x8A\xED"=>"\xE5\x99\xA8", + "\x8A\xEE"=>"\xE5\x9F\xBA", + "\x8A\xEF"=>"\xE5\xA5\x87", + "\x8A\xF0"=>"\xE5\xAC\x89", + "\x8A\xF1"=>"\xE5\xAF\x84", + "\x8A\xF2"=>"\xE5\xB2\x90", + "\x8A\xF3"=>"\xE5\xB8\x8C", + "\x8A\xF4"=>"\xE5\xB9\xBE", + "\x8A\xF5"=>"\xE5\xBF\x8C", + "\x8A\xF6"=>"\xE6\x8F\xAE", + "\x8A\xF7"=>"\xE6\x9C\xBA", + "\x8A\xF8"=>"\xE6\x97\x97", + "\x8A\xF9"=>"\xE6\x97\xA2", + "\x8A\xFA"=>"\xE6\x9C\x9F", + "\x8A\xFB"=>"\xE6\xA3\x8B", + "\x8A\xFC"=>"\xE6\xA3\x84", + "\x8B\x40"=>"\xE6\xA9\x9F", + "\x8B\x41"=>"\xE5\xB8\xB0", + "\x8B\x42"=>"\xE6\xAF\x85", + "\x8B\x43"=>"\xE6\xB0\x97", + "\x8B\x44"=>"\xE6\xB1\xBD", + "\x8B\x45"=>"\xE7\x95\xBF", + "\x8B\x46"=>"\xE7\xA5\x88", + "\x8B\x47"=>"\xE5\xAD\xA3", + "\x8B\x48"=>"\xE7\xA8\x80", + "\x8B\x49"=>"\xE7\xB4\x80", + "\x8B\x4A"=>"\xE5\xBE\xBD", + "\x8B\x4B"=>"\xE8\xA6\x8F", + "\x8B\x4C"=>"\xE8\xA8\x98", + "\x8B\x4D"=>"\xE8\xB2\xB4", + "\x8B\x4E"=>"\xE8\xB5\xB7", + "\x8B\x4F"=>"\xE8\xBB\x8C", + "\x8B\x50"=>"\xE8\xBC\x9D", + "\x8B\x51"=>"\xE9\xA3\xA2", + "\x8B\x52"=>"\xE9\xA8\x8E", + "\x8B\x53"=>"\xE9\xAC\xBC", + "\x8B\x54"=>"\xE4\xBA\x80", + "\x8B\x55"=>"\xE5\x81\xBD", + "\x8B\x56"=>"\xE5\x84\x80", + "\x8B\x57"=>"\xE5\xA6\x93", + "\x8B\x58"=>"\xE5\xAE\x9C", + "\x8B\x59"=>"\xE6\x88\xAF", + "\x8B\x5A"=>"\xE6\x8A\x80", + "\x8B\x5B"=>"\xE6\x93\xAC", + "\x8B\x5C"=>"\xE6\xAC\xBA", + "\x8B\x5D"=>"\xE7\x8A\xA0", + "\x8B\x5E"=>"\xE7\x96\x91", + "\x8B\x5F"=>"\xE7\xA5\x87", + "\x8B\x60"=>"\xE7\xBE\xA9", + "\x8B\x61"=>"\xE8\x9F\xBB", + "\x8B\x62"=>"\xE8\xAA\xBC", + "\x8B\x63"=>"\xE8\xAD\xB0", + "\x8B\x64"=>"\xE6\x8E\xAC", + "\x8B\x65"=>"\xE8\x8F\x8A", + "\x8B\x66"=>"\xE9\x9E\xA0", + "\x8B\x67"=>"\xE5\x90\x89", + "\x8B\x68"=>"\xE5\x90\x83", + "\x8B\x69"=>"\xE5\x96\xAB", + "\x8B\x6A"=>"\xE6\xA1\x94", + "\x8B\x6B"=>"\xE6\xA9\x98", + "\x8B\x6C"=>"\xE8\xA9\xB0", + "\x8B\x6D"=>"\xE7\xA0\xA7", + "\x8B\x6E"=>"\xE6\x9D\xB5", + "\x8B\x6F"=>"\xE9\xBB\x8D", + "\x8B\x70"=>"\xE5\x8D\xB4", + "\x8B\x71"=>"\xE5\xAE\xA2", + "\x8B\x72"=>"\xE8\x84\x9A", + "\x8B\x73"=>"\xE8\x99\x90", + "\x8B\x74"=>"\xE9\x80\x86", + "\x8B\x75"=>"\xE4\xB8\x98", + "\x8B\x76"=>"\xE4\xB9\x85", + "\x8B\x77"=>"\xE4\xBB\x87", + "\x8B\x78"=>"\xE4\xBC\x91", + "\x8B\x79"=>"\xE5\x8F\x8A", + "\x8B\x7A"=>"\xE5\x90\xB8", + "\x8B\x7B"=>"\xE5\xAE\xAE", + "\x8B\x7C"=>"\xE5\xBC\x93", + "\x8B\x7D"=>"\xE6\x80\xA5", + "\x8B\x7E"=>"\xE6\x95\x91", + "\x8B\x80"=>"\xE6\x9C\xBD", + "\x8B\x81"=>"\xE6\xB1\x82", + "\x8B\x82"=>"\xE6\xB1\xB2", + "\x8B\x83"=>"\xE6\xB3\xA3", + "\x8B\x84"=>"\xE7\x81\xB8", + "\x8B\x85"=>"\xE7\x90\x83", + "\x8B\x86"=>"\xE7\xA9\xB6", + "\x8B\x87"=>"\xE7\xAA\xAE", + "\x8B\x88"=>"\xE7\xAC\x88", + "\x8B\x89"=>"\xE7\xB4\x9A", + "\x8B\x8A"=>"\xE7\xB3\xBE", + "\x8B\x8B"=>"\xE7\xB5\xA6", + "\x8B\x8C"=>"\xE6\x97\xA7", + "\x8B\x8D"=>"\xE7\x89\x9B", + "\x8B\x8E"=>"\xE5\x8E\xBB", + "\x8B\x8F"=>"\xE5\xB1\x85", + "\x8B\x90"=>"\xE5\xB7\xA8", + "\x8B\x91"=>"\xE6\x8B\x92", + "\x8B\x92"=>"\xE6\x8B\xA0", + "\x8B\x93"=>"\xE6\x8C\x99", + "\x8B\x94"=>"\xE6\xB8\xA0", + "\x8B\x95"=>"\xE8\x99\x9A", + "\x8B\x96"=>"\xE8\xA8\xB1", + "\x8B\x97"=>"\xE8\xB7\x9D", + "\x8B\x98"=>"\xE9\x8B\xB8", + "\x8B\x99"=>"\xE6\xBC\x81", + "\x8B\x9A"=>"\xE7\xA6\xA6", + "\x8B\x9B"=>"\xE9\xAD\x9A", + "\x8B\x9C"=>"\xE4\xBA\xA8", + "\x8B\x9D"=>"\xE4\xBA\xAB", + "\x8B\x9E"=>"\xE4\xBA\xAC", + "\x8B\x9F"=>"\xE4\xBE\x9B", + "\x8B\xA0"=>"\xE4\xBE\xA0", + "\x8B\xA1"=>"\xE5\x83\x91", + "\x8B\xA2"=>"\xE5\x85\x87", + "\x8B\xA3"=>"\xE7\xAB\xB6", + "\x8B\xA4"=>"\xE5\x85\xB1", + "\x8B\xA5"=>"\xE5\x87\xB6", + "\x8B\xA6"=>"\xE5\x8D\x94", + "\x8B\xA7"=>"\xE5\x8C\xA1", + "\x8B\xA8"=>"\xE5\x8D\xBF", + "\x8B\xA9"=>"\xE5\x8F\xAB", + "\x8B\xAA"=>"\xE5\x96\xAC", + "\x8B\xAB"=>"\xE5\xA2\x83", + "\x8B\xAC"=>"\xE5\xB3\xA1", + "\x8B\xAD"=>"\xE5\xBC\xB7", + "\x8B\xAE"=>"\xE5\xBD\x8A", + "\x8B\xAF"=>"\xE6\x80\xAF", + "\x8B\xB0"=>"\xE6\x81\x90", + "\x8B\xB1"=>"\xE6\x81\xAD", + "\x8B\xB2"=>"\xE6\x8C\x9F", + "\x8B\xB3"=>"\xE6\x95\x99", + "\x8B\xB4"=>"\xE6\xA9\x8B", + "\x8B\xB5"=>"\xE6\xB3\x81", + "\x8B\xB6"=>"\xE7\x8B\x82", + "\x8B\xB7"=>"\xE7\x8B\xAD", + "\x8B\xB8"=>"\xE7\x9F\xAF", + "\x8B\xB9"=>"\xE8\x83\xB8", + "\x8B\xBA"=>"\xE8\x84\x85", + "\x8B\xBB"=>"\xE8\x88\x88", + "\x8B\xBC"=>"\xE8\x95\x8E", + "\x8B\xBD"=>"\xE9\x83\xB7", + "\x8B\xBE"=>"\xE9\x8F\xA1", + "\x8B\xBF"=>"\xE9\x9F\xBF", + "\x8B\xC0"=>"\xE9\xA5\x97", + "\x8B\xC1"=>"\xE9\xA9\x9A", + "\x8B\xC2"=>"\xE4\xBB\xB0", + "\x8B\xC3"=>"\xE5\x87\x9D", + "\x8B\xC4"=>"\xE5\xB0\xAD", + "\x8B\xC5"=>"\xE6\x9A\x81", + "\x8B\xC6"=>"\xE6\xA5\xAD", + "\x8B\xC7"=>"\xE5\xB1\x80", + "\x8B\xC8"=>"\xE6\x9B\xB2", + "\x8B\xC9"=>"\xE6\xA5\xB5", + "\x8B\xCA"=>"\xE7\x8E\x89", + "\x8B\xCB"=>"\xE6\xA1\x90", + "\x8B\xCC"=>"\xE7\xB2\x81", + "\x8B\xCD"=>"\xE5\x83\x85", + "\x8B\xCE"=>"\xE5\x8B\xA4", + "\x8B\xCF"=>"\xE5\x9D\x87", + "\x8B\xD0"=>"\xE5\xB7\xBE", + "\x8B\xD1"=>"\xE9\x8C\xA6", + "\x8B\xD2"=>"\xE6\x96\xA4", + "\x8B\xD3"=>"\xE6\xAC\xA3", + "\x8B\xD4"=>"\xE6\xAC\xBD", + "\x8B\xD5"=>"\xE7\x90\xB4", + "\x8B\xD6"=>"\xE7\xA6\x81", + "\x8B\xD7"=>"\xE7\xA6\xBD", + "\x8B\xD8"=>"\xE7\xAD\x8B", + "\x8B\xD9"=>"\xE7\xB7\x8A", + "\x8B\xDA"=>"\xE8\x8A\xB9", + "\x8B\xDB"=>"\xE8\x8F\x8C", + "\x8B\xDC"=>"\xE8\xA1\xBF", + "\x8B\xDD"=>"\xE8\xA5\x9F", + "\x8B\xDE"=>"\xE8\xAC\xB9", + "\x8B\xDF"=>"\xE8\xBF\x91", + "\x8B\xE0"=>"\xE9\x87\x91", + "\x8B\xE1"=>"\xE5\x90\x9F", + "\x8B\xE2"=>"\xE9\x8A\x80", + "\x8B\xE3"=>"\xE4\xB9\x9D", + "\x8B\xE4"=>"\xE5\x80\xB6", + "\x8B\xE5"=>"\xE5\x8F\xA5", + "\x8B\xE6"=>"\xE5\x8C\xBA", + "\x8B\xE7"=>"\xE7\x8B\x97", + "\x8B\xE8"=>"\xE7\x8E\x96", + "\x8B\xE9"=>"\xE7\x9F\xA9", + "\x8B\xEA"=>"\xE8\x8B\xA6", + "\x8B\xEB"=>"\xE8\xBA\xAF", + "\x8B\xEC"=>"\xE9\xA7\x86", + "\x8B\xED"=>"\xE9\xA7\x88", + "\x8B\xEE"=>"\xE9\xA7\x92", + "\x8B\xEF"=>"\xE5\x85\xB7", + "\x8B\xF0"=>"\xE6\x84\x9A", + "\x8B\xF1"=>"\xE8\x99\x9E", + "\x8B\xF2"=>"\xE5\x96\xB0", + "\x8B\xF3"=>"\xE7\xA9\xBA", + "\x8B\xF4"=>"\xE5\x81\xB6", + "\x8B\xF5"=>"\xE5\xAF\x93", + "\x8B\xF6"=>"\xE9\x81\x87", + "\x8B\xF7"=>"\xE9\x9A\x85", + "\x8B\xF8"=>"\xE4\xB8\xB2", + "\x8B\xF9"=>"\xE6\xAB\x9B", + "\x8B\xFA"=>"\xE9\x87\xA7", + "\x8B\xFB"=>"\xE5\xB1\x91", + "\x8B\xFC"=>"\xE5\xB1\x88", + "\x8C\x40"=>"\xE6\x8E\x98", + "\x8C\x41"=>"\xE7\xAA\x9F", + "\x8C\x42"=>"\xE6\xB2\x93", + "\x8C\x43"=>"\xE9\x9D\xB4", + "\x8C\x44"=>"\xE8\xBD\xA1", + "\x8C\x45"=>"\xE7\xAA\xAA", + "\x8C\x46"=>"\xE7\x86\x8A", + "\x8C\x47"=>"\xE9\x9A\x88", + "\x8C\x48"=>"\xE7\xB2\x82", + "\x8C\x49"=>"\xE6\xA0\x97", + "\x8C\x4A"=>"\xE7\xB9\xB0", + "\x8C\x4B"=>"\xE6\xA1\x91", + "\x8C\x4C"=>"\xE9\x8D\xAC", + "\x8C\x4D"=>"\xE5\x8B\xB2", + "\x8C\x4E"=>"\xE5\x90\x9B", + "\x8C\x4F"=>"\xE8\x96\xAB", + "\x8C\x50"=>"\xE8\xA8\x93", + "\x8C\x51"=>"\xE7\xBE\xA4", + "\x8C\x52"=>"\xE8\xBB\x8D", + "\x8C\x53"=>"\xE9\x83\xA1", + "\x8C\x54"=>"\xE5\x8D\xA6", + "\x8C\x55"=>"\xE8\xA2\x88", + "\x8C\x56"=>"\xE7\xA5\x81", + "\x8C\x57"=>"\xE4\xBF\x82", + "\x8C\x58"=>"\xE5\x82\xBE", + "\x8C\x59"=>"\xE5\x88\x91", + "\x8C\x5A"=>"\xE5\x85\x84", + "\x8C\x5B"=>"\xE5\x95\x93", + "\x8C\x5C"=>"\xE5\x9C\xAD", + "\x8C\x5D"=>"\xE7\x8F\xAA", + "\x8C\x5E"=>"\xE5\x9E\x8B", + "\x8C\x5F"=>"\xE5\xA5\x91", + "\x8C\x60"=>"\xE5\xBD\xA2", + "\x8C\x61"=>"\xE5\xBE\x84", + "\x8C\x62"=>"\xE6\x81\xB5", + "\x8C\x63"=>"\xE6\x85\xB6", + "\x8C\x64"=>"\xE6\x85\xA7", + "\x8C\x65"=>"\xE6\x86\xA9", + "\x8C\x66"=>"\xE6\x8E\xB2", + "\x8C\x67"=>"\xE6\x90\xBA", + "\x8C\x68"=>"\xE6\x95\xAC", + "\x8C\x69"=>"\xE6\x99\xAF", + "\x8C\x6A"=>"\xE6\xA1\x82", + "\x8C\x6B"=>"\xE6\xB8\x93", + "\x8C\x6C"=>"\xE7\x95\xA6", + "\x8C\x6D"=>"\xE7\xA8\xBD", + "\x8C\x6E"=>"\xE7\xB3\xBB", + "\x8C\x6F"=>"\xE7\xB5\x8C", + "\x8C\x70"=>"\xE7\xB6\x99", + "\x8C\x71"=>"\xE7\xB9\x8B", + "\x8C\x72"=>"\xE7\xBD\xAB", + "\x8C\x73"=>"\xE8\x8C\x8E", + "\x8C\x74"=>"\xE8\x8D\x8A", + "\x8C\x75"=>"\xE8\x9B\x8D", + "\x8C\x76"=>"\xE8\xA8\x88", + "\x8C\x77"=>"\xE8\xA9\xA3", + "\x8C\x78"=>"\xE8\xAD\xA6", + "\x8C\x79"=>"\xE8\xBB\xBD", + "\x8C\x7A"=>"\xE9\xA0\x9A", + "\x8C\x7B"=>"\xE9\xB6\x8F", + "\x8C\x7C"=>"\xE8\x8A\xB8", + "\x8C\x7D"=>"\xE8\xBF\x8E", + "\x8C\x7E"=>"\xE9\xAF\xA8", + "\x8C\x80"=>"\xE5\x8A\x87", + "\x8C\x81"=>"\xE6\x88\x9F", + "\x8C\x82"=>"\xE6\x92\x83", + "\x8C\x83"=>"\xE6\xBF\x80", + "\x8C\x84"=>"\xE9\x9A\x99", + "\x8C\x85"=>"\xE6\xA1\x81", + "\x8C\x86"=>"\xE5\x82\x91", + "\x8C\x87"=>"\xE6\xAC\xA0", + "\x8C\x88"=>"\xE6\xB1\xBA", + "\x8C\x89"=>"\xE6\xBD\x94", + "\x8C\x8A"=>"\xE7\xA9\xB4", + "\x8C\x8B"=>"\xE7\xB5\x90", + "\x8C\x8C"=>"\xE8\xA1\x80", + "\x8C\x8D"=>"\xE8\xA8\xA3", + "\x8C\x8E"=>"\xE6\x9C\x88", + "\x8C\x8F"=>"\xE4\xBB\xB6", + "\x8C\x90"=>"\xE5\x80\xB9", + "\x8C\x91"=>"\xE5\x80\xA6", + "\x8C\x92"=>"\xE5\x81\xA5", + "\x8C\x93"=>"\xE5\x85\xBC", + "\x8C\x94"=>"\xE5\x88\xB8", + "\x8C\x95"=>"\xE5\x89\xA3", + "\x8C\x96"=>"\xE5\x96\xA7", + "\x8C\x97"=>"\xE5\x9C\x8F", + "\x8C\x98"=>"\xE5\xA0\x85", + "\x8C\x99"=>"\xE5\xAB\x8C", + "\x8C\x9A"=>"\xE5\xBB\xBA", + "\x8C\x9B"=>"\xE6\x86\xB2", + "\x8C\x9C"=>"\xE6\x87\xB8", + "\x8C\x9D"=>"\xE6\x8B\xB3", + "\x8C\x9E"=>"\xE6\x8D\xB2", + "\x8C\x9F"=>"\xE6\xA4\x9C", + "\x8C\xA0"=>"\xE6\xA8\xA9", + "\x8C\xA1"=>"\xE7\x89\xBD", + "\x8C\xA2"=>"\xE7\x8A\xAC", + "\x8C\xA3"=>"\xE7\x8C\xAE", + "\x8C\xA4"=>"\xE7\xA0\x94", + "\x8C\xA5"=>"\xE7\xA1\xAF", + "\x8C\xA6"=>"\xE7\xB5\xB9", + "\x8C\xA7"=>"\xE7\x9C\x8C", + "\x8C\xA8"=>"\xE8\x82\xA9", + "\x8C\xA9"=>"\xE8\xA6\x8B", + "\x8C\xAA"=>"\xE8\xAC\x99", + "\x8C\xAB"=>"\xE8\xB3\xA2", + "\x8C\xAC"=>"\xE8\xBB\x92", + "\x8C\xAD"=>"\xE9\x81\xA3", + "\x8C\xAE"=>"\xE9\x8D\xB5", + "\x8C\xAF"=>"\xE9\x99\xBA", + "\x8C\xB0"=>"\xE9\xA1\x95", + "\x8C\xB1"=>"\xE9\xA8\x93", + "\x8C\xB2"=>"\xE9\xB9\xB8", + "\x8C\xB3"=>"\xE5\x85\x83", + "\x8C\xB4"=>"\xE5\x8E\x9F", + "\x8C\xB5"=>"\xE5\x8E\xB3", + "\x8C\xB6"=>"\xE5\xB9\xBB", + "\x8C\xB7"=>"\xE5\xBC\xA6", + "\x8C\xB8"=>"\xE6\xB8\x9B", + "\x8C\xB9"=>"\xE6\xBA\x90", + "\x8C\xBA"=>"\xE7\x8E\x84", + "\x8C\xBB"=>"\xE7\x8F\xBE", + "\x8C\xBC"=>"\xE7\xB5\x83", + "\x8C\xBD"=>"\xE8\x88\xB7", + "\x8C\xBE"=>"\xE8\xA8\x80", + "\x8C\xBF"=>"\xE8\xAB\xBA", + "\x8C\xC0"=>"\xE9\x99\x90", + "\x8C\xC1"=>"\xE4\xB9\x8E", + "\x8C\xC2"=>"\xE5\x80\x8B", + "\x8C\xC3"=>"\xE5\x8F\xA4", + "\x8C\xC4"=>"\xE5\x91\xBC", + "\x8C\xC5"=>"\xE5\x9B\xBA", + "\x8C\xC6"=>"\xE5\xA7\x91", + "\x8C\xC7"=>"\xE5\xAD\xA4", + "\x8C\xC8"=>"\xE5\xB7\xB1", + "\x8C\xC9"=>"\xE5\xBA\xAB", + "\x8C\xCA"=>"\xE5\xBC\xA7", + "\x8C\xCB"=>"\xE6\x88\xB8", + "\x8C\xCC"=>"\xE6\x95\x85", + "\x8C\xCD"=>"\xE6\x9E\xAF", + "\x8C\xCE"=>"\xE6\xB9\x96", + "\x8C\xCF"=>"\xE7\x8B\x90", + "\x8C\xD0"=>"\xE7\xB3\x8A", + "\x8C\xD1"=>"\xE8\xA2\xB4", + "\x8C\xD2"=>"\xE8\x82\xA1", + "\x8C\xD3"=>"\xE8\x83\xA1", + "\x8C\xD4"=>"\xE8\x8F\xB0", + "\x8C\xD5"=>"\xE8\x99\x8E", + "\x8C\xD6"=>"\xE8\xAA\x87", + "\x8C\xD7"=>"\xE8\xB7\xA8", + "\x8C\xD8"=>"\xE9\x88\xB7", + "\x8C\xD9"=>"\xE9\x9B\x87", + "\x8C\xDA"=>"\xE9\xA1\xA7", + "\x8C\xDB"=>"\xE9\xBC\x93", + "\x8C\xDC"=>"\xE4\xBA\x94", + "\x8C\xDD"=>"\xE4\xBA\x92", + "\x8C\xDE"=>"\xE4\xBC\x8D", + "\x8C\xDF"=>"\xE5\x8D\x88", + "\x8C\xE0"=>"\xE5\x91\x89", + "\x8C\xE1"=>"\xE5\x90\xBE", + "\x8C\xE2"=>"\xE5\xA8\xAF", + "\x8C\xE3"=>"\xE5\xBE\x8C", + "\x8C\xE4"=>"\xE5\xBE\xA1", + "\x8C\xE5"=>"\xE6\x82\x9F", + "\x8C\xE6"=>"\xE6\xA2\xA7", + "\x8C\xE7"=>"\xE6\xAA\x8E", + "\x8C\xE8"=>"\xE7\x91\x9A", + "\x8C\xE9"=>"\xE7\xA2\x81", + "\x8C\xEA"=>"\xE8\xAA\x9E", + "\x8C\xEB"=>"\xE8\xAA\xA4", + "\x8C\xEC"=>"\xE8\xAD\xB7", + "\x8C\xED"=>"\xE9\x86\x90", + "\x8C\xEE"=>"\xE4\xB9\x9E", + "\x8C\xEF"=>"\xE9\xAF\x89", + "\x8C\xF0"=>"\xE4\xBA\xA4", + "\x8C\xF1"=>"\xE4\xBD\xBC", + "\x8C\xF2"=>"\xE4\xBE\xAF", + "\x8C\xF3"=>"\xE5\x80\x99", + "\x8C\xF4"=>"\xE5\x80\x96", + "\x8C\xF5"=>"\xE5\x85\x89", + "\x8C\xF6"=>"\xE5\x85\xAC", + "\x8C\xF7"=>"\xE5\x8A\x9F", + "\x8C\xF8"=>"\xE5\x8A\xB9", + "\x8C\xF9"=>"\xE5\x8B\xBE", + "\x8C\xFA"=>"\xE5\x8E\x9A", + "\x8C\xFB"=>"\xE5\x8F\xA3", + "\x8C\xFC"=>"\xE5\x90\x91", + "\x8D\x40"=>"\xE5\x90\x8E", + "\x8D\x41"=>"\xE5\x96\x89", + "\x8D\x42"=>"\xE5\x9D\x91", + "\x8D\x43"=>"\xE5\x9E\xA2", + "\x8D\x44"=>"\xE5\xA5\xBD", + "\x8D\x45"=>"\xE5\xAD\x94", + "\x8D\x46"=>"\xE5\xAD\x9D", + "\x8D\x47"=>"\xE5\xAE\x8F", + "\x8D\x48"=>"\xE5\xB7\xA5", + "\x8D\x49"=>"\xE5\xB7\xA7", + "\x8D\x4A"=>"\xE5\xB7\xB7", + "\x8D\x4B"=>"\xE5\xB9\xB8", + "\x8D\x4C"=>"\xE5\xBA\x83", + "\x8D\x4D"=>"\xE5\xBA\x9A", + "\x8D\x4E"=>"\xE5\xBA\xB7", + "\x8D\x4F"=>"\xE5\xBC\x98", + "\x8D\x50"=>"\xE6\x81\x92", + "\x8D\x51"=>"\xE6\x85\x8C", + "\x8D\x52"=>"\xE6\x8A\x97", + "\x8D\x53"=>"\xE6\x8B\x98", + "\x8D\x54"=>"\xE6\x8E\xA7", + "\x8D\x55"=>"\xE6\x94\xBB", + "\x8D\x56"=>"\xE6\x98\x82", + "\x8D\x57"=>"\xE6\x99\x83", + "\x8D\x58"=>"\xE6\x9B\xB4", + "\x8D\x59"=>"\xE6\x9D\xAD", + "\x8D\x5A"=>"\xE6\xA0\xA1", + "\x8D\x5B"=>"\xE6\xA2\x97", + "\x8D\x5C"=>"\xE6\xA7\x8B", + "\x8D\x5D"=>"\xE6\xB1\x9F", + "\x8D\x5E"=>"\xE6\xB4\xAA", + "\x8D\x5F"=>"\xE6\xB5\xA9", + "\x8D\x60"=>"\xE6\xB8\xAF", + "\x8D\x61"=>"\xE6\xBA\x9D", + "\x8D\x62"=>"\xE7\x94\xB2", + "\x8D\x63"=>"\xE7\x9A\x87", + "\x8D\x64"=>"\xE7\xA1\xAC", + "\x8D\x65"=>"\xE7\xA8\xBF", + "\x8D\x66"=>"\xE7\xB3\xA0", + "\x8D\x67"=>"\xE7\xB4\x85", + "\x8D\x68"=>"\xE7\xB4\x98", + "\x8D\x69"=>"\xE7\xB5\x9E", + "\x8D\x6A"=>"\xE7\xB6\xB1", + "\x8D\x6B"=>"\xE8\x80\x95", + "\x8D\x6C"=>"\xE8\x80\x83", + "\x8D\x6D"=>"\xE8\x82\xAF", + "\x8D\x6E"=>"\xE8\x82\xB1", + "\x8D\x6F"=>"\xE8\x85\x94", + "\x8D\x70"=>"\xE8\x86\x8F", + "\x8D\x71"=>"\xE8\x88\xAA", + "\x8D\x72"=>"\xE8\x8D\x92", + "\x8D\x73"=>"\xE8\xA1\x8C", + "\x8D\x74"=>"\xE8\xA1\xA1", + "\x8D\x75"=>"\xE8\xAC\x9B", + "\x8D\x76"=>"\xE8\xB2\xA2", + "\x8D\x77"=>"\xE8\xB3\xBC", + "\x8D\x78"=>"\xE9\x83\x8A", + "\x8D\x79"=>"\xE9\x85\xB5", + "\x8D\x7A"=>"\xE9\x89\xB1", + "\x8D\x7B"=>"\xE7\xA0\xBF", + "\x8D\x7C"=>"\xE9\x8B\xBC", + "\x8D\x7D"=>"\xE9\x96\xA4", + "\x8D\x7E"=>"\xE9\x99\x8D", + "\x8D\x80"=>"\xE9\xA0\x85", + "\x8D\x81"=>"\xE9\xA6\x99", + "\x8D\x82"=>"\xE9\xAB\x98", + "\x8D\x83"=>"\xE9\xB4\xBB", + "\x8D\x84"=>"\xE5\x89\x9B", + "\x8D\x85"=>"\xE5\x8A\xAB", + "\x8D\x86"=>"\xE5\x8F\xB7", + "\x8D\x87"=>"\xE5\x90\x88", + "\x8D\x88"=>"\xE5\xA3\x95", + "\x8D\x89"=>"\xE6\x8B\xB7", + "\x8D\x8A"=>"\xE6\xBF\xA0", + "\x8D\x8B"=>"\xE8\xB1\xAA", + "\x8D\x8C"=>"\xE8\xBD\x9F", + "\x8D\x8D"=>"\xE9\xBA\xB9", + "\x8D\x8E"=>"\xE5\x85\x8B", + "\x8D\x8F"=>"\xE5\x88\xBB", + "\x8D\x90"=>"\xE5\x91\x8A", + "\x8D\x91"=>"\xE5\x9B\xBD", + "\x8D\x92"=>"\xE7\xA9\x80", + "\x8D\x93"=>"\xE9\x85\xB7", + "\x8D\x94"=>"\xE9\xB5\xA0", + "\x8D\x95"=>"\xE9\xBB\x92", + "\x8D\x96"=>"\xE7\x8D\x84", + "\x8D\x97"=>"\xE6\xBC\x89", + "\x8D\x98"=>"\xE8\x85\xB0", + "\x8D\x99"=>"\xE7\x94\x91", + "\x8D\x9A"=>"\xE5\xBF\xBD", + "\x8D\x9B"=>"\xE6\x83\x9A", + "\x8D\x9C"=>"\xE9\xAA\xA8", + "\x8D\x9D"=>"\xE7\x8B\x9B", + "\x8D\x9E"=>"\xE8\xBE\xBC", + "\x8D\x9F"=>"\xE6\xAD\xA4", + "\x8D\xA0"=>"\xE9\xA0\x83", + "\x8D\xA1"=>"\xE4\xBB\x8A", + "\x8D\xA2"=>"\xE5\x9B\xB0", + "\x8D\xA3"=>"\xE5\x9D\xA4", + "\x8D\xA4"=>"\xE5\xA2\xBE", + "\x8D\xA5"=>"\xE5\xA9\x9A", + "\x8D\xA6"=>"\xE6\x81\xA8", + "\x8D\xA7"=>"\xE6\x87\x87", + "\x8D\xA8"=>"\xE6\x98\x8F", + "\x8D\xA9"=>"\xE6\x98\x86", + "\x8D\xAA"=>"\xE6\xA0\xB9", + "\x8D\xAB"=>"\xE6\xA2\xB1", + "\x8D\xAC"=>"\xE6\xB7\xB7", + "\x8D\xAD"=>"\xE7\x97\x95", + "\x8D\xAE"=>"\xE7\xB4\xBA", + "\x8D\xAF"=>"\xE8\x89\xAE", + "\x8D\xB0"=>"\xE9\xAD\x82", + "\x8D\xB1"=>"\xE4\xBA\x9B", + "\x8D\xB2"=>"\xE4\xBD\x90", + "\x8D\xB3"=>"\xE5\x8F\x89", + "\x8D\xB4"=>"\xE5\x94\x86", + "\x8D\xB5"=>"\xE5\xB5\xAF", + "\x8D\xB6"=>"\xE5\xB7\xA6", + "\x8D\xB7"=>"\xE5\xB7\xAE", + "\x8D\xB8"=>"\xE6\x9F\xBB", + "\x8D\xB9"=>"\xE6\xB2\x99", + "\x8D\xBA"=>"\xE7\x91\xB3", + "\x8D\xBB"=>"\xE7\xA0\x82", + "\x8D\xBC"=>"\xE8\xA9\x90", + "\x8D\xBD"=>"\xE9\x8E\x96", + "\x8D\xBE"=>"\xE8\xA3\x9F", + "\x8D\xBF"=>"\xE5\x9D\x90", + "\x8D\xC0"=>"\xE5\xBA\xA7", + "\x8D\xC1"=>"\xE6\x8C\xAB", + "\x8D\xC2"=>"\xE5\x82\xB5", + "\x8D\xC3"=>"\xE5\x82\xAC", + "\x8D\xC4"=>"\xE5\x86\x8D", + "\x8D\xC5"=>"\xE6\x9C\x80", + "\x8D\xC6"=>"\xE5\x93\x89", + "\x8D\xC7"=>"\xE5\xA1\x9E", + "\x8D\xC8"=>"\xE5\xA6\xBB", + "\x8D\xC9"=>"\xE5\xAE\xB0", + "\x8D\xCA"=>"\xE5\xBD\xA9", + "\x8D\xCB"=>"\xE6\x89\x8D", + "\x8D\xCC"=>"\xE6\x8E\xA1", + "\x8D\xCD"=>"\xE6\xA0\xBD", + "\x8D\xCE"=>"\xE6\xAD\xB3", + "\x8D\xCF"=>"\xE6\xB8\x88", + "\x8D\xD0"=>"\xE7\x81\xBD", + "\x8D\xD1"=>"\xE9\x87\x87", + "\x8D\xD2"=>"\xE7\x8A\x80", + "\x8D\xD3"=>"\xE7\xA0\x95", + "\x8D\xD4"=>"\xE7\xA0\xA6", + "\x8D\xD5"=>"\xE7\xA5\xAD", + "\x8D\xD6"=>"\xE6\x96\x8E", + "\x8D\xD7"=>"\xE7\xB4\xB0", + "\x8D\xD8"=>"\xE8\x8F\x9C", + "\x8D\xD9"=>"\xE8\xA3\x81", + "\x8D\xDA"=>"\xE8\xBC\x89", + "\x8D\xDB"=>"\xE9\x9A\x9B", + "\x8D\xDC"=>"\xE5\x89\xA4", + "\x8D\xDD"=>"\xE5\x9C\xA8", + "\x8D\xDE"=>"\xE6\x9D\x90", + "\x8D\xDF"=>"\xE7\xBD\xAA", + "\x8D\xE0"=>"\xE8\xB2\xA1", + "\x8D\xE1"=>"\xE5\x86\xB4", + "\x8D\xE2"=>"\xE5\x9D\x82", + "\x8D\xE3"=>"\xE9\x98\xAA", + "\x8D\xE4"=>"\xE5\xA0\xBA", + "\x8D\xE5"=>"\xE6\xA6\x8A", + "\x8D\xE6"=>"\xE8\x82\xB4", + "\x8D\xE7"=>"\xE5\x92\xB2", + "\x8D\xE8"=>"\xE5\xB4\x8E", + "\x8D\xE9"=>"\xE5\x9F\xBC", + "\x8D\xEA"=>"\xE7\xA2\x95", + "\x8D\xEB"=>"\xE9\xB7\xBA", + "\x8D\xEC"=>"\xE4\xBD\x9C", + "\x8D\xED"=>"\xE5\x89\x8A", + "\x8D\xEE"=>"\xE5\x92\x8B", + "\x8D\xEF"=>"\xE6\x90\xBE", + "\x8D\xF0"=>"\xE6\x98\xA8", + "\x8D\xF1"=>"\xE6\x9C\x94", + "\x8D\xF2"=>"\xE6\x9F\xB5", + "\x8D\xF3"=>"\xE7\xAA\x84", + "\x8D\xF4"=>"\xE7\xAD\x96", + "\x8D\xF5"=>"\xE7\xB4\xA2", + "\x8D\xF6"=>"\xE9\x8C\xAF", + "\x8D\xF7"=>"\xE6\xA1\x9C", + "\x8D\xF8"=>"\xE9\xAE\xAD", + "\x8D\xF9"=>"\xE7\xAC\xB9", + "\x8D\xFA"=>"\xE5\x8C\x99", + "\x8D\xFB"=>"\xE5\x86\x8A", + "\x8D\xFC"=>"\xE5\x88\xB7", + "\x8E\x40"=>"\xE5\xAF\x9F", + "\x8E\x41"=>"\xE6\x8B\xB6", + "\x8E\x42"=>"\xE6\x92\xAE", + "\x8E\x43"=>"\xE6\x93\xA6", + "\x8E\x44"=>"\xE6\x9C\xAD", + "\x8E\x45"=>"\xE6\xAE\xBA", + "\x8E\x46"=>"\xE8\x96\xA9", + "\x8E\x47"=>"\xE9\x9B\x91", + "\x8E\x48"=>"\xE7\x9A\x90", + "\x8E\x49"=>"\xE9\xAF\x96", + "\x8E\x4A"=>"\xE6\x8D\x8C", + "\x8E\x4B"=>"\xE9\x8C\x86", + "\x8E\x4C"=>"\xE9\xAE\xAB", + "\x8E\x4D"=>"\xE7\x9A\xBF", + "\x8E\x4E"=>"\xE6\x99\x92", + "\x8E\x4F"=>"\xE4\xB8\x89", + "\x8E\x50"=>"\xE5\x82\x98", + "\x8E\x51"=>"\xE5\x8F\x82", + "\x8E\x52"=>"\xE5\xB1\xB1", + "\x8E\x53"=>"\xE6\x83\xA8", + "\x8E\x54"=>"\xE6\x92\x92", + "\x8E\x55"=>"\xE6\x95\xA3", + "\x8E\x56"=>"\xE6\xA1\x9F", + "\x8E\x57"=>"\xE7\x87\xA6", + "\x8E\x58"=>"\xE7\x8F\x8A", + "\x8E\x59"=>"\xE7\x94\xA3", + "\x8E\x5A"=>"\xE7\xAE\x97", + "\x8E\x5B"=>"\xE7\xBA\x82", + "\x8E\x5C"=>"\xE8\x9A\x95", + "\x8E\x5D"=>"\xE8\xAE\x83", + "\x8E\x5E"=>"\xE8\xB3\x9B", + "\x8E\x5F"=>"\xE9\x85\xB8", + "\x8E\x60"=>"\xE9\xA4\x90", + "\x8E\x61"=>"\xE6\x96\xAC", + "\x8E\x62"=>"\xE6\x9A\xAB", + "\x8E\x63"=>"\xE6\xAE\x8B", + "\x8E\x64"=>"\xE4\xBB\x95", + "\x8E\x65"=>"\xE4\xBB\x94", + "\x8E\x66"=>"\xE4\xBC\xBA", + "\x8E\x67"=>"\xE4\xBD\xBF", + "\x8E\x68"=>"\xE5\x88\xBA", + "\x8E\x69"=>"\xE5\x8F\xB8", + "\x8E\x6A"=>"\xE5\x8F\xB2", + "\x8E\x6B"=>"\xE5\x97\xA3", + "\x8E\x6C"=>"\xE5\x9B\x9B", + "\x8E\x6D"=>"\xE5\xA3\xAB", + "\x8E\x6E"=>"\xE5\xA7\x8B", + "\x8E\x6F"=>"\xE5\xA7\x89", + "\x8E\x70"=>"\xE5\xA7\xBF", + "\x8E\x71"=>"\xE5\xAD\x90", + "\x8E\x72"=>"\xE5\xB1\x8D", + "\x8E\x73"=>"\xE5\xB8\x82", + "\x8E\x74"=>"\xE5\xB8\xAB", + "\x8E\x75"=>"\xE5\xBF\x97", + "\x8E\x76"=>"\xE6\x80\x9D", + "\x8E\x77"=>"\xE6\x8C\x87", + "\x8E\x78"=>"\xE6\x94\xAF", + "\x8E\x79"=>"\xE5\xAD\x9C", + "\x8E\x7A"=>"\xE6\x96\xAF", + "\x8E\x7B"=>"\xE6\x96\xBD", + "\x8E\x7C"=>"\xE6\x97\xA8", + "\x8E\x7D"=>"\xE6\x9E\x9D", + "\x8E\x7E"=>"\xE6\xAD\xA2", + "\x8E\x80"=>"\xE6\xAD\xBB", + "\x8E\x81"=>"\xE6\xB0\x8F", + "\x8E\x82"=>"\xE7\x8D\x85", + "\x8E\x83"=>"\xE7\xA5\x89", + "\x8E\x84"=>"\xE7\xA7\x81", + "\x8E\x85"=>"\xE7\xB3\xB8", + "\x8E\x86"=>"\xE7\xB4\x99", + "\x8E\x87"=>"\xE7\xB4\xAB", + "\x8E\x88"=>"\xE8\x82\xA2", + "\x8E\x89"=>"\xE8\x84\x82", + "\x8E\x8A"=>"\xE8\x87\xB3", + "\x8E\x8B"=>"\xE8\xA6\x96", + "\x8E\x8C"=>"\xE8\xA9\x9E", + "\x8E\x8D"=>"\xE8\xA9\xA9", + "\x8E\x8E"=>"\xE8\xA9\xA6", + "\x8E\x8F"=>"\xE8\xAA\x8C", + "\x8E\x90"=>"\xE8\xAB\xAE", + "\x8E\x91"=>"\xE8\xB3\x87", + "\x8E\x92"=>"\xE8\xB3\x9C", + "\x8E\x93"=>"\xE9\x9B\x8C", + "\x8E\x94"=>"\xE9\xA3\xBC", + "\x8E\x95"=>"\xE6\xAD\xAF", + "\x8E\x96"=>"\xE4\xBA\x8B", + "\x8E\x97"=>"\xE4\xBC\xBC", + "\x8E\x98"=>"\xE4\xBE\x8D", + "\x8E\x99"=>"\xE5\x85\x90", + "\x8E\x9A"=>"\xE5\xAD\x97", + "\x8E\x9B"=>"\xE5\xAF\xBA", + "\x8E\x9C"=>"\xE6\x85\x88", + "\x8E\x9D"=>"\xE6\x8C\x81", + "\x8E\x9E"=>"\xE6\x99\x82", + "\x8E\x9F"=>"\xE6\xAC\xA1", + "\x8E\xA0"=>"\xE6\xBB\x8B", + "\x8E\xA1"=>"\xE6\xB2\xBB", + "\x8E\xA2"=>"\xE7\x88\xBE", + "\x8E\xA3"=>"\xE7\x92\xBD", + "\x8E\xA4"=>"\xE7\x97\x94", + "\x8E\xA5"=>"\xE7\xA3\x81", + "\x8E\xA6"=>"\xE7\xA4\xBA", + "\x8E\xA7"=>"\xE8\x80\x8C", + "\x8E\xA8"=>"\xE8\x80\xB3", + "\x8E\xA9"=>"\xE8\x87\xAA", + "\x8E\xAA"=>"\xE8\x92\x94", + "\x8E\xAB"=>"\xE8\xBE\x9E", + "\x8E\xAC"=>"\xE6\xB1\x90", + "\x8E\xAD"=>"\xE9\xB9\xBF", + "\x8E\xAE"=>"\xE5\xBC\x8F", + "\x8E\xAF"=>"\xE8\xAD\x98", + "\x8E\xB0"=>"\xE9\xB4\xAB", + "\x8E\xB1"=>"\xE7\xAB\xBA", + "\x8E\xB2"=>"\xE8\xBB\xB8", + "\x8E\xB3"=>"\xE5\xAE\x8D", + "\x8E\xB4"=>"\xE9\x9B\xAB", + "\x8E\xB5"=>"\xE4\xB8\x83", + "\x8E\xB6"=>"\xE5\x8F\xB1", + "\x8E\xB7"=>"\xE5\x9F\xB7", + "\x8E\xB8"=>"\xE5\xA4\xB1", + "\x8E\xB9"=>"\xE5\xAB\x89", + "\x8E\xBA"=>"\xE5\xAE\xA4", + "\x8E\xBB"=>"\xE6\x82\x89", + "\x8E\xBC"=>"\xE6\xB9\xBF", + "\x8E\xBD"=>"\xE6\xBC\x86", + "\x8E\xBE"=>"\xE7\x96\xBE", + "\x8E\xBF"=>"\xE8\xB3\xAA", + "\x8E\xC0"=>"\xE5\xAE\x9F", + "\x8E\xC1"=>"\xE8\x94\x80", + "\x8E\xC2"=>"\xE7\xAF\xA0", + "\x8E\xC3"=>"\xE5\x81\xB2", + "\x8E\xC4"=>"\xE6\x9F\xB4", + "\x8E\xC5"=>"\xE8\x8A\x9D", + "\x8E\xC6"=>"\xE5\xB1\xA1", + "\x8E\xC7"=>"\xE8\x95\x8A", + "\x8E\xC8"=>"\xE7\xB8\x9E", + "\x8E\xC9"=>"\xE8\x88\x8E", + "\x8E\xCA"=>"\xE5\x86\x99", + "\x8E\xCB"=>"\xE5\xB0\x84", + "\x8E\xCC"=>"\xE6\x8D\xA8", + "\x8E\xCD"=>"\xE8\xB5\xA6", + "\x8E\xCE"=>"\xE6\x96\x9C", + "\x8E\xCF"=>"\xE7\x85\xAE", + "\x8E\xD0"=>"\xE7\xA4\xBE", + "\x8E\xD1"=>"\xE7\xB4\x97", + "\x8E\xD2"=>"\xE8\x80\x85", + "\x8E\xD3"=>"\xE8\xAC\x9D", + "\x8E\xD4"=>"\xE8\xBB\x8A", + "\x8E\xD5"=>"\xE9\x81\xAE", + "\x8E\xD6"=>"\xE8\x9B\x87", + "\x8E\xD7"=>"\xE9\x82\xAA", + "\x8E\xD8"=>"\xE5\x80\x9F", + "\x8E\xD9"=>"\xE5\x8B\xBA", + "\x8E\xDA"=>"\xE5\xB0\xBA", + "\x8E\xDB"=>"\xE6\x9D\x93", + "\x8E\xDC"=>"\xE7\x81\xBC", + "\x8E\xDD"=>"\xE7\x88\xB5", + "\x8E\xDE"=>"\xE9\x85\x8C", + "\x8E\xDF"=>"\xE9\x87\x88", + "\x8E\xE0"=>"\xE9\x8C\xAB", + "\x8E\xE1"=>"\xE8\x8B\xA5", + "\x8E\xE2"=>"\xE5\xAF\x82", + "\x8E\xE3"=>"\xE5\xBC\xB1", + "\x8E\xE4"=>"\xE6\x83\xB9", + "\x8E\xE5"=>"\xE4\xB8\xBB", + "\x8E\xE6"=>"\xE5\x8F\x96", + "\x8E\xE7"=>"\xE5\xAE\x88", + "\x8E\xE8"=>"\xE6\x89\x8B", + "\x8E\xE9"=>"\xE6\x9C\xB1", + "\x8E\xEA"=>"\xE6\xAE\x8A", + "\x8E\xEB"=>"\xE7\x8B\xA9", + "\x8E\xEC"=>"\xE7\x8F\xA0", + "\x8E\xED"=>"\xE7\xA8\xAE", + "\x8E\xEE"=>"\xE8\x85\xAB", + "\x8E\xEF"=>"\xE8\xB6\xA3", + "\x8E\xF0"=>"\xE9\x85\x92", + "\x8E\xF1"=>"\xE9\xA6\x96", + "\x8E\xF2"=>"\xE5\x84\x92", + "\x8E\xF3"=>"\xE5\x8F\x97", + "\x8E\xF4"=>"\xE5\x91\xAA", + "\x8E\xF5"=>"\xE5\xAF\xBF", + "\x8E\xF6"=>"\xE6\x8E\x88", + "\x8E\xF7"=>"\xE6\xA8\xB9", + "\x8E\xF8"=>"\xE7\xB6\xAC", + "\x8E\xF9"=>"\xE9\x9C\x80", + "\x8E\xFA"=>"\xE5\x9B\x9A", + "\x8E\xFB"=>"\xE5\x8F\x8E", + "\x8E\xFC"=>"\xE5\x91\xA8", + "\x8F\x40"=>"\xE5\xAE\x97", + "\x8F\x41"=>"\xE5\xB0\xB1", + "\x8F\x42"=>"\xE5\xB7\x9E", + "\x8F\x43"=>"\xE4\xBF\xAE", + "\x8F\x44"=>"\xE6\x84\x81", + "\x8F\x45"=>"\xE6\x8B\xBE", + "\x8F\x46"=>"\xE6\xB4\xB2", + "\x8F\x47"=>"\xE7\xA7\x80", + "\x8F\x48"=>"\xE7\xA7\x8B", + "\x8F\x49"=>"\xE7\xB5\x82", + "\x8F\x4A"=>"\xE7\xB9\x8D", + "\x8F\x4B"=>"\xE7\xBF\x92", + "\x8F\x4C"=>"\xE8\x87\xAD", + "\x8F\x4D"=>"\xE8\x88\x9F", + "\x8F\x4E"=>"\xE8\x92\x90", + "\x8F\x4F"=>"\xE8\xA1\x86", + "\x8F\x50"=>"\xE8\xA5\xB2", + "\x8F\x51"=>"\xE8\xAE\x90", + "\x8F\x52"=>"\xE8\xB9\xB4", + "\x8F\x53"=>"\xE8\xBC\xAF", + "\x8F\x54"=>"\xE9\x80\xB1", + "\x8F\x55"=>"\xE9\x85\x8B", + "\x8F\x56"=>"\xE9\x85\xAC", + "\x8F\x57"=>"\xE9\x9B\x86", + "\x8F\x58"=>"\xE9\x86\x9C", + "\x8F\x59"=>"\xE4\xBB\x80", + "\x8F\x5A"=>"\xE4\xBD\x8F", + "\x8F\x5B"=>"\xE5\x85\x85", + "\x8F\x5C"=>"\xE5\x8D\x81", + "\x8F\x5D"=>"\xE5\xBE\x93", + "\x8F\x5E"=>"\xE6\x88\x8E", + "\x8F\x5F"=>"\xE6\x9F\x94", + "\x8F\x60"=>"\xE6\xB1\x81", + "\x8F\x61"=>"\xE6\xB8\x8B", + "\x8F\x62"=>"\xE7\x8D\xA3", + "\x8F\x63"=>"\xE7\xB8\xA6", + "\x8F\x64"=>"\xE9\x87\x8D", + "\x8F\x65"=>"\xE9\x8A\x83", + "\x8F\x66"=>"\xE5\x8F\x94", + "\x8F\x67"=>"\xE5\xA4\x99", + "\x8F\x68"=>"\xE5\xAE\xBF", + "\x8F\x69"=>"\xE6\xB7\x91", + "\x8F\x6A"=>"\xE7\xA5\x9D", + "\x8F\x6B"=>"\xE7\xB8\xAE", + "\x8F\x6C"=>"\xE7\xB2\x9B", + "\x8F\x6D"=>"\xE5\xA1\xBE", + "\x8F\x6E"=>"\xE7\x86\x9F", + "\x8F\x6F"=>"\xE5\x87\xBA", + "\x8F\x70"=>"\xE8\xA1\x93", + "\x8F\x71"=>"\xE8\xBF\xB0", + "\x8F\x72"=>"\xE4\xBF\x8A", + "\x8F\x73"=>"\xE5\xB3\xBB", + "\x8F\x74"=>"\xE6\x98\xA5", + "\x8F\x75"=>"\xE7\x9E\xAC", + "\x8F\x76"=>"\xE7\xAB\xA3", + "\x8F\x77"=>"\xE8\x88\x9C", + "\x8F\x78"=>"\xE9\xA7\xBF", + "\x8F\x79"=>"\xE5\x87\x86", + "\x8F\x7A"=>"\xE5\xBE\xAA", + "\x8F\x7B"=>"\xE6\x97\xAC", + "\x8F\x7C"=>"\xE6\xA5\xAF", + "\x8F\x7D"=>"\xE6\xAE\x89", + "\x8F\x7E"=>"\xE6\xB7\xB3", + "\x8F\x80"=>"\xE6\xBA\x96", + "\x8F\x81"=>"\xE6\xBD\xA4", + "\x8F\x82"=>"\xE7\x9B\xBE", + "\x8F\x83"=>"\xE7\xB4\x94", + "\x8F\x84"=>"\xE5\xB7\xA1", + "\x8F\x85"=>"\xE9\x81\xB5", + "\x8F\x86"=>"\xE9\x86\x87", + "\x8F\x87"=>"\xE9\xA0\x86", + "\x8F\x88"=>"\xE5\x87\xA6", + "\x8F\x89"=>"\xE5\x88\x9D", + "\x8F\x8A"=>"\xE6\x89\x80", + "\x8F\x8B"=>"\xE6\x9A\x91", + "\x8F\x8C"=>"\xE6\x9B\x99", + "\x8F\x8D"=>"\xE6\xB8\x9A", + "\x8F\x8E"=>"\xE5\xBA\xB6", + "\x8F\x8F"=>"\xE7\xB7\x92", + "\x8F\x90"=>"\xE7\xBD\xB2", + "\x8F\x91"=>"\xE6\x9B\xB8", + "\x8F\x92"=>"\xE8\x96\xAF", + "\x8F\x93"=>"\xE8\x97\xB7", + "\x8F\x94"=>"\xE8\xAB\xB8", + "\x8F\x95"=>"\xE5\x8A\xA9", + "\x8F\x96"=>"\xE5\x8F\x99", + "\x8F\x97"=>"\xE5\xA5\xB3", + "\x8F\x98"=>"\xE5\xBA\x8F", + "\x8F\x99"=>"\xE5\xBE\x90", + "\x8F\x9A"=>"\xE6\x81\x95", + "\x8F\x9B"=>"\xE9\x8B\xA4", + "\x8F\x9C"=>"\xE9\x99\xA4", + "\x8F\x9D"=>"\xE5\x82\xB7", + "\x8F\x9E"=>"\xE5\x84\x9F", + "\x8F\x9F"=>"\xE5\x8B\x9D", + "\x8F\xA0"=>"\xE5\x8C\xA0", + "\x8F\xA1"=>"\xE5\x8D\x87", + "\x8F\xA2"=>"\xE5\x8F\xAC", + "\x8F\xA3"=>"\xE5\x93\xA8", + "\x8F\xA4"=>"\xE5\x95\x86", + "\x8F\xA5"=>"\xE5\x94\xB1", + "\x8F\xA6"=>"\xE5\x98\x97", + "\x8F\xA7"=>"\xE5\xA5\xA8", + "\x8F\xA8"=>"\xE5\xA6\xBE", + "\x8F\xA9"=>"\xE5\xA8\xBC", + "\x8F\xAA"=>"\xE5\xAE\xB5", + "\x8F\xAB"=>"\xE5\xB0\x86", + "\x8F\xAC"=>"\xE5\xB0\x8F", + "\x8F\xAD"=>"\xE5\xB0\x91", + "\x8F\xAE"=>"\xE5\xB0\x9A", + "\x8F\xAF"=>"\xE5\xBA\x84", + "\x8F\xB0"=>"\xE5\xBA\x8A", + "\x8F\xB1"=>"\xE5\xBB\xA0", + "\x8F\xB2"=>"\xE5\xBD\xB0", + "\x8F\xB3"=>"\xE6\x89\xBF", + "\x8F\xB4"=>"\xE6\x8A\x84", + "\x8F\xB5"=>"\xE6\x8B\x9B", + "\x8F\xB6"=>"\xE6\x8E\x8C", + "\x8F\xB7"=>"\xE6\x8D\xB7", + "\x8F\xB8"=>"\xE6\x98\x87", + "\x8F\xB9"=>"\xE6\x98\x8C", + "\x8F\xBA"=>"\xE6\x98\xAD", + "\x8F\xBB"=>"\xE6\x99\xB6", + "\x8F\xBC"=>"\xE6\x9D\xBE", + "\x8F\xBD"=>"\xE6\xA2\xA2", + "\x8F\xBE"=>"\xE6\xA8\x9F", + "\x8F\xBF"=>"\xE6\xA8\xB5", + "\x8F\xC0"=>"\xE6\xB2\xBC", + "\x8F\xC1"=>"\xE6\xB6\x88", + "\x8F\xC2"=>"\xE6\xB8\x89", + "\x8F\xC3"=>"\xE6\xB9\x98", + "\x8F\xC4"=>"\xE7\x84\xBC", + "\x8F\xC5"=>"\xE7\x84\xA6", + "\x8F\xC6"=>"\xE7\x85\xA7", + "\x8F\xC7"=>"\xE7\x97\x87", + "\x8F\xC8"=>"\xE7\x9C\x81", + "\x8F\xC9"=>"\xE7\xA1\x9D", + "\x8F\xCA"=>"\xE7\xA4\x81", + "\x8F\xCB"=>"\xE7\xA5\xA5", + "\x8F\xCC"=>"\xE7\xA7\xB0", + "\x8F\xCD"=>"\xE7\xAB\xA0", + "\x8F\xCE"=>"\xE7\xAC\x91", + "\x8F\xCF"=>"\xE7\xB2\xA7", + "\x8F\xD0"=>"\xE7\xB4\xB9", + "\x8F\xD1"=>"\xE8\x82\x96", + "\x8F\xD2"=>"\xE8\x8F\x96", + "\x8F\xD3"=>"\xE8\x92\x8B", + "\x8F\xD4"=>"\xE8\x95\x89", + "\x8F\xD5"=>"\xE8\xA1\x9D", + "\x8F\xD6"=>"\xE8\xA3\xB3", + "\x8F\xD7"=>"\xE8\xA8\x9F", + "\x8F\xD8"=>"\xE8\xA8\xBC", + "\x8F\xD9"=>"\xE8\xA9\x94", + "\x8F\xDA"=>"\xE8\xA9\xB3", + "\x8F\xDB"=>"\xE8\xB1\xA1", + "\x8F\xDC"=>"\xE8\xB3\x9E", + "\x8F\xDD"=>"\xE9\x86\xA4", + "\x8F\xDE"=>"\xE9\x89\xA6", + "\x8F\xDF"=>"\xE9\x8D\xBE", + "\x8F\xE0"=>"\xE9\x90\x98", + "\x8F\xE1"=>"\xE9\x9A\x9C", + "\x8F\xE2"=>"\xE9\x9E\x98", + "\x8F\xE3"=>"\xE4\xB8\x8A", + "\x8F\xE4"=>"\xE4\xB8\x88", + "\x8F\xE5"=>"\xE4\xB8\x9E", + "\x8F\xE6"=>"\xE4\xB9\x97", + "\x8F\xE7"=>"\xE5\x86\x97", + "\x8F\xE8"=>"\xE5\x89\xB0", + "\x8F\xE9"=>"\xE5\x9F\x8E", + "\x8F\xEA"=>"\xE5\xA0\xB4", + "\x8F\xEB"=>"\xE5\xA3\x8C", + "\x8F\xEC"=>"\xE5\xAC\xA2", + "\x8F\xED"=>"\xE5\xB8\xB8", + "\x8F\xEE"=>"\xE6\x83\x85", + "\x8F\xEF"=>"\xE6\x93\xBE", + "\x8F\xF0"=>"\xE6\x9D\xA1", + "\x8F\xF1"=>"\xE6\x9D\x96", + "\x8F\xF2"=>"\xE6\xB5\x84", + "\x8F\xF3"=>"\xE7\x8A\xB6", + "\x8F\xF4"=>"\xE7\x95\xB3", + "\x8F\xF5"=>"\xE7\xA9\xA3", + "\x8F\xF6"=>"\xE8\x92\xB8", + "\x8F\xF7"=>"\xE8\xAD\xB2", + "\x8F\xF8"=>"\xE9\x86\xB8", + "\x8F\xF9"=>"\xE9\x8C\xA0", + "\x8F\xFA"=>"\xE5\x98\xB1", + "\x8F\xFB"=>"\xE5\x9F\xB4", + "\x8F\xFC"=>"\xE9\xA3\xBE", + "\x90\x40"=>"\xE6\x8B\xAD", + "\x90\x41"=>"\xE6\xA4\x8D", + "\x90\x42"=>"\xE6\xAE\x96", + "\x90\x43"=>"\xE7\x87\xAD", + "\x90\x44"=>"\xE7\xB9\x94", + "\x90\x45"=>"\xE8\x81\xB7", + "\x90\x46"=>"\xE8\x89\xB2", + "\x90\x47"=>"\xE8\xA7\xA6", + "\x90\x48"=>"\xE9\xA3\x9F", + "\x90\x49"=>"\xE8\x9D\x95", + "\x90\x4A"=>"\xE8\xBE\xB1", + "\x90\x4B"=>"\xE5\xB0\xBB", + "\x90\x4C"=>"\xE4\xBC\xB8", + "\x90\x4D"=>"\xE4\xBF\xA1", + "\x90\x4E"=>"\xE4\xBE\xB5", + "\x90\x4F"=>"\xE5\x94\x87", + "\x90\x50"=>"\xE5\xA8\xA0", + "\x90\x51"=>"\xE5\xAF\x9D", + "\x90\x52"=>"\xE5\xAF\xA9", + "\x90\x53"=>"\xE5\xBF\x83", + "\x90\x54"=>"\xE6\x85\x8E", + "\x90\x55"=>"\xE6\x8C\xAF", + "\x90\x56"=>"\xE6\x96\xB0", + "\x90\x57"=>"\xE6\x99\x8B", + "\x90\x58"=>"\xE6\xA3\xAE", + "\x90\x59"=>"\xE6\xA6\x9B", + "\x90\x5A"=>"\xE6\xB5\xB8", + "\x90\x5B"=>"\xE6\xB7\xB1", + "\x90\x5C"=>"\xE7\x94\xB3", + "\x90\x5D"=>"\xE7\x96\xB9", + "\x90\x5E"=>"\xE7\x9C\x9F", + "\x90\x5F"=>"\xE7\xA5\x9E", + "\x90\x60"=>"\xE7\xA7\xA6", + "\x90\x61"=>"\xE7\xB4\xB3", + "\x90\x62"=>"\xE8\x87\xA3", + "\x90\x63"=>"\xE8\x8A\xAF", + "\x90\x64"=>"\xE8\x96\xAA", + "\x90\x65"=>"\xE8\xA6\xAA", + "\x90\x66"=>"\xE8\xA8\xBA", + "\x90\x67"=>"\xE8\xBA\xAB", + "\x90\x68"=>"\xE8\xBE\x9B", + "\x90\x69"=>"\xE9\x80\xB2", + "\x90\x6A"=>"\xE9\x87\x9D", + "\x90\x6B"=>"\xE9\x9C\x87", + "\x90\x6C"=>"\xE4\xBA\xBA", + "\x90\x6D"=>"\xE4\xBB\x81", + "\x90\x6E"=>"\xE5\x88\x83", + "\x90\x6F"=>"\xE5\xA1\xB5", + "\x90\x70"=>"\xE5\xA3\xAC", + "\x90\x71"=>"\xE5\xB0\x8B", + "\x90\x72"=>"\xE7\x94\x9A", + "\x90\x73"=>"\xE5\xB0\xBD", + "\x90\x74"=>"\xE8\x85\x8E", + "\x90\x75"=>"\xE8\xA8\x8A", + "\x90\x76"=>"\xE8\xBF\x85", + "\x90\x77"=>"\xE9\x99\xA3", + "\x90\x78"=>"\xE9\x9D\xAD", + "\x90\x79"=>"\xE7\xAC\xA5", + "\x90\x7A"=>"\xE8\xAB\x8F", + "\x90\x7B"=>"\xE9\xA0\x88", + "\x90\x7C"=>"\xE9\x85\xA2", + "\x90\x7D"=>"\xE5\x9B\xB3", + "\x90\x7E"=>"\xE5\x8E\xA8", + "\x90\x80"=>"\xE9\x80\x97", + "\x90\x81"=>"\xE5\x90\xB9", + "\x90\x82"=>"\xE5\x9E\x82", + "\x90\x83"=>"\xE5\xB8\xA5", + "\x90\x84"=>"\xE6\x8E\xA8", + "\x90\x85"=>"\xE6\xB0\xB4", + "\x90\x86"=>"\xE7\x82\x8A", + "\x90\x87"=>"\xE7\x9D\xA1", + "\x90\x88"=>"\xE7\xB2\x8B", + "\x90\x89"=>"\xE7\xBF\xA0", + "\x90\x8A"=>"\xE8\xA1\xB0", + "\x90\x8B"=>"\xE9\x81\x82", + "\x90\x8C"=>"\xE9\x85\x94", + "\x90\x8D"=>"\xE9\x8C\x90", + "\x90\x8E"=>"\xE9\x8C\x98", + "\x90\x8F"=>"\xE9\x9A\x8F", + "\x90\x90"=>"\xE7\x91\x9E", + "\x90\x91"=>"\xE9\xAB\x84", + "\x90\x92"=>"\xE5\xB4\x87", + "\x90\x93"=>"\xE5\xB5\xA9", + "\x90\x94"=>"\xE6\x95\xB0", + "\x90\x95"=>"\xE6\x9E\xA2", + "\x90\x96"=>"\xE8\xB6\xA8", + "\x90\x97"=>"\xE9\x9B\x9B", + "\x90\x98"=>"\xE6\x8D\xAE", + "\x90\x99"=>"\xE6\x9D\x89", + "\x90\x9A"=>"\xE6\xA4\x99", + "\x90\x9B"=>"\xE8\x8F\x85", + "\x90\x9C"=>"\xE9\xA0\x97", + "\x90\x9D"=>"\xE9\x9B\x80", + "\x90\x9E"=>"\xE8\xA3\xBE", + "\x90\x9F"=>"\xE6\xBE\x84", + "\x90\xA0"=>"\xE6\x91\xBA", + "\x90\xA1"=>"\xE5\xAF\xB8", + "\x90\xA2"=>"\xE4\xB8\x96", + "\x90\xA3"=>"\xE7\x80\xAC", + "\x90\xA4"=>"\xE7\x95\x9D", + "\x90\xA5"=>"\xE6\x98\xAF", + "\x90\xA6"=>"\xE5\x87\x84", + "\x90\xA7"=>"\xE5\x88\xB6", + "\x90\xA8"=>"\xE5\x8B\xA2", + "\x90\xA9"=>"\xE5\xA7\x93", + "\x90\xAA"=>"\xE5\xBE\x81", + "\x90\xAB"=>"\xE6\x80\xA7", + "\x90\xAC"=>"\xE6\x88\x90", + "\x90\xAD"=>"\xE6\x94\xBF", + "\x90\xAE"=>"\xE6\x95\xB4", + "\x90\xAF"=>"\xE6\x98\x9F", + "\x90\xB0"=>"\xE6\x99\xB4", + "\x90\xB1"=>"\xE6\xA3\xB2", + "\x90\xB2"=>"\xE6\xA0\x96", + "\x90\xB3"=>"\xE6\xAD\xA3", + "\x90\xB4"=>"\xE6\xB8\x85", + "\x90\xB5"=>"\xE7\x89\xB2", + "\x90\xB6"=>"\xE7\x94\x9F", + "\x90\xB7"=>"\xE7\x9B\x9B", + "\x90\xB8"=>"\xE7\xB2\xBE", + "\x90\xB9"=>"\xE8\x81\x96", + "\x90\xBA"=>"\xE5\xA3\xB0", + "\x90\xBB"=>"\xE8\xA3\xBD", + "\x90\xBC"=>"\xE8\xA5\xBF", + "\x90\xBD"=>"\xE8\xAA\xA0", + "\x90\xBE"=>"\xE8\xAA\x93", + "\x90\xBF"=>"\xE8\xAB\x8B", + "\x90\xC0"=>"\xE9\x80\x9D", + "\x90\xC1"=>"\xE9\x86\x92", + "\x90\xC2"=>"\xE9\x9D\x92", + "\x90\xC3"=>"\xE9\x9D\x99", + "\x90\xC4"=>"\xE6\x96\x89", + "\x90\xC5"=>"\xE7\xA8\x8E", + "\x90\xC6"=>"\xE8\x84\x86", + "\x90\xC7"=>"\xE9\x9A\xBB", + "\x90\xC8"=>"\xE5\xB8\xAD", + "\x90\xC9"=>"\xE6\x83\x9C", + "\x90\xCA"=>"\xE6\x88\x9A", + "\x90\xCB"=>"\xE6\x96\xA5", + "\x90\xCC"=>"\xE6\x98\x94", + "\x90\xCD"=>"\xE6\x9E\x90", + "\x90\xCE"=>"\xE7\x9F\xB3", + "\x90\xCF"=>"\xE7\xA9\x8D", + "\x90\xD0"=>"\xE7\xB1\x8D", + "\x90\xD1"=>"\xE7\xB8\xBE", + "\x90\xD2"=>"\xE8\x84\x8A", + "\x90\xD3"=>"\xE8\xB2\xAC", + "\x90\xD4"=>"\xE8\xB5\xA4", + "\x90\xD5"=>"\xE8\xB7\xA1", + "\x90\xD6"=>"\xE8\xB9\x9F", + "\x90\xD7"=>"\xE7\xA2\xA9", + "\x90\xD8"=>"\xE5\x88\x87", + "\x90\xD9"=>"\xE6\x8B\x99", + "\x90\xDA"=>"\xE6\x8E\xA5", + "\x90\xDB"=>"\xE6\x91\x82", + "\x90\xDC"=>"\xE6\x8A\x98", + "\x90\xDD"=>"\xE8\xA8\xAD", + "\x90\xDE"=>"\xE7\xAA\x83", + "\x90\xDF"=>"\xE7\xAF\x80", + "\x90\xE0"=>"\xE8\xAA\xAC", + "\x90\xE1"=>"\xE9\x9B\xAA", + "\x90\xE2"=>"\xE7\xB5\xB6", + "\x90\xE3"=>"\xE8\x88\x8C", + "\x90\xE4"=>"\xE8\x9D\x89", + "\x90\xE5"=>"\xE4\xBB\x99", + "\x90\xE6"=>"\xE5\x85\x88", + "\x90\xE7"=>"\xE5\x8D\x83", + "\x90\xE8"=>"\xE5\x8D\xA0", + "\x90\xE9"=>"\xE5\xAE\xA3", + "\x90\xEA"=>"\xE5\xB0\x82", + "\x90\xEB"=>"\xE5\xB0\x96", + "\x90\xEC"=>"\xE5\xB7\x9D", + "\x90\xED"=>"\xE6\x88\xA6", + "\x90\xEE"=>"\xE6\x89\x87", + "\x90\xEF"=>"\xE6\x92\xB0", + "\x90\xF0"=>"\xE6\xA0\x93", + "\x90\xF1"=>"\xE6\xA0\xB4", + "\x90\xF2"=>"\xE6\xB3\x89", + "\x90\xF3"=>"\xE6\xB5\x85", + "\x90\xF4"=>"\xE6\xB4\x97", + "\x90\xF5"=>"\xE6\x9F\x93", + "\x90\xF6"=>"\xE6\xBD\x9C", + "\x90\xF7"=>"\xE7\x85\x8E", + "\x90\xF8"=>"\xE7\x85\xBD", + "\x90\xF9"=>"\xE6\x97\x8B", + "\x90\xFA"=>"\xE7\xA9\xBF", + "\x90\xFB"=>"\xE7\xAE\xAD", + "\x90\xFC"=>"\xE7\xB7\x9A", + "\x91\x40"=>"\xE7\xB9\x8A", + "\x91\x41"=>"\xE7\xBE\xA8", + "\x91\x42"=>"\xE8\x85\xBA", + "\x91\x43"=>"\xE8\x88\x9B", + "\x91\x44"=>"\xE8\x88\xB9", + "\x91\x45"=>"\xE8\x96\xA6", + "\x91\x46"=>"\xE8\xA9\xAE", + "\x91\x47"=>"\xE8\xB3\x8E", + "\x91\x48"=>"\xE8\xB7\xB5", + "\x91\x49"=>"\xE9\x81\xB8", + "\x91\x4A"=>"\xE9\x81\xB7", + "\x91\x4B"=>"\xE9\x8A\xAD", + "\x91\x4C"=>"\xE9\x8A\x91", + "\x91\x4D"=>"\xE9\x96\x83", + "\x91\x4E"=>"\xE9\xAE\xAE", + "\x91\x4F"=>"\xE5\x89\x8D", + "\x91\x50"=>"\xE5\x96\x84", + "\x91\x51"=>"\xE6\xBC\xB8", + "\x91\x52"=>"\xE7\x84\xB6", + "\x91\x53"=>"\xE5\x85\xA8", + "\x91\x54"=>"\xE7\xA6\x85", + "\x91\x55"=>"\xE7\xB9\x95", + "\x91\x56"=>"\xE8\x86\xB3", + "\x91\x57"=>"\xE7\xB3\x8E", + "\x91\x58"=>"\xE5\x99\x8C", + "\x91\x59"=>"\xE5\xA1\x91", + "\x91\x5A"=>"\xE5\xB2\xA8", + "\x91\x5B"=>"\xE6\x8E\xAA", + "\x91\x5C"=>"\xE6\x9B\xBE", + "\x91\x5D"=>"\xE6\x9B\xBD", + "\x91\x5E"=>"\xE6\xA5\x9A", + "\x91\x5F"=>"\xE7\x8B\x99", + "\x91\x60"=>"\xE7\x96\x8F", + "\x91\x61"=>"\xE7\x96\x8E", + "\x91\x62"=>"\xE7\xA4\x8E", + "\x91\x63"=>"\xE7\xA5\x96", + "\x91\x64"=>"\xE7\xA7\x9F", + "\x91\x65"=>"\xE7\xB2\x97", + "\x91\x66"=>"\xE7\xB4\xA0", + "\x91\x67"=>"\xE7\xB5\x84", + "\x91\x68"=>"\xE8\x98\x87", + "\x91\x69"=>"\xE8\xA8\xB4", + "\x91\x6A"=>"\xE9\x98\xBB", + "\x91\x6B"=>"\xE9\x81\xA1", + "\x91\x6C"=>"\xE9\xBC\xA0", + "\x91\x6D"=>"\xE5\x83\xA7", + "\x91\x6E"=>"\xE5\x89\xB5", + "\x91\x6F"=>"\xE5\x8F\x8C", + "\x91\x70"=>"\xE5\x8F\xA2", + "\x91\x71"=>"\xE5\x80\x89", + "\x91\x72"=>"\xE5\x96\xAA", + "\x91\x73"=>"\xE5\xA3\xAE", + "\x91\x74"=>"\xE5\xA5\x8F", + "\x91\x75"=>"\xE7\x88\xBD", + "\x91\x76"=>"\xE5\xAE\x8B", + "\x91\x77"=>"\xE5\xB1\xA4", + "\x91\x78"=>"\xE5\x8C\x9D", + "\x91\x79"=>"\xE6\x83\xA3", + "\x91\x7A"=>"\xE6\x83\xB3", + "\x91\x7B"=>"\xE6\x8D\x9C", + "\x91\x7C"=>"\xE6\x8E\x83", + "\x91\x7D"=>"\xE6\x8C\xBF", + "\x91\x7E"=>"\xE6\x8E\xBB", + "\x91\x80"=>"\xE6\x93\x8D", + "\x91\x81"=>"\xE6\x97\xA9", + "\x91\x82"=>"\xE6\x9B\xB9", + "\x91\x83"=>"\xE5\xB7\xA3", + "\x91\x84"=>"\xE6\xA7\x8D", + "\x91\x85"=>"\xE6\xA7\xBD", + "\x91\x86"=>"\xE6\xBC\x95", + "\x91\x87"=>"\xE7\x87\xA5", + "\x91\x88"=>"\xE4\xBA\x89", + "\x91\x89"=>"\xE7\x97\xA9", + "\x91\x8A"=>"\xE7\x9B\xB8", + "\x91\x8B"=>"\xE7\xAA\x93", + "\x91\x8C"=>"\xE7\xB3\x9F", + "\x91\x8D"=>"\xE7\xB7\x8F", + "\x91\x8E"=>"\xE7\xB6\x9C", + "\x91\x8F"=>"\xE8\x81\xA1", + "\x91\x90"=>"\xE8\x8D\x89", + "\x91\x91"=>"\xE8\x8D\x98", + "\x91\x92"=>"\xE8\x91\xAC", + "\x91\x93"=>"\xE8\x92\xBC", + "\x91\x94"=>"\xE8\x97\xBB", + "\x91\x95"=>"\xE8\xA3\x85", + "\x91\x96"=>"\xE8\xB5\xB0", + "\x91\x97"=>"\xE9\x80\x81", + "\x91\x98"=>"\xE9\x81\xAD", + "\x91\x99"=>"\xE9\x8E\x97", + "\x91\x9A"=>"\xE9\x9C\x9C", + "\x91\x9B"=>"\xE9\xA8\x92", + "\x91\x9C"=>"\xE5\x83\x8F", + "\x91\x9D"=>"\xE5\xA2\x97", + "\x91\x9E"=>"\xE6\x86\x8E", + "\x91\x9F"=>"\xE8\x87\x93", + "\x91\xA0"=>"\xE8\x94\xB5", + "\x91\xA1"=>"\xE8\xB4\x88", + "\x91\xA2"=>"\xE9\x80\xA0", + "\x91\xA3"=>"\xE4\xBF\x83", + "\x91\xA4"=>"\xE5\x81\xB4", + "\x91\xA5"=>"\xE5\x89\x87", + "\x91\xA6"=>"\xE5\x8D\xB3", + "\x91\xA7"=>"\xE6\x81\xAF", + "\x91\xA8"=>"\xE6\x8D\x89", + "\x91\xA9"=>"\xE6\x9D\x9F", + "\x91\xAA"=>"\xE6\xB8\xAC", + "\x91\xAB"=>"\xE8\xB6\xB3", + "\x91\xAC"=>"\xE9\x80\x9F", + "\x91\xAD"=>"\xE4\xBF\x97", + "\x91\xAE"=>"\xE5\xB1\x9E", + "\x91\xAF"=>"\xE8\xB3\x8A", + "\x91\xB0"=>"\xE6\x97\x8F", + "\x91\xB1"=>"\xE7\xB6\x9A", + "\x91\xB2"=>"\xE5\x8D\x92", + "\x91\xB3"=>"\xE8\xA2\x96", + "\x91\xB4"=>"\xE5\x85\xB6", + "\x91\xB5"=>"\xE6\x8F\x83", + "\x91\xB6"=>"\xE5\xAD\x98", + "\x91\xB7"=>"\xE5\xAD\xAB", + "\x91\xB8"=>"\xE5\xB0\x8A", + "\x91\xB9"=>"\xE6\x90\x8D", + "\x91\xBA"=>"\xE6\x9D\x91", + "\x91\xBB"=>"\xE9\x81\x9C", + "\x91\xBC"=>"\xE4\xBB\x96", + "\x91\xBD"=>"\xE5\xA4\x9A", + "\x91\xBE"=>"\xE5\xA4\xAA", + "\x91\xBF"=>"\xE6\xB1\xB0", + "\x91\xC0"=>"\xE8\xA9\x91", + "\x91\xC1"=>"\xE5\x94\xBE", + "\x91\xC2"=>"\xE5\xA0\x95", + "\x91\xC3"=>"\xE5\xA6\xA5", + "\x91\xC4"=>"\xE6\x83\xB0", + "\x91\xC5"=>"\xE6\x89\x93", + "\x91\xC6"=>"\xE6\x9F\x81", + "\x91\xC7"=>"\xE8\x88\xB5", + "\x91\xC8"=>"\xE6\xA5\x95", + "\x91\xC9"=>"\xE9\x99\x80", + "\x91\xCA"=>"\xE9\xA7\x84", + "\x91\xCB"=>"\xE9\xA8\xA8", + "\x91\xCC"=>"\xE4\xBD\x93", + "\x91\xCD"=>"\xE5\xA0\x86", + "\x91\xCE"=>"\xE5\xAF\xBE", + "\x91\xCF"=>"\xE8\x80\x90", + "\x91\xD0"=>"\xE5\xB2\xB1", + "\x91\xD1"=>"\xE5\xB8\xAF", + "\x91\xD2"=>"\xE5\xBE\x85", + "\x91\xD3"=>"\xE6\x80\xA0", + "\x91\xD4"=>"\xE6\x85\x8B", + "\x91\xD5"=>"\xE6\x88\xB4", + "\x91\xD6"=>"\xE6\x9B\xBF", + "\x91\xD7"=>"\xE6\xB3\xB0", + "\x91\xD8"=>"\xE6\xBB\x9E", + "\x91\xD9"=>"\xE8\x83\x8E", + "\x91\xDA"=>"\xE8\x85\xBF", + "\x91\xDB"=>"\xE8\x8B\x94", + "\x91\xDC"=>"\xE8\xA2\x8B", + "\x91\xDD"=>"\xE8\xB2\xB8", + "\x91\xDE"=>"\xE9\x80\x80", + "\x91\xDF"=>"\xE9\x80\xAE", + "\x91\xE0"=>"\xE9\x9A\x8A", + "\x91\xE1"=>"\xE9\xBB\x9B", + "\x91\xE2"=>"\xE9\xAF\x9B", + "\x91\xE3"=>"\xE4\xBB\xA3", + "\x91\xE4"=>"\xE5\x8F\xB0", + "\x91\xE5"=>"\xE5\xA4\xA7", + "\x91\xE6"=>"\xE7\xAC\xAC", + "\x91\xE7"=>"\xE9\x86\x8D", + "\x91\xE8"=>"\xE9\xA1\x8C", + "\x91\xE9"=>"\xE9\xB7\xB9", + "\x91\xEA"=>"\xE6\xBB\x9D", + "\x91\xEB"=>"\xE7\x80\xA7", + "\x91\xEC"=>"\xE5\x8D\x93", + "\x91\xED"=>"\xE5\x95\x84", + "\x91\xEE"=>"\xE5\xAE\x85", + "\x91\xEF"=>"\xE6\x89\x98", + "\x91\xF0"=>"\xE6\x8A\x9E", + "\x91\xF1"=>"\xE6\x8B\x93", + "\x91\xF2"=>"\xE6\xB2\xA2", + "\x91\xF3"=>"\xE6\xBF\xAF", + "\x91\xF4"=>"\xE7\x90\xA2", + "\x91\xF5"=>"\xE8\xA8\x97", + "\x91\xF6"=>"\xE9\x90\xB8", + "\x91\xF7"=>"\xE6\xBF\x81", + "\x91\xF8"=>"\xE8\xAB\xBE", + "\x91\xF9"=>"\xE8\x8C\xB8", + "\x91\xFA"=>"\xE5\x87\xA7", + "\x91\xFB"=>"\xE8\x9B\xB8", + "\x91\xFC"=>"\xE5\x8F\xAA", + "\x92\x40"=>"\xE5\x8F\xA9", + "\x92\x41"=>"\xE4\xBD\x86", + "\x92\x42"=>"\xE9\x81\x94", + "\x92\x43"=>"\xE8\xBE\xB0", + "\x92\x44"=>"\xE5\xA5\xAA", + "\x92\x45"=>"\xE8\x84\xB1", + "\x92\x46"=>"\xE5\xB7\xBD", + "\x92\x47"=>"\xE7\xAB\xAA", + "\x92\x48"=>"\xE8\xBE\xBF", + "\x92\x49"=>"\xE6\xA3\x9A", + "\x92\x4A"=>"\xE8\xB0\xB7", + "\x92\x4B"=>"\xE7\x8B\xB8", + "\x92\x4C"=>"\xE9\xB1\x88", + "\x92\x4D"=>"\xE6\xA8\xBD", + "\x92\x4E"=>"\xE8\xAA\xB0", + "\x92\x4F"=>"\xE4\xB8\xB9", + "\x92\x50"=>"\xE5\x8D\x98", + "\x92\x51"=>"\xE5\x98\x86", + "\x92\x52"=>"\xE5\x9D\xA6", + "\x92\x53"=>"\xE6\x8B\x85", + "\x92\x54"=>"\xE6\x8E\xA2", + "\x92\x55"=>"\xE6\x97\xA6", + "\x92\x56"=>"\xE6\xAD\x8E", + "\x92\x57"=>"\xE6\xB7\xA1", + "\x92\x58"=>"\xE6\xB9\x9B", + "\x92\x59"=>"\xE7\x82\xAD", + "\x92\x5A"=>"\xE7\x9F\xAD", + "\x92\x5B"=>"\xE7\xAB\xAF", + "\x92\x5C"=>"\xE7\xAE\xAA", + "\x92\x5D"=>"\xE7\xB6\xBB", + "\x92\x5E"=>"\xE8\x80\xBD", + "\x92\x5F"=>"\xE8\x83\x86", + "\x92\x60"=>"\xE8\x9B\x8B", + "\x92\x61"=>"\xE8\xAA\x95", + "\x92\x62"=>"\xE9\x8D\x9B", + "\x92\x63"=>"\xE5\x9B\xA3", + "\x92\x64"=>"\xE5\xA3\x87", + "\x92\x65"=>"\xE5\xBC\xBE", + "\x92\x66"=>"\xE6\x96\xAD", + "\x92\x67"=>"\xE6\x9A\x96", + "\x92\x68"=>"\xE6\xAA\x80", + "\x92\x69"=>"\xE6\xAE\xB5", + "\x92\x6A"=>"\xE7\x94\xB7", + "\x92\x6B"=>"\xE8\xAB\x87", + "\x92\x6C"=>"\xE5\x80\xA4", + "\x92\x6D"=>"\xE7\x9F\xA5", + "\x92\x6E"=>"\xE5\x9C\xB0", + "\x92\x6F"=>"\xE5\xBC\x9B", + "\x92\x70"=>"\xE6\x81\xA5", + "\x92\x71"=>"\xE6\x99\xBA", + "\x92\x72"=>"\xE6\xB1\xA0", + "\x92\x73"=>"\xE7\x97\xB4", + "\x92\x74"=>"\xE7\xA8\x9A", + "\x92\x75"=>"\xE7\xBD\xAE", + "\x92\x76"=>"\xE8\x87\xB4", + "\x92\x77"=>"\xE8\x9C\x98", + "\x92\x78"=>"\xE9\x81\x85", + "\x92\x79"=>"\xE9\xA6\xB3", + "\x92\x7A"=>"\xE7\xAF\x89", + "\x92\x7B"=>"\xE7\x95\x9C", + "\x92\x7C"=>"\xE7\xAB\xB9", + "\x92\x7D"=>"\xE7\xAD\x91", + "\x92\x7E"=>"\xE8\x93\x84", + "\x92\x80"=>"\xE9\x80\x90", + "\x92\x81"=>"\xE7\xA7\xA9", + "\x92\x82"=>"\xE7\xAA\x92", + "\x92\x83"=>"\xE8\x8C\xB6", + "\x92\x84"=>"\xE5\xAB\xA1", + "\x92\x85"=>"\xE7\x9D\x80", + "\x92\x86"=>"\xE4\xB8\xAD", + "\x92\x87"=>"\xE4\xBB\xB2", + "\x92\x88"=>"\xE5\xAE\x99", + "\x92\x89"=>"\xE5\xBF\xA0", + "\x92\x8A"=>"\xE6\x8A\xBD", + "\x92\x8B"=>"\xE6\x98\xBC", + "\x92\x8C"=>"\xE6\x9F\xB1", + "\x92\x8D"=>"\xE6\xB3\xA8", + "\x92\x8E"=>"\xE8\x99\xAB", + "\x92\x8F"=>"\xE8\xA1\xB7", + "\x92\x90"=>"\xE8\xA8\xBB", + "\x92\x91"=>"\xE9\x85\x8E", + "\x92\x92"=>"\xE9\x8B\xB3", + "\x92\x93"=>"\xE9\xA7\x90", + "\x92\x94"=>"\xE6\xA8\x97", + "\x92\x95"=>"\xE7\x80\xA6", + "\x92\x96"=>"\xE7\x8C\xAA", + "\x92\x97"=>"\xE8\x8B\xA7", + "\x92\x98"=>"\xE8\x91\x97", + "\x92\x99"=>"\xE8\xB2\xAF", + "\x92\x9A"=>"\xE4\xB8\x81", + "\x92\x9B"=>"\xE5\x85\x86", + "\x92\x9C"=>"\xE5\x87\x8B", + "\x92\x9D"=>"\xE5\x96\x8B", + "\x92\x9E"=>"\xE5\xAF\xB5", + "\x92\x9F"=>"\xE5\xB8\x96", + "\x92\xA0"=>"\xE5\xB8\xB3", + "\x92\xA1"=>"\xE5\xBA\x81", + "\x92\xA2"=>"\xE5\xBC\x94", + "\x92\xA3"=>"\xE5\xBC\xB5", + "\x92\xA4"=>"\xE5\xBD\xAB", + "\x92\xA5"=>"\xE5\xBE\xB4", + "\x92\xA6"=>"\xE6\x87\xB2", + "\x92\xA7"=>"\xE6\x8C\x91", + "\x92\xA8"=>"\xE6\x9A\xA2", + "\x92\xA9"=>"\xE6\x9C\x9D", + "\x92\xAA"=>"\xE6\xBD\xAE", + "\x92\xAB"=>"\xE7\x89\x92", + "\x92\xAC"=>"\xE7\x94\xBA", + "\x92\xAD"=>"\xE7\x9C\xBA", + "\x92\xAE"=>"\xE8\x81\xB4", + "\x92\xAF"=>"\xE8\x84\xB9", + "\x92\xB0"=>"\xE8\x85\xB8", + "\x92\xB1"=>"\xE8\x9D\xB6", + "\x92\xB2"=>"\xE8\xAA\xBF", + "\x92\xB3"=>"\xE8\xAB\x9C", + "\x92\xB4"=>"\xE8\xB6\x85", + "\x92\xB5"=>"\xE8\xB7\xB3", + "\x92\xB6"=>"\xE9\x8A\x9A", + "\x92\xB7"=>"\xE9\x95\xB7", + "\x92\xB8"=>"\xE9\xA0\x82", + "\x92\xB9"=>"\xE9\xB3\xA5", + "\x92\xBA"=>"\xE5\x8B\x85", + "\x92\xBB"=>"\xE6\x8D\x97", + "\x92\xBC"=>"\xE7\x9B\xB4", + "\x92\xBD"=>"\xE6\x9C\x95", + "\x92\xBE"=>"\xE6\xB2\x88", + "\x92\xBF"=>"\xE7\x8F\x8D", + "\x92\xC0"=>"\xE8\xB3\x83", + "\x92\xC1"=>"\xE9\x8E\xAE", + "\x92\xC2"=>"\xE9\x99\xB3", + "\x92\xC3"=>"\xE6\xB4\xA5", + "\x92\xC4"=>"\xE5\xA2\x9C", + "\x92\xC5"=>"\xE6\xA4\x8E", + "\x92\xC6"=>"\xE6\xA7\x8C", + "\x92\xC7"=>"\xE8\xBF\xBD", + "\x92\xC8"=>"\xE9\x8E\x9A", + "\x92\xC9"=>"\xE7\x97\x9B", + "\x92\xCA"=>"\xE9\x80\x9A", + "\x92\xCB"=>"\xE5\xA1\x9A", + "\x92\xCC"=>"\xE6\xA0\x82", + "\x92\xCD"=>"\xE6\x8E\xB4", + "\x92\xCE"=>"\xE6\xA7\xBB", + "\x92\xCF"=>"\xE4\xBD\x83", + "\x92\xD0"=>"\xE6\xBC\xAC", + "\x92\xD1"=>"\xE6\x9F\x98", + "\x92\xD2"=>"\xE8\xBE\xBB", + "\x92\xD3"=>"\xE8\x94\xA6", + "\x92\xD4"=>"\xE7\xB6\xB4", + "\x92\xD5"=>"\xE9\x8D\x94", + "\x92\xD6"=>"\xE6\xA4\xBF", + "\x92\xD7"=>"\xE6\xBD\xB0", + "\x92\xD8"=>"\xE5\x9D\xAA", + "\x92\xD9"=>"\xE5\xA3\xB7", + "\x92\xDA"=>"\xE5\xAC\xAC", + "\x92\xDB"=>"\xE7\xB4\xAC", + "\x92\xDC"=>"\xE7\x88\xAA", + "\x92\xDD"=>"\xE5\x90\x8A", + "\x92\xDE"=>"\xE9\x87\xA3", + "\x92\xDF"=>"\xE9\xB6\xB4", + "\x92\xE0"=>"\xE4\xBA\xAD", + "\x92\xE1"=>"\xE4\xBD\x8E", + "\x92\xE2"=>"\xE5\x81\x9C", + "\x92\xE3"=>"\xE5\x81\xB5", + "\x92\xE4"=>"\xE5\x89\x83", + "\x92\xE5"=>"\xE8\xB2\x9E", + "\x92\xE6"=>"\xE5\x91\x88", + "\x92\xE7"=>"\xE5\xA0\xA4", + "\x92\xE8"=>"\xE5\xAE\x9A", + "\x92\xE9"=>"\xE5\xB8\x9D", + "\x92\xEA"=>"\xE5\xBA\x95", + "\x92\xEB"=>"\xE5\xBA\xAD", + "\x92\xEC"=>"\xE5\xBB\xB7", + "\x92\xED"=>"\xE5\xBC\x9F", + "\x92\xEE"=>"\xE6\x82\x8C", + "\x92\xEF"=>"\xE6\x8A\xB5", + "\x92\xF0"=>"\xE6\x8C\xBA", + "\x92\xF1"=>"\xE6\x8F\x90", + "\x92\xF2"=>"\xE6\xA2\xAF", + "\x92\xF3"=>"\xE6\xB1\x80", + "\x92\xF4"=>"\xE7\xA2\x87", + "\x92\xF5"=>"\xE7\xA6\x8E", + "\x92\xF6"=>"\xE7\xA8\x8B", + "\x92\xF7"=>"\xE7\xB7\xA0", + "\x92\xF8"=>"\xE8\x89\x87", + "\x92\xF9"=>"\xE8\xA8\x82", + "\x92\xFA"=>"\xE8\xAB\xA6", + "\x92\xFB"=>"\xE8\xB9\x84", + "\x92\xFC"=>"\xE9\x80\x93", + "\x93\x40"=>"\xE9\x82\xB8", + "\x93\x41"=>"\xE9\x84\xAD", + "\x93\x42"=>"\xE9\x87\x98", + "\x93\x43"=>"\xE9\xBC\x8E", + "\x93\x44"=>"\xE6\xB3\xA5", + "\x93\x45"=>"\xE6\x91\x98", + "\x93\x46"=>"\xE6\x93\xA2", + "\x93\x47"=>"\xE6\x95\xB5", + "\x93\x48"=>"\xE6\xBB\xB4", + "\x93\x49"=>"\xE7\x9A\x84", + "\x93\x4A"=>"\xE7\xAC\x9B", + "\x93\x4B"=>"\xE9\x81\xA9", + "\x93\x4C"=>"\xE9\x8F\x91", + "\x93\x4D"=>"\xE6\xBA\xBA", + "\x93\x4E"=>"\xE5\x93\xB2", + "\x93\x4F"=>"\xE5\xBE\xB9", + "\x93\x50"=>"\xE6\x92\xA4", + "\x93\x51"=>"\xE8\xBD\x8D", + "\x93\x52"=>"\xE8\xBF\xAD", + "\x93\x53"=>"\xE9\x89\x84", + "\x93\x54"=>"\xE5\x85\xB8", + "\x93\x55"=>"\xE5\xA1\xAB", + "\x93\x56"=>"\xE5\xA4\xA9", + "\x93\x57"=>"\xE5\xB1\x95", + "\x93\x58"=>"\xE5\xBA\x97", + "\x93\x59"=>"\xE6\xB7\xBB", + "\x93\x5A"=>"\xE7\xBA\x8F", + "\x93\x5B"=>"\xE7\x94\x9C", + "\x93\x5C"=>"\xE8\xB2\xBC", + "\x93\x5D"=>"\xE8\xBB\xA2", + "\x93\x5E"=>"\xE9\xA1\x9B", + "\x93\x5F"=>"\xE7\x82\xB9", + "\x93\x60"=>"\xE4\xBC\x9D", + "\x93\x61"=>"\xE6\xAE\xBF", + "\x93\x62"=>"\xE6\xBE\xB1", + "\x93\x63"=>"\xE7\x94\xB0", + "\x93\x64"=>"\xE9\x9B\xBB", + "\x93\x65"=>"\xE5\x85\x8E", + "\x93\x66"=>"\xE5\x90\x90", + "\x93\x67"=>"\xE5\xA0\xB5", + "\x93\x68"=>"\xE5\xA1\x97", + "\x93\x69"=>"\xE5\xA6\xAC", + "\x93\x6A"=>"\xE5\xB1\xA0", + "\x93\x6B"=>"\xE5\xBE\x92", + "\x93\x6C"=>"\xE6\x96\x97", + "\x93\x6D"=>"\xE6\x9D\x9C", + "\x93\x6E"=>"\xE6\xB8\xA1", + "\x93\x6F"=>"\xE7\x99\xBB", + "\x93\x70"=>"\xE8\x8F\x9F", + "\x93\x71"=>"\xE8\xB3\xAD", + "\x93\x72"=>"\xE9\x80\x94", + "\x93\x73"=>"\xE9\x83\xBD", + "\x93\x74"=>"\xE9\x8D\x8D", + "\x93\x75"=>"\xE7\xA0\xA5", + "\x93\x76"=>"\xE7\xA0\xBA", + "\x93\x77"=>"\xE5\x8A\xAA", + "\x93\x78"=>"\xE5\xBA\xA6", + "\x93\x79"=>"\xE5\x9C\x9F", + "\x93\x7A"=>"\xE5\xA5\xB4", + "\x93\x7B"=>"\xE6\x80\x92", + "\x93\x7C"=>"\xE5\x80\x92", + "\x93\x7D"=>"\xE5\x85\x9A", + "\x93\x7E"=>"\xE5\x86\xAC", + "\x93\x80"=>"\xE5\x87\x8D", + "\x93\x81"=>"\xE5\x88\x80", + "\x93\x82"=>"\xE5\x94\x90", + "\x93\x83"=>"\xE5\xA1\x94", + "\x93\x84"=>"\xE5\xA1\x98", + "\x93\x85"=>"\xE5\xA5\x97", + "\x93\x86"=>"\xE5\xAE\x95", + "\x93\x87"=>"\xE5\xB3\xB6", + "\x93\x88"=>"\xE5\xB6\x8B", + "\x93\x89"=>"\xE6\x82\xBC", + "\x93\x8A"=>"\xE6\x8A\x95", + "\x93\x8B"=>"\xE6\x90\xAD", + "\x93\x8C"=>"\xE6\x9D\xB1", + "\x93\x8D"=>"\xE6\xA1\x83", + "\x93\x8E"=>"\xE6\xA2\xBC", + "\x93\x8F"=>"\xE6\xA3\x9F", + "\x93\x90"=>"\xE7\x9B\x97", + "\x93\x91"=>"\xE6\xB7\x98", + "\x93\x92"=>"\xE6\xB9\xAF", + "\x93\x93"=>"\xE6\xB6\x9B", + "\x93\x94"=>"\xE7\x81\xAF", + "\x93\x95"=>"\xE7\x87\x88", + "\x93\x96"=>"\xE5\xBD\x93", + "\x93\x97"=>"\xE7\x97\x98", + "\x93\x98"=>"\xE7\xA5\xB7", + "\x93\x99"=>"\xE7\xAD\x89", + "\x93\x9A"=>"\xE7\xAD\x94", + "\x93\x9B"=>"\xE7\xAD\x92", + "\x93\x9C"=>"\xE7\xB3\x96", + "\x93\x9D"=>"\xE7\xB5\xB1", + "\x93\x9E"=>"\xE5\x88\xB0", + "\x93\x9F"=>"\xE8\x91\xA3", + "\x93\xA0"=>"\xE8\x95\xA9", + "\x93\xA1"=>"\xE8\x97\xA4", + "\x93\xA2"=>"\xE8\xA8\x8E", + "\x93\xA3"=>"\xE8\xAC\x84", + "\x93\xA4"=>"\xE8\xB1\x86", + "\x93\xA5"=>"\xE8\xB8\x8F", + "\x93\xA6"=>"\xE9\x80\x83", + "\x93\xA7"=>"\xE9\x80\x8F", + "\x93\xA8"=>"\xE9\x90\x99", + "\x93\xA9"=>"\xE9\x99\xB6", + "\x93\xAA"=>"\xE9\xA0\xAD", + "\x93\xAB"=>"\xE9\xA8\xB0", + "\x93\xAC"=>"\xE9\x97\x98", + "\x93\xAD"=>"\xE5\x83\x8D", + "\x93\xAE"=>"\xE5\x8B\x95", + "\x93\xAF"=>"\xE5\x90\x8C", + "\x93\xB0"=>"\xE5\xA0\x82", + "\x93\xB1"=>"\xE5\xB0\x8E", + "\x93\xB2"=>"\xE6\x86\xA7", + "\x93\xB3"=>"\xE6\x92\x9E", + "\x93\xB4"=>"\xE6\xB4\x9E", + "\x93\xB5"=>"\xE7\x9E\xB3", + "\x93\xB6"=>"\xE7\xAB\xA5", + "\x93\xB7"=>"\xE8\x83\xB4", + "\x93\xB8"=>"\xE8\x90\x84", + "\x93\xB9"=>"\xE9\x81\x93", + "\x93\xBA"=>"\xE9\x8A\x85", + "\x93\xBB"=>"\xE5\xB3\xA0", + "\x93\xBC"=>"\xE9\xB4\x87", + "\x93\xBD"=>"\xE5\x8C\xBF", + "\x93\xBE"=>"\xE5\xBE\x97", + "\x93\xBF"=>"\xE5\xBE\xB3", + "\x93\xC0"=>"\xE6\xB6\x9C", + "\x93\xC1"=>"\xE7\x89\xB9", + "\x93\xC2"=>"\xE7\x9D\xA3", + "\x93\xC3"=>"\xE7\xA6\xBF", + "\x93\xC4"=>"\xE7\xAF\xA4", + "\x93\xC5"=>"\xE6\xAF\x92", + "\x93\xC6"=>"\xE7\x8B\xAC", + "\x93\xC7"=>"\xE8\xAA\xAD", + "\x93\xC8"=>"\xE6\xA0\x83", + "\x93\xC9"=>"\xE6\xA9\xA1", + "\x93\xCA"=>"\xE5\x87\xB8", + "\x93\xCB"=>"\xE7\xAA\x81", + "\x93\xCC"=>"\xE6\xA4\xB4", + "\x93\xCD"=>"\xE5\xB1\x8A", + "\x93\xCE"=>"\xE9\xB3\xB6", + "\x93\xCF"=>"\xE8\x8B\xAB", + "\x93\xD0"=>"\xE5\xAF\x85", + "\x93\xD1"=>"\xE9\x85\x89", + "\x93\xD2"=>"\xE7\x80\x9E", + "\x93\xD3"=>"\xE5\x99\xB8", + "\x93\xD4"=>"\xE5\xB1\xAF", + "\x93\xD5"=>"\xE6\x83\x87", + "\x93\xD6"=>"\xE6\x95\xA6", + "\x93\xD7"=>"\xE6\xB2\x8C", + "\x93\xD8"=>"\xE8\xB1\x9A", + "\x93\xD9"=>"\xE9\x81\x81", + "\x93\xDA"=>"\xE9\xA0\x93", + "\x93\xDB"=>"\xE5\x91\x91", + "\x93\xDC"=>"\xE6\x9B\x87", + "\x93\xDD"=>"\xE9\x88\x8D", + "\x93\xDE"=>"\xE5\xA5\x88", + "\x93\xDF"=>"\xE9\x82\xA3", + "\x93\xE0"=>"\xE5\x86\x85", + "\x93\xE1"=>"\xE4\xB9\x8D", + "\x93\xE2"=>"\xE5\x87\xAA", + "\x93\xE3"=>"\xE8\x96\x99", + "\x93\xE4"=>"\xE8\xAC\x8E", + "\x93\xE5"=>"\xE7\x81\x98", + "\x93\xE6"=>"\xE6\x8D\xBA", + "\x93\xE7"=>"\xE9\x8D\x8B", + "\x93\xE8"=>"\xE6\xA5\xA2", + "\x93\xE9"=>"\xE9\xA6\xB4", + "\x93\xEA"=>"\xE7\xB8\x84", + "\x93\xEB"=>"\xE7\x95\xB7", + "\x93\xEC"=>"\xE5\x8D\x97", + "\x93\xED"=>"\xE6\xA5\xA0", + "\x93\xEE"=>"\xE8\xBB\x9F", + "\x93\xEF"=>"\xE9\x9B\xA3", + "\x93\xF0"=>"\xE6\xB1\x9D", + "\x93\xF1"=>"\xE4\xBA\x8C", + "\x93\xF2"=>"\xE5\xB0\xBC", + "\x93\xF3"=>"\xE5\xBC\x90", + "\x93\xF4"=>"\xE8\xBF\xA9", + "\x93\xF5"=>"\xE5\x8C\x82", + "\x93\xF6"=>"\xE8\xB3\x91", + "\x93\xF7"=>"\xE8\x82\x89", + "\x93\xF8"=>"\xE8\x99\xB9", + "\x93\xF9"=>"\xE5\xBB\xBF", + "\x93\xFA"=>"\xE6\x97\xA5", + "\x93\xFB"=>"\xE4\xB9\xB3", + "\x93\xFC"=>"\xE5\x85\xA5", + "\x94\x40"=>"\xE5\xA6\x82", + "\x94\x41"=>"\xE5\xB0\xBF", + "\x94\x42"=>"\xE9\x9F\xAE", + "\x94\x43"=>"\xE4\xBB\xBB", + "\x94\x44"=>"\xE5\xA6\x8A", + "\x94\x45"=>"\xE5\xBF\x8D", + "\x94\x46"=>"\xE8\xAA\x8D", + "\x94\x47"=>"\xE6\xBF\xA1", + "\x94\x48"=>"\xE7\xA6\xB0", + "\x94\x49"=>"\xE7\xA5\xA2", + "\x94\x4A"=>"\xE5\xAF\xA7", + "\x94\x4B"=>"\xE8\x91\xB1", + "\x94\x4C"=>"\xE7\x8C\xAB", + "\x94\x4D"=>"\xE7\x86\xB1", + "\x94\x4E"=>"\xE5\xB9\xB4", + "\x94\x4F"=>"\xE5\xBF\xB5", + "\x94\x50"=>"\xE6\x8D\xBB", + "\x94\x51"=>"\xE6\x92\x9A", + "\x94\x52"=>"\xE7\x87\x83", + "\x94\x53"=>"\xE7\xB2\x98", + "\x94\x54"=>"\xE4\xB9\x83", + "\x94\x55"=>"\xE5\xBB\xBC", + "\x94\x56"=>"\xE4\xB9\x8B", + "\x94\x57"=>"\xE5\x9F\x9C", + "\x94\x58"=>"\xE5\x9A\xA2", + "\x94\x59"=>"\xE6\x82\xA9", + "\x94\x5A"=>"\xE6\xBF\x83", + "\x94\x5B"=>"\xE7\xB4\x8D", + "\x94\x5C"=>"\xE8\x83\xBD", + "\x94\x5D"=>"\xE8\x84\xB3", + "\x94\x5E"=>"\xE8\x86\xBF", + "\x94\x5F"=>"\xE8\xBE\xB2", + "\x94\x60"=>"\xE8\xA6\x97", + "\x94\x61"=>"\xE8\x9A\xA4", + "\x94\x62"=>"\xE5\xB7\xB4", + "\x94\x63"=>"\xE6\x8A\x8A", + "\x94\x64"=>"\xE6\x92\xAD", + "\x94\x65"=>"\xE8\xA6\x87", + "\x94\x66"=>"\xE6\x9D\xB7", + "\x94\x67"=>"\xE6\xB3\xA2", + "\x94\x68"=>"\xE6\xB4\xBE", + "\x94\x69"=>"\xE7\x90\xB6", + "\x94\x6A"=>"\xE7\xA0\xB4", + "\x94\x6B"=>"\xE5\xA9\x86", + "\x94\x6C"=>"\xE7\xBD\xB5", + "\x94\x6D"=>"\xE8\x8A\xAD", + "\x94\x6E"=>"\xE9\xA6\xAC", + "\x94\x6F"=>"\xE4\xBF\xB3", + "\x94\x70"=>"\xE5\xBB\x83", + "\x94\x71"=>"\xE6\x8B\x9D", + "\x94\x72"=>"\xE6\x8E\x92", + "\x94\x73"=>"\xE6\x95\x97", + "\x94\x74"=>"\xE6\x9D\xAF", + "\x94\x75"=>"\xE7\x9B\x83", + "\x94\x76"=>"\xE7\x89\x8C", + "\x94\x77"=>"\xE8\x83\x8C", + "\x94\x78"=>"\xE8\x82\xBA", + "\x94\x79"=>"\xE8\xBC\xA9", + "\x94\x7A"=>"\xE9\x85\x8D", + "\x94\x7B"=>"\xE5\x80\x8D", + "\x94\x7C"=>"\xE5\x9F\xB9", + "\x94\x7D"=>"\xE5\xAA\x92", + "\x94\x7E"=>"\xE6\xA2\x85", + "\x94\x80"=>"\xE6\xA5\xB3", + "\x94\x81"=>"\xE7\x85\xA4", + "\x94\x82"=>"\xE7\x8B\xBD", + "\x94\x83"=>"\xE8\xB2\xB7", + "\x94\x84"=>"\xE5\xA3\xB2", + "\x94\x85"=>"\xE8\xB3\xA0", + "\x94\x86"=>"\xE9\x99\xAA", + "\x94\x87"=>"\xE9\x80\x99", + "\x94\x88"=>"\xE8\x9D\xBF", + "\x94\x89"=>"\xE7\xA7\xA4", + "\x94\x8A"=>"\xE7\x9F\xA7", + "\x94\x8B"=>"\xE8\x90\xA9", + "\x94\x8C"=>"\xE4\xBC\xAF", + "\x94\x8D"=>"\xE5\x89\xA5", + "\x94\x8E"=>"\xE5\x8D\x9A", + "\x94\x8F"=>"\xE6\x8B\x8D", + "\x94\x90"=>"\xE6\x9F\x8F", + "\x94\x91"=>"\xE6\xB3\x8A", + "\x94\x92"=>"\xE7\x99\xBD", + "\x94\x93"=>"\xE7\xAE\x94", + "\x94\x94"=>"\xE7\xB2\x95", + "\x94\x95"=>"\xE8\x88\xB6", + "\x94\x96"=>"\xE8\x96\x84", + "\x94\x97"=>"\xE8\xBF\xAB", + "\x94\x98"=>"\xE6\x9B\x9D", + "\x94\x99"=>"\xE6\xBC\xA0", + "\x94\x9A"=>"\xE7\x88\x86", + "\x94\x9B"=>"\xE7\xB8\x9B", + "\x94\x9C"=>"\xE8\x8E\xAB", + "\x94\x9D"=>"\xE9\xA7\x81", + "\x94\x9E"=>"\xE9\xBA\xA6", + "\x94\x9F"=>"\xE5\x87\xBD", + "\x94\xA0"=>"\xE7\xAE\xB1", + "\x94\xA1"=>"\xE7\xA1\xB2", + "\x94\xA2"=>"\xE7\xAE\xB8", + "\x94\xA3"=>"\xE8\x82\x87", + "\x94\xA4"=>"\xE7\xAD\x88", + "\x94\xA5"=>"\xE6\xAB\xA8", + "\x94\xA6"=>"\xE5\xB9\xA1", + "\x94\xA7"=>"\xE8\x82\x8C", + "\x94\xA8"=>"\xE7\x95\x91", + "\x94\xA9"=>"\xE7\x95\xA0", + "\x94\xAA"=>"\xE5\x85\xAB", + "\x94\xAB"=>"\xE9\x89\xA2", + "\x94\xAC"=>"\xE6\xBA\x8C", + "\x94\xAD"=>"\xE7\x99\xBA", + "\x94\xAE"=>"\xE9\x86\x97", + "\x94\xAF"=>"\xE9\xAB\xAA", + "\x94\xB0"=>"\xE4\xBC\x90", + "\x94\xB1"=>"\xE7\xBD\xB0", + "\x94\xB2"=>"\xE6\x8A\x9C", + "\x94\xB3"=>"\xE7\xAD\x8F", + "\x94\xB4"=>"\xE9\x96\xA5", + "\x94\xB5"=>"\xE9\xB3\xA9", + "\x94\xB6"=>"\xE5\x99\xBA", + "\x94\xB7"=>"\xE5\xA1\x99", + "\x94\xB8"=>"\xE8\x9B\xA4", + "\x94\xB9"=>"\xE9\x9A\xBC", + "\x94\xBA"=>"\xE4\xBC\xB4", + "\x94\xBB"=>"\xE5\x88\xA4", + "\x94\xBC"=>"\xE5\x8D\x8A", + "\x94\xBD"=>"\xE5\x8F\x8D", + "\x94\xBE"=>"\xE5\x8F\x9B", + "\x94\xBF"=>"\xE5\xB8\x86", + "\x94\xC0"=>"\xE6\x90\xAC", + "\x94\xC1"=>"\xE6\x96\x91", + "\x94\xC2"=>"\xE6\x9D\xBF", + "\x94\xC3"=>"\xE6\xB0\xBE", + "\x94\xC4"=>"\xE6\xB1\x8E", + "\x94\xC5"=>"\xE7\x89\x88", + "\x94\xC6"=>"\xE7\x8A\xAF", + "\x94\xC7"=>"\xE7\x8F\xAD", + "\x94\xC8"=>"\xE7\x95\x94", + "\x94\xC9"=>"\xE7\xB9\x81", + "\x94\xCA"=>"\xE8\x88\xAC", + "\x94\xCB"=>"\xE8\x97\xA9", + "\x94\xCC"=>"\xE8\xB2\xA9", + "\x94\xCD"=>"\xE7\xAF\x84", + "\x94\xCE"=>"\xE9\x87\x86", + "\x94\xCF"=>"\xE7\x85\xA9", + "\x94\xD0"=>"\xE9\xA0\x92", + "\x94\xD1"=>"\xE9\xA3\xAF", + "\x94\xD2"=>"\xE6\x8C\xBD", + "\x94\xD3"=>"\xE6\x99\xA9", + "\x94\xD4"=>"\xE7\x95\xAA", + "\x94\xD5"=>"\xE7\x9B\xA4", + "\x94\xD6"=>"\xE7\xA3\x90", + "\x94\xD7"=>"\xE8\x95\x83", + "\x94\xD8"=>"\xE8\x9B\xAE", + "\x94\xD9"=>"\xE5\x8C\xAA", + "\x94\xDA"=>"\xE5\x8D\x91", + "\x94\xDB"=>"\xE5\x90\xA6", + "\x94\xDC"=>"\xE5\xA6\x83", + "\x94\xDD"=>"\xE5\xBA\x87", + "\x94\xDE"=>"\xE5\xBD\xBC", + "\x94\xDF"=>"\xE6\x82\xB2", + "\x94\xE0"=>"\xE6\x89\x89", + "\x94\xE1"=>"\xE6\x89\xB9", + "\x94\xE2"=>"\xE6\x8A\xAB", + "\x94\xE3"=>"\xE6\x96\x90", + "\x94\xE4"=>"\xE6\xAF\x94", + "\x94\xE5"=>"\xE6\xB3\x8C", + "\x94\xE6"=>"\xE7\x96\xB2", + "\x94\xE7"=>"\xE7\x9A\xAE", + "\x94\xE8"=>"\xE7\xA2\x91", + "\x94\xE9"=>"\xE7\xA7\x98", + "\x94\xEA"=>"\xE7\xB7\x8B", + "\x94\xEB"=>"\xE7\xBD\xB7", + "\x94\xEC"=>"\xE8\x82\xA5", + "\x94\xED"=>"\xE8\xA2\xAB", + "\x94\xEE"=>"\xE8\xAA\xB9", + "\x94\xEF"=>"\xE8\xB2\xBB", + "\x94\xF0"=>"\xE9\x81\xBF", + "\x94\xF1"=>"\xE9\x9D\x9E", + "\x94\xF2"=>"\xE9\xA3\x9B", + "\x94\xF3"=>"\xE6\xA8\x8B", + "\x94\xF4"=>"\xE7\xB0\xB8", + "\x94\xF5"=>"\xE5\x82\x99", + "\x94\xF6"=>"\xE5\xB0\xBE", + "\x94\xF7"=>"\xE5\xBE\xAE", + "\x94\xF8"=>"\xE6\x9E\x87", + "\x94\xF9"=>"\xE6\xAF\x98", + "\x94\xFA"=>"\xE7\x90\xB5", + "\x94\xFB"=>"\xE7\x9C\x89", + "\x94\xFC"=>"\xE7\xBE\x8E", + "\x95\x40"=>"\xE9\xBC\xBB", + "\x95\x41"=>"\xE6\x9F\x8A", + "\x95\x42"=>"\xE7\xA8\x97", + "\x95\x43"=>"\xE5\x8C\xB9", + "\x95\x44"=>"\xE7\x96\x8B", + "\x95\x45"=>"\xE9\xAB\xAD", + "\x95\x46"=>"\xE5\xBD\xA6", + "\x95\x47"=>"\xE8\x86\x9D", + "\x95\x48"=>"\xE8\x8F\xB1", + "\x95\x49"=>"\xE8\x82\x98", + "\x95\x4A"=>"\xE5\xBC\xBC", + "\x95\x4B"=>"\xE5\xBF\x85", + "\x95\x4C"=>"\xE7\x95\xA2", + "\x95\x4D"=>"\xE7\xAD\x86", + "\x95\x4E"=>"\xE9\x80\xBC", + "\x95\x4F"=>"\xE6\xA1\xA7", + "\x95\x50"=>"\xE5\xA7\xAB", + "\x95\x51"=>"\xE5\xAA\x9B", + "\x95\x52"=>"\xE7\xB4\x90", + "\x95\x53"=>"\xE7\x99\xBE", + "\x95\x54"=>"\xE8\xAC\xAC", + "\x95\x55"=>"\xE4\xBF\xB5", + "\x95\x56"=>"\xE5\xBD\xAA", + "\x95\x57"=>"\xE6\xA8\x99", + "\x95\x58"=>"\xE6\xB0\xB7", + "\x95\x59"=>"\xE6\xBC\x82", + "\x95\x5A"=>"\xE7\x93\xA2", + "\x95\x5B"=>"\xE7\xA5\xA8", + "\x95\x5C"=>"\xE8\xA1\xA8", + "\x95\x5D"=>"\xE8\xA9\x95", + "\x95\x5E"=>"\xE8\xB1\xB9", + "\x95\x5F"=>"\xE5\xBB\x9F", + "\x95\x60"=>"\xE6\x8F\x8F", + "\x95\x61"=>"\xE7\x97\x85", + "\x95\x62"=>"\xE7\xA7\x92", + "\x95\x63"=>"\xE8\x8B\x97", + "\x95\x64"=>"\xE9\x8C\xA8", + "\x95\x65"=>"\xE9\x8B\xB2", + "\x95\x66"=>"\xE8\x92\x9C", + "\x95\x67"=>"\xE8\x9B\xAD", + "\x95\x68"=>"\xE9\xB0\xAD", + "\x95\x69"=>"\xE5\x93\x81", + "\x95\x6A"=>"\xE5\xBD\xAC", + "\x95\x6B"=>"\xE6\x96\x8C", + "\x95\x6C"=>"\xE6\xB5\x9C", + "\x95\x6D"=>"\xE7\x80\x95", + "\x95\x6E"=>"\xE8\xB2\xA7", + "\x95\x6F"=>"\xE8\xB3\x93", + "\x95\x70"=>"\xE9\xA0\xBB", + "\x95\x71"=>"\xE6\x95\x8F", + "\x95\x72"=>"\xE7\x93\xB6", + "\x95\x73"=>"\xE4\xB8\x8D", + "\x95\x74"=>"\xE4\xBB\x98", + "\x95\x75"=>"\xE5\x9F\xA0", + "\x95\x76"=>"\xE5\xA4\xAB", + "\x95\x77"=>"\xE5\xA9\xA6", + "\x95\x78"=>"\xE5\xAF\x8C", + "\x95\x79"=>"\xE5\x86\xA8", + "\x95\x7A"=>"\xE5\xB8\x83", + "\x95\x7B"=>"\xE5\xBA\x9C", + "\x95\x7C"=>"\xE6\x80\x96", + "\x95\x7D"=>"\xE6\x89\xB6", + "\x95\x7E"=>"\xE6\x95\xB7", + "\x95\x80"=>"\xE6\x96\xA7", + "\x95\x81"=>"\xE6\x99\xAE", + "\x95\x82"=>"\xE6\xB5\xAE", + "\x95\x83"=>"\xE7\x88\xB6", + "\x95\x84"=>"\xE7\xAC\xA6", + "\x95\x85"=>"\xE8\x85\x90", + "\x95\x86"=>"\xE8\x86\x9A", + "\x95\x87"=>"\xE8\x8A\x99", + "\x95\x88"=>"\xE8\xAD\x9C", + "\x95\x89"=>"\xE8\xB2\xA0", + "\x95\x8A"=>"\xE8\xB3\xA6", + "\x95\x8B"=>"\xE8\xB5\xB4", + "\x95\x8C"=>"\xE9\x98\x9C", + "\x95\x8D"=>"\xE9\x99\x84", + "\x95\x8E"=>"\xE4\xBE\xAE", + "\x95\x8F"=>"\xE6\x92\xAB", + "\x95\x90"=>"\xE6\xAD\xA6", + "\x95\x91"=>"\xE8\x88\x9E", + "\x95\x92"=>"\xE8\x91\xA1", + "\x95\x93"=>"\xE8\x95\xAA", + "\x95\x94"=>"\xE9\x83\xA8", + "\x95\x95"=>"\xE5\xB0\x81", + "\x95\x96"=>"\xE6\xA5\x93", + "\x95\x97"=>"\xE9\xA2\xA8", + "\x95\x98"=>"\xE8\x91\xBA", + "\x95\x99"=>"\xE8\x95\x97", + "\x95\x9A"=>"\xE4\xBC\x8F", + "\x95\x9B"=>"\xE5\x89\xAF", + "\x95\x9C"=>"\xE5\xBE\xA9", + "\x95\x9D"=>"\xE5\xB9\x85", + "\x95\x9E"=>"\xE6\x9C\x8D", + "\x95\x9F"=>"\xE7\xA6\x8F", + "\x95\xA0"=>"\xE8\x85\xB9", + "\x95\xA1"=>"\xE8\xA4\x87", + "\x95\xA2"=>"\xE8\xA6\x86", + "\x95\xA3"=>"\xE6\xB7\xB5", + "\x95\xA4"=>"\xE5\xBC\x97", + "\x95\xA5"=>"\xE6\x89\x95", + "\x95\xA6"=>"\xE6\xB2\xB8", + "\x95\xA7"=>"\xE4\xBB\x8F", + "\x95\xA8"=>"\xE7\x89\xA9", + "\x95\xA9"=>"\xE9\xAE\x92", + "\x95\xAA"=>"\xE5\x88\x86", + "\x95\xAB"=>"\xE5\x90\xBB", + "\x95\xAC"=>"\xE5\x99\xB4", + "\x95\xAD"=>"\xE5\xA2\xB3", + "\x95\xAE"=>"\xE6\x86\xA4", + "\x95\xAF"=>"\xE6\x89\xAE", + "\x95\xB0"=>"\xE7\x84\x9A", + "\x95\xB1"=>"\xE5\xA5\xAE", + "\x95\xB2"=>"\xE7\xB2\x89", + "\x95\xB3"=>"\xE7\xB3\x9E", + "\x95\xB4"=>"\xE7\xB4\x9B", + "\x95\xB5"=>"\xE9\x9B\xB0", + "\x95\xB6"=>"\xE6\x96\x87", + "\x95\xB7"=>"\xE8\x81\x9E", + "\x95\xB8"=>"\xE4\xB8\x99", + "\x95\xB9"=>"\xE4\xBD\xB5", + "\x95\xBA"=>"\xE5\x85\xB5", + "\x95\xBB"=>"\xE5\xA1\x80", + "\x95\xBC"=>"\xE5\xB9\xA3", + "\x95\xBD"=>"\xE5\xB9\xB3", + "\x95\xBE"=>"\xE5\xBC\x8A", + "\x95\xBF"=>"\xE6\x9F\x84", + "\x95\xC0"=>"\xE4\xB8\xA6", + "\x95\xC1"=>"\xE8\x94\xBD", + "\x95\xC2"=>"\xE9\x96\x89", + "\x95\xC3"=>"\xE9\x99\x9B", + "\x95\xC4"=>"\xE7\xB1\xB3", + "\x95\xC5"=>"\xE9\xA0\x81", + "\x95\xC6"=>"\xE5\x83\xBB", + "\x95\xC7"=>"\xE5\xA3\x81", + "\x95\xC8"=>"\xE7\x99\x96", + "\x95\xC9"=>"\xE7\xA2\xA7", + "\x95\xCA"=>"\xE5\x88\xA5", + "\x95\xCB"=>"\xE7\x9E\xA5", + "\x95\xCC"=>"\xE8\x94\x91", + "\x95\xCD"=>"\xE7\xAE\x86", + "\x95\xCE"=>"\xE5\x81\x8F", + "\x95\xCF"=>"\xE5\xA4\x89", + "\x95\xD0"=>"\xE7\x89\x87", + "\x95\xD1"=>"\xE7\xAF\x87", + "\x95\xD2"=>"\xE7\xB7\xA8", + "\x95\xD3"=>"\xE8\xBE\xBA", + "\x95\xD4"=>"\xE8\xBF\x94", + "\x95\xD5"=>"\xE9\x81\x8D", + "\x95\xD6"=>"\xE4\xBE\xBF", + "\x95\xD7"=>"\xE5\x8B\x89", + "\x95\xD8"=>"\xE5\xA8\xA9", + "\x95\xD9"=>"\xE5\xBC\x81", + "\x95\xDA"=>"\xE9\x9E\xAD", + "\x95\xDB"=>"\xE4\xBF\x9D", + "\x95\xDC"=>"\xE8\x88\x97", + "\x95\xDD"=>"\xE9\x8B\xAA", + "\x95\xDE"=>"\xE5\x9C\x83", + "\x95\xDF"=>"\xE6\x8D\x95", + "\x95\xE0"=>"\xE6\xAD\xA9", + "\x95\xE1"=>"\xE7\x94\xAB", + "\x95\xE2"=>"\xE8\xA3\x9C", + "\x95\xE3"=>"\xE8\xBC\x94", + "\x95\xE4"=>"\xE7\xA9\x82", + "\x95\xE5"=>"\xE5\x8B\x9F", + "\x95\xE6"=>"\xE5\xA2\x93", + "\x95\xE7"=>"\xE6\x85\x95", + "\x95\xE8"=>"\xE6\x88\x8A", + "\x95\xE9"=>"\xE6\x9A\xAE", + "\x95\xEA"=>"\xE6\xAF\x8D", + "\x95\xEB"=>"\xE7\xB0\xBF", + "\x95\xEC"=>"\xE8\x8F\xA9", + "\x95\xED"=>"\xE5\x80\xA3", + "\x95\xEE"=>"\xE4\xBF\xB8", + "\x95\xEF"=>"\xE5\x8C\x85", + "\x95\xF0"=>"\xE5\x91\x86", + "\x95\xF1"=>"\xE5\xA0\xB1", + "\x95\xF2"=>"\xE5\xA5\x89", + "\x95\xF3"=>"\xE5\xAE\x9D", + "\x95\xF4"=>"\xE5\xB3\xB0", + "\x95\xF5"=>"\xE5\xB3\xAF", + "\x95\xF6"=>"\xE5\xB4\xA9", + "\x95\xF7"=>"\xE5\xBA\x96", + "\x95\xF8"=>"\xE6\x8A\xB1", + "\x95\xF9"=>"\xE6\x8D\xA7", + "\x95\xFA"=>"\xE6\x94\xBE", + "\x95\xFB"=>"\xE6\x96\xB9", + "\x95\xFC"=>"\xE6\x9C\x8B", + "\x96\x40"=>"\xE6\xB3\x95", + "\x96\x41"=>"\xE6\xB3\xA1", + "\x96\x42"=>"\xE7\x83\xB9", + "\x96\x43"=>"\xE7\xA0\xB2", + "\x96\x44"=>"\xE7\xB8\xAB", + "\x96\x45"=>"\xE8\x83\x9E", + "\x96\x46"=>"\xE8\x8A\xB3", + "\x96\x47"=>"\xE8\x90\x8C", + "\x96\x48"=>"\xE8\x93\xAC", + "\x96\x49"=>"\xE8\x9C\x82", + "\x96\x4A"=>"\xE8\xA4\x92", + "\x96\x4B"=>"\xE8\xA8\xAA", + "\x96\x4C"=>"\xE8\xB1\x8A", + "\x96\x4D"=>"\xE9\x82\xA6", + "\x96\x4E"=>"\xE9\x8B\x92", + "\x96\x4F"=>"\xE9\xA3\xBD", + "\x96\x50"=>"\xE9\xB3\xB3", + "\x96\x51"=>"\xE9\xB5\xAC", + "\x96\x52"=>"\xE4\xB9\x8F", + "\x96\x53"=>"\xE4\xBA\xA1", + "\x96\x54"=>"\xE5\x82\x8D", + "\x96\x55"=>"\xE5\x89\x96", + "\x96\x56"=>"\xE5\x9D\x8A", + "\x96\x57"=>"\xE5\xA6\xA8", + "\x96\x58"=>"\xE5\xB8\xBD", + "\x96\x59"=>"\xE5\xBF\x98", + "\x96\x5A"=>"\xE5\xBF\x99", + "\x96\x5B"=>"\xE6\x88\xBF", + "\x96\x5C"=>"\xE6\x9A\xB4", + "\x96\x5D"=>"\xE6\x9C\x9B", + "\x96\x5E"=>"\xE6\x9F\x90", + "\x96\x5F"=>"\xE6\xA3\x92", + "\x96\x60"=>"\xE5\x86\x92", + "\x96\x61"=>"\xE7\xB4\xA1", + "\x96\x62"=>"\xE8\x82\xAA", + "\x96\x63"=>"\xE8\x86\xA8", + "\x96\x64"=>"\xE8\xAC\x80", + "\x96\x65"=>"\xE8\xB2\x8C", + "\x96\x66"=>"\xE8\xB2\xBF", + "\x96\x67"=>"\xE9\x89\xBE", + "\x96\x68"=>"\xE9\x98\xB2", + "\x96\x69"=>"\xE5\x90\xA0", + "\x96\x6A"=>"\xE9\xA0\xAC", + "\x96\x6B"=>"\xE5\x8C\x97", + "\x96\x6C"=>"\xE5\x83\x95", + "\x96\x6D"=>"\xE5\x8D\x9C", + "\x96\x6E"=>"\xE5\xA2\xA8", + "\x96\x6F"=>"\xE6\x92\xB2", + "\x96\x70"=>"\xE6\x9C\xB4", + "\x96\x71"=>"\xE7\x89\xA7", + "\x96\x72"=>"\xE7\x9D\xA6", + "\x96\x73"=>"\xE7\xA9\x86", + "\x96\x74"=>"\xE9\x87\xA6", + "\x96\x75"=>"\xE5\x8B\x83", + "\x96\x76"=>"\xE6\xB2\xA1", + "\x96\x77"=>"\xE6\xAE\x86", + "\x96\x78"=>"\xE5\xA0\x80", + "\x96\x79"=>"\xE5\xB9\x8C", + "\x96\x7A"=>"\xE5\xA5\x94", + "\x96\x7B"=>"\xE6\x9C\xAC", + "\x96\x7C"=>"\xE7\xBF\xBB", + "\x96\x7D"=>"\xE5\x87\xA1", + "\x96\x7E"=>"\xE7\x9B\x86", + "\x96\x80"=>"\xE6\x91\xA9", + "\x96\x81"=>"\xE7\xA3\xA8", + "\x96\x82"=>"\xE9\xAD\x94", + "\x96\x83"=>"\xE9\xBA\xBB", + "\x96\x84"=>"\xE5\x9F\x8B", + "\x96\x85"=>"\xE5\xA6\xB9", + "\x96\x86"=>"\xE6\x98\xA7", + "\x96\x87"=>"\xE6\x9E\x9A", + "\x96\x88"=>"\xE6\xAF\x8E", + "\x96\x89"=>"\xE5\x93\xA9", + "\x96\x8A"=>"\xE6\xA7\x99", + "\x96\x8B"=>"\xE5\xB9\x95", + "\x96\x8C"=>"\xE8\x86\x9C", + "\x96\x8D"=>"\xE6\x9E\x95", + "\x96\x8E"=>"\xE9\xAE\xAA", + "\x96\x8F"=>"\xE6\x9F\xBE", + "\x96\x90"=>"\xE9\xB1\x92", + "\x96\x91"=>"\xE6\xA1\x9D", + "\x96\x92"=>"\xE4\xBA\xA6", + "\x96\x93"=>"\xE4\xBF\xA3", + "\x96\x94"=>"\xE5\x8F\x88", + "\x96\x95"=>"\xE6\x8A\xB9", + "\x96\x96"=>"\xE6\x9C\xAB", + "\x96\x97"=>"\xE6\xB2\xAB", + "\x96\x98"=>"\xE8\xBF\x84", + "\x96\x99"=>"\xE4\xBE\xAD", + "\x96\x9A"=>"\xE7\xB9\xAD", + "\x96\x9B"=>"\xE9\xBA\xBF", + "\x96\x9C"=>"\xE4\xB8\x87", + "\x96\x9D"=>"\xE6\x85\xA2", + "\x96\x9E"=>"\xE6\xBA\x80", + "\x96\x9F"=>"\xE6\xBC\xAB", + "\x96\xA0"=>"\xE8\x94\x93", + "\x96\xA1"=>"\xE5\x91\xB3", + "\x96\xA2"=>"\xE6\x9C\xAA", + "\x96\xA3"=>"\xE9\xAD\x85", + "\x96\xA4"=>"\xE5\xB7\xB3", + "\x96\xA5"=>"\xE7\xAE\x95", + "\x96\xA6"=>"\xE5\xB2\xAC", + "\x96\xA7"=>"\xE5\xAF\x86", + "\x96\xA8"=>"\xE8\x9C\x9C", + "\x96\xA9"=>"\xE6\xB9\x8A", + "\x96\xAA"=>"\xE8\x93\x91", + "\x96\xAB"=>"\xE7\xA8\x94", + "\x96\xAC"=>"\xE8\x84\x88", + "\x96\xAD"=>"\xE5\xA6\x99", + "\x96\xAE"=>"\xE7\xB2\x8D", + "\x96\xAF"=>"\xE6\xB0\x91", + "\x96\xB0"=>"\xE7\x9C\xA0", + "\x96\xB1"=>"\xE5\x8B\x99", + "\x96\xB2"=>"\xE5\xA4\xA2", + "\x96\xB3"=>"\xE7\x84\xA1", + "\x96\xB4"=>"\xE7\x89\x9F", + "\x96\xB5"=>"\xE7\x9F\x9B", + "\x96\xB6"=>"\xE9\x9C\xA7", + "\x96\xB7"=>"\xE9\xB5\xA1", + "\x96\xB8"=>"\xE6\xA4\x8B", + "\x96\xB9"=>"\xE5\xA9\xBF", + "\x96\xBA"=>"\xE5\xA8\x98", + "\x96\xBB"=>"\xE5\x86\xA5", + "\x96\xBC"=>"\xE5\x90\x8D", + "\x96\xBD"=>"\xE5\x91\xBD", + "\x96\xBE"=>"\xE6\x98\x8E", + "\x96\xBF"=>"\xE7\x9B\x9F", + "\x96\xC0"=>"\xE8\xBF\xB7", + "\x96\xC1"=>"\xE9\x8A\x98", + "\x96\xC2"=>"\xE9\xB3\xB4", + "\x96\xC3"=>"\xE5\xA7\xAA", + "\x96\xC4"=>"\xE7\x89\x9D", + "\x96\xC5"=>"\xE6\xBB\x85", + "\x96\xC6"=>"\xE5\x85\x8D", + "\x96\xC7"=>"\xE6\xA3\x89", + "\x96\xC8"=>"\xE7\xB6\xBF", + "\x96\xC9"=>"\xE7\xB7\xAC", + "\x96\xCA"=>"\xE9\x9D\xA2", + "\x96\xCB"=>"\xE9\xBA\xBA", + "\x96\xCC"=>"\xE6\x91\xB8", + "\x96\xCD"=>"\xE6\xA8\xA1", + "\x96\xCE"=>"\xE8\x8C\x82", + "\x96\xCF"=>"\xE5\xA6\x84", + "\x96\xD0"=>"\xE5\xAD\x9F", + "\x96\xD1"=>"\xE6\xAF\x9B", + "\x96\xD2"=>"\xE7\x8C\x9B", + "\x96\xD3"=>"\xE7\x9B\xB2", + "\x96\xD4"=>"\xE7\xB6\xB2", + "\x96\xD5"=>"\xE8\x80\x97", + "\x96\xD6"=>"\xE8\x92\x99", + "\x96\xD7"=>"\xE5\x84\xB2", + "\x96\xD8"=>"\xE6\x9C\xA8", + "\x96\xD9"=>"\xE9\xBB\x99", + "\x96\xDA"=>"\xE7\x9B\xAE", + "\x96\xDB"=>"\xE6\x9D\xA2", + "\x96\xDC"=>"\xE5\x8B\xBF", + "\x96\xDD"=>"\xE9\xA4\x85", + "\x96\xDE"=>"\xE5\xB0\xA4", + "\x96\xDF"=>"\xE6\x88\xBB", + "\x96\xE0"=>"\xE7\xB1\xBE", + "\x96\xE1"=>"\xE8\xB2\xB0", + "\x96\xE2"=>"\xE5\x95\x8F", + "\x96\xE3"=>"\xE6\x82\xB6", + "\x96\xE4"=>"\xE7\xB4\x8B", + "\x96\xE5"=>"\xE9\x96\x80", + "\x96\xE6"=>"\xE5\x8C\x81", + "\x96\xE7"=>"\xE4\xB9\x9F", + "\x96\xE8"=>"\xE5\x86\xB6", + "\x96\xE9"=>"\xE5\xA4\x9C", + "\x96\xEA"=>"\xE7\x88\xBA", + "\x96\xEB"=>"\xE8\x80\xB6", + "\x96\xEC"=>"\xE9\x87\x8E", + "\x96\xED"=>"\xE5\xBC\xA5", + "\x96\xEE"=>"\xE7\x9F\xA2", + "\x96\xEF"=>"\xE5\x8E\x84", + "\x96\xF0"=>"\xE5\xBD\xB9", + "\x96\xF1"=>"\xE7\xB4\x84", + "\x96\xF2"=>"\xE8\x96\xAC", + "\x96\xF3"=>"\xE8\xA8\xB3", + "\x96\xF4"=>"\xE8\xBA\x8D", + "\x96\xF5"=>"\xE9\x9D\x96", + "\x96\xF6"=>"\xE6\x9F\xB3", + "\x96\xF7"=>"\xE8\x96\xAE", + "\x96\xF8"=>"\xE9\x91\x93", + "\x96\xF9"=>"\xE6\x84\x89", + "\x96\xFA"=>"\xE6\x84\x88", + "\x96\xFB"=>"\xE6\xB2\xB9", + "\x96\xFC"=>"\xE7\x99\x92", + "\x97\x40"=>"\xE8\xAB\xAD", + "\x97\x41"=>"\xE8\xBC\xB8", + "\x97\x42"=>"\xE5\x94\xAF", + "\x97\x43"=>"\xE4\xBD\x91", + "\x97\x44"=>"\xE5\x84\xAA", + "\x97\x45"=>"\xE5\x8B\x87", + "\x97\x46"=>"\xE5\x8F\x8B", + "\x97\x47"=>"\xE5\xAE\xA5", + "\x97\x48"=>"\xE5\xB9\xBD", + "\x97\x49"=>"\xE6\x82\xA0", + "\x97\x4A"=>"\xE6\x86\x82", + "\x97\x4B"=>"\xE6\x8F\x96", + "\x97\x4C"=>"\xE6\x9C\x89", + "\x97\x4D"=>"\xE6\x9F\x9A", + "\x97\x4E"=>"\xE6\xB9\xA7", + "\x97\x4F"=>"\xE6\xB6\x8C", + "\x97\x50"=>"\xE7\x8C\xB6", + "\x97\x51"=>"\xE7\x8C\xB7", + "\x97\x52"=>"\xE7\x94\xB1", + "\x97\x53"=>"\xE7\xA5\x90", + "\x97\x54"=>"\xE8\xA3\x95", + "\x97\x55"=>"\xE8\xAA\x98", + "\x97\x56"=>"\xE9\x81\x8A", + "\x97\x57"=>"\xE9\x82\x91", + "\x97\x58"=>"\xE9\x83\xB5", + "\x97\x59"=>"\xE9\x9B\x84", + "\x97\x5A"=>"\xE8\x9E\x8D", + "\x97\x5B"=>"\xE5\xA4\x95", + "\x97\x5C"=>"\xE4\xBA\x88", + "\x97\x5D"=>"\xE4\xBD\x99", + "\x97\x5E"=>"\xE4\xB8\x8E", + "\x97\x5F"=>"\xE8\xAA\x89", + "\x97\x60"=>"\xE8\xBC\xBF", + "\x97\x61"=>"\xE9\xA0\x90", + "\x97\x62"=>"\xE5\x82\xAD", + "\x97\x63"=>"\xE5\xB9\xBC", + "\x97\x64"=>"\xE5\xA6\x96", + "\x97\x65"=>"\xE5\xAE\xB9", + "\x97\x66"=>"\xE5\xBA\xB8", + "\x97\x67"=>"\xE6\x8F\x9A", + "\x97\x68"=>"\xE6\x8F\xBA", + "\x97\x69"=>"\xE6\x93\x81", + "\x97\x6A"=>"\xE6\x9B\x9C", + "\x97\x6B"=>"\xE6\xA5\x8A", + "\x97\x6C"=>"\xE6\xA7\x98", + "\x97\x6D"=>"\xE6\xB4\x8B", + "\x97\x6E"=>"\xE6\xBA\xB6", + "\x97\x6F"=>"\xE7\x86\x94", + "\x97\x70"=>"\xE7\x94\xA8", + "\x97\x71"=>"\xE7\xAA\xAF", + "\x97\x72"=>"\xE7\xBE\x8A", + "\x97\x73"=>"\xE8\x80\x80", + "\x97\x74"=>"\xE8\x91\x89", + "\x97\x75"=>"\xE8\x93\x89", + "\x97\x76"=>"\xE8\xA6\x81", + "\x97\x77"=>"\xE8\xAC\xA1", + "\x97\x78"=>"\xE8\xB8\x8A", + "\x97\x79"=>"\xE9\x81\xA5", + "\x97\x7A"=>"\xE9\x99\xBD", + "\x97\x7B"=>"\xE9\xA4\x8A", + "\x97\x7C"=>"\xE6\x85\xBE", + "\x97\x7D"=>"\xE6\x8A\x91", + "\x97\x7E"=>"\xE6\xAC\xB2", + "\x97\x80"=>"\xE6\xB2\x83", + "\x97\x81"=>"\xE6\xB5\xB4", + "\x97\x82"=>"\xE7\xBF\x8C", + "\x97\x83"=>"\xE7\xBF\xBC", + "\x97\x84"=>"\xE6\xB7\x80", + "\x97\x85"=>"\xE7\xBE\x85", + "\x97\x86"=>"\xE8\x9E\xBA", + "\x97\x87"=>"\xE8\xA3\xB8", + "\x97\x88"=>"\xE6\x9D\xA5", + "\x97\x89"=>"\xE8\x8E\xB1", + "\x97\x8A"=>"\xE9\xA0\xBC", + "\x97\x8B"=>"\xE9\x9B\xB7", + "\x97\x8C"=>"\xE6\xB4\x9B", + "\x97\x8D"=>"\xE7\xB5\xA1", + "\x97\x8E"=>"\xE8\x90\xBD", + "\x97\x8F"=>"\xE9\x85\xAA", + "\x97\x90"=>"\xE4\xB9\xB1", + "\x97\x91"=>"\xE5\x8D\xB5", + "\x97\x92"=>"\xE5\xB5\x90", + "\x97\x93"=>"\xE6\xAC\x84", + "\x97\x94"=>"\xE6\xBF\xAB", + "\x97\x95"=>"\xE8\x97\x8D", + "\x97\x96"=>"\xE8\x98\xAD", + "\x97\x97"=>"\xE8\xA6\xA7", + "\x97\x98"=>"\xE5\x88\xA9", + "\x97\x99"=>"\xE5\x90\x8F", + "\x97\x9A"=>"\xE5\xB1\xA5", + "\x97\x9B"=>"\xE6\x9D\x8E", + "\x97\x9C"=>"\xE6\xA2\xA8", + "\x97\x9D"=>"\xE7\x90\x86", + "\x97\x9E"=>"\xE7\x92\x83", + "\x97\x9F"=>"\xE7\x97\xA2", + "\x97\xA0"=>"\xE8\xA3\x8F", + "\x97\xA1"=>"\xE8\xA3\xA1", + "\x97\xA2"=>"\xE9\x87\x8C", + "\x97\xA3"=>"\xE9\x9B\xA2", + "\x97\xA4"=>"\xE9\x99\xB8", + "\x97\xA5"=>"\xE5\xBE\x8B", + "\x97\xA6"=>"\xE7\x8E\x87", + "\x97\xA7"=>"\xE7\xAB\x8B", + "\x97\xA8"=>"\xE8\x91\x8E", + "\x97\xA9"=>"\xE6\x8E\xA0", + "\x97\xAA"=>"\xE7\x95\xA5", + "\x97\xAB"=>"\xE5\x8A\x89", + "\x97\xAC"=>"\xE6\xB5\x81", + "\x97\xAD"=>"\xE6\xBA\x9C", + "\x97\xAE"=>"\xE7\x90\x89", + "\x97\xAF"=>"\xE7\x95\x99", + "\x97\xB0"=>"\xE7\xA1\xAB", + "\x97\xB1"=>"\xE7\xB2\x92", + "\x97\xB2"=>"\xE9\x9A\x86", + "\x97\xB3"=>"\xE7\xAB\x9C", + "\x97\xB4"=>"\xE9\xBE\x8D", + "\x97\xB5"=>"\xE4\xBE\xB6", + "\x97\xB6"=>"\xE6\x85\xAE", + "\x97\xB7"=>"\xE6\x97\x85", + "\x97\xB8"=>"\xE8\x99\x9C", + "\x97\xB9"=>"\xE4\xBA\x86", + "\x97\xBA"=>"\xE4\xBA\xAE", + "\x97\xBB"=>"\xE5\x83\x9A", + "\x97\xBC"=>"\xE4\xB8\xA1", + "\x97\xBD"=>"\xE5\x87\x8C", + "\x97\xBE"=>"\xE5\xAF\xAE", + "\x97\xBF"=>"\xE6\x96\x99", + "\x97\xC0"=>"\xE6\xA2\x81", + "\x97\xC1"=>"\xE6\xB6\xBC", + "\x97\xC2"=>"\xE7\x8C\x9F", + "\x97\xC3"=>"\xE7\x99\x82", + "\x97\xC4"=>"\xE7\x9E\xAD", + "\x97\xC5"=>"\xE7\xA8\x9C", + "\x97\xC6"=>"\xE7\xB3\xA7", + "\x97\xC7"=>"\xE8\x89\xAF", + "\x97\xC8"=>"\xE8\xAB\x92", + "\x97\xC9"=>"\xE9\x81\xBC", + "\x97\xCA"=>"\xE9\x87\x8F", + "\x97\xCB"=>"\xE9\x99\xB5", + "\x97\xCC"=>"\xE9\xA0\x98", + "\x97\xCD"=>"\xE5\x8A\x9B", + "\x97\xCE"=>"\xE7\xB7\x91", + "\x97\xCF"=>"\xE5\x80\xAB", + "\x97\xD0"=>"\xE5\x8E\x98", + "\x97\xD1"=>"\xE6\x9E\x97", + "\x97\xD2"=>"\xE6\xB7\x8B", + "\x97\xD3"=>"\xE7\x87\x90", + "\x97\xD4"=>"\xE7\x90\xB3", + "\x97\xD5"=>"\xE8\x87\xA8", + "\x97\xD6"=>"\xE8\xBC\xAA", + "\x97\xD7"=>"\xE9\x9A\xA3", + "\x97\xD8"=>"\xE9\xB1\x97", + "\x97\xD9"=>"\xE9\xBA\x9F", + "\x97\xDA"=>"\xE7\x91\xA0", + "\x97\xDB"=>"\xE5\xA1\x81", + "\x97\xDC"=>"\xE6\xB6\x99", + "\x97\xDD"=>"\xE7\xB4\xAF", + "\x97\xDE"=>"\xE9\xA1\x9E", + "\x97\xDF"=>"\xE4\xBB\xA4", + "\x97\xE0"=>"\xE4\xBC\xB6", + "\x97\xE1"=>"\xE4\xBE\x8B", + "\x97\xE2"=>"\xE5\x86\xB7", + "\x97\xE3"=>"\xE5\x8A\xB1", + "\x97\xE4"=>"\xE5\xB6\xBA", + "\x97\xE5"=>"\xE6\x80\x9C", + "\x97\xE6"=>"\xE7\x8E\xB2", + "\x97\xE7"=>"\xE7\xA4\xBC", + "\x97\xE8"=>"\xE8\x8B\x93", + "\x97\xE9"=>"\xE9\x88\xB4", + "\x97\xEA"=>"\xE9\x9A\xB7", + "\x97\xEB"=>"\xE9\x9B\xB6", + "\x97\xEC"=>"\xE9\x9C\x8A", + "\x97\xED"=>"\xE9\xBA\x97", + "\x97\xEE"=>"\xE9\xBD\xA2", + "\x97\xEF"=>"\xE6\x9A\xA6", + "\x97\xF0"=>"\xE6\xAD\xB4", + "\x97\xF1"=>"\xE5\x88\x97", + "\x97\xF2"=>"\xE5\x8A\xA3", + "\x97\xF3"=>"\xE7\x83\x88", + "\x97\xF4"=>"\xE8\xA3\x82", + "\x97\xF5"=>"\xE5\xBB\x89", + "\x97\xF6"=>"\xE6\x81\x8B", + "\x97\xF7"=>"\xE6\x86\x90", + "\x97\xF8"=>"\xE6\xBC\xA3", + "\x97\xF9"=>"\xE7\x85\x89", + "\x97\xFA"=>"\xE7\xB0\xBE", + "\x97\xFB"=>"\xE7\xB7\xB4", + "\x97\xFC"=>"\xE8\x81\xAF", + "\x98\x40"=>"\xE8\x93\xAE", + "\x98\x41"=>"\xE9\x80\xA3", + "\x98\x42"=>"\xE9\x8C\xAC", + "\x98\x43"=>"\xE5\x91\x82", + "\x98\x44"=>"\xE9\xAD\xAF", + "\x98\x45"=>"\xE6\xAB\x93", + "\x98\x46"=>"\xE7\x82\x89", + "\x98\x47"=>"\xE8\xB3\x82", + "\x98\x48"=>"\xE8\xB7\xAF", + "\x98\x49"=>"\xE9\x9C\xB2", + "\x98\x4A"=>"\xE5\x8A\xB4", + "\x98\x4B"=>"\xE5\xA9\x81", + "\x98\x4C"=>"\xE5\xBB\x8A", + "\x98\x4D"=>"\xE5\xBC\x84", + "\x98\x4E"=>"\xE6\x9C\x97", + "\x98\x4F"=>"\xE6\xA5\xBC", + "\x98\x50"=>"\xE6\xA6\x94", + "\x98\x51"=>"\xE6\xB5\xAA", + "\x98\x52"=>"\xE6\xBC\x8F", + "\x98\x53"=>"\xE7\x89\xA2", + "\x98\x54"=>"\xE7\x8B\xBC", + "\x98\x55"=>"\xE7\xAF\xAD", + "\x98\x56"=>"\xE8\x80\x81", + "\x98\x57"=>"\xE8\x81\xBE", + "\x98\x58"=>"\xE8\x9D\x8B", + "\x98\x59"=>"\xE9\x83\x8E", + "\x98\x5A"=>"\xE5\x85\xAD", + "\x98\x5B"=>"\xE9\xBA\x93", + "\x98\x5C"=>"\xE7\xA6\x84", + "\x98\x5D"=>"\xE8\x82\x8B", + "\x98\x5E"=>"\xE9\x8C\xB2", + "\x98\x5F"=>"\xE8\xAB\x96", + "\x98\x60"=>"\xE5\x80\xAD", + "\x98\x61"=>"\xE5\x92\x8C", + "\x98\x62"=>"\xE8\xA9\xB1", + "\x98\x63"=>"\xE6\xAD\xAA", + "\x98\x64"=>"\xE8\xB3\x84", + "\x98\x65"=>"\xE8\x84\x87", + "\x98\x66"=>"\xE6\x83\x91", + "\x98\x67"=>"\xE6\x9E\xA0", + "\x98\x68"=>"\xE9\xB7\xB2", + "\x98\x69"=>"\xE4\xBA\x99", + "\x98\x6A"=>"\xE4\xBA\x98", + "\x98\x6B"=>"\xE9\xB0\x90", + "\x98\x6C"=>"\xE8\xA9\xAB", + "\x98\x6D"=>"\xE8\x97\x81", + "\x98\x6E"=>"\xE8\x95\xA8", + "\x98\x6F"=>"\xE6\xA4\x80", + "\x98\x70"=>"\xE6\xB9\xBE", + "\x98\x71"=>"\xE7\xA2\x97", + "\x98\x72"=>"\xE8\x85\x95", + "\x98\x9F"=>"\xE5\xBC\x8C", + "\x98\xA0"=>"\xE4\xB8\x90", + "\x98\xA1"=>"\xE4\xB8\x95", + "\x98\xA2"=>"\xE4\xB8\xAA", + "\x98\xA3"=>"\xE4\xB8\xB1", + "\x98\xA4"=>"\xE4\xB8\xB6", + "\x98\xA5"=>"\xE4\xB8\xBC", + "\x98\xA6"=>"\xE4\xB8\xBF", + "\x98\xA7"=>"\xE4\xB9\x82", + "\x98\xA8"=>"\xE4\xB9\x96", + "\x98\xA9"=>"\xE4\xB9\x98", + "\x98\xAA"=>"\xE4\xBA\x82", + "\x98\xAB"=>"\xE4\xBA\x85", + "\x98\xAC"=>"\xE8\xB1\xAB", + "\x98\xAD"=>"\xE4\xBA\x8A", + "\x98\xAE"=>"\xE8\x88\x92", + "\x98\xAF"=>"\xE5\xBC\x8D", + "\x98\xB0"=>"\xE4\xBA\x8E", + "\x98\xB1"=>"\xE4\xBA\x9E", + "\x98\xB2"=>"\xE4\xBA\x9F", + "\x98\xB3"=>"\xE4\xBA\xA0", + "\x98\xB4"=>"\xE4\xBA\xA2", + "\x98\xB5"=>"\xE4\xBA\xB0", + "\x98\xB6"=>"\xE4\xBA\xB3", + "\x98\xB7"=>"\xE4\xBA\xB6", + "\x98\xB8"=>"\xE4\xBB\x8E", + "\x98\xB9"=>"\xE4\xBB\x8D", + "\x98\xBA"=>"\xE4\xBB\x84", + "\x98\xBB"=>"\xE4\xBB\x86", + "\x98\xBC"=>"\xE4\xBB\x82", + "\x98\xBD"=>"\xE4\xBB\x97", + "\x98\xBE"=>"\xE4\xBB\x9E", + "\x98\xBF"=>"\xE4\xBB\xAD", + "\x98\xC0"=>"\xE4\xBB\x9F", + "\x98\xC1"=>"\xE4\xBB\xB7", + "\x98\xC2"=>"\xE4\xBC\x89", + "\x98\xC3"=>"\xE4\xBD\x9A", + "\x98\xC4"=>"\xE4\xBC\xB0", + "\x98\xC5"=>"\xE4\xBD\x9B", + "\x98\xC6"=>"\xE4\xBD\x9D", + "\x98\xC7"=>"\xE4\xBD\x97", + "\x98\xC8"=>"\xE4\xBD\x87", + "\x98\xC9"=>"\xE4\xBD\xB6", + "\x98\xCA"=>"\xE4\xBE\x88", + "\x98\xCB"=>"\xE4\xBE\x8F", + "\x98\xCC"=>"\xE4\xBE\x98", + "\x98\xCD"=>"\xE4\xBD\xBB", + "\x98\xCE"=>"\xE4\xBD\xA9", + "\x98\xCF"=>"\xE4\xBD\xB0", + "\x98\xD0"=>"\xE4\xBE\x91", + "\x98\xD1"=>"\xE4\xBD\xAF", + "\x98\xD2"=>"\xE4\xBE\x86", + "\x98\xD3"=>"\xE4\xBE\x96", + "\x98\xD4"=>"\xE5\x84\x98", + "\x98\xD5"=>"\xE4\xBF\x94", + "\x98\xD6"=>"\xE4\xBF\x9F", + "\x98\xD7"=>"\xE4\xBF\x8E", + "\x98\xD8"=>"\xE4\xBF\x98", + "\x98\xD9"=>"\xE4\xBF\x9B", + "\x98\xDA"=>"\xE4\xBF\x91", + "\x98\xDB"=>"\xE4\xBF\x9A", + "\x98\xDC"=>"\xE4\xBF\x90", + "\x98\xDD"=>"\xE4\xBF\xA4", + "\x98\xDE"=>"\xE4\xBF\xA5", + "\x98\xDF"=>"\xE5\x80\x9A", + "\x98\xE0"=>"\xE5\x80\xA8", + "\x98\xE1"=>"\xE5\x80\x94", + "\x98\xE2"=>"\xE5\x80\xAA", + "\x98\xE3"=>"\xE5\x80\xA5", + "\x98\xE4"=>"\xE5\x80\x85", + "\x98\xE5"=>"\xE4\xBC\x9C", + "\x98\xE6"=>"\xE4\xBF\xB6", + "\x98\xE7"=>"\xE5\x80\xA1", + "\x98\xE8"=>"\xE5\x80\xA9", + "\x98\xE9"=>"\xE5\x80\xAC", + "\x98\xEA"=>"\xE4\xBF\xBE", + "\x98\xEB"=>"\xE4\xBF\xAF", + "\x98\xEC"=>"\xE5\x80\x91", + "\x98\xED"=>"\xE5\x80\x86", + "\x98\xEE"=>"\xE5\x81\x83", + "\x98\xEF"=>"\xE5\x81\x87", + "\x98\xF0"=>"\xE6\x9C\x83", + "\x98\xF1"=>"\xE5\x81\x95", + "\x98\xF2"=>"\xE5\x81\x90", + "\x98\xF3"=>"\xE5\x81\x88", + "\x98\xF4"=>"\xE5\x81\x9A", + "\x98\xF5"=>"\xE5\x81\x96", + "\x98\xF6"=>"\xE5\x81\xAC", + "\x98\xF7"=>"\xE5\x81\xB8", + "\x98\xF8"=>"\xE5\x82\x80", + "\x98\xF9"=>"\xE5\x82\x9A", + "\x98\xFA"=>"\xE5\x82\x85", + "\x98\xFB"=>"\xE5\x82\xB4", + "\x98\xFC"=>"\xE5\x82\xB2", + "\x99\x40"=>"\xE5\x83\x89", + "\x99\x41"=>"\xE5\x83\x8A", + "\x99\x42"=>"\xE5\x82\xB3", + "\x99\x43"=>"\xE5\x83\x82", + "\x99\x44"=>"\xE5\x83\x96", + "\x99\x45"=>"\xE5\x83\x9E", + "\x99\x46"=>"\xE5\x83\xA5", + "\x99\x47"=>"\xE5\x83\xAD", + "\x99\x48"=>"\xE5\x83\xA3", + "\x99\x49"=>"\xE5\x83\xAE", + "\x99\x4A"=>"\xE5\x83\xB9", + "\x99\x4B"=>"\xE5\x83\xB5", + "\x99\x4C"=>"\xE5\x84\x89", + "\x99\x4D"=>"\xE5\x84\x81", + "\x99\x4E"=>"\xE5\x84\x82", + "\x99\x4F"=>"\xE5\x84\x96", + "\x99\x50"=>"\xE5\x84\x95", + "\x99\x51"=>"\xE5\x84\x94", + "\x99\x52"=>"\xE5\x84\x9A", + "\x99\x53"=>"\xE5\x84\xA1", + "\x99\x54"=>"\xE5\x84\xBA", + "\x99\x55"=>"\xE5\x84\xB7", + "\x99\x56"=>"\xE5\x84\xBC", + "\x99\x57"=>"\xE5\x84\xBB", + "\x99\x58"=>"\xE5\x84\xBF", + "\x99\x59"=>"\xE5\x85\x80", + "\x99\x5A"=>"\xE5\x85\x92", + "\x99\x5B"=>"\xE5\x85\x8C", + "\x99\x5C"=>"\xE5\x85\x94", + "\x99\x5D"=>"\xE5\x85\xA2", + "\x99\x5E"=>"\xE7\xAB\xB8", + "\x99\x5F"=>"\xE5\x85\xA9", + "\x99\x60"=>"\xE5\x85\xAA", + "\x99\x61"=>"\xE5\x85\xAE", + "\x99\x62"=>"\xE5\x86\x80", + "\x99\x63"=>"\xE5\x86\x82", + "\x99\x64"=>"\xE5\x9B\x98", + "\x99\x65"=>"\xE5\x86\x8C", + "\x99\x66"=>"\xE5\x86\x89", + "\x99\x67"=>"\xE5\x86\x8F", + "\x99\x68"=>"\xE5\x86\x91", + "\x99\x69"=>"\xE5\x86\x93", + "\x99\x6A"=>"\xE5\x86\x95", + "\x99\x6B"=>"\xE5\x86\x96", + "\x99\x6C"=>"\xE5\x86\xA4", + "\x99\x6D"=>"\xE5\x86\xA6", + "\x99\x6E"=>"\xE5\x86\xA2", + "\x99\x6F"=>"\xE5\x86\xA9", + "\x99\x70"=>"\xE5\x86\xAA", + "\x99\x71"=>"\xE5\x86\xAB", + "\x99\x72"=>"\xE5\x86\xB3", + "\x99\x73"=>"\xE5\x86\xB1", + "\x99\x74"=>"\xE5\x86\xB2", + "\x99\x75"=>"\xE5\x86\xB0", + "\x99\x76"=>"\xE5\x86\xB5", + "\x99\x77"=>"\xE5\x86\xBD", + "\x99\x78"=>"\xE5\x87\x85", + "\x99\x79"=>"\xE5\x87\x89", + "\x99\x7A"=>"\xE5\x87\x9B", + "\x99\x7B"=>"\xE5\x87\xA0", + "\x99\x7C"=>"\xE8\x99\x95", + "\x99\x7D"=>"\xE5\x87\xA9", + "\x99\x7E"=>"\xE5\x87\xAD", + "\x99\x80"=>"\xE5\x87\xB0", + "\x99\x81"=>"\xE5\x87\xB5", + "\x99\x82"=>"\xE5\x87\xBE", + "\x99\x83"=>"\xE5\x88\x84", + "\x99\x84"=>"\xE5\x88\x8B", + "\x99\x85"=>"\xE5\x88\x94", + "\x99\x86"=>"\xE5\x88\x8E", + "\x99\x87"=>"\xE5\x88\xA7", + "\x99\x88"=>"\xE5\x88\xAA", + "\x99\x89"=>"\xE5\x88\xAE", + "\x99\x8A"=>"\xE5\x88\xB3", + "\x99\x8B"=>"\xE5\x88\xB9", + "\x99\x8C"=>"\xE5\x89\x8F", + "\x99\x8D"=>"\xE5\x89\x84", + "\x99\x8E"=>"\xE5\x89\x8B", + "\x99\x8F"=>"\xE5\x89\x8C", + "\x99\x90"=>"\xE5\x89\x9E", + "\x99\x91"=>"\xE5\x89\x94", + "\x99\x92"=>"\xE5\x89\xAA", + "\x99\x93"=>"\xE5\x89\xB4", + "\x99\x94"=>"\xE5\x89\xA9", + "\x99\x95"=>"\xE5\x89\xB3", + "\x99\x96"=>"\xE5\x89\xBF", + "\x99\x97"=>"\xE5\x89\xBD", + "\x99\x98"=>"\xE5\x8A\x8D", + "\x99\x99"=>"\xE5\x8A\x94", + "\x99\x9A"=>"\xE5\x8A\x92", + "\x99\x9B"=>"\xE5\x89\xB1", + "\x99\x9C"=>"\xE5\x8A\x88", + "\x99\x9D"=>"\xE5\x8A\x91", + "\x99\x9E"=>"\xE8\xBE\xA8", + "\x99\x9F"=>"\xE8\xBE\xA7", + "\x99\xA0"=>"\xE5\x8A\xAC", + "\x99\xA1"=>"\xE5\x8A\xAD", + "\x99\xA2"=>"\xE5\x8A\xBC", + "\x99\xA3"=>"\xE5\x8A\xB5", + "\x99\xA4"=>"\xE5\x8B\x81", + "\x99\xA5"=>"\xE5\x8B\x8D", + "\x99\xA6"=>"\xE5\x8B\x97", + "\x99\xA7"=>"\xE5\x8B\x9E", + "\x99\xA8"=>"\xE5\x8B\xA3", + "\x99\xA9"=>"\xE5\x8B\xA6", + "\x99\xAA"=>"\xE9\xA3\xAD", + "\x99\xAB"=>"\xE5\x8B\xA0", + "\x99\xAC"=>"\xE5\x8B\xB3", + "\x99\xAD"=>"\xE5\x8B\xB5", + "\x99\xAE"=>"\xE5\x8B\xB8", + "\x99\xAF"=>"\xE5\x8B\xB9", + "\x99\xB0"=>"\xE5\x8C\x86", + "\x99\xB1"=>"\xE5\x8C\x88", + "\x99\xB2"=>"\xE7\x94\xB8", + "\x99\xB3"=>"\xE5\x8C\x8D", + "\x99\xB4"=>"\xE5\x8C\x90", + "\x99\xB5"=>"\xE5\x8C\x8F", + "\x99\xB6"=>"\xE5\x8C\x95", + "\x99\xB7"=>"\xE5\x8C\x9A", + "\x99\xB8"=>"\xE5\x8C\xA3", + "\x99\xB9"=>"\xE5\x8C\xAF", + "\x99\xBA"=>"\xE5\x8C\xB1", + "\x99\xBB"=>"\xE5\x8C\xB3", + "\x99\xBC"=>"\xE5\x8C\xB8", + "\x99\xBD"=>"\xE5\x8D\x80", + "\x99\xBE"=>"\xE5\x8D\x86", + "\x99\xBF"=>"\xE5\x8D\x85", + "\x99\xC0"=>"\xE4\xB8\x97", + "\x99\xC1"=>"\xE5\x8D\x89", + "\x99\xC2"=>"\xE5\x8D\x8D", + "\x99\xC3"=>"\xE5\x87\x96", + "\x99\xC4"=>"\xE5\x8D\x9E", + "\x99\xC5"=>"\xE5\x8D\xA9", + "\x99\xC6"=>"\xE5\x8D\xAE", + "\x99\xC7"=>"\xE5\xA4\x98", + "\x99\xC8"=>"\xE5\x8D\xBB", + "\x99\xC9"=>"\xE5\x8D\xB7", + "\x99\xCA"=>"\xE5\x8E\x82", + "\x99\xCB"=>"\xE5\x8E\x96", + "\x99\xCC"=>"\xE5\x8E\xA0", + "\x99\xCD"=>"\xE5\x8E\xA6", + "\x99\xCE"=>"\xE5\x8E\xA5", + "\x99\xCF"=>"\xE5\x8E\xAE", + "\x99\xD0"=>"\xE5\x8E\xB0", + "\x99\xD1"=>"\xE5\x8E\xB6", + "\x99\xD2"=>"\xE5\x8F\x83", + "\x99\xD3"=>"\xE7\xB0\x92", + "\x99\xD4"=>"\xE9\x9B\x99", + "\x99\xD5"=>"\xE5\x8F\x9F", + "\x99\xD6"=>"\xE6\x9B\xBC", + "\x99\xD7"=>"\xE7\x87\xAE", + "\x99\xD8"=>"\xE5\x8F\xAE", + "\x99\xD9"=>"\xE5\x8F\xA8", + "\x99\xDA"=>"\xE5\x8F\xAD", + "\x99\xDB"=>"\xE5\x8F\xBA", + "\x99\xDC"=>"\xE5\x90\x81", + "\x99\xDD"=>"\xE5\x90\xBD", + "\x99\xDE"=>"\xE5\x91\x80", + "\x99\xDF"=>"\xE5\x90\xAC", + "\x99\xE0"=>"\xE5\x90\xAD", + "\x99\xE1"=>"\xE5\x90\xBC", + "\x99\xE2"=>"\xE5\x90\xAE", + "\x99\xE3"=>"\xE5\x90\xB6", + "\x99\xE4"=>"\xE5\x90\xA9", + "\x99\xE5"=>"\xE5\x90\x9D", + "\x99\xE6"=>"\xE5\x91\x8E", + "\x99\xE7"=>"\xE5\x92\x8F", + "\x99\xE8"=>"\xE5\x91\xB5", + "\x99\xE9"=>"\xE5\x92\x8E", + "\x99\xEA"=>"\xE5\x91\x9F", + "\x99\xEB"=>"\xE5\x91\xB1", + "\x99\xEC"=>"\xE5\x91\xB7", + "\x99\xED"=>"\xE5\x91\xB0", + "\x99\xEE"=>"\xE5\x92\x92", + "\x99\xEF"=>"\xE5\x91\xBB", + "\x99\xF0"=>"\xE5\x92\x80", + "\x99\xF1"=>"\xE5\x91\xB6", + "\x99\xF2"=>"\xE5\x92\x84", + "\x99\xF3"=>"\xE5\x92\x90", + "\x99\xF4"=>"\xE5\x92\x86", + "\x99\xF5"=>"\xE5\x93\x87", + "\x99\xF6"=>"\xE5\x92\xA2", + "\x99\xF7"=>"\xE5\x92\xB8", + "\x99\xF8"=>"\xE5\x92\xA5", + "\x99\xF9"=>"\xE5\x92\xAC", + "\x99\xFA"=>"\xE5\x93\x84", + "\x99\xFB"=>"\xE5\x93\x88", + "\x99\xFC"=>"\xE5\x92\xA8", + "\x9A\x40"=>"\xE5\x92\xAB", + "\x9A\x41"=>"\xE5\x93\x82", + "\x9A\x42"=>"\xE5\x92\xA4", + "\x9A\x43"=>"\xE5\x92\xBE", + "\x9A\x44"=>"\xE5\x92\xBC", + "\x9A\x45"=>"\xE5\x93\x98", + "\x9A\x46"=>"\xE5\x93\xA5", + "\x9A\x47"=>"\xE5\x93\xA6", + "\x9A\x48"=>"\xE5\x94\x8F", + "\x9A\x49"=>"\xE5\x94\x94", + "\x9A\x4A"=>"\xE5\x93\xBD", + "\x9A\x4B"=>"\xE5\x93\xAE", + "\x9A\x4C"=>"\xE5\x93\xAD", + "\x9A\x4D"=>"\xE5\x93\xBA", + "\x9A\x4E"=>"\xE5\x93\xA2", + "\x9A\x4F"=>"\xE5\x94\xB9", + "\x9A\x50"=>"\xE5\x95\x80", + "\x9A\x51"=>"\xE5\x95\xA3", + "\x9A\x52"=>"\xE5\x95\x8C", + "\x9A\x53"=>"\xE5\x94\xAE", + "\x9A\x54"=>"\xE5\x95\x9C", + "\x9A\x55"=>"\xE5\x95\x85", + "\x9A\x56"=>"\xE5\x95\x96", + "\x9A\x57"=>"\xE5\x95\x97", + "\x9A\x58"=>"\xE5\x94\xB8", + "\x9A\x59"=>"\xE5\x94\xB3", + "\x9A\x5A"=>"\xE5\x95\x9D", + "\x9A\x5B"=>"\xE5\x96\x99", + "\x9A\x5C"=>"\xE5\x96\x80", + "\x9A\x5D"=>"\xE5\x92\xAF", + "\x9A\x5E"=>"\xE5\x96\x8A", + "\x9A\x5F"=>"\xE5\x96\x9F", + "\x9A\x60"=>"\xE5\x95\xBB", + "\x9A\x61"=>"\xE5\x95\xBE", + "\x9A\x62"=>"\xE5\x96\x98", + "\x9A\x63"=>"\xE5\x96\x9E", + "\x9A\x64"=>"\xE5\x96\xAE", + "\x9A\x65"=>"\xE5\x95\xBC", + "\x9A\x66"=>"\xE5\x96\x83", + "\x9A\x67"=>"\xE5\x96\xA9", + "\x9A\x68"=>"\xE5\x96\x87", + "\x9A\x69"=>"\xE5\x96\xA8", + "\x9A\x6A"=>"\xE5\x97\x9A", + "\x9A\x6B"=>"\xE5\x97\x85", + "\x9A\x6C"=>"\xE5\x97\x9F", + "\x9A\x6D"=>"\xE5\x97\x84", + "\x9A\x6E"=>"\xE5\x97\x9C", + "\x9A\x6F"=>"\xE5\x97\xA4", + "\x9A\x70"=>"\xE5\x97\x94", + "\x9A\x71"=>"\xE5\x98\x94", + "\x9A\x72"=>"\xE5\x97\xB7", + "\x9A\x73"=>"\xE5\x98\x96", + "\x9A\x74"=>"\xE5\x97\xBE", + "\x9A\x75"=>"\xE5\x97\xBD", + "\x9A\x76"=>"\xE5\x98\x9B", + "\x9A\x77"=>"\xE5\x97\xB9", + "\x9A\x78"=>"\xE5\x99\x8E", + "\x9A\x79"=>"\xE5\x99\x90", + "\x9A\x7A"=>"\xE7\x87\x9F", + "\x9A\x7B"=>"\xE5\x98\xB4", + "\x9A\x7C"=>"\xE5\x98\xB6", + "\x9A\x7D"=>"\xE5\x98\xB2", + "\x9A\x7E"=>"\xE5\x98\xB8", + "\x9A\x80"=>"\xE5\x99\xAB", + "\x9A\x81"=>"\xE5\x99\xA4", + "\x9A\x82"=>"\xE5\x98\xAF", + "\x9A\x83"=>"\xE5\x99\xAC", + "\x9A\x84"=>"\xE5\x99\xAA", + "\x9A\x85"=>"\xE5\x9A\x86", + "\x9A\x86"=>"\xE5\x9A\x80", + "\x9A\x87"=>"\xE5\x9A\x8A", + "\x9A\x88"=>"\xE5\x9A\xA0", + "\x9A\x89"=>"\xE5\x9A\x94", + "\x9A\x8A"=>"\xE5\x9A\x8F", + "\x9A\x8B"=>"\xE5\x9A\xA5", + "\x9A\x8C"=>"\xE5\x9A\xAE", + "\x9A\x8D"=>"\xE5\x9A\xB6", + "\x9A\x8E"=>"\xE5\x9A\xB4", + "\x9A\x8F"=>"\xE5\x9B\x82", + "\x9A\x90"=>"\xE5\x9A\xBC", + "\x9A\x91"=>"\xE5\x9B\x81", + "\x9A\x92"=>"\xE5\x9B\x83", + "\x9A\x93"=>"\xE5\x9B\x80", + "\x9A\x94"=>"\xE5\x9B\x88", + "\x9A\x95"=>"\xE5\x9B\x8E", + "\x9A\x96"=>"\xE5\x9B\x91", + "\x9A\x97"=>"\xE5\x9B\x93", + "\x9A\x98"=>"\xE5\x9B\x97", + "\x9A\x99"=>"\xE5\x9B\xAE", + "\x9A\x9A"=>"\xE5\x9B\xB9", + "\x9A\x9B"=>"\xE5\x9C\x80", + "\x9A\x9C"=>"\xE5\x9B\xBF", + "\x9A\x9D"=>"\xE5\x9C\x84", + "\x9A\x9E"=>"\xE5\x9C\x89", + "\x9A\x9F"=>"\xE5\x9C\x88", + "\x9A\xA0"=>"\xE5\x9C\x8B", + "\x9A\xA1"=>"\xE5\x9C\x8D", + "\x9A\xA2"=>"\xE5\x9C\x93", + "\x9A\xA3"=>"\xE5\x9C\x98", + "\x9A\xA4"=>"\xE5\x9C\x96", + "\x9A\xA5"=>"\xE5\x97\x87", + "\x9A\xA6"=>"\xE5\x9C\x9C", + "\x9A\xA7"=>"\xE5\x9C\xA6", + "\x9A\xA8"=>"\xE5\x9C\xB7", + "\x9A\xA9"=>"\xE5\x9C\xB8", + "\x9A\xAA"=>"\xE5\x9D\x8E", + "\x9A\xAB"=>"\xE5\x9C\xBB", + "\x9A\xAC"=>"\xE5\x9D\x80", + "\x9A\xAD"=>"\xE5\x9D\x8F", + "\x9A\xAE"=>"\xE5\x9D\xA9", + "\x9A\xAF"=>"\xE5\x9F\x80", + "\x9A\xB0"=>"\xE5\x9E\x88", + "\x9A\xB1"=>"\xE5\x9D\xA1", + "\x9A\xB2"=>"\xE5\x9D\xBF", + "\x9A\xB3"=>"\xE5\x9E\x89", + "\x9A\xB4"=>"\xE5\x9E\x93", + "\x9A\xB5"=>"\xE5\x9E\xA0", + "\x9A\xB6"=>"\xE5\x9E\xB3", + "\x9A\xB7"=>"\xE5\x9E\xA4", + "\x9A\xB8"=>"\xE5\x9E\xAA", + "\x9A\xB9"=>"\xE5\x9E\xB0", + "\x9A\xBA"=>"\xE5\x9F\x83", + "\x9A\xBB"=>"\xE5\x9F\x86", + "\x9A\xBC"=>"\xE5\x9F\x94", + "\x9A\xBD"=>"\xE5\x9F\x92", + "\x9A\xBE"=>"\xE5\x9F\x93", + "\x9A\xBF"=>"\xE5\xA0\x8A", + "\x9A\xC0"=>"\xE5\x9F\x96", + "\x9A\xC1"=>"\xE5\x9F\xA3", + "\x9A\xC2"=>"\xE5\xA0\x8B", + "\x9A\xC3"=>"\xE5\xA0\x99", + "\x9A\xC4"=>"\xE5\xA0\x9D", + "\x9A\xC5"=>"\xE5\xA1\xB2", + "\x9A\xC6"=>"\xE5\xA0\xA1", + "\x9A\xC7"=>"\xE5\xA1\xA2", + "\x9A\xC8"=>"\xE5\xA1\x8B", + "\x9A\xC9"=>"\xE5\xA1\xB0", + "\x9A\xCA"=>"\xE6\xAF\x80", + "\x9A\xCB"=>"\xE5\xA1\x92", + "\x9A\xCC"=>"\xE5\xA0\xBD", + "\x9A\xCD"=>"\xE5\xA1\xB9", + "\x9A\xCE"=>"\xE5\xA2\x85", + "\x9A\xCF"=>"\xE5\xA2\xB9", + "\x9A\xD0"=>"\xE5\xA2\x9F", + "\x9A\xD1"=>"\xE5\xA2\xAB", + "\x9A\xD2"=>"\xE5\xA2\xBA", + "\x9A\xD3"=>"\xE5\xA3\x9E", + "\x9A\xD4"=>"\xE5\xA2\xBB", + "\x9A\xD5"=>"\xE5\xA2\xB8", + "\x9A\xD6"=>"\xE5\xA2\xAE", + "\x9A\xD7"=>"\xE5\xA3\x85", + "\x9A\xD8"=>"\xE5\xA3\x93", + "\x9A\xD9"=>"\xE5\xA3\x91", + "\x9A\xDA"=>"\xE5\xA3\x97", + "\x9A\xDB"=>"\xE5\xA3\x99", + "\x9A\xDC"=>"\xE5\xA3\x98", + "\x9A\xDD"=>"\xE5\xA3\xA5", + "\x9A\xDE"=>"\xE5\xA3\x9C", + "\x9A\xDF"=>"\xE5\xA3\xA4", + "\x9A\xE0"=>"\xE5\xA3\x9F", + "\x9A\xE1"=>"\xE5\xA3\xAF", + "\x9A\xE2"=>"\xE5\xA3\xBA", + "\x9A\xE3"=>"\xE5\xA3\xB9", + "\x9A\xE4"=>"\xE5\xA3\xBB", + "\x9A\xE5"=>"\xE5\xA3\xBC", + "\x9A\xE6"=>"\xE5\xA3\xBD", + "\x9A\xE7"=>"\xE5\xA4\x82", + "\x9A\xE8"=>"\xE5\xA4\x8A", + "\x9A\xE9"=>"\xE5\xA4\x90", + "\x9A\xEA"=>"\xE5\xA4\x9B", + "\x9A\xEB"=>"\xE6\xA2\xA6", + "\x9A\xEC"=>"\xE5\xA4\xA5", + "\x9A\xED"=>"\xE5\xA4\xAC", + "\x9A\xEE"=>"\xE5\xA4\xAD", + "\x9A\xEF"=>"\xE5\xA4\xB2", + "\x9A\xF0"=>"\xE5\xA4\xB8", + "\x9A\xF1"=>"\xE5\xA4\xBE", + "\x9A\xF2"=>"\xE7\xAB\x92", + "\x9A\xF3"=>"\xE5\xA5\x95", + "\x9A\xF4"=>"\xE5\xA5\x90", + "\x9A\xF5"=>"\xE5\xA5\x8E", + "\x9A\xF6"=>"\xE5\xA5\x9A", + "\x9A\xF7"=>"\xE5\xA5\x98", + "\x9A\xF8"=>"\xE5\xA5\xA2", + "\x9A\xF9"=>"\xE5\xA5\xA0", + "\x9A\xFA"=>"\xE5\xA5\xA7", + "\x9A\xFB"=>"\xE5\xA5\xAC", + "\x9A\xFC"=>"\xE5\xA5\xA9", + "\x9B\x40"=>"\xE5\xA5\xB8", + "\x9B\x41"=>"\xE5\xA6\x81", + "\x9B\x42"=>"\xE5\xA6\x9D", + "\x9B\x43"=>"\xE4\xBD\x9E", + "\x9B\x44"=>"\xE4\xBE\xAB", + "\x9B\x45"=>"\xE5\xA6\xA3", + "\x9B\x46"=>"\xE5\xA6\xB2", + "\x9B\x47"=>"\xE5\xA7\x86", + "\x9B\x48"=>"\xE5\xA7\xA8", + "\x9B\x49"=>"\xE5\xA7\x9C", + "\x9B\x4A"=>"\xE5\xA6\x8D", + "\x9B\x4B"=>"\xE5\xA7\x99", + "\x9B\x4C"=>"\xE5\xA7\x9A", + "\x9B\x4D"=>"\xE5\xA8\xA5", + "\x9B\x4E"=>"\xE5\xA8\x9F", + "\x9B\x4F"=>"\xE5\xA8\x91", + "\x9B\x50"=>"\xE5\xA8\x9C", + "\x9B\x51"=>"\xE5\xA8\x89", + "\x9B\x52"=>"\xE5\xA8\x9A", + "\x9B\x53"=>"\xE5\xA9\x80", + "\x9B\x54"=>"\xE5\xA9\xAC", + "\x9B\x55"=>"\xE5\xA9\x89", + "\x9B\x56"=>"\xE5\xA8\xB5", + "\x9B\x57"=>"\xE5\xA8\xB6", + "\x9B\x58"=>"\xE5\xA9\xA2", + "\x9B\x59"=>"\xE5\xA9\xAA", + "\x9B\x5A"=>"\xE5\xAA\x9A", + "\x9B\x5B"=>"\xE5\xAA\xBC", + "\x9B\x5C"=>"\xE5\xAA\xBE", + "\x9B\x5D"=>"\xE5\xAB\x8B", + "\x9B\x5E"=>"\xE5\xAB\x82", + "\x9B\x5F"=>"\xE5\xAA\xBD", + "\x9B\x60"=>"\xE5\xAB\xA3", + "\x9B\x61"=>"\xE5\xAB\x97", + "\x9B\x62"=>"\xE5\xAB\xA6", + "\x9B\x63"=>"\xE5\xAB\xA9", + "\x9B\x64"=>"\xE5\xAB\x96", + "\x9B\x65"=>"\xE5\xAB\xBA", + "\x9B\x66"=>"\xE5\xAB\xBB", + "\x9B\x67"=>"\xE5\xAC\x8C", + "\x9B\x68"=>"\xE5\xAC\x8B", + "\x9B\x69"=>"\xE5\xAC\x96", + "\x9B\x6A"=>"\xE5\xAC\xB2", + "\x9B\x6B"=>"\xE5\xAB\x90", + "\x9B\x6C"=>"\xE5\xAC\xAA", + "\x9B\x6D"=>"\xE5\xAC\xB6", + "\x9B\x6E"=>"\xE5\xAC\xBE", + "\x9B\x6F"=>"\xE5\xAD\x83", + "\x9B\x70"=>"\xE5\xAD\x85", + "\x9B\x71"=>"\xE5\xAD\x80", + "\x9B\x72"=>"\xE5\xAD\x91", + "\x9B\x73"=>"\xE5\xAD\x95", + "\x9B\x74"=>"\xE5\xAD\x9A", + "\x9B\x75"=>"\xE5\xAD\x9B", + "\x9B\x76"=>"\xE5\xAD\xA5", + "\x9B\x77"=>"\xE5\xAD\xA9", + "\x9B\x78"=>"\xE5\xAD\xB0", + "\x9B\x79"=>"\xE5\xAD\xB3", + "\x9B\x7A"=>"\xE5\xAD\xB5", + "\x9B\x7B"=>"\xE5\xAD\xB8", + "\x9B\x7C"=>"\xE6\x96\x88", + "\x9B\x7D"=>"\xE5\xAD\xBA", + "\x9B\x7E"=>"\xE5\xAE\x80", + "\x9B\x80"=>"\xE5\xAE\x83", + "\x9B\x81"=>"\xE5\xAE\xA6", + "\x9B\x82"=>"\xE5\xAE\xB8", + "\x9B\x83"=>"\xE5\xAF\x83", + "\x9B\x84"=>"\xE5\xAF\x87", + "\x9B\x85"=>"\xE5\xAF\x89", + "\x9B\x86"=>"\xE5\xAF\x94", + "\x9B\x87"=>"\xE5\xAF\x90", + "\x9B\x88"=>"\xE5\xAF\xA4", + "\x9B\x89"=>"\xE5\xAF\xA6", + "\x9B\x8A"=>"\xE5\xAF\xA2", + "\x9B\x8B"=>"\xE5\xAF\x9E", + "\x9B\x8C"=>"\xE5\xAF\xA5", + "\x9B\x8D"=>"\xE5\xAF\xAB", + "\x9B\x8E"=>"\xE5\xAF\xB0", + "\x9B\x8F"=>"\xE5\xAF\xB6", + "\x9B\x90"=>"\xE5\xAF\xB3", + "\x9B\x91"=>"\xE5\xB0\x85", + "\x9B\x92"=>"\xE5\xB0\x87", + "\x9B\x93"=>"\xE5\xB0\x88", + "\x9B\x94"=>"\xE5\xB0\x8D", + "\x9B\x95"=>"\xE5\xB0\x93", + "\x9B\x96"=>"\xE5\xB0\xA0", + "\x9B\x97"=>"\xE5\xB0\xA2", + "\x9B\x98"=>"\xE5\xB0\xA8", + "\x9B\x99"=>"\xE5\xB0\xB8", + "\x9B\x9A"=>"\xE5\xB0\xB9", + "\x9B\x9B"=>"\xE5\xB1\x81", + "\x9B\x9C"=>"\xE5\xB1\x86", + "\x9B\x9D"=>"\xE5\xB1\x8E", + "\x9B\x9E"=>"\xE5\xB1\x93", + "\x9B\x9F"=>"\xE5\xB1\x90", + "\x9B\xA0"=>"\xE5\xB1\x8F", + "\x9B\xA1"=>"\xE5\xAD\xB1", + "\x9B\xA2"=>"\xE5\xB1\xAC", + "\x9B\xA3"=>"\xE5\xB1\xAE", + "\x9B\xA4"=>"\xE4\xB9\xA2", + "\x9B\xA5"=>"\xE5\xB1\xB6", + "\x9B\xA6"=>"\xE5\xB1\xB9", + "\x9B\xA7"=>"\xE5\xB2\x8C", + "\x9B\xA8"=>"\xE5\xB2\x91", + "\x9B\xA9"=>"\xE5\xB2\x94", + "\x9B\xAA"=>"\xE5\xA6\x9B", + "\x9B\xAB"=>"\xE5\xB2\xAB", + "\x9B\xAC"=>"\xE5\xB2\xBB", + "\x9B\xAD"=>"\xE5\xB2\xB6", + "\x9B\xAE"=>"\xE5\xB2\xBC", + "\x9B\xAF"=>"\xE5\xB2\xB7", + "\x9B\xB0"=>"\xE5\xB3\x85", + "\x9B\xB1"=>"\xE5\xB2\xBE", + "\x9B\xB2"=>"\xE5\xB3\x87", + "\x9B\xB3"=>"\xE5\xB3\x99", + "\x9B\xB4"=>"\xE5\xB3\xA9", + "\x9B\xB5"=>"\xE5\xB3\xBD", + "\x9B\xB6"=>"\xE5\xB3\xBA", + "\x9B\xB7"=>"\xE5\xB3\xAD", + "\x9B\xB8"=>"\xE5\xB6\x8C", + "\x9B\xB9"=>"\xE5\xB3\xAA", + "\x9B\xBA"=>"\xE5\xB4\x8B", + "\x9B\xBB"=>"\xE5\xB4\x95", + "\x9B\xBC"=>"\xE5\xB4\x97", + "\x9B\xBD"=>"\xE5\xB5\x9C", + "\x9B\xBE"=>"\xE5\xB4\x9F", + "\x9B\xBF"=>"\xE5\xB4\x9B", + "\x9B\xC0"=>"\xE5\xB4\x91", + "\x9B\xC1"=>"\xE5\xB4\x94", + "\x9B\xC2"=>"\xE5\xB4\xA2", + "\x9B\xC3"=>"\xE5\xB4\x9A", + "\x9B\xC4"=>"\xE5\xB4\x99", + "\x9B\xC5"=>"\xE5\xB4\x98", + "\x9B\xC6"=>"\xE5\xB5\x8C", + "\x9B\xC7"=>"\xE5\xB5\x92", + "\x9B\xC8"=>"\xE5\xB5\x8E", + "\x9B\xC9"=>"\xE5\xB5\x8B", + "\x9B\xCA"=>"\xE5\xB5\xAC", + "\x9B\xCB"=>"\xE5\xB5\xB3", + "\x9B\xCC"=>"\xE5\xB5\xB6", + "\x9B\xCD"=>"\xE5\xB6\x87", + "\x9B\xCE"=>"\xE5\xB6\x84", + "\x9B\xCF"=>"\xE5\xB6\x82", + "\x9B\xD0"=>"\xE5\xB6\xA2", + "\x9B\xD1"=>"\xE5\xB6\x9D", + "\x9B\xD2"=>"\xE5\xB6\xAC", + "\x9B\xD3"=>"\xE5\xB6\xAE", + "\x9B\xD4"=>"\xE5\xB6\xBD", + "\x9B\xD5"=>"\xE5\xB6\x90", + "\x9B\xD6"=>"\xE5\xB6\xB7", + "\x9B\xD7"=>"\xE5\xB6\xBC", + "\x9B\xD8"=>"\xE5\xB7\x89", + "\x9B\xD9"=>"\xE5\xB7\x8D", + "\x9B\xDA"=>"\xE5\xB7\x93", + "\x9B\xDB"=>"\xE5\xB7\x92", + "\x9B\xDC"=>"\xE5\xB7\x96", + "\x9B\xDD"=>"\xE5\xB7\x9B", + "\x9B\xDE"=>"\xE5\xB7\xAB", + "\x9B\xDF"=>"\xE5\xB7\xB2", + "\x9B\xE0"=>"\xE5\xB7\xB5", + "\x9B\xE1"=>"\xE5\xB8\x8B", + "\x9B\xE2"=>"\xE5\xB8\x9A", + "\x9B\xE3"=>"\xE5\xB8\x99", + "\x9B\xE4"=>"\xE5\xB8\x91", + "\x9B\xE5"=>"\xE5\xB8\x9B", + "\x9B\xE6"=>"\xE5\xB8\xB6", + "\x9B\xE7"=>"\xE5\xB8\xB7", + "\x9B\xE8"=>"\xE5\xB9\x84", + "\x9B\xE9"=>"\xE5\xB9\x83", + "\x9B\xEA"=>"\xE5\xB9\x80", + "\x9B\xEB"=>"\xE5\xB9\x8E", + "\x9B\xEC"=>"\xE5\xB9\x97", + "\x9B\xED"=>"\xE5\xB9\x94", + "\x9B\xEE"=>"\xE5\xB9\x9F", + "\x9B\xEF"=>"\xE5\xB9\xA2", + "\x9B\xF0"=>"\xE5\xB9\xA4", + "\x9B\xF1"=>"\xE5\xB9\x87", + "\x9B\xF2"=>"\xE5\xB9\xB5", + "\x9B\xF3"=>"\xE5\xB9\xB6", + "\x9B\xF4"=>"\xE5\xB9\xBA", + "\x9B\xF5"=>"\xE9\xBA\xBC", + "\x9B\xF6"=>"\xE5\xB9\xBF", + "\x9B\xF7"=>"\xE5\xBA\xA0", + "\x9B\xF8"=>"\xE5\xBB\x81", + "\x9B\xF9"=>"\xE5\xBB\x82", + "\x9B\xFA"=>"\xE5\xBB\x88", + "\x9B\xFB"=>"\xE5\xBB\x90", + "\x9B\xFC"=>"\xE5\xBB\x8F", + "\x9C\x40"=>"\xE5\xBB\x96", + "\x9C\x41"=>"\xE5\xBB\xA3", + "\x9C\x42"=>"\xE5\xBB\x9D", + "\x9C\x43"=>"\xE5\xBB\x9A", + "\x9C\x44"=>"\xE5\xBB\x9B", + "\x9C\x45"=>"\xE5\xBB\xA2", + "\x9C\x46"=>"\xE5\xBB\xA1", + "\x9C\x47"=>"\xE5\xBB\xA8", + "\x9C\x48"=>"\xE5\xBB\xA9", + "\x9C\x49"=>"\xE5\xBB\xAC", + "\x9C\x4A"=>"\xE5\xBB\xB1", + "\x9C\x4B"=>"\xE5\xBB\xB3", + "\x9C\x4C"=>"\xE5\xBB\xB0", + "\x9C\x4D"=>"\xE5\xBB\xB4", + "\x9C\x4E"=>"\xE5\xBB\xB8", + "\x9C\x4F"=>"\xE5\xBB\xBE", + "\x9C\x50"=>"\xE5\xBC\x83", + "\x9C\x51"=>"\xE5\xBC\x89", + "\x9C\x52"=>"\xE5\xBD\x9D", + "\x9C\x53"=>"\xE5\xBD\x9C", + "\x9C\x54"=>"\xE5\xBC\x8B", + "\x9C\x55"=>"\xE5\xBC\x91", + "\x9C\x56"=>"\xE5\xBC\x96", + "\x9C\x57"=>"\xE5\xBC\xA9", + "\x9C\x58"=>"\xE5\xBC\xAD", + "\x9C\x59"=>"\xE5\xBC\xB8", + "\x9C\x5A"=>"\xE5\xBD\x81", + "\x9C\x5B"=>"\xE5\xBD\x88", + "\x9C\x5C"=>"\xE5\xBD\x8C", + "\x9C\x5D"=>"\xE5\xBD\x8E", + "\x9C\x5E"=>"\xE5\xBC\xAF", + "\x9C\x5F"=>"\xE5\xBD\x91", + "\x9C\x60"=>"\xE5\xBD\x96", + "\x9C\x61"=>"\xE5\xBD\x97", + "\x9C\x62"=>"\xE5\xBD\x99", + "\x9C\x63"=>"\xE5\xBD\xA1", + "\x9C\x64"=>"\xE5\xBD\xAD", + "\x9C\x65"=>"\xE5\xBD\xB3", + "\x9C\x66"=>"\xE5\xBD\xB7", + "\x9C\x67"=>"\xE5\xBE\x83", + "\x9C\x68"=>"\xE5\xBE\x82", + "\x9C\x69"=>"\xE5\xBD\xBF", + "\x9C\x6A"=>"\xE5\xBE\x8A", + "\x9C\x6B"=>"\xE5\xBE\x88", + "\x9C\x6C"=>"\xE5\xBE\x91", + "\x9C\x6D"=>"\xE5\xBE\x87", + "\x9C\x6E"=>"\xE5\xBE\x9E", + "\x9C\x6F"=>"\xE5\xBE\x99", + "\x9C\x70"=>"\xE5\xBE\x98", + "\x9C\x71"=>"\xE5\xBE\xA0", + "\x9C\x72"=>"\xE5\xBE\xA8", + "\x9C\x73"=>"\xE5\xBE\xAD", + "\x9C\x74"=>"\xE5\xBE\xBC", + "\x9C\x75"=>"\xE5\xBF\x96", + "\x9C\x76"=>"\xE5\xBF\xBB", + "\x9C\x77"=>"\xE5\xBF\xA4", + "\x9C\x78"=>"\xE5\xBF\xB8", + "\x9C\x79"=>"\xE5\xBF\xB1", + "\x9C\x7A"=>"\xE5\xBF\x9D", + "\x9C\x7B"=>"\xE6\x82\xB3", + "\x9C\x7C"=>"\xE5\xBF\xBF", + "\x9C\x7D"=>"\xE6\x80\xA1", + "\x9C\x7E"=>"\xE6\x81\xA0", + "\x9C\x80"=>"\xE6\x80\x99", + "\x9C\x81"=>"\xE6\x80\x90", + "\x9C\x82"=>"\xE6\x80\xA9", + "\x9C\x83"=>"\xE6\x80\x8E", + "\x9C\x84"=>"\xE6\x80\xB1", + "\x9C\x85"=>"\xE6\x80\x9B", + "\x9C\x86"=>"\xE6\x80\x95", + "\x9C\x87"=>"\xE6\x80\xAB", + "\x9C\x88"=>"\xE6\x80\xA6", + "\x9C\x89"=>"\xE6\x80\x8F", + "\x9C\x8A"=>"\xE6\x80\xBA", + "\x9C\x8B"=>"\xE6\x81\x9A", + "\x9C\x8C"=>"\xE6\x81\x81", + "\x9C\x8D"=>"\xE6\x81\xAA", + "\x9C\x8E"=>"\xE6\x81\xB7", + "\x9C\x8F"=>"\xE6\x81\x9F", + "\x9C\x90"=>"\xE6\x81\x8A", + "\x9C\x91"=>"\xE6\x81\x86", + "\x9C\x92"=>"\xE6\x81\x8D", + "\x9C\x93"=>"\xE6\x81\xA3", + "\x9C\x94"=>"\xE6\x81\x83", + "\x9C\x95"=>"\xE6\x81\xA4", + "\x9C\x96"=>"\xE6\x81\x82", + "\x9C\x97"=>"\xE6\x81\xAC", + "\x9C\x98"=>"\xE6\x81\xAB", + "\x9C\x99"=>"\xE6\x81\x99", + "\x9C\x9A"=>"\xE6\x82\x81", + "\x9C\x9B"=>"\xE6\x82\x8D", + "\x9C\x9C"=>"\xE6\x83\xA7", + "\x9C\x9D"=>"\xE6\x82\x83", + "\x9C\x9E"=>"\xE6\x82\x9A", + "\x9C\x9F"=>"\xE6\x82\x84", + "\x9C\xA0"=>"\xE6\x82\x9B", + "\x9C\xA1"=>"\xE6\x82\x96", + "\x9C\xA2"=>"\xE6\x82\x97", + "\x9C\xA3"=>"\xE6\x82\x92", + "\x9C\xA4"=>"\xE6\x82\xA7", + "\x9C\xA5"=>"\xE6\x82\x8B", + "\x9C\xA6"=>"\xE6\x83\xA1", + "\x9C\xA7"=>"\xE6\x82\xB8", + "\x9C\xA8"=>"\xE6\x83\xA0", + "\x9C\xA9"=>"\xE6\x83\x93", + "\x9C\xAA"=>"\xE6\x82\xB4", + "\x9C\xAB"=>"\xE5\xBF\xB0", + "\x9C\xAC"=>"\xE6\x82\xBD", + "\x9C\xAD"=>"\xE6\x83\x86", + "\x9C\xAE"=>"\xE6\x82\xB5", + "\x9C\xAF"=>"\xE6\x83\x98", + "\x9C\xB0"=>"\xE6\x85\x8D", + "\x9C\xB1"=>"\xE6\x84\x95", + "\x9C\xB2"=>"\xE6\x84\x86", + "\x9C\xB3"=>"\xE6\x83\xB6", + "\x9C\xB4"=>"\xE6\x83\xB7", + "\x9C\xB5"=>"\xE6\x84\x80", + "\x9C\xB6"=>"\xE6\x83\xB4", + "\x9C\xB7"=>"\xE6\x83\xBA", + "\x9C\xB8"=>"\xE6\x84\x83", + "\x9C\xB9"=>"\xE6\x84\xA1", + "\x9C\xBA"=>"\xE6\x83\xBB", + "\x9C\xBB"=>"\xE6\x83\xB1", + "\x9C\xBC"=>"\xE6\x84\x8D", + "\x9C\xBD"=>"\xE6\x84\x8E", + "\x9C\xBE"=>"\xE6\x85\x87", + "\x9C\xBF"=>"\xE6\x84\xBE", + "\x9C\xC0"=>"\xE6\x84\xA8", + "\x9C\xC1"=>"\xE6\x84\xA7", + "\x9C\xC2"=>"\xE6\x85\x8A", + "\x9C\xC3"=>"\xE6\x84\xBF", + "\x9C\xC4"=>"\xE6\x84\xBC", + "\x9C\xC5"=>"\xE6\x84\xAC", + "\x9C\xC6"=>"\xE6\x84\xB4", + "\x9C\xC7"=>"\xE6\x84\xBD", + "\x9C\xC8"=>"\xE6\x85\x82", + "\x9C\xC9"=>"\xE6\x85\x84", + "\x9C\xCA"=>"\xE6\x85\xB3", + "\x9C\xCB"=>"\xE6\x85\xB7", + "\x9C\xCC"=>"\xE6\x85\x98", + "\x9C\xCD"=>"\xE6\x85\x99", + "\x9C\xCE"=>"\xE6\x85\x9A", + "\x9C\xCF"=>"\xE6\x85\xAB", + "\x9C\xD0"=>"\xE6\x85\xB4", + "\x9C\xD1"=>"\xE6\x85\xAF", + "\x9C\xD2"=>"\xE6\x85\xA5", + "\x9C\xD3"=>"\xE6\x85\xB1", + "\x9C\xD4"=>"\xE6\x85\x9F", + "\x9C\xD5"=>"\xE6\x85\x9D", + "\x9C\xD6"=>"\xE6\x85\x93", + "\x9C\xD7"=>"\xE6\x85\xB5", + "\x9C\xD8"=>"\xE6\x86\x99", + "\x9C\xD9"=>"\xE6\x86\x96", + "\x9C\xDA"=>"\xE6\x86\x87", + "\x9C\xDB"=>"\xE6\x86\xAC", + "\x9C\xDC"=>"\xE6\x86\x94", + "\x9C\xDD"=>"\xE6\x86\x9A", + "\x9C\xDE"=>"\xE6\x86\x8A", + "\x9C\xDF"=>"\xE6\x86\x91", + "\x9C\xE0"=>"\xE6\x86\xAB", + "\x9C\xE1"=>"\xE6\x86\xAE", + "\x9C\xE2"=>"\xE6\x87\x8C", + "\x9C\xE3"=>"\xE6\x87\x8A", + "\x9C\xE4"=>"\xE6\x87\x89", + "\x9C\xE5"=>"\xE6\x87\xB7", + "\x9C\xE6"=>"\xE6\x87\x88", + "\x9C\xE7"=>"\xE6\x87\x83", + "\x9C\xE8"=>"\xE6\x87\x86", + "\x9C\xE9"=>"\xE6\x86\xBA", + "\x9C\xEA"=>"\xE6\x87\x8B", + "\x9C\xEB"=>"\xE7\xBD\xB9", + "\x9C\xEC"=>"\xE6\x87\x8D", + "\x9C\xED"=>"\xE6\x87\xA6", + "\x9C\xEE"=>"\xE6\x87\xA3", + "\x9C\xEF"=>"\xE6\x87\xB6", + "\x9C\xF0"=>"\xE6\x87\xBA", + "\x9C\xF1"=>"\xE6\x87\xB4", + "\x9C\xF2"=>"\xE6\x87\xBF", + "\x9C\xF3"=>"\xE6\x87\xBD", + "\x9C\xF4"=>"\xE6\x87\xBC", + "\x9C\xF5"=>"\xE6\x87\xBE", + "\x9C\xF6"=>"\xE6\x88\x80", + "\x9C\xF7"=>"\xE6\x88\x88", + "\x9C\xF8"=>"\xE6\x88\x89", + "\x9C\xF9"=>"\xE6\x88\x8D", + "\x9C\xFA"=>"\xE6\x88\x8C", + "\x9C\xFB"=>"\xE6\x88\x94", + "\x9C\xFC"=>"\xE6\x88\x9B", + "\x9D\x40"=>"\xE6\x88\x9E", + "\x9D\x41"=>"\xE6\x88\xA1", + "\x9D\x42"=>"\xE6\x88\xAA", + "\x9D\x43"=>"\xE6\x88\xAE", + "\x9D\x44"=>"\xE6\x88\xB0", + "\x9D\x45"=>"\xE6\x88\xB2", + "\x9D\x46"=>"\xE6\x88\xB3", + "\x9D\x47"=>"\xE6\x89\x81", + "\x9D\x48"=>"\xE6\x89\x8E", + "\x9D\x49"=>"\xE6\x89\x9E", + "\x9D\x4A"=>"\xE6\x89\xA3", + "\x9D\x4B"=>"\xE6\x89\x9B", + "\x9D\x4C"=>"\xE6\x89\xA0", + "\x9D\x4D"=>"\xE6\x89\xA8", + "\x9D\x4E"=>"\xE6\x89\xBC", + "\x9D\x4F"=>"\xE6\x8A\x82", + "\x9D\x50"=>"\xE6\x8A\x89", + "\x9D\x51"=>"\xE6\x89\xBE", + "\x9D\x52"=>"\xE6\x8A\x92", + "\x9D\x53"=>"\xE6\x8A\x93", + "\x9D\x54"=>"\xE6\x8A\x96", + "\x9D\x55"=>"\xE6\x8B\x94", + "\x9D\x56"=>"\xE6\x8A\x83", + "\x9D\x57"=>"\xE6\x8A\x94", + "\x9D\x58"=>"\xE6\x8B\x97", + "\x9D\x59"=>"\xE6\x8B\x91", + "\x9D\x5A"=>"\xE6\x8A\xBB", + "\x9D\x5B"=>"\xE6\x8B\x8F", + "\x9D\x5C"=>"\xE6\x8B\xBF", + "\x9D\x5D"=>"\xE6\x8B\x86", + "\x9D\x5E"=>"\xE6\x93\x94", + "\x9D\x5F"=>"\xE6\x8B\x88", + "\x9D\x60"=>"\xE6\x8B\x9C", + "\x9D\x61"=>"\xE6\x8B\x8C", + "\x9D\x62"=>"\xE6\x8B\x8A", + "\x9D\x63"=>"\xE6\x8B\x82", + "\x9D\x64"=>"\xE6\x8B\x87", + "\x9D\x65"=>"\xE6\x8A\x9B", + "\x9D\x66"=>"\xE6\x8B\x89", + "\x9D\x67"=>"\xE6\x8C\x8C", + "\x9D\x68"=>"\xE6\x8B\xAE", + "\x9D\x69"=>"\xE6\x8B\xB1", + "\x9D\x6A"=>"\xE6\x8C\xA7", + "\x9D\x6B"=>"\xE6\x8C\x82", + "\x9D\x6C"=>"\xE6\x8C\x88", + "\x9D\x6D"=>"\xE6\x8B\xAF", + "\x9D\x6E"=>"\xE6\x8B\xB5", + "\x9D\x6F"=>"\xE6\x8D\x90", + "\x9D\x70"=>"\xE6\x8C\xBE", + "\x9D\x71"=>"\xE6\x8D\x8D", + "\x9D\x72"=>"\xE6\x90\x9C", + "\x9D\x73"=>"\xE6\x8D\x8F", + "\x9D\x74"=>"\xE6\x8E\x96", + "\x9D\x75"=>"\xE6\x8E\x8E", + "\x9D\x76"=>"\xE6\x8E\x80", + "\x9D\x77"=>"\xE6\x8E\xAB", + "\x9D\x78"=>"\xE6\x8D\xB6", + "\x9D\x79"=>"\xE6\x8E\xA3", + "\x9D\x7A"=>"\xE6\x8E\x8F", + "\x9D\x7B"=>"\xE6\x8E\x89", + "\x9D\x7C"=>"\xE6\x8E\x9F", + "\x9D\x7D"=>"\xE6\x8E\xB5", + "\x9D\x7E"=>"\xE6\x8D\xAB", + "\x9D\x80"=>"\xE6\x8D\xA9", + "\x9D\x81"=>"\xE6\x8E\xBE", + "\x9D\x82"=>"\xE6\x8F\xA9", + "\x9D\x83"=>"\xE6\x8F\x80", + "\x9D\x84"=>"\xE6\x8F\x86", + "\x9D\x85"=>"\xE6\x8F\xA3", + "\x9D\x86"=>"\xE6\x8F\x89", + "\x9D\x87"=>"\xE6\x8F\x92", + "\x9D\x88"=>"\xE6\x8F\xB6", + "\x9D\x89"=>"\xE6\x8F\x84", + "\x9D\x8A"=>"\xE6\x90\x96", + "\x9D\x8B"=>"\xE6\x90\xB4", + "\x9D\x8C"=>"\xE6\x90\x86", + "\x9D\x8D"=>"\xE6\x90\x93", + "\x9D\x8E"=>"\xE6\x90\xA6", + "\x9D\x8F"=>"\xE6\x90\xB6", + "\x9D\x90"=>"\xE6\x94\x9D", + "\x9D\x91"=>"\xE6\x90\x97", + "\x9D\x92"=>"\xE6\x90\xA8", + "\x9D\x93"=>"\xE6\x90\x8F", + "\x9D\x94"=>"\xE6\x91\xA7", + "\x9D\x95"=>"\xE6\x91\xAF", + "\x9D\x96"=>"\xE6\x91\xB6", + "\x9D\x97"=>"\xE6\x91\x8E", + "\x9D\x98"=>"\xE6\x94\xAA", + "\x9D\x99"=>"\xE6\x92\x95", + "\x9D\x9A"=>"\xE6\x92\x93", + "\x9D\x9B"=>"\xE6\x92\xA5", + "\x9D\x9C"=>"\xE6\x92\xA9", + "\x9D\x9D"=>"\xE6\x92\x88", + "\x9D\x9E"=>"\xE6\x92\xBC", + "\x9D\x9F"=>"\xE6\x93\x9A", + "\x9D\xA0"=>"\xE6\x93\x92", + "\x9D\xA1"=>"\xE6\x93\x85", + "\x9D\xA2"=>"\xE6\x93\x87", + "\x9D\xA3"=>"\xE6\x92\xBB", + "\x9D\xA4"=>"\xE6\x93\x98", + "\x9D\xA5"=>"\xE6\x93\x82", + "\x9D\xA6"=>"\xE6\x93\xB1", + "\x9D\xA7"=>"\xE6\x93\xA7", + "\x9D\xA8"=>"\xE8\x88\x89", + "\x9D\xA9"=>"\xE6\x93\xA0", + "\x9D\xAA"=>"\xE6\x93\xA1", + "\x9D\xAB"=>"\xE6\x8A\xAC", + "\x9D\xAC"=>"\xE6\x93\xA3", + "\x9D\xAD"=>"\xE6\x93\xAF", + "\x9D\xAE"=>"\xE6\x94\xAC", + "\x9D\xAF"=>"\xE6\x93\xB6", + "\x9D\xB0"=>"\xE6\x93\xB4", + "\x9D\xB1"=>"\xE6\x93\xB2", + "\x9D\xB2"=>"\xE6\x93\xBA", + "\x9D\xB3"=>"\xE6\x94\x80", + "\x9D\xB4"=>"\xE6\x93\xBD", + "\x9D\xB5"=>"\xE6\x94\x98", + "\x9D\xB6"=>"\xE6\x94\x9C", + "\x9D\xB7"=>"\xE6\x94\x85", + "\x9D\xB8"=>"\xE6\x94\xA4", + "\x9D\xB9"=>"\xE6\x94\xA3", + "\x9D\xBA"=>"\xE6\x94\xAB", + "\x9D\xBB"=>"\xE6\x94\xB4", + "\x9D\xBC"=>"\xE6\x94\xB5", + "\x9D\xBD"=>"\xE6\x94\xB7", + "\x9D\xBE"=>"\xE6\x94\xB6", + "\x9D\xBF"=>"\xE6\x94\xB8", + "\x9D\xC0"=>"\xE7\x95\x8B", + "\x9D\xC1"=>"\xE6\x95\x88", + "\x9D\xC2"=>"\xE6\x95\x96", + "\x9D\xC3"=>"\xE6\x95\x95", + "\x9D\xC4"=>"\xE6\x95\x8D", + "\x9D\xC5"=>"\xE6\x95\x98", + "\x9D\xC6"=>"\xE6\x95\x9E", + "\x9D\xC7"=>"\xE6\x95\x9D", + "\x9D\xC8"=>"\xE6\x95\xB2", + "\x9D\xC9"=>"\xE6\x95\xB8", + "\x9D\xCA"=>"\xE6\x96\x82", + "\x9D\xCB"=>"\xE6\x96\x83", + "\x9D\xCC"=>"\xE8\xAE\x8A", + "\x9D\xCD"=>"\xE6\x96\x9B", + "\x9D\xCE"=>"\xE6\x96\x9F", + "\x9D\xCF"=>"\xE6\x96\xAB", + "\x9D\xD0"=>"\xE6\x96\xB7", + "\x9D\xD1"=>"\xE6\x97\x83", + "\x9D\xD2"=>"\xE6\x97\x86", + "\x9D\xD3"=>"\xE6\x97\x81", + "\x9D\xD4"=>"\xE6\x97\x84", + "\x9D\xD5"=>"\xE6\x97\x8C", + "\x9D\xD6"=>"\xE6\x97\x92", + "\x9D\xD7"=>"\xE6\x97\x9B", + "\x9D\xD8"=>"\xE6\x97\x99", + "\x9D\xD9"=>"\xE6\x97\xA0", + "\x9D\xDA"=>"\xE6\x97\xA1", + "\x9D\xDB"=>"\xE6\x97\xB1", + "\x9D\xDC"=>"\xE6\x9D\xB2", + "\x9D\xDD"=>"\xE6\x98\x8A", + "\x9D\xDE"=>"\xE6\x98\x83", + "\x9D\xDF"=>"\xE6\x97\xBB", + "\x9D\xE0"=>"\xE6\x9D\xB3", + "\x9D\xE1"=>"\xE6\x98\xB5", + "\x9D\xE2"=>"\xE6\x98\xB6", + "\x9D\xE3"=>"\xE6\x98\xB4", + "\x9D\xE4"=>"\xE6\x98\x9C", + "\x9D\xE5"=>"\xE6\x99\x8F", + "\x9D\xE6"=>"\xE6\x99\x84", + "\x9D\xE7"=>"\xE6\x99\x89", + "\x9D\xE8"=>"\xE6\x99\x81", + "\x9D\xE9"=>"\xE6\x99\x9E", + "\x9D\xEA"=>"\xE6\x99\x9D", + "\x9D\xEB"=>"\xE6\x99\xA4", + "\x9D\xEC"=>"\xE6\x99\xA7", + "\x9D\xED"=>"\xE6\x99\xA8", + "\x9D\xEE"=>"\xE6\x99\x9F", + "\x9D\xEF"=>"\xE6\x99\xA2", + "\x9D\xF0"=>"\xE6\x99\xB0", + "\x9D\xF1"=>"\xE6\x9A\x83", + "\x9D\xF2"=>"\xE6\x9A\x88", + "\x9D\xF3"=>"\xE6\x9A\x8E", + "\x9D\xF4"=>"\xE6\x9A\x89", + "\x9D\xF5"=>"\xE6\x9A\x84", + "\x9D\xF6"=>"\xE6\x9A\x98", + "\x9D\xF7"=>"\xE6\x9A\x9D", + "\x9D\xF8"=>"\xE6\x9B\x81", + "\x9D\xF9"=>"\xE6\x9A\xB9", + "\x9D\xFA"=>"\xE6\x9B\x89", + "\x9D\xFB"=>"\xE6\x9A\xBE", + "\x9D\xFC"=>"\xE6\x9A\xBC", + "\x9E\x40"=>"\xE6\x9B\x84", + "\x9E\x41"=>"\xE6\x9A\xB8", + "\x9E\x42"=>"\xE6\x9B\x96", + "\x9E\x43"=>"\xE6\x9B\x9A", + "\x9E\x44"=>"\xE6\x9B\xA0", + "\x9E\x45"=>"\xE6\x98\xBF", + "\x9E\x46"=>"\xE6\x9B\xA6", + "\x9E\x47"=>"\xE6\x9B\xA9", + "\x9E\x48"=>"\xE6\x9B\xB0", + "\x9E\x49"=>"\xE6\x9B\xB5", + "\x9E\x4A"=>"\xE6\x9B\xB7", + "\x9E\x4B"=>"\xE6\x9C\x8F", + "\x9E\x4C"=>"\xE6\x9C\x96", + "\x9E\x4D"=>"\xE6\x9C\x9E", + "\x9E\x4E"=>"\xE6\x9C\xA6", + "\x9E\x4F"=>"\xE6\x9C\xA7", + "\x9E\x50"=>"\xE9\x9C\xB8", + "\x9E\x51"=>"\xE6\x9C\xAE", + "\x9E\x52"=>"\xE6\x9C\xBF", + "\x9E\x53"=>"\xE6\x9C\xB6", + "\x9E\x54"=>"\xE6\x9D\x81", + "\x9E\x55"=>"\xE6\x9C\xB8", + "\x9E\x56"=>"\xE6\x9C\xB7", + "\x9E\x57"=>"\xE6\x9D\x86", + "\x9E\x58"=>"\xE6\x9D\x9E", + "\x9E\x59"=>"\xE6\x9D\xA0", + "\x9E\x5A"=>"\xE6\x9D\x99", + "\x9E\x5B"=>"\xE6\x9D\xA3", + "\x9E\x5C"=>"\xE6\x9D\xA4", + "\x9E\x5D"=>"\xE6\x9E\x89", + "\x9E\x5E"=>"\xE6\x9D\xB0", + "\x9E\x5F"=>"\xE6\x9E\xA9", + "\x9E\x60"=>"\xE6\x9D\xBC", + "\x9E\x61"=>"\xE6\x9D\xAA", + "\x9E\x62"=>"\xE6\x9E\x8C", + "\x9E\x63"=>"\xE6\x9E\x8B", + "\x9E\x64"=>"\xE6\x9E\xA6", + "\x9E\x65"=>"\xE6\x9E\xA1", + "\x9E\x66"=>"\xE6\x9E\x85", + "\x9E\x67"=>"\xE6\x9E\xB7", + "\x9E\x68"=>"\xE6\x9F\xAF", + "\x9E\x69"=>"\xE6\x9E\xB4", + "\x9E\x6A"=>"\xE6\x9F\xAC", + "\x9E\x6B"=>"\xE6\x9E\xB3", + "\x9E\x6C"=>"\xE6\x9F\xA9", + "\x9E\x6D"=>"\xE6\x9E\xB8", + "\x9E\x6E"=>"\xE6\x9F\xA4", + "\x9E\x6F"=>"\xE6\x9F\x9E", + "\x9E\x70"=>"\xE6\x9F\x9D", + "\x9E\x71"=>"\xE6\x9F\xA2", + "\x9E\x72"=>"\xE6\x9F\xAE", + "\x9E\x73"=>"\xE6\x9E\xB9", + "\x9E\x74"=>"\xE6\x9F\x8E", + "\x9E\x75"=>"\xE6\x9F\x86", + "\x9E\x76"=>"\xE6\x9F\xA7", + "\x9E\x77"=>"\xE6\xAA\x9C", + "\x9E\x78"=>"\xE6\xA0\x9E", + "\x9E\x79"=>"\xE6\xA1\x86", + "\x9E\x7A"=>"\xE6\xA0\xA9", + "\x9E\x7B"=>"\xE6\xA1\x80", + "\x9E\x7C"=>"\xE6\xA1\x8D", + "\x9E\x7D"=>"\xE6\xA0\xB2", + "\x9E\x7E"=>"\xE6\xA1\x8E", + "\x9E\x80"=>"\xE6\xA2\xB3", + "\x9E\x81"=>"\xE6\xA0\xAB", + "\x9E\x82"=>"\xE6\xA1\x99", + "\x9E\x83"=>"\xE6\xA1\xA3", + "\x9E\x84"=>"\xE6\xA1\xB7", + "\x9E\x85"=>"\xE6\xA1\xBF", + "\x9E\x86"=>"\xE6\xA2\x9F", + "\x9E\x87"=>"\xE6\xA2\x8F", + "\x9E\x88"=>"\xE6\xA2\xAD", + "\x9E\x89"=>"\xE6\xA2\x94", + "\x9E\x8A"=>"\xE6\xA2\x9D", + "\x9E\x8B"=>"\xE6\xA2\x9B", + "\x9E\x8C"=>"\xE6\xA2\x83", + "\x9E\x8D"=>"\xE6\xAA\xAE", + "\x9E\x8E"=>"\xE6\xA2\xB9", + "\x9E\x8F"=>"\xE6\xA1\xB4", + "\x9E\x90"=>"\xE6\xA2\xB5", + "\x9E\x91"=>"\xE6\xA2\xA0", + "\x9E\x92"=>"\xE6\xA2\xBA", + "\x9E\x93"=>"\xE6\xA4\x8F", + "\x9E\x94"=>"\xE6\xA2\x8D", + "\x9E\x95"=>"\xE6\xA1\xBE", + "\x9E\x96"=>"\xE6\xA4\x81", + "\x9E\x97"=>"\xE6\xA3\x8A", + "\x9E\x98"=>"\xE6\xA4\x88", + "\x9E\x99"=>"\xE6\xA3\x98", + "\x9E\x9A"=>"\xE6\xA4\xA2", + "\x9E\x9B"=>"\xE6\xA4\xA6", + "\x9E\x9C"=>"\xE6\xA3\xA1", + "\x9E\x9D"=>"\xE6\xA4\x8C", + "\x9E\x9E"=>"\xE6\xA3\x8D", + "\x9E\x9F"=>"\xE6\xA3\x94", + "\x9E\xA0"=>"\xE6\xA3\xA7", + "\x9E\xA1"=>"\xE6\xA3\x95", + "\x9E\xA2"=>"\xE6\xA4\xB6", + "\x9E\xA3"=>"\xE6\xA4\x92", + "\x9E\xA4"=>"\xE6\xA4\x84", + "\x9E\xA5"=>"\xE6\xA3\x97", + "\x9E\xA6"=>"\xE6\xA3\xA3", + "\x9E\xA7"=>"\xE6\xA4\xA5", + "\x9E\xA8"=>"\xE6\xA3\xB9", + "\x9E\xA9"=>"\xE6\xA3\xA0", + "\x9E\xAA"=>"\xE6\xA3\xAF", + "\x9E\xAB"=>"\xE6\xA4\xA8", + "\x9E\xAC"=>"\xE6\xA4\xAA", + "\x9E\xAD"=>"\xE6\xA4\x9A", + "\x9E\xAE"=>"\xE6\xA4\xA3", + "\x9E\xAF"=>"\xE6\xA4\xA1", + "\x9E\xB0"=>"\xE6\xA3\x86", + "\x9E\xB1"=>"\xE6\xA5\xB9", + "\x9E\xB2"=>"\xE6\xA5\xB7", + "\x9E\xB3"=>"\xE6\xA5\x9C", + "\x9E\xB4"=>"\xE6\xA5\xB8", + "\x9E\xB5"=>"\xE6\xA5\xAB", + "\x9E\xB6"=>"\xE6\xA5\x94", + "\x9E\xB7"=>"\xE6\xA5\xBE", + "\x9E\xB8"=>"\xE6\xA5\xAE", + "\x9E\xB9"=>"\xE6\xA4\xB9", + "\x9E\xBA"=>"\xE6\xA5\xB4", + "\x9E\xBB"=>"\xE6\xA4\xBD", + "\x9E\xBC"=>"\xE6\xA5\x99", + "\x9E\xBD"=>"\xE6\xA4\xB0", + "\x9E\xBE"=>"\xE6\xA5\xA1", + "\x9E\xBF"=>"\xE6\xA5\x9E", + "\x9E\xC0"=>"\xE6\xA5\x9D", + "\x9E\xC1"=>"\xE6\xA6\x81", + "\x9E\xC2"=>"\xE6\xA5\xAA", + "\x9E\xC3"=>"\xE6\xA6\xB2", + "\x9E\xC4"=>"\xE6\xA6\xAE", + "\x9E\xC5"=>"\xE6\xA7\x90", + "\x9E\xC6"=>"\xE6\xA6\xBF", + "\x9E\xC7"=>"\xE6\xA7\x81", + "\x9E\xC8"=>"\xE6\xA7\x93", + "\x9E\xC9"=>"\xE6\xA6\xBE", + "\x9E\xCA"=>"\xE6\xA7\x8E", + "\x9E\xCB"=>"\xE5\xAF\xA8", + "\x9E\xCC"=>"\xE6\xA7\x8A", + "\x9E\xCD"=>"\xE6\xA7\x9D", + "\x9E\xCE"=>"\xE6\xA6\xBB", + "\x9E\xCF"=>"\xE6\xA7\x83", + "\x9E\xD0"=>"\xE6\xA6\xA7", + "\x9E\xD1"=>"\xE6\xA8\xAE", + "\x9E\xD2"=>"\xE6\xA6\x91", + "\x9E\xD3"=>"\xE6\xA6\xA0", + "\x9E\xD4"=>"\xE6\xA6\x9C", + "\x9E\xD5"=>"\xE6\xA6\x95", + "\x9E\xD6"=>"\xE6\xA6\xB4", + "\x9E\xD7"=>"\xE6\xA7\x9E", + "\x9E\xD8"=>"\xE6\xA7\xA8", + "\x9E\xD9"=>"\xE6\xA8\x82", + "\x9E\xDA"=>"\xE6\xA8\x9B", + "\x9E\xDB"=>"\xE6\xA7\xBF", + "\x9E\xDC"=>"\xE6\xAC\x8A", + "\x9E\xDD"=>"\xE6\xA7\xB9", + "\x9E\xDE"=>"\xE6\xA7\xB2", + "\x9E\xDF"=>"\xE6\xA7\xA7", + "\x9E\xE0"=>"\xE6\xA8\x85", + "\x9E\xE1"=>"\xE6\xA6\xB1", + "\x9E\xE2"=>"\xE6\xA8\x9E", + "\x9E\xE3"=>"\xE6\xA7\xAD", + "\x9E\xE4"=>"\xE6\xA8\x94", + "\x9E\xE5"=>"\xE6\xA7\xAB", + "\x9E\xE6"=>"\xE6\xA8\x8A", + "\x9E\xE7"=>"\xE6\xA8\x92", + "\x9E\xE8"=>"\xE6\xAB\x81", + "\x9E\xE9"=>"\xE6\xA8\xA3", + "\x9E\xEA"=>"\xE6\xA8\x93", + "\x9E\xEB"=>"\xE6\xA9\x84", + "\x9E\xEC"=>"\xE6\xA8\x8C", + "\x9E\xED"=>"\xE6\xA9\xB2", + "\x9E\xEE"=>"\xE6\xA8\xB6", + "\x9E\xEF"=>"\xE6\xA9\xB8", + "\x9E\xF0"=>"\xE6\xA9\x87", + "\x9E\xF1"=>"\xE6\xA9\xA2", + "\x9E\xF2"=>"\xE6\xA9\x99", + "\x9E\xF3"=>"\xE6\xA9\xA6", + "\x9E\xF4"=>"\xE6\xA9\x88", + "\x9E\xF5"=>"\xE6\xA8\xB8", + "\x9E\xF6"=>"\xE6\xA8\xA2", + "\x9E\xF7"=>"\xE6\xAA\x90", + "\x9E\xF8"=>"\xE6\xAA\x8D", + "\x9E\xF9"=>"\xE6\xAA\xA0", + "\x9E\xFA"=>"\xE6\xAA\x84", + "\x9E\xFB"=>"\xE6\xAA\xA2", + "\x9E\xFC"=>"\xE6\xAA\xA3", + "\x9F\x40"=>"\xE6\xAA\x97", + "\x9F\x41"=>"\xE8\x98\x97", + "\x9F\x42"=>"\xE6\xAA\xBB", + "\x9F\x43"=>"\xE6\xAB\x83", + "\x9F\x44"=>"\xE6\xAB\x82", + "\x9F\x45"=>"\xE6\xAA\xB8", + "\x9F\x46"=>"\xE6\xAA\xB3", + "\x9F\x47"=>"\xE6\xAA\xAC", + "\x9F\x48"=>"\xE6\xAB\x9E", + "\x9F\x49"=>"\xE6\xAB\x91", + "\x9F\x4A"=>"\xE6\xAB\x9F", + "\x9F\x4B"=>"\xE6\xAA\xAA", + "\x9F\x4C"=>"\xE6\xAB\x9A", + "\x9F\x4D"=>"\xE6\xAB\xAA", + "\x9F\x4E"=>"\xE6\xAB\xBB", + "\x9F\x4F"=>"\xE6\xAC\x85", + "\x9F\x50"=>"\xE8\x98\x96", + "\x9F\x51"=>"\xE6\xAB\xBA", + "\x9F\x52"=>"\xE6\xAC\x92", + "\x9F\x53"=>"\xE6\xAC\x96", + "\x9F\x54"=>"\xE9\xAC\xB1", + "\x9F\x55"=>"\xE6\xAC\x9F", + "\x9F\x56"=>"\xE6\xAC\xB8", + "\x9F\x57"=>"\xE6\xAC\xB7", + "\x9F\x58"=>"\xE7\x9B\x9C", + "\x9F\x59"=>"\xE6\xAC\xB9", + "\x9F\x5A"=>"\xE9\xA3\xAE", + "\x9F\x5B"=>"\xE6\xAD\x87", + "\x9F\x5C"=>"\xE6\xAD\x83", + "\x9F\x5D"=>"\xE6\xAD\x89", + "\x9F\x5E"=>"\xE6\xAD\x90", + "\x9F\x5F"=>"\xE6\xAD\x99", + "\x9F\x60"=>"\xE6\xAD\x94", + "\x9F\x61"=>"\xE6\xAD\x9B", + "\x9F\x62"=>"\xE6\xAD\x9F", + "\x9F\x63"=>"\xE6\xAD\xA1", + "\x9F\x64"=>"\xE6\xAD\xB8", + "\x9F\x65"=>"\xE6\xAD\xB9", + "\x9F\x66"=>"\xE6\xAD\xBF", + "\x9F\x67"=>"\xE6\xAE\x80", + "\x9F\x68"=>"\xE6\xAE\x84", + "\x9F\x69"=>"\xE6\xAE\x83", + "\x9F\x6A"=>"\xE6\xAE\x8D", + "\x9F\x6B"=>"\xE6\xAE\x98", + "\x9F\x6C"=>"\xE6\xAE\x95", + "\x9F\x6D"=>"\xE6\xAE\x9E", + "\x9F\x6E"=>"\xE6\xAE\xA4", + "\x9F\x6F"=>"\xE6\xAE\xAA", + "\x9F\x70"=>"\xE6\xAE\xAB", + "\x9F\x71"=>"\xE6\xAE\xAF", + "\x9F\x72"=>"\xE6\xAE\xB2", + "\x9F\x73"=>"\xE6\xAE\xB1", + "\x9F\x74"=>"\xE6\xAE\xB3", + "\x9F\x75"=>"\xE6\xAE\xB7", + "\x9F\x76"=>"\xE6\xAE\xBC", + "\x9F\x77"=>"\xE6\xAF\x86", + "\x9F\x78"=>"\xE6\xAF\x8B", + "\x9F\x79"=>"\xE6\xAF\x93", + "\x9F\x7A"=>"\xE6\xAF\x9F", + "\x9F\x7B"=>"\xE6\xAF\xAC", + "\x9F\x7C"=>"\xE6\xAF\xAB", + "\x9F\x7D"=>"\xE6\xAF\xB3", + "\x9F\x7E"=>"\xE6\xAF\xAF", + "\x9F\x80"=>"\xE9\xBA\xBE", + "\x9F\x81"=>"\xE6\xB0\x88", + "\x9F\x82"=>"\xE6\xB0\x93", + "\x9F\x83"=>"\xE6\xB0\x94", + "\x9F\x84"=>"\xE6\xB0\x9B", + "\x9F\x85"=>"\xE6\xB0\xA4", + "\x9F\x86"=>"\xE6\xB0\xA3", + "\x9F\x87"=>"\xE6\xB1\x9E", + "\x9F\x88"=>"\xE6\xB1\x95", + "\x9F\x89"=>"\xE6\xB1\xA2", + "\x9F\x8A"=>"\xE6\xB1\xAA", + "\x9F\x8B"=>"\xE6\xB2\x82", + "\x9F\x8C"=>"\xE6\xB2\x8D", + "\x9F\x8D"=>"\xE6\xB2\x9A", + "\x9F\x8E"=>"\xE6\xB2\x81", + "\x9F\x8F"=>"\xE6\xB2\x9B", + "\x9F\x90"=>"\xE6\xB1\xBE", + "\x9F\x91"=>"\xE6\xB1\xA8", + "\x9F\x92"=>"\xE6\xB1\xB3", + "\x9F\x93"=>"\xE6\xB2\x92", + "\x9F\x94"=>"\xE6\xB2\x90", + "\x9F\x95"=>"\xE6\xB3\x84", + "\x9F\x96"=>"\xE6\xB3\xB1", + "\x9F\x97"=>"\xE6\xB3\x93", + "\x9F\x98"=>"\xE6\xB2\xBD", + "\x9F\x99"=>"\xE6\xB3\x97", + "\x9F\x9A"=>"\xE6\xB3\x85", + "\x9F\x9B"=>"\xE6\xB3\x9D", + "\x9F\x9C"=>"\xE6\xB2\xAE", + "\x9F\x9D"=>"\xE6\xB2\xB1", + "\x9F\x9E"=>"\xE6\xB2\xBE", + "\x9F\x9F"=>"\xE6\xB2\xBA", + "\x9F\xA0"=>"\xE6\xB3\x9B", + "\x9F\xA1"=>"\xE6\xB3\xAF", + "\x9F\xA2"=>"\xE6\xB3\x99", + "\x9F\xA3"=>"\xE6\xB3\xAA", + "\x9F\xA4"=>"\xE6\xB4\x9F", + "\x9F\xA5"=>"\xE8\xA1\x8D", + "\x9F\xA6"=>"\xE6\xB4\xB6", + "\x9F\xA7"=>"\xE6\xB4\xAB", + "\x9F\xA8"=>"\xE6\xB4\xBD", + "\x9F\xA9"=>"\xE6\xB4\xB8", + "\x9F\xAA"=>"\xE6\xB4\x99", + "\x9F\xAB"=>"\xE6\xB4\xB5", + "\x9F\xAC"=>"\xE6\xB4\xB3", + "\x9F\xAD"=>"\xE6\xB4\x92", + "\x9F\xAE"=>"\xE6\xB4\x8C", + "\x9F\xAF"=>"\xE6\xB5\xA3", + "\x9F\xB0"=>"\xE6\xB6\x93", + "\x9F\xB1"=>"\xE6\xB5\xA4", + "\x9F\xB2"=>"\xE6\xB5\x9A", + "\x9F\xB3"=>"\xE6\xB5\xB9", + "\x9F\xB4"=>"\xE6\xB5\x99", + "\x9F\xB5"=>"\xE6\xB6\x8E", + "\x9F\xB6"=>"\xE6\xB6\x95", + "\x9F\xB7"=>"\xE6\xBF\xA4", + "\x9F\xB8"=>"\xE6\xB6\x85", + "\x9F\xB9"=>"\xE6\xB7\xB9", + "\x9F\xBA"=>"\xE6\xB8\x95", + "\x9F\xBB"=>"\xE6\xB8\x8A", + "\x9F\xBC"=>"\xE6\xB6\xB5", + "\x9F\xBD"=>"\xE6\xB7\x87", + "\x9F\xBE"=>"\xE6\xB7\xA6", + "\x9F\xBF"=>"\xE6\xB6\xB8", + "\x9F\xC0"=>"\xE6\xB7\x86", + "\x9F\xC1"=>"\xE6\xB7\xAC", + "\x9F\xC2"=>"\xE6\xB7\x9E", + "\x9F\xC3"=>"\xE6\xB7\x8C", + "\x9F\xC4"=>"\xE6\xB7\xA8", + "\x9F\xC5"=>"\xE6\xB7\x92", + "\x9F\xC6"=>"\xE6\xB7\x85", + "\x9F\xC7"=>"\xE6\xB7\xBA", + "\x9F\xC8"=>"\xE6\xB7\x99", + "\x9F\xC9"=>"\xE6\xB7\xA4", + "\x9F\xCA"=>"\xE6\xB7\x95", + "\x9F\xCB"=>"\xE6\xB7\xAA", + "\x9F\xCC"=>"\xE6\xB7\xAE", + "\x9F\xCD"=>"\xE6\xB8\xAD", + "\x9F\xCE"=>"\xE6\xB9\xAE", + "\x9F\xCF"=>"\xE6\xB8\xAE", + "\x9F\xD0"=>"\xE6\xB8\x99", + "\x9F\xD1"=>"\xE6\xB9\xB2", + "\x9F\xD2"=>"\xE6\xB9\x9F", + "\x9F\xD3"=>"\xE6\xB8\xBE", + "\x9F\xD4"=>"\xE6\xB8\xA3", + "\x9F\xD5"=>"\xE6\xB9\xAB", + "\x9F\xD6"=>"\xE6\xB8\xAB", + "\x9F\xD7"=>"\xE6\xB9\xB6", + "\x9F\xD8"=>"\xE6\xB9\x8D", + "\x9F\xD9"=>"\xE6\xB8\x9F", + "\x9F\xDA"=>"\xE6\xB9\x83", + "\x9F\xDB"=>"\xE6\xB8\xBA", + "\x9F\xDC"=>"\xE6\xB9\x8E", + "\x9F\xDD"=>"\xE6\xB8\xA4", + "\x9F\xDE"=>"\xE6\xBB\xBF", + "\x9F\xDF"=>"\xE6\xB8\x9D", + "\x9F\xE0"=>"\xE6\xB8\xB8", + "\x9F\xE1"=>"\xE6\xBA\x82", + "\x9F\xE2"=>"\xE6\xBA\xAA", + "\x9F\xE3"=>"\xE6\xBA\x98", + "\x9F\xE4"=>"\xE6\xBB\x89", + "\x9F\xE5"=>"\xE6\xBA\xB7", + "\x9F\xE6"=>"\xE6\xBB\x93", + "\x9F\xE7"=>"\xE6\xBA\xBD", + "\x9F\xE8"=>"\xE6\xBA\xAF", + "\x9F\xE9"=>"\xE6\xBB\x84", + "\x9F\xEA"=>"\xE6\xBA\xB2", + "\x9F\xEB"=>"\xE6\xBB\x94", + "\x9F\xEC"=>"\xE6\xBB\x95", + "\x9F\xED"=>"\xE6\xBA\x8F", + "\x9F\xEE"=>"\xE6\xBA\xA5", + "\x9F\xEF"=>"\xE6\xBB\x82", + "\x9F\xF0"=>"\xE6\xBA\x9F", + "\x9F\xF1"=>"\xE6\xBD\x81", + "\x9F\xF2"=>"\xE6\xBC\x91", + "\x9F\xF3"=>"\xE7\x81\x8C", + "\x9F\xF4"=>"\xE6\xBB\xAC", + "\x9F\xF5"=>"\xE6\xBB\xB8", + "\x9F\xF6"=>"\xE6\xBB\xBE", + "\x9F\xF7"=>"\xE6\xBC\xBF", + "\x9F\xF8"=>"\xE6\xBB\xB2", + "\x9F\xF9"=>"\xE6\xBC\xB1", + "\x9F\xFA"=>"\xE6\xBB\xAF", + "\x9F\xFB"=>"\xE6\xBC\xB2", + "\x9F\xFC"=>"\xE6\xBB\x8C", + "\xA1"=>"\xEF\xBD\xA1", + "\xA2"=>"\xEF\xBD\xA2", + "\xA3"=>"\xEF\xBD\xA3", + "\xA4"=>"\xEF\xBD\xA4", + "\xA5"=>"\xEF\xBD\xA5", + "\xA6"=>"\xEF\xBD\xA6", + "\xA7"=>"\xEF\xBD\xA7", + "\xA8"=>"\xEF\xBD\xA8", + "\xA9"=>"\xEF\xBD\xA9", + "\xAA"=>"\xEF\xBD\xAA", + "\xAB"=>"\xEF\xBD\xAB", + "\xAC"=>"\xEF\xBD\xAC", + "\xAD"=>"\xEF\xBD\xAD", + "\xAE"=>"\xEF\xBD\xAE", + "\xAF"=>"\xEF\xBD\xAF", + "\xB0"=>"\xEF\xBD\xB0", + "\xB1"=>"\xEF\xBD\xB1", + "\xB2"=>"\xEF\xBD\xB2", + "\xB3"=>"\xEF\xBD\xB3", + "\xB4"=>"\xEF\xBD\xB4", + "\xB5"=>"\xEF\xBD\xB5", + "\xB6"=>"\xEF\xBD\xB6", + "\xB7"=>"\xEF\xBD\xB7", + "\xB8"=>"\xEF\xBD\xB8", + "\xB9"=>"\xEF\xBD\xB9", + "\xBA"=>"\xEF\xBD\xBA", + "\xBB"=>"\xEF\xBD\xBB", + "\xBC"=>"\xEF\xBD\xBC", + "\xBD"=>"\xEF\xBD\xBD", + "\xBE"=>"\xEF\xBD\xBE", + "\xBF"=>"\xEF\xBD\xBF", + "\xC0"=>"\xEF\xBE\x80", + "\xC1"=>"\xEF\xBE\x81", + "\xC2"=>"\xEF\xBE\x82", + "\xC3"=>"\xEF\xBE\x83", + "\xC4"=>"\xEF\xBE\x84", + "\xC5"=>"\xEF\xBE\x85", + "\xC6"=>"\xEF\xBE\x86", + "\xC7"=>"\xEF\xBE\x87", + "\xC8"=>"\xEF\xBE\x88", + "\xC9"=>"\xEF\xBE\x89", + "\xCA"=>"\xEF\xBE\x8A", + "\xCB"=>"\xEF\xBE\x8B", + "\xCC"=>"\xEF\xBE\x8C", + "\xCD"=>"\xEF\xBE\x8D", + "\xCE"=>"\xEF\xBE\x8E", + "\xCF"=>"\xEF\xBE\x8F", + "\xD0"=>"\xEF\xBE\x90", + "\xD1"=>"\xEF\xBE\x91", + "\xD2"=>"\xEF\xBE\x92", + "\xD3"=>"\xEF\xBE\x93", + "\xD4"=>"\xEF\xBE\x94", + "\xD5"=>"\xEF\xBE\x95", + "\xD6"=>"\xEF\xBE\x96", + "\xD7"=>"\xEF\xBE\x97", + "\xD8"=>"\xEF\xBE\x98", + "\xD9"=>"\xEF\xBE\x99", + "\xDA"=>"\xEF\xBE\x9A", + "\xDB"=>"\xEF\xBE\x9B", + "\xDC"=>"\xEF\xBE\x9C", + "\xDD"=>"\xEF\xBE\x9D", + "\xDE"=>"\xEF\xBE\x9E", + "\xDF"=>"\xEF\xBE\x9F", + "\xE0\x40"=>"\xE6\xBC\xBE", + "\xE0\x41"=>"\xE6\xBC\x93", + "\xE0\x42"=>"\xE6\xBB\xB7", + "\xE0\x43"=>"\xE6\xBE\x86", + "\xE0\x44"=>"\xE6\xBD\xBA", + "\xE0\x45"=>"\xE6\xBD\xB8", + "\xE0\x46"=>"\xE6\xBE\x81", + "\xE0\x47"=>"\xE6\xBE\x80", + "\xE0\x48"=>"\xE6\xBD\xAF", + "\xE0\x49"=>"\xE6\xBD\x9B", + "\xE0\x4A"=>"\xE6\xBF\xB3", + "\xE0\x4B"=>"\xE6\xBD\xAD", + "\xE0\x4C"=>"\xE6\xBE\x82", + "\xE0\x4D"=>"\xE6\xBD\xBC", + "\xE0\x4E"=>"\xE6\xBD\x98", + "\xE0\x4F"=>"\xE6\xBE\x8E", + "\xE0\x50"=>"\xE6\xBE\x91", + "\xE0\x51"=>"\xE6\xBF\x82", + "\xE0\x52"=>"\xE6\xBD\xA6", + "\xE0\x53"=>"\xE6\xBE\xB3", + "\xE0\x54"=>"\xE6\xBE\xA3", + "\xE0\x55"=>"\xE6\xBE\xA1", + "\xE0\x56"=>"\xE6\xBE\xA4", + "\xE0\x57"=>"\xE6\xBE\xB9", + "\xE0\x58"=>"\xE6\xBF\x86", + "\xE0\x59"=>"\xE6\xBE\xAA", + "\xE0\x5A"=>"\xE6\xBF\x9F", + "\xE0\x5B"=>"\xE6\xBF\x95", + "\xE0\x5C"=>"\xE6\xBF\xAC", + "\xE0\x5D"=>"\xE6\xBF\x94", + "\xE0\x5E"=>"\xE6\xBF\x98", + "\xE0\x5F"=>"\xE6\xBF\xB1", + "\xE0\x60"=>"\xE6\xBF\xAE", + "\xE0\x61"=>"\xE6\xBF\x9B", + "\xE0\x62"=>"\xE7\x80\x89", + "\xE0\x63"=>"\xE7\x80\x8B", + "\xE0\x64"=>"\xE6\xBF\xBA", + "\xE0\x65"=>"\xE7\x80\x91", + "\xE0\x66"=>"\xE7\x80\x81", + "\xE0\x67"=>"\xE7\x80\x8F", + "\xE0\x68"=>"\xE6\xBF\xBE", + "\xE0\x69"=>"\xE7\x80\x9B", + "\xE0\x6A"=>"\xE7\x80\x9A", + "\xE0\x6B"=>"\xE6\xBD\xB4", + "\xE0\x6C"=>"\xE7\x80\x9D", + "\xE0\x6D"=>"\xE7\x80\x98", + "\xE0\x6E"=>"\xE7\x80\x9F", + "\xE0\x6F"=>"\xE7\x80\xB0", + "\xE0\x70"=>"\xE7\x80\xBE", + "\xE0\x71"=>"\xE7\x80\xB2", + "\xE0\x72"=>"\xE7\x81\x91", + "\xE0\x73"=>"\xE7\x81\xA3", + "\xE0\x74"=>"\xE7\x82\x99", + "\xE0\x75"=>"\xE7\x82\x92", + "\xE0\x76"=>"\xE7\x82\xAF", + "\xE0\x77"=>"\xE7\x83\xB1", + "\xE0\x78"=>"\xE7\x82\xAC", + "\xE0\x79"=>"\xE7\x82\xB8", + "\xE0\x7A"=>"\xE7\x82\xB3", + "\xE0\x7B"=>"\xE7\x82\xAE", + "\xE0\x7C"=>"\xE7\x83\x9F", + "\xE0\x7D"=>"\xE7\x83\x8B", + "\xE0\x7E"=>"\xE7\x83\x9D", + "\xE0\x80"=>"\xE7\x83\x99", + "\xE0\x81"=>"\xE7\x84\x89", + "\xE0\x82"=>"\xE7\x83\xBD", + "\xE0\x83"=>"\xE7\x84\x9C", + "\xE0\x84"=>"\xE7\x84\x99", + "\xE0\x85"=>"\xE7\x85\xA5", + "\xE0\x86"=>"\xE7\x85\x95", + "\xE0\x87"=>"\xE7\x86\x88", + "\xE0\x88"=>"\xE7\x85\xA6", + "\xE0\x89"=>"\xE7\x85\xA2", + "\xE0\x8A"=>"\xE7\x85\x8C", + "\xE0\x8B"=>"\xE7\x85\x96", + "\xE0\x8C"=>"\xE7\x85\xAC", + "\xE0\x8D"=>"\xE7\x86\x8F", + "\xE0\x8E"=>"\xE7\x87\xBB", + "\xE0\x8F"=>"\xE7\x86\x84", + "\xE0\x90"=>"\xE7\x86\x95", + "\xE0\x91"=>"\xE7\x86\xA8", + "\xE0\x92"=>"\xE7\x86\xAC", + "\xE0\x93"=>"\xE7\x87\x97", + "\xE0\x94"=>"\xE7\x86\xB9", + "\xE0\x95"=>"\xE7\x86\xBE", + "\xE0\x96"=>"\xE7\x87\x92", + "\xE0\x97"=>"\xE7\x87\x89", + "\xE0\x98"=>"\xE7\x87\x94", + "\xE0\x99"=>"\xE7\x87\x8E", + "\xE0\x9A"=>"\xE7\x87\xA0", + "\xE0\x9B"=>"\xE7\x87\xAC", + "\xE0\x9C"=>"\xE7\x87\xA7", + "\xE0\x9D"=>"\xE7\x87\xB5", + "\xE0\x9E"=>"\xE7\x87\xBC", + "\xE0\x9F"=>"\xE7\x87\xB9", + "\xE0\xA0"=>"\xE7\x87\xBF", + "\xE0\xA1"=>"\xE7\x88\x8D", + "\xE0\xA2"=>"\xE7\x88\x90", + "\xE0\xA3"=>"\xE7\x88\x9B", + "\xE0\xA4"=>"\xE7\x88\xA8", + "\xE0\xA5"=>"\xE7\x88\xAD", + "\xE0\xA6"=>"\xE7\x88\xAC", + "\xE0\xA7"=>"\xE7\x88\xB0", + "\xE0\xA8"=>"\xE7\x88\xB2", + "\xE0\xA9"=>"\xE7\x88\xBB", + "\xE0\xAA"=>"\xE7\x88\xBC", + "\xE0\xAB"=>"\xE7\x88\xBF", + "\xE0\xAC"=>"\xE7\x89\x80", + "\xE0\xAD"=>"\xE7\x89\x86", + "\xE0\xAE"=>"\xE7\x89\x8B", + "\xE0\xAF"=>"\xE7\x89\x98", + "\xE0\xB0"=>"\xE7\x89\xB4", + "\xE0\xB1"=>"\xE7\x89\xBE", + "\xE0\xB2"=>"\xE7\x8A\x82", + "\xE0\xB3"=>"\xE7\x8A\x81", + "\xE0\xB4"=>"\xE7\x8A\x87", + "\xE0\xB5"=>"\xE7\x8A\x92", + "\xE0\xB6"=>"\xE7\x8A\x96", + "\xE0\xB7"=>"\xE7\x8A\xA2", + "\xE0\xB8"=>"\xE7\x8A\xA7", + "\xE0\xB9"=>"\xE7\x8A\xB9", + "\xE0\xBA"=>"\xE7\x8A\xB2", + "\xE0\xBB"=>"\xE7\x8B\x83", + "\xE0\xBC"=>"\xE7\x8B\x86", + "\xE0\xBD"=>"\xE7\x8B\x84", + "\xE0\xBE"=>"\xE7\x8B\x8E", + "\xE0\xBF"=>"\xE7\x8B\x92", + "\xE0\xC0"=>"\xE7\x8B\xA2", + "\xE0\xC1"=>"\xE7\x8B\xA0", + "\xE0\xC2"=>"\xE7\x8B\xA1", + "\xE0\xC3"=>"\xE7\x8B\xB9", + "\xE0\xC4"=>"\xE7\x8B\xB7", + "\xE0\xC5"=>"\xE5\x80\x8F", + "\xE0\xC6"=>"\xE7\x8C\x97", + "\xE0\xC7"=>"\xE7\x8C\x8A", + "\xE0\xC8"=>"\xE7\x8C\x9C", + "\xE0\xC9"=>"\xE7\x8C\x96", + "\xE0\xCA"=>"\xE7\x8C\x9D", + "\xE0\xCB"=>"\xE7\x8C\xB4", + "\xE0\xCC"=>"\xE7\x8C\xAF", + "\xE0\xCD"=>"\xE7\x8C\xA9", + "\xE0\xCE"=>"\xE7\x8C\xA5", + "\xE0\xCF"=>"\xE7\x8C\xBE", + "\xE0\xD0"=>"\xE7\x8D\x8E", + "\xE0\xD1"=>"\xE7\x8D\x8F", + "\xE0\xD2"=>"\xE9\xBB\x98", + "\xE0\xD3"=>"\xE7\x8D\x97", + "\xE0\xD4"=>"\xE7\x8D\xAA", + "\xE0\xD5"=>"\xE7\x8D\xA8", + "\xE0\xD6"=>"\xE7\x8D\xB0", + "\xE0\xD7"=>"\xE7\x8D\xB8", + "\xE0\xD8"=>"\xE7\x8D\xB5", + "\xE0\xD9"=>"\xE7\x8D\xBB", + "\xE0\xDA"=>"\xE7\x8D\xBA", + "\xE0\xDB"=>"\xE7\x8F\x88", + "\xE0\xDC"=>"\xE7\x8E\xB3", + "\xE0\xDD"=>"\xE7\x8F\x8E", + "\xE0\xDE"=>"\xE7\x8E\xBB", + "\xE0\xDF"=>"\xE7\x8F\x80", + "\xE0\xE0"=>"\xE7\x8F\xA5", + "\xE0\xE1"=>"\xE7\x8F\xAE", + "\xE0\xE2"=>"\xE7\x8F\x9E", + "\xE0\xE3"=>"\xE7\x92\xA2", + "\xE0\xE4"=>"\xE7\x90\x85", + "\xE0\xE5"=>"\xE7\x91\xAF", + "\xE0\xE6"=>"\xE7\x90\xA5", + "\xE0\xE7"=>"\xE7\x8F\xB8", + "\xE0\xE8"=>"\xE7\x90\xB2", + "\xE0\xE9"=>"\xE7\x90\xBA", + "\xE0\xEA"=>"\xE7\x91\x95", + "\xE0\xEB"=>"\xE7\x90\xBF", + "\xE0\xEC"=>"\xE7\x91\x9F", + "\xE0\xED"=>"\xE7\x91\x99", + "\xE0\xEE"=>"\xE7\x91\x81", + "\xE0\xEF"=>"\xE7\x91\x9C", + "\xE0\xF0"=>"\xE7\x91\xA9", + "\xE0\xF1"=>"\xE7\x91\xB0", + "\xE0\xF2"=>"\xE7\x91\xA3", + "\xE0\xF3"=>"\xE7\x91\xAA", + "\xE0\xF4"=>"\xE7\x91\xB6", + "\xE0\xF5"=>"\xE7\x91\xBE", + "\xE0\xF6"=>"\xE7\x92\x8B", + "\xE0\xF7"=>"\xE7\x92\x9E", + "\xE0\xF8"=>"\xE7\x92\xA7", + "\xE0\xF9"=>"\xE7\x93\x8A", + "\xE0\xFA"=>"\xE7\x93\x8F", + "\xE0\xFB"=>"\xE7\x93\x94", + "\xE0\xFC"=>"\xE7\x8F\xB1", + "\xE1\x40"=>"\xE7\x93\xA0", + "\xE1\x41"=>"\xE7\x93\xA3", + "\xE1\x42"=>"\xE7\x93\xA7", + "\xE1\x43"=>"\xE7\x93\xA9", + "\xE1\x44"=>"\xE7\x93\xAE", + "\xE1\x45"=>"\xE7\x93\xB2", + "\xE1\x46"=>"\xE7\x93\xB0", + "\xE1\x47"=>"\xE7\x93\xB1", + "\xE1\x48"=>"\xE7\x93\xB8", + "\xE1\x49"=>"\xE7\x93\xB7", + "\xE1\x4A"=>"\xE7\x94\x84", + "\xE1\x4B"=>"\xE7\x94\x83", + "\xE1\x4C"=>"\xE7\x94\x85", + "\xE1\x4D"=>"\xE7\x94\x8C", + "\xE1\x4E"=>"\xE7\x94\x8E", + "\xE1\x4F"=>"\xE7\x94\x8D", + "\xE1\x50"=>"\xE7\x94\x95", + "\xE1\x51"=>"\xE7\x94\x93", + "\xE1\x52"=>"\xE7\x94\x9E", + "\xE1\x53"=>"\xE7\x94\xA6", + "\xE1\x54"=>"\xE7\x94\xAC", + "\xE1\x55"=>"\xE7\x94\xBC", + "\xE1\x56"=>"\xE7\x95\x84", + "\xE1\x57"=>"\xE7\x95\x8D", + "\xE1\x58"=>"\xE7\x95\x8A", + "\xE1\x59"=>"\xE7\x95\x89", + "\xE1\x5A"=>"\xE7\x95\x9B", + "\xE1\x5B"=>"\xE7\x95\x86", + "\xE1\x5C"=>"\xE7\x95\x9A", + "\xE1\x5D"=>"\xE7\x95\xA9", + "\xE1\x5E"=>"\xE7\x95\xA4", + "\xE1\x5F"=>"\xE7\x95\xA7", + "\xE1\x60"=>"\xE7\x95\xAB", + "\xE1\x61"=>"\xE7\x95\xAD", + "\xE1\x62"=>"\xE7\x95\xB8", + "\xE1\x63"=>"\xE7\x95\xB6", + "\xE1\x64"=>"\xE7\x96\x86", + "\xE1\x65"=>"\xE7\x96\x87", + "\xE1\x66"=>"\xE7\x95\xB4", + "\xE1\x67"=>"\xE7\x96\x8A", + "\xE1\x68"=>"\xE7\x96\x89", + "\xE1\x69"=>"\xE7\x96\x82", + "\xE1\x6A"=>"\xE7\x96\x94", + "\xE1\x6B"=>"\xE7\x96\x9A", + "\xE1\x6C"=>"\xE7\x96\x9D", + "\xE1\x6D"=>"\xE7\x96\xA5", + "\xE1\x6E"=>"\xE7\x96\xA3", + "\xE1\x6F"=>"\xE7\x97\x82", + "\xE1\x70"=>"\xE7\x96\xB3", + "\xE1\x71"=>"\xE7\x97\x83", + "\xE1\x72"=>"\xE7\x96\xB5", + "\xE1\x73"=>"\xE7\x96\xBD", + "\xE1\x74"=>"\xE7\x96\xB8", + "\xE1\x75"=>"\xE7\x96\xBC", + "\xE1\x76"=>"\xE7\x96\xB1", + "\xE1\x77"=>"\xE7\x97\x8D", + "\xE1\x78"=>"\xE7\x97\x8A", + "\xE1\x79"=>"\xE7\x97\x92", + "\xE1\x7A"=>"\xE7\x97\x99", + "\xE1\x7B"=>"\xE7\x97\xA3", + "\xE1\x7C"=>"\xE7\x97\x9E", + "\xE1\x7D"=>"\xE7\x97\xBE", + "\xE1\x7E"=>"\xE7\x97\xBF", + "\xE1\x80"=>"\xE7\x97\xBC", + "\xE1\x81"=>"\xE7\x98\x81", + "\xE1\x82"=>"\xE7\x97\xB0", + "\xE1\x83"=>"\xE7\x97\xBA", + "\xE1\x84"=>"\xE7\x97\xB2", + "\xE1\x85"=>"\xE7\x97\xB3", + "\xE1\x86"=>"\xE7\x98\x8B", + "\xE1\x87"=>"\xE7\x98\x8D", + "\xE1\x88"=>"\xE7\x98\x89", + "\xE1\x89"=>"\xE7\x98\x9F", + "\xE1\x8A"=>"\xE7\x98\xA7", + "\xE1\x8B"=>"\xE7\x98\xA0", + "\xE1\x8C"=>"\xE7\x98\xA1", + "\xE1\x8D"=>"\xE7\x98\xA2", + "\xE1\x8E"=>"\xE7\x98\xA4", + "\xE1\x8F"=>"\xE7\x98\xB4", + "\xE1\x90"=>"\xE7\x98\xB0", + "\xE1\x91"=>"\xE7\x98\xBB", + "\xE1\x92"=>"\xE7\x99\x87", + "\xE1\x93"=>"\xE7\x99\x88", + "\xE1\x94"=>"\xE7\x99\x86", + "\xE1\x95"=>"\xE7\x99\x9C", + "\xE1\x96"=>"\xE7\x99\x98", + "\xE1\x97"=>"\xE7\x99\xA1", + "\xE1\x98"=>"\xE7\x99\xA2", + "\xE1\x99"=>"\xE7\x99\xA8", + "\xE1\x9A"=>"\xE7\x99\xA9", + "\xE1\x9B"=>"\xE7\x99\xAA", + "\xE1\x9C"=>"\xE7\x99\xA7", + "\xE1\x9D"=>"\xE7\x99\xAC", + "\xE1\x9E"=>"\xE7\x99\xB0", + "\xE1\x9F"=>"\xE7\x99\xB2", + "\xE1\xA0"=>"\xE7\x99\xB6", + "\xE1\xA1"=>"\xE7\x99\xB8", + "\xE1\xA2"=>"\xE7\x99\xBC", + "\xE1\xA3"=>"\xE7\x9A\x80", + "\xE1\xA4"=>"\xE7\x9A\x83", + "\xE1\xA5"=>"\xE7\x9A\x88", + "\xE1\xA6"=>"\xE7\x9A\x8B", + "\xE1\xA7"=>"\xE7\x9A\x8E", + "\xE1\xA8"=>"\xE7\x9A\x96", + "\xE1\xA9"=>"\xE7\x9A\x93", + "\xE1\xAA"=>"\xE7\x9A\x99", + "\xE1\xAB"=>"\xE7\x9A\x9A", + "\xE1\xAC"=>"\xE7\x9A\xB0", + "\xE1\xAD"=>"\xE7\x9A\xB4", + "\xE1\xAE"=>"\xE7\x9A\xB8", + "\xE1\xAF"=>"\xE7\x9A\xB9", + "\xE1\xB0"=>"\xE7\x9A\xBA", + "\xE1\xB1"=>"\xE7\x9B\x82", + "\xE1\xB2"=>"\xE7\x9B\x8D", + "\xE1\xB3"=>"\xE7\x9B\x96", + "\xE1\xB4"=>"\xE7\x9B\x92", + "\xE1\xB5"=>"\xE7\x9B\x9E", + "\xE1\xB6"=>"\xE7\x9B\xA1", + "\xE1\xB7"=>"\xE7\x9B\xA5", + "\xE1\xB8"=>"\xE7\x9B\xA7", + "\xE1\xB9"=>"\xE7\x9B\xAA", + "\xE1\xBA"=>"\xE8\x98\xAF", + "\xE1\xBB"=>"\xE7\x9B\xBB", + "\xE1\xBC"=>"\xE7\x9C\x88", + "\xE1\xBD"=>"\xE7\x9C\x87", + "\xE1\xBE"=>"\xE7\x9C\x84", + "\xE1\xBF"=>"\xE7\x9C\xA9", + "\xE1\xC0"=>"\xE7\x9C\xA4", + "\xE1\xC1"=>"\xE7\x9C\x9E", + "\xE1\xC2"=>"\xE7\x9C\xA5", + "\xE1\xC3"=>"\xE7\x9C\xA6", + "\xE1\xC4"=>"\xE7\x9C\x9B", + "\xE1\xC5"=>"\xE7\x9C\xB7", + "\xE1\xC6"=>"\xE7\x9C\xB8", + "\xE1\xC7"=>"\xE7\x9D\x87", + "\xE1\xC8"=>"\xE7\x9D\x9A", + "\xE1\xC9"=>"\xE7\x9D\xA8", + "\xE1\xCA"=>"\xE7\x9D\xAB", + "\xE1\xCB"=>"\xE7\x9D\x9B", + "\xE1\xCC"=>"\xE7\x9D\xA5", + "\xE1\xCD"=>"\xE7\x9D\xBF", + "\xE1\xCE"=>"\xE7\x9D\xBE", + "\xE1\xCF"=>"\xE7\x9D\xB9", + "\xE1\xD0"=>"\xE7\x9E\x8E", + "\xE1\xD1"=>"\xE7\x9E\x8B", + "\xE1\xD2"=>"\xE7\x9E\x91", + "\xE1\xD3"=>"\xE7\x9E\xA0", + "\xE1\xD4"=>"\xE7\x9E\x9E", + "\xE1\xD5"=>"\xE7\x9E\xB0", + "\xE1\xD6"=>"\xE7\x9E\xB6", + "\xE1\xD7"=>"\xE7\x9E\xB9", + "\xE1\xD8"=>"\xE7\x9E\xBF", + "\xE1\xD9"=>"\xE7\x9E\xBC", + "\xE1\xDA"=>"\xE7\x9E\xBD", + "\xE1\xDB"=>"\xE7\x9E\xBB", + "\xE1\xDC"=>"\xE7\x9F\x87", + "\xE1\xDD"=>"\xE7\x9F\x8D", + "\xE1\xDE"=>"\xE7\x9F\x97", + "\xE1\xDF"=>"\xE7\x9F\x9A", + "\xE1\xE0"=>"\xE7\x9F\x9C", + "\xE1\xE1"=>"\xE7\x9F\xA3", + "\xE1\xE2"=>"\xE7\x9F\xAE", + "\xE1\xE3"=>"\xE7\x9F\xBC", + "\xE1\xE4"=>"\xE7\xA0\x8C", + "\xE1\xE5"=>"\xE7\xA0\x92", + "\xE1\xE6"=>"\xE7\xA4\xA6", + "\xE1\xE7"=>"\xE7\xA0\xA0", + "\xE1\xE8"=>"\xE7\xA4\xAA", + "\xE1\xE9"=>"\xE7\xA1\x85", + "\xE1\xEA"=>"\xE7\xA2\x8E", + "\xE1\xEB"=>"\xE7\xA1\xB4", + "\xE1\xEC"=>"\xE7\xA2\x86", + "\xE1\xED"=>"\xE7\xA1\xBC", + "\xE1\xEE"=>"\xE7\xA2\x9A", + "\xE1\xEF"=>"\xE7\xA2\x8C", + "\xE1\xF0"=>"\xE7\xA2\xA3", + "\xE1\xF1"=>"\xE7\xA2\xB5", + "\xE1\xF2"=>"\xE7\xA2\xAA", + "\xE1\xF3"=>"\xE7\xA2\xAF", + "\xE1\xF4"=>"\xE7\xA3\x91", + "\xE1\xF5"=>"\xE7\xA3\x86", + "\xE1\xF6"=>"\xE7\xA3\x8B", + "\xE1\xF7"=>"\xE7\xA3\x94", + "\xE1\xF8"=>"\xE7\xA2\xBE", + "\xE1\xF9"=>"\xE7\xA2\xBC", + "\xE1\xFA"=>"\xE7\xA3\x85", + "\xE1\xFB"=>"\xE7\xA3\x8A", + "\xE1\xFC"=>"\xE7\xA3\xAC", + "\xE2\x40"=>"\xE7\xA3\xA7", + "\xE2\x41"=>"\xE7\xA3\x9A", + "\xE2\x42"=>"\xE7\xA3\xBD", + "\xE2\x43"=>"\xE7\xA3\xB4", + "\xE2\x44"=>"\xE7\xA4\x87", + "\xE2\x45"=>"\xE7\xA4\x92", + "\xE2\x46"=>"\xE7\xA4\x91", + "\xE2\x47"=>"\xE7\xA4\x99", + "\xE2\x48"=>"\xE7\xA4\xAC", + "\xE2\x49"=>"\xE7\xA4\xAB", + "\xE2\x4A"=>"\xE7\xA5\x80", + "\xE2\x4B"=>"\xE7\xA5\xA0", + "\xE2\x4C"=>"\xE7\xA5\x97", + "\xE2\x4D"=>"\xE7\xA5\x9F", + "\xE2\x4E"=>"\xE7\xA5\x9A", + "\xE2\x4F"=>"\xE7\xA5\x95", + "\xE2\x50"=>"\xE7\xA5\x93", + "\xE2\x51"=>"\xE7\xA5\xBA", + "\xE2\x52"=>"\xE7\xA5\xBF", + "\xE2\x53"=>"\xE7\xA6\x8A", + "\xE2\x54"=>"\xE7\xA6\x9D", + "\xE2\x55"=>"\xE7\xA6\xA7", + "\xE2\x56"=>"\xE9\xBD\x8B", + "\xE2\x57"=>"\xE7\xA6\xAA", + "\xE2\x58"=>"\xE7\xA6\xAE", + "\xE2\x59"=>"\xE7\xA6\xB3", + "\xE2\x5A"=>"\xE7\xA6\xB9", + "\xE2\x5B"=>"\xE7\xA6\xBA", + "\xE2\x5C"=>"\xE7\xA7\x89", + "\xE2\x5D"=>"\xE7\xA7\x95", + "\xE2\x5E"=>"\xE7\xA7\xA7", + "\xE2\x5F"=>"\xE7\xA7\xAC", + "\xE2\x60"=>"\xE7\xA7\xA1", + "\xE2\x61"=>"\xE7\xA7\xA3", + "\xE2\x62"=>"\xE7\xA8\x88", + "\xE2\x63"=>"\xE7\xA8\x8D", + "\xE2\x64"=>"\xE7\xA8\x98", + "\xE2\x65"=>"\xE7\xA8\x99", + "\xE2\x66"=>"\xE7\xA8\xA0", + "\xE2\x67"=>"\xE7\xA8\x9F", + "\xE2\x68"=>"\xE7\xA6\x80", + "\xE2\x69"=>"\xE7\xA8\xB1", + "\xE2\x6A"=>"\xE7\xA8\xBB", + "\xE2\x6B"=>"\xE7\xA8\xBE", + "\xE2\x6C"=>"\xE7\xA8\xB7", + "\xE2\x6D"=>"\xE7\xA9\x83", + "\xE2\x6E"=>"\xE7\xA9\x97", + "\xE2\x6F"=>"\xE7\xA9\x89", + "\xE2\x70"=>"\xE7\xA9\xA1", + "\xE2\x71"=>"\xE7\xA9\xA2", + "\xE2\x72"=>"\xE7\xA9\xA9", + "\xE2\x73"=>"\xE9\xBE\x9D", + "\xE2\x74"=>"\xE7\xA9\xB0", + "\xE2\x75"=>"\xE7\xA9\xB9", + "\xE2\x76"=>"\xE7\xA9\xBD", + "\xE2\x77"=>"\xE7\xAA\x88", + "\xE2\x78"=>"\xE7\xAA\x97", + "\xE2\x79"=>"\xE7\xAA\x95", + "\xE2\x7A"=>"\xE7\xAA\x98", + "\xE2\x7B"=>"\xE7\xAA\x96", + "\xE2\x7C"=>"\xE7\xAA\xA9", + "\xE2\x7D"=>"\xE7\xAB\x88", + "\xE2\x7E"=>"\xE7\xAA\xB0", + "\xE2\x80"=>"\xE7\xAA\xB6", + "\xE2\x81"=>"\xE7\xAB\x85", + "\xE2\x82"=>"\xE7\xAB\x84", + "\xE2\x83"=>"\xE7\xAA\xBF", + "\xE2\x84"=>"\xE9\x82\x83", + "\xE2\x85"=>"\xE7\xAB\x87", + "\xE2\x86"=>"\xE7\xAB\x8A", + "\xE2\x87"=>"\xE7\xAB\x8D", + "\xE2\x88"=>"\xE7\xAB\x8F", + "\xE2\x89"=>"\xE7\xAB\x95", + "\xE2\x8A"=>"\xE7\xAB\x93", + "\xE2\x8B"=>"\xE7\xAB\x99", + "\xE2\x8C"=>"\xE7\xAB\x9A", + "\xE2\x8D"=>"\xE7\xAB\x9D", + "\xE2\x8E"=>"\xE7\xAB\xA1", + "\xE2\x8F"=>"\xE7\xAB\xA2", + "\xE2\x90"=>"\xE7\xAB\xA6", + "\xE2\x91"=>"\xE7\xAB\xAD", + "\xE2\x92"=>"\xE7\xAB\xB0", + "\xE2\x93"=>"\xE7\xAC\x82", + "\xE2\x94"=>"\xE7\xAC\x8F", + "\xE2\x95"=>"\xE7\xAC\x8A", + "\xE2\x96"=>"\xE7\xAC\x86", + "\xE2\x97"=>"\xE7\xAC\xB3", + "\xE2\x98"=>"\xE7\xAC\x98", + "\xE2\x99"=>"\xE7\xAC\x99", + "\xE2\x9A"=>"\xE7\xAC\x9E", + "\xE2\x9B"=>"\xE7\xAC\xB5", + "\xE2\x9C"=>"\xE7\xAC\xA8", + "\xE2\x9D"=>"\xE7\xAC\xB6", + "\xE2\x9E"=>"\xE7\xAD\x90", + "\xE2\x9F"=>"\xE7\xAD\xBA", + "\xE2\xA0"=>"\xE7\xAC\x84", + "\xE2\xA1"=>"\xE7\xAD\x8D", + "\xE2\xA2"=>"\xE7\xAC\x8B", + "\xE2\xA3"=>"\xE7\xAD\x8C", + "\xE2\xA4"=>"\xE7\xAD\x85", + "\xE2\xA5"=>"\xE7\xAD\xB5", + "\xE2\xA6"=>"\xE7\xAD\xA5", + "\xE2\xA7"=>"\xE7\xAD\xB4", + "\xE2\xA8"=>"\xE7\xAD\xA7", + "\xE2\xA9"=>"\xE7\xAD\xB0", + "\xE2\xAA"=>"\xE7\xAD\xB1", + "\xE2\xAB"=>"\xE7\xAD\xAC", + "\xE2\xAC"=>"\xE7\xAD\xAE", + "\xE2\xAD"=>"\xE7\xAE\x9D", + "\xE2\xAE"=>"\xE7\xAE\x98", + "\xE2\xAF"=>"\xE7\xAE\x9F", + "\xE2\xB0"=>"\xE7\xAE\x8D", + "\xE2\xB1"=>"\xE7\xAE\x9C", + "\xE2\xB2"=>"\xE7\xAE\x9A", + "\xE2\xB3"=>"\xE7\xAE\x8B", + "\xE2\xB4"=>"\xE7\xAE\x92", + "\xE2\xB5"=>"\xE7\xAE\x8F", + "\xE2\xB6"=>"\xE7\xAD\x9D", + "\xE2\xB7"=>"\xE7\xAE\x99", + "\xE2\xB8"=>"\xE7\xAF\x8B", + "\xE2\xB9"=>"\xE7\xAF\x81", + "\xE2\xBA"=>"\xE7\xAF\x8C", + "\xE2\xBB"=>"\xE7\xAF\x8F", + "\xE2\xBC"=>"\xE7\xAE\xB4", + "\xE2\xBD"=>"\xE7\xAF\x86", + "\xE2\xBE"=>"\xE7\xAF\x9D", + "\xE2\xBF"=>"\xE7\xAF\xA9", + "\xE2\xC0"=>"\xE7\xB0\x91", + "\xE2\xC1"=>"\xE7\xB0\x94", + "\xE2\xC2"=>"\xE7\xAF\xA6", + "\xE2\xC3"=>"\xE7\xAF\xA5", + "\xE2\xC4"=>"\xE7\xB1\xA0", + "\xE2\xC5"=>"\xE7\xB0\x80", + "\xE2\xC6"=>"\xE7\xB0\x87", + "\xE2\xC7"=>"\xE7\xB0\x93", + "\xE2\xC8"=>"\xE7\xAF\xB3", + "\xE2\xC9"=>"\xE7\xAF\xB7", + "\xE2\xCA"=>"\xE7\xB0\x97", + "\xE2\xCB"=>"\xE7\xB0\x8D", + "\xE2\xCC"=>"\xE7\xAF\xB6", + "\xE2\xCD"=>"\xE7\xB0\xA3", + "\xE2\xCE"=>"\xE7\xB0\xA7", + "\xE2\xCF"=>"\xE7\xB0\xAA", + "\xE2\xD0"=>"\xE7\xB0\x9F", + "\xE2\xD1"=>"\xE7\xB0\xB7", + "\xE2\xD2"=>"\xE7\xB0\xAB", + "\xE2\xD3"=>"\xE7\xB0\xBD", + "\xE2\xD4"=>"\xE7\xB1\x8C", + "\xE2\xD5"=>"\xE7\xB1\x83", + "\xE2\xD6"=>"\xE7\xB1\x94", + "\xE2\xD7"=>"\xE7\xB1\x8F", + "\xE2\xD8"=>"\xE7\xB1\x80", + "\xE2\xD9"=>"\xE7\xB1\x90", + "\xE2\xDA"=>"\xE7\xB1\x98", + "\xE2\xDB"=>"\xE7\xB1\x9F", + "\xE2\xDC"=>"\xE7\xB1\xA4", + "\xE2\xDD"=>"\xE7\xB1\x96", + "\xE2\xDE"=>"\xE7\xB1\xA5", + "\xE2\xDF"=>"\xE7\xB1\xAC", + "\xE2\xE0"=>"\xE7\xB1\xB5", + "\xE2\xE1"=>"\xE7\xB2\x83", + "\xE2\xE2"=>"\xE7\xB2\x90", + "\xE2\xE3"=>"\xE7\xB2\xA4", + "\xE2\xE4"=>"\xE7\xB2\xAD", + "\xE2\xE5"=>"\xE7\xB2\xA2", + "\xE2\xE6"=>"\xE7\xB2\xAB", + "\xE2\xE7"=>"\xE7\xB2\xA1", + "\xE2\xE8"=>"\xE7\xB2\xA8", + "\xE2\xE9"=>"\xE7\xB2\xB3", + "\xE2\xEA"=>"\xE7\xB2\xB2", + "\xE2\xEB"=>"\xE7\xB2\xB1", + "\xE2\xEC"=>"\xE7\xB2\xAE", + "\xE2\xED"=>"\xE7\xB2\xB9", + "\xE2\xEE"=>"\xE7\xB2\xBD", + "\xE2\xEF"=>"\xE7\xB3\x80", + "\xE2\xF0"=>"\xE7\xB3\x85", + "\xE2\xF1"=>"\xE7\xB3\x82", + "\xE2\xF2"=>"\xE7\xB3\x98", + "\xE2\xF3"=>"\xE7\xB3\x92", + "\xE2\xF4"=>"\xE7\xB3\x9C", + "\xE2\xF5"=>"\xE7\xB3\xA2", + "\xE2\xF6"=>"\xE9\xAC\xBB", + "\xE2\xF7"=>"\xE7\xB3\xAF", + "\xE2\xF8"=>"\xE7\xB3\xB2", + "\xE2\xF9"=>"\xE7\xB3\xB4", + "\xE2\xFA"=>"\xE7\xB3\xB6", + "\xE2\xFB"=>"\xE7\xB3\xBA", + "\xE2\xFC"=>"\xE7\xB4\x86", + "\xE3\x40"=>"\xE7\xB4\x82", + "\xE3\x41"=>"\xE7\xB4\x9C", + "\xE3\x42"=>"\xE7\xB4\x95", + "\xE3\x43"=>"\xE7\xB4\x8A", + "\xE3\x44"=>"\xE7\xB5\x85", + "\xE3\x45"=>"\xE7\xB5\x8B", + "\xE3\x46"=>"\xE7\xB4\xAE", + "\xE3\x47"=>"\xE7\xB4\xB2", + "\xE3\x48"=>"\xE7\xB4\xBF", + "\xE3\x49"=>"\xE7\xB4\xB5", + "\xE3\x4A"=>"\xE7\xB5\x86", + "\xE3\x4B"=>"\xE7\xB5\xB3", + "\xE3\x4C"=>"\xE7\xB5\x96", + "\xE3\x4D"=>"\xE7\xB5\x8E", + "\xE3\x4E"=>"\xE7\xB5\xB2", + "\xE3\x4F"=>"\xE7\xB5\xA8", + "\xE3\x50"=>"\xE7\xB5\xAE", + "\xE3\x51"=>"\xE7\xB5\x8F", + "\xE3\x52"=>"\xE7\xB5\xA3", + "\xE3\x53"=>"\xE7\xB6\x93", + "\xE3\x54"=>"\xE7\xB6\x89", + "\xE3\x55"=>"\xE7\xB5\x9B", + "\xE3\x56"=>"\xE7\xB6\x8F", + "\xE3\x57"=>"\xE7\xB5\xBD", + "\xE3\x58"=>"\xE7\xB6\x9B", + "\xE3\x59"=>"\xE7\xB6\xBA", + "\xE3\x5A"=>"\xE7\xB6\xAE", + "\xE3\x5B"=>"\xE7\xB6\xA3", + "\xE3\x5C"=>"\xE7\xB6\xB5", + "\xE3\x5D"=>"\xE7\xB7\x87", + "\xE3\x5E"=>"\xE7\xB6\xBD", + "\xE3\x5F"=>"\xE7\xB6\xAB", + "\xE3\x60"=>"\xE7\xB8\xBD", + "\xE3\x61"=>"\xE7\xB6\xA2", + "\xE3\x62"=>"\xE7\xB6\xAF", + "\xE3\x63"=>"\xE7\xB7\x9C", + "\xE3\x64"=>"\xE7\xB6\xB8", + "\xE3\x65"=>"\xE7\xB6\x9F", + "\xE3\x66"=>"\xE7\xB6\xB0", + "\xE3\x67"=>"\xE7\xB7\x98", + "\xE3\x68"=>"\xE7\xB7\x9D", + "\xE3\x69"=>"\xE7\xB7\xA4", + "\xE3\x6A"=>"\xE7\xB7\x9E", + "\xE3\x6B"=>"\xE7\xB7\xBB", + "\xE3\x6C"=>"\xE7\xB7\xB2", + "\xE3\x6D"=>"\xE7\xB7\xA1", + "\xE3\x6E"=>"\xE7\xB8\x85", + "\xE3\x6F"=>"\xE7\xB8\x8A", + "\xE3\x70"=>"\xE7\xB8\xA3", + "\xE3\x71"=>"\xE7\xB8\xA1", + "\xE3\x72"=>"\xE7\xB8\x92", + "\xE3\x73"=>"\xE7\xB8\xB1", + "\xE3\x74"=>"\xE7\xB8\x9F", + "\xE3\x75"=>"\xE7\xB8\x89", + "\xE3\x76"=>"\xE7\xB8\x8B", + "\xE3\x77"=>"\xE7\xB8\xA2", + "\xE3\x78"=>"\xE7\xB9\x86", + "\xE3\x79"=>"\xE7\xB9\xA6", + "\xE3\x7A"=>"\xE7\xB8\xBB", + "\xE3\x7B"=>"\xE7\xB8\xB5", + "\xE3\x7C"=>"\xE7\xB8\xB9", + "\xE3\x7D"=>"\xE7\xB9\x83", + "\xE3\x7E"=>"\xE7\xB8\xB7", + "\xE3\x80"=>"\xE7\xB8\xB2", + "\xE3\x81"=>"\xE7\xB8\xBA", + "\xE3\x82"=>"\xE7\xB9\xA7", + "\xE3\x83"=>"\xE7\xB9\x9D", + "\xE3\x84"=>"\xE7\xB9\x96", + "\xE3\x85"=>"\xE7\xB9\x9E", + "\xE3\x86"=>"\xE7\xB9\x99", + "\xE3\x87"=>"\xE7\xB9\x9A", + "\xE3\x88"=>"\xE7\xB9\xB9", + "\xE3\x89"=>"\xE7\xB9\xAA", + "\xE3\x8A"=>"\xE7\xB9\xA9", + "\xE3\x8B"=>"\xE7\xB9\xBC", + "\xE3\x8C"=>"\xE7\xB9\xBB", + "\xE3\x8D"=>"\xE7\xBA\x83", + "\xE3\x8E"=>"\xE7\xB7\x95", + "\xE3\x8F"=>"\xE7\xB9\xBD", + "\xE3\x90"=>"\xE8\xBE\xAE", + "\xE3\x91"=>"\xE7\xB9\xBF", + "\xE3\x92"=>"\xE7\xBA\x88", + "\xE3\x93"=>"\xE7\xBA\x89", + "\xE3\x94"=>"\xE7\xBA\x8C", + "\xE3\x95"=>"\xE7\xBA\x92", + "\xE3\x96"=>"\xE7\xBA\x90", + "\xE3\x97"=>"\xE7\xBA\x93", + "\xE3\x98"=>"\xE7\xBA\x94", + "\xE3\x99"=>"\xE7\xBA\x96", + "\xE3\x9A"=>"\xE7\xBA\x8E", + "\xE3\x9B"=>"\xE7\xBA\x9B", + "\xE3\x9C"=>"\xE7\xBA\x9C", + "\xE3\x9D"=>"\xE7\xBC\xB8", + "\xE3\x9E"=>"\xE7\xBC\xBA", + "\xE3\x9F"=>"\xE7\xBD\x85", + "\xE3\xA0"=>"\xE7\xBD\x8C", + "\xE3\xA1"=>"\xE7\xBD\x8D", + "\xE3\xA2"=>"\xE7\xBD\x8E", + "\xE3\xA3"=>"\xE7\xBD\x90", + "\xE3\xA4"=>"\xE7\xBD\x91", + "\xE3\xA5"=>"\xE7\xBD\x95", + "\xE3\xA6"=>"\xE7\xBD\x94", + "\xE3\xA7"=>"\xE7\xBD\x98", + "\xE3\xA8"=>"\xE7\xBD\x9F", + "\xE3\xA9"=>"\xE7\xBD\xA0", + "\xE3\xAA"=>"\xE7\xBD\xA8", + "\xE3\xAB"=>"\xE7\xBD\xA9", + "\xE3\xAC"=>"\xE7\xBD\xA7", + "\xE3\xAD"=>"\xE7\xBD\xB8", + "\xE3\xAE"=>"\xE7\xBE\x82", + "\xE3\xAF"=>"\xE7\xBE\x86", + "\xE3\xB0"=>"\xE7\xBE\x83", + "\xE3\xB1"=>"\xE7\xBE\x88", + "\xE3\xB2"=>"\xE7\xBE\x87", + "\xE3\xB3"=>"\xE7\xBE\x8C", + "\xE3\xB4"=>"\xE7\xBE\x94", + "\xE3\xB5"=>"\xE7\xBE\x9E", + "\xE3\xB6"=>"\xE7\xBE\x9D", + "\xE3\xB7"=>"\xE7\xBE\x9A", + "\xE3\xB8"=>"\xE7\xBE\xA3", + "\xE3\xB9"=>"\xE7\xBE\xAF", + "\xE3\xBA"=>"\xE7\xBE\xB2", + "\xE3\xBB"=>"\xE7\xBE\xB9", + "\xE3\xBC"=>"\xE7\xBE\xAE", + "\xE3\xBD"=>"\xE7\xBE\xB6", + "\xE3\xBE"=>"\xE7\xBE\xB8", + "\xE3\xBF"=>"\xE8\xAD\xB1", + "\xE3\xC0"=>"\xE7\xBF\x85", + "\xE3\xC1"=>"\xE7\xBF\x86", + "\xE3\xC2"=>"\xE7\xBF\x8A", + "\xE3\xC3"=>"\xE7\xBF\x95", + "\xE3\xC4"=>"\xE7\xBF\x94", + "\xE3\xC5"=>"\xE7\xBF\xA1", + "\xE3\xC6"=>"\xE7\xBF\xA6", + "\xE3\xC7"=>"\xE7\xBF\xA9", + "\xE3\xC8"=>"\xE7\xBF\xB3", + "\xE3\xC9"=>"\xE7\xBF\xB9", + "\xE3\xCA"=>"\xE9\xA3\x9C", + "\xE3\xCB"=>"\xE8\x80\x86", + "\xE3\xCC"=>"\xE8\x80\x84", + "\xE3\xCD"=>"\xE8\x80\x8B", + "\xE3\xCE"=>"\xE8\x80\x92", + "\xE3\xCF"=>"\xE8\x80\x98", + "\xE3\xD0"=>"\xE8\x80\x99", + "\xE3\xD1"=>"\xE8\x80\x9C", + "\xE3\xD2"=>"\xE8\x80\xA1", + "\xE3\xD3"=>"\xE8\x80\xA8", + "\xE3\xD4"=>"\xE8\x80\xBF", + "\xE3\xD5"=>"\xE8\x80\xBB", + "\xE3\xD6"=>"\xE8\x81\x8A", + "\xE3\xD7"=>"\xE8\x81\x86", + "\xE3\xD8"=>"\xE8\x81\x92", + "\xE3\xD9"=>"\xE8\x81\x98", + "\xE3\xDA"=>"\xE8\x81\x9A", + "\xE3\xDB"=>"\xE8\x81\x9F", + "\xE3\xDC"=>"\xE8\x81\xA2", + "\xE3\xDD"=>"\xE8\x81\xA8", + "\xE3\xDE"=>"\xE8\x81\xB3", + "\xE3\xDF"=>"\xE8\x81\xB2", + "\xE3\xE0"=>"\xE8\x81\xB0", + "\xE3\xE1"=>"\xE8\x81\xB6", + "\xE3\xE2"=>"\xE8\x81\xB9", + "\xE3\xE3"=>"\xE8\x81\xBD", + "\xE3\xE4"=>"\xE8\x81\xBF", + "\xE3\xE5"=>"\xE8\x82\x84", + "\xE3\xE6"=>"\xE8\x82\x86", + "\xE3\xE7"=>"\xE8\x82\x85", + "\xE3\xE8"=>"\xE8\x82\x9B", + "\xE3\xE9"=>"\xE8\x82\x93", + "\xE3\xEA"=>"\xE8\x82\x9A", + "\xE3\xEB"=>"\xE8\x82\xAD", + "\xE3\xEC"=>"\xE5\x86\x90", + "\xE3\xED"=>"\xE8\x82\xAC", + "\xE3\xEE"=>"\xE8\x83\x9B", + "\xE3\xEF"=>"\xE8\x83\xA5", + "\xE3\xF0"=>"\xE8\x83\x99", + "\xE3\xF1"=>"\xE8\x83\x9D", + "\xE3\xF2"=>"\xE8\x83\x84", + "\xE3\xF3"=>"\xE8\x83\x9A", + "\xE3\xF4"=>"\xE8\x83\x96", + "\xE3\xF5"=>"\xE8\x84\x89", + "\xE3\xF6"=>"\xE8\x83\xAF", + "\xE3\xF7"=>"\xE8\x83\xB1", + "\xE3\xF8"=>"\xE8\x84\x9B", + "\xE3\xF9"=>"\xE8\x84\xA9", + "\xE3\xFA"=>"\xE8\x84\xA3", + "\xE3\xFB"=>"\xE8\x84\xAF", + "\xE3\xFC"=>"\xE8\x85\x8B", + "\xE4\x40"=>"\xE9\x9A\x8B", + "\xE4\x41"=>"\xE8\x85\x86", + "\xE4\x42"=>"\xE8\x84\xBE", + "\xE4\x43"=>"\xE8\x85\x93", + "\xE4\x44"=>"\xE8\x85\x91", + "\xE4\x45"=>"\xE8\x83\xBC", + "\xE4\x46"=>"\xE8\x85\xB1", + "\xE4\x47"=>"\xE8\x85\xAE", + "\xE4\x48"=>"\xE8\x85\xA5", + "\xE4\x49"=>"\xE8\x85\xA6", + "\xE4\x4A"=>"\xE8\x85\xB4", + "\xE4\x4B"=>"\xE8\x86\x83", + "\xE4\x4C"=>"\xE8\x86\x88", + "\xE4\x4D"=>"\xE8\x86\x8A", + "\xE4\x4E"=>"\xE8\x86\x80", + "\xE4\x4F"=>"\xE8\x86\x82", + "\xE4\x50"=>"\xE8\x86\xA0", + "\xE4\x51"=>"\xE8\x86\x95", + "\xE4\x52"=>"\xE8\x86\xA4", + "\xE4\x53"=>"\xE8\x86\xA3", + "\xE4\x54"=>"\xE8\x85\x9F", + "\xE4\x55"=>"\xE8\x86\x93", + "\xE4\x56"=>"\xE8\x86\xA9", + "\xE4\x57"=>"\xE8\x86\xB0", + "\xE4\x58"=>"\xE8\x86\xB5", + "\xE4\x59"=>"\xE8\x86\xBE", + "\xE4\x5A"=>"\xE8\x86\xB8", + "\xE4\x5B"=>"\xE8\x86\xBD", + "\xE4\x5C"=>"\xE8\x87\x80", + "\xE4\x5D"=>"\xE8\x87\x82", + "\xE4\x5E"=>"\xE8\x86\xBA", + "\xE4\x5F"=>"\xE8\x87\x89", + "\xE4\x60"=>"\xE8\x87\x8D", + "\xE4\x61"=>"\xE8\x87\x91", + "\xE4\x62"=>"\xE8\x87\x99", + "\xE4\x63"=>"\xE8\x87\x98", + "\xE4\x64"=>"\xE8\x87\x88", + "\xE4\x65"=>"\xE8\x87\x9A", + "\xE4\x66"=>"\xE8\x87\x9F", + "\xE4\x67"=>"\xE8\x87\xA0", + "\xE4\x68"=>"\xE8\x87\xA7", + "\xE4\x69"=>"\xE8\x87\xBA", + "\xE4\x6A"=>"\xE8\x87\xBB", + "\xE4\x6B"=>"\xE8\x87\xBE", + "\xE4\x6C"=>"\xE8\x88\x81", + "\xE4\x6D"=>"\xE8\x88\x82", + "\xE4\x6E"=>"\xE8\x88\x85", + "\xE4\x6F"=>"\xE8\x88\x87", + "\xE4\x70"=>"\xE8\x88\x8A", + "\xE4\x71"=>"\xE8\x88\x8D", + "\xE4\x72"=>"\xE8\x88\x90", + "\xE4\x73"=>"\xE8\x88\x96", + "\xE4\x74"=>"\xE8\x88\xA9", + "\xE4\x75"=>"\xE8\x88\xAB", + "\xE4\x76"=>"\xE8\x88\xB8", + "\xE4\x77"=>"\xE8\x88\xB3", + "\xE4\x78"=>"\xE8\x89\x80", + "\xE4\x79"=>"\xE8\x89\x99", + "\xE4\x7A"=>"\xE8\x89\x98", + "\xE4\x7B"=>"\xE8\x89\x9D", + "\xE4\x7C"=>"\xE8\x89\x9A", + "\xE4\x7D"=>"\xE8\x89\x9F", + "\xE4\x7E"=>"\xE8\x89\xA4", + "\xE4\x80"=>"\xE8\x89\xA2", + "\xE4\x81"=>"\xE8\x89\xA8", + "\xE4\x82"=>"\xE8\x89\xAA", + "\xE4\x83"=>"\xE8\x89\xAB", + "\xE4\x84"=>"\xE8\x88\xAE", + "\xE4\x85"=>"\xE8\x89\xB1", + "\xE4\x86"=>"\xE8\x89\xB7", + "\xE4\x87"=>"\xE8\x89\xB8", + "\xE4\x88"=>"\xE8\x89\xBE", + "\xE4\x89"=>"\xE8\x8A\x8D", + "\xE4\x8A"=>"\xE8\x8A\x92", + "\xE4\x8B"=>"\xE8\x8A\xAB", + "\xE4\x8C"=>"\xE8\x8A\x9F", + "\xE4\x8D"=>"\xE8\x8A\xBB", + "\xE4\x8E"=>"\xE8\x8A\xAC", + "\xE4\x8F"=>"\xE8\x8B\xA1", + "\xE4\x90"=>"\xE8\x8B\xA3", + "\xE4\x91"=>"\xE8\x8B\x9F", + "\xE4\x92"=>"\xE8\x8B\x92", + "\xE4\x93"=>"\xE8\x8B\xB4", + "\xE4\x94"=>"\xE8\x8B\xB3", + "\xE4\x95"=>"\xE8\x8B\xBA", + "\xE4\x96"=>"\xE8\x8E\x93", + "\xE4\x97"=>"\xE8\x8C\x83", + "\xE4\x98"=>"\xE8\x8B\xBB", + "\xE4\x99"=>"\xE8\x8B\xB9", + "\xE4\x9A"=>"\xE8\x8B\x9E", + "\xE4\x9B"=>"\xE8\x8C\x86", + "\xE4\x9C"=>"\xE8\x8B\x9C", + "\xE4\x9D"=>"\xE8\x8C\x89", + "\xE4\x9E"=>"\xE8\x8B\x99", + "\xE4\x9F"=>"\xE8\x8C\xB5", + "\xE4\xA0"=>"\xE8\x8C\xB4", + "\xE4\xA1"=>"\xE8\x8C\x96", + "\xE4\xA2"=>"\xE8\x8C\xB2", + "\xE4\xA3"=>"\xE8\x8C\xB1", + "\xE4\xA4"=>"\xE8\x8D\x80", + "\xE4\xA5"=>"\xE8\x8C\xB9", + "\xE4\xA6"=>"\xE8\x8D\x90", + "\xE4\xA7"=>"\xE8\x8D\x85", + "\xE4\xA8"=>"\xE8\x8C\xAF", + "\xE4\xA9"=>"\xE8\x8C\xAB", + "\xE4\xAA"=>"\xE8\x8C\x97", + "\xE4\xAB"=>"\xE8\x8C\x98", + "\xE4\xAC"=>"\xE8\x8E\x85", + "\xE4\xAD"=>"\xE8\x8E\x9A", + "\xE4\xAE"=>"\xE8\x8E\xAA", + "\xE4\xAF"=>"\xE8\x8E\x9F", + "\xE4\xB0"=>"\xE8\x8E\xA2", + "\xE4\xB1"=>"\xE8\x8E\x96", + "\xE4\xB2"=>"\xE8\x8C\xA3", + "\xE4\xB3"=>"\xE8\x8E\x8E", + "\xE4\xB4"=>"\xE8\x8E\x87", + "\xE4\xB5"=>"\xE8\x8E\x8A", + "\xE4\xB6"=>"\xE8\x8D\xBC", + "\xE4\xB7"=>"\xE8\x8E\xB5", + "\xE4\xB8"=>"\xE8\x8D\xB3", + "\xE4\xB9"=>"\xE8\x8D\xB5", + "\xE4\xBA"=>"\xE8\x8E\xA0", + "\xE4\xBB"=>"\xE8\x8E\x89", + "\xE4\xBC"=>"\xE8\x8E\xA8", + "\xE4\xBD"=>"\xE8\x8F\xB4", + "\xE4\xBE"=>"\xE8\x90\x93", + "\xE4\xBF"=>"\xE8\x8F\xAB", + "\xE4\xC0"=>"\xE8\x8F\x8E", + "\xE4\xC1"=>"\xE8\x8F\xBD", + "\xE4\xC2"=>"\xE8\x90\x83", + "\xE4\xC3"=>"\xE8\x8F\x98", + "\xE4\xC4"=>"\xE8\x90\x8B", + "\xE4\xC5"=>"\xE8\x8F\x81", + "\xE4\xC6"=>"\xE8\x8F\xB7", + "\xE4\xC7"=>"\xE8\x90\x87", + "\xE4\xC8"=>"\xE8\x8F\xA0", + "\xE4\xC9"=>"\xE8\x8F\xB2", + "\xE4\xCA"=>"\xE8\x90\x8D", + "\xE4\xCB"=>"\xE8\x90\xA2", + "\xE4\xCC"=>"\xE8\x90\xA0", + "\xE4\xCD"=>"\xE8\x8E\xBD", + "\xE4\xCE"=>"\xE8\x90\xB8", + "\xE4\xCF"=>"\xE8\x94\x86", + "\xE4\xD0"=>"\xE8\x8F\xBB", + "\xE4\xD1"=>"\xE8\x91\xAD", + "\xE4\xD2"=>"\xE8\x90\xAA", + "\xE4\xD3"=>"\xE8\x90\xBC", + "\xE4\xD4"=>"\xE8\x95\x9A", + "\xE4\xD5"=>"\xE8\x92\x84", + "\xE4\xD6"=>"\xE8\x91\xB7", + "\xE4\xD7"=>"\xE8\x91\xAB", + "\xE4\xD8"=>"\xE8\x92\xAD", + "\xE4\xD9"=>"\xE8\x91\xAE", + "\xE4\xDA"=>"\xE8\x92\x82", + "\xE4\xDB"=>"\xE8\x91\xA9", + "\xE4\xDC"=>"\xE8\x91\x86", + "\xE4\xDD"=>"\xE8\x90\xAC", + "\xE4\xDE"=>"\xE8\x91\xAF", + "\xE4\xDF"=>"\xE8\x91\xB9", + "\xE4\xE0"=>"\xE8\x90\xB5", + "\xE4\xE1"=>"\xE8\x93\x8A", + "\xE4\xE2"=>"\xE8\x91\xA2", + "\xE4\xE3"=>"\xE8\x92\xB9", + "\xE4\xE4"=>"\xE8\x92\xBF", + "\xE4\xE5"=>"\xE8\x92\x9F", + "\xE4\xE6"=>"\xE8\x93\x99", + "\xE4\xE7"=>"\xE8\x93\x8D", + "\xE4\xE8"=>"\xE8\x92\xBB", + "\xE4\xE9"=>"\xE8\x93\x9A", + "\xE4\xEA"=>"\xE8\x93\x90", + "\xE4\xEB"=>"\xE8\x93\x81", + "\xE4\xEC"=>"\xE8\x93\x86", + "\xE4\xED"=>"\xE8\x93\x96", + "\xE4\xEE"=>"\xE8\x92\xA1", + "\xE4\xEF"=>"\xE8\x94\xA1", + "\xE4\xF0"=>"\xE8\x93\xBF", + "\xE4\xF1"=>"\xE8\x93\xB4", + "\xE4\xF2"=>"\xE8\x94\x97", + "\xE4\xF3"=>"\xE8\x94\x98", + "\xE4\xF4"=>"\xE8\x94\xAC", + "\xE4\xF5"=>"\xE8\x94\x9F", + "\xE4\xF6"=>"\xE8\x94\x95", + "\xE4\xF7"=>"\xE8\x94\x94", + "\xE4\xF8"=>"\xE8\x93\xBC", + "\xE4\xF9"=>"\xE8\x95\x80", + "\xE4\xFA"=>"\xE8\x95\xA3", + "\xE4\xFB"=>"\xE8\x95\x98", + "\xE4\xFC"=>"\xE8\x95\x88", + "\xE5\x40"=>"\xE8\x95\x81", + "\xE5\x41"=>"\xE8\x98\x82", + "\xE5\x42"=>"\xE8\x95\x8B", + "\xE5\x43"=>"\xE8\x95\x95", + "\xE5\x44"=>"\xE8\x96\x80", + "\xE5\x45"=>"\xE8\x96\xA4", + "\xE5\x46"=>"\xE8\x96\x88", + "\xE5\x47"=>"\xE8\x96\x91", + "\xE5\x48"=>"\xE8\x96\x8A", + "\xE5\x49"=>"\xE8\x96\xA8", + "\xE5\x4A"=>"\xE8\x95\xAD", + "\xE5\x4B"=>"\xE8\x96\x94", + "\xE5\x4C"=>"\xE8\x96\x9B", + "\xE5\x4D"=>"\xE8\x97\xAA", + "\xE5\x4E"=>"\xE8\x96\x87", + "\xE5\x4F"=>"\xE8\x96\x9C", + "\xE5\x50"=>"\xE8\x95\xB7", + "\xE5\x51"=>"\xE8\x95\xBE", + "\xE5\x52"=>"\xE8\x96\x90", + "\xE5\x53"=>"\xE8\x97\x89", + "\xE5\x54"=>"\xE8\x96\xBA", + "\xE5\x55"=>"\xE8\x97\x8F", + "\xE5\x56"=>"\xE8\x96\xB9", + "\xE5\x57"=>"\xE8\x97\x90", + "\xE5\x58"=>"\xE8\x97\x95", + "\xE5\x59"=>"\xE8\x97\x9D", + "\xE5\x5A"=>"\xE8\x97\xA5", + "\xE5\x5B"=>"\xE8\x97\x9C", + "\xE5\x5C"=>"\xE8\x97\xB9", + "\xE5\x5D"=>"\xE8\x98\x8A", + "\xE5\x5E"=>"\xE8\x98\x93", + "\xE5\x5F"=>"\xE8\x98\x8B", + "\xE5\x60"=>"\xE8\x97\xBE", + "\xE5\x61"=>"\xE8\x97\xBA", + "\xE5\x62"=>"\xE8\x98\x86", + "\xE5\x63"=>"\xE8\x98\xA2", + "\xE5\x64"=>"\xE8\x98\x9A", + "\xE5\x65"=>"\xE8\x98\xB0", + "\xE5\x66"=>"\xE8\x98\xBF", + "\xE5\x67"=>"\xE8\x99\x8D", + "\xE5\x68"=>"\xE4\xB9\x95", + "\xE5\x69"=>"\xE8\x99\x94", + "\xE5\x6A"=>"\xE8\x99\x9F", + "\xE5\x6B"=>"\xE8\x99\xA7", + "\xE5\x6C"=>"\xE8\x99\xB1", + "\xE5\x6D"=>"\xE8\x9A\x93", + "\xE5\x6E"=>"\xE8\x9A\xA3", + "\xE5\x6F"=>"\xE8\x9A\xA9", + "\xE5\x70"=>"\xE8\x9A\xAA", + "\xE5\x71"=>"\xE8\x9A\x8B", + "\xE5\x72"=>"\xE8\x9A\x8C", + "\xE5\x73"=>"\xE8\x9A\xB6", + "\xE5\x74"=>"\xE8\x9A\xAF", + "\xE5\x75"=>"\xE8\x9B\x84", + "\xE5\x76"=>"\xE8\x9B\x86", + "\xE5\x77"=>"\xE8\x9A\xB0", + "\xE5\x78"=>"\xE8\x9B\x89", + "\xE5\x79"=>"\xE8\xA0\xA3", + "\xE5\x7A"=>"\xE8\x9A\xAB", + "\xE5\x7B"=>"\xE8\x9B\x94", + "\xE5\x7C"=>"\xE8\x9B\x9E", + "\xE5\x7D"=>"\xE8\x9B\xA9", + "\xE5\x7E"=>"\xE8\x9B\xAC", + "\xE5\x80"=>"\xE8\x9B\x9F", + "\xE5\x81"=>"\xE8\x9B\x9B", + "\xE5\x82"=>"\xE8\x9B\xAF", + "\xE5\x83"=>"\xE8\x9C\x92", + "\xE5\x84"=>"\xE8\x9C\x86", + "\xE5\x85"=>"\xE8\x9C\x88", + "\xE5\x86"=>"\xE8\x9C\x80", + "\xE5\x87"=>"\xE8\x9C\x83", + "\xE5\x88"=>"\xE8\x9B\xBB", + "\xE5\x89"=>"\xE8\x9C\x91", + "\xE5\x8A"=>"\xE8\x9C\x89", + "\xE5\x8B"=>"\xE8\x9C\x8D", + "\xE5\x8C"=>"\xE8\x9B\xB9", + "\xE5\x8D"=>"\xE8\x9C\x8A", + "\xE5\x8E"=>"\xE8\x9C\xB4", + "\xE5\x8F"=>"\xE8\x9C\xBF", + "\xE5\x90"=>"\xE8\x9C\xB7", + "\xE5\x91"=>"\xE8\x9C\xBB", + "\xE5\x92"=>"\xE8\x9C\xA5", + "\xE5\x93"=>"\xE8\x9C\xA9", + "\xE5\x94"=>"\xE8\x9C\x9A", + "\xE5\x95"=>"\xE8\x9D\xA0", + "\xE5\x96"=>"\xE8\x9D\x9F", + "\xE5\x97"=>"\xE8\x9D\xB8", + "\xE5\x98"=>"\xE8\x9D\x8C", + "\xE5\x99"=>"\xE8\x9D\x8E", + "\xE5\x9A"=>"\xE8\x9D\xB4", + "\xE5\x9B"=>"\xE8\x9D\x97", + "\xE5\x9C"=>"\xE8\x9D\xA8", + "\xE5\x9D"=>"\xE8\x9D\xAE", + "\xE5\x9E"=>"\xE8\x9D\x99", + "\xE5\x9F"=>"\xE8\x9D\x93", + "\xE5\xA0"=>"\xE8\x9D\xA3", + "\xE5\xA1"=>"\xE8\x9D\xAA", + "\xE5\xA2"=>"\xE8\xA0\x85", + "\xE5\xA3"=>"\xE8\x9E\xA2", + "\xE5\xA4"=>"\xE8\x9E\x9F", + "\xE5\xA5"=>"\xE8\x9E\x82", + "\xE5\xA6"=>"\xE8\x9E\xAF", + "\xE5\xA7"=>"\xE8\x9F\x8B", + "\xE5\xA8"=>"\xE8\x9E\xBD", + "\xE5\xA9"=>"\xE8\x9F\x80", + "\xE5\xAA"=>"\xE8\x9F\x90", + "\xE5\xAB"=>"\xE9\x9B\x96", + "\xE5\xAC"=>"\xE8\x9E\xAB", + "\xE5\xAD"=>"\xE8\x9F\x84", + "\xE5\xAE"=>"\xE8\x9E\xB3", + "\xE5\xAF"=>"\xE8\x9F\x87", + "\xE5\xB0"=>"\xE8\x9F\x86", + "\xE5\xB1"=>"\xE8\x9E\xBB", + "\xE5\xB2"=>"\xE8\x9F\xAF", + "\xE5\xB3"=>"\xE8\x9F\xB2", + "\xE5\xB4"=>"\xE8\x9F\xA0", + "\xE5\xB5"=>"\xE8\xA0\x8F", + "\xE5\xB6"=>"\xE8\xA0\x8D", + "\xE5\xB7"=>"\xE8\x9F\xBE", + "\xE5\xB8"=>"\xE8\x9F\xB6", + "\xE5\xB9"=>"\xE8\x9F\xB7", + "\xE5\xBA"=>"\xE8\xA0\x8E", + "\xE5\xBB"=>"\xE8\x9F\x92", + "\xE5\xBC"=>"\xE8\xA0\x91", + "\xE5\xBD"=>"\xE8\xA0\x96", + "\xE5\xBE"=>"\xE8\xA0\x95", + "\xE5\xBF"=>"\xE8\xA0\xA2", + "\xE5\xC0"=>"\xE8\xA0\xA1", + "\xE5\xC1"=>"\xE8\xA0\xB1", + "\xE5\xC2"=>"\xE8\xA0\xB6", + "\xE5\xC3"=>"\xE8\xA0\xB9", + "\xE5\xC4"=>"\xE8\xA0\xA7", + "\xE5\xC5"=>"\xE8\xA0\xBB", + "\xE5\xC6"=>"\xE8\xA1\x84", + "\xE5\xC7"=>"\xE8\xA1\x82", + "\xE5\xC8"=>"\xE8\xA1\x92", + "\xE5\xC9"=>"\xE8\xA1\x99", + "\xE5\xCA"=>"\xE8\xA1\x9E", + "\xE5\xCB"=>"\xE8\xA1\xA2", + "\xE5\xCC"=>"\xE8\xA1\xAB", + "\xE5\xCD"=>"\xE8\xA2\x81", + "\xE5\xCE"=>"\xE8\xA1\xBE", + "\xE5\xCF"=>"\xE8\xA2\x9E", + "\xE5\xD0"=>"\xE8\xA1\xB5", + "\xE5\xD1"=>"\xE8\xA1\xBD", + "\xE5\xD2"=>"\xE8\xA2\xB5", + "\xE5\xD3"=>"\xE8\xA1\xB2", + "\xE5\xD4"=>"\xE8\xA2\x82", + "\xE5\xD5"=>"\xE8\xA2\x97", + "\xE5\xD6"=>"\xE8\xA2\x92", + "\xE5\xD7"=>"\xE8\xA2\xAE", + "\xE5\xD8"=>"\xE8\xA2\x99", + "\xE5\xD9"=>"\xE8\xA2\xA2", + "\xE5\xDA"=>"\xE8\xA2\x8D", + "\xE5\xDB"=>"\xE8\xA2\xA4", + "\xE5\xDC"=>"\xE8\xA2\xB0", + "\xE5\xDD"=>"\xE8\xA2\xBF", + "\xE5\xDE"=>"\xE8\xA2\xB1", + "\xE5\xDF"=>"\xE8\xA3\x83", + "\xE5\xE0"=>"\xE8\xA3\x84", + "\xE5\xE1"=>"\xE8\xA3\x94", + "\xE5\xE2"=>"\xE8\xA3\x98", + "\xE5\xE3"=>"\xE8\xA3\x99", + "\xE5\xE4"=>"\xE8\xA3\x9D", + "\xE5\xE5"=>"\xE8\xA3\xB9", + "\xE5\xE6"=>"\xE8\xA4\x82", + "\xE5\xE7"=>"\xE8\xA3\xBC", + "\xE5\xE8"=>"\xE8\xA3\xB4", + "\xE5\xE9"=>"\xE8\xA3\xA8", + "\xE5\xEA"=>"\xE8\xA3\xB2", + "\xE5\xEB"=>"\xE8\xA4\x84", + "\xE5\xEC"=>"\xE8\xA4\x8C", + "\xE5\xED"=>"\xE8\xA4\x8A", + "\xE5\xEE"=>"\xE8\xA4\x93", + "\xE5\xEF"=>"\xE8\xA5\x83", + "\xE5\xF0"=>"\xE8\xA4\x9E", + "\xE5\xF1"=>"\xE8\xA4\xA5", + "\xE5\xF2"=>"\xE8\xA4\xAA", + "\xE5\xF3"=>"\xE8\xA4\xAB", + "\xE5\xF4"=>"\xE8\xA5\x81", + "\xE5\xF5"=>"\xE8\xA5\x84", + "\xE5\xF6"=>"\xE8\xA4\xBB", + "\xE5\xF7"=>"\xE8\xA4\xB6", + "\xE5\xF8"=>"\xE8\xA4\xB8", + "\xE5\xF9"=>"\xE8\xA5\x8C", + "\xE5\xFA"=>"\xE8\xA4\x9D", + "\xE5\xFB"=>"\xE8\xA5\xA0", + "\xE5\xFC"=>"\xE8\xA5\x9E", + "\xE6\x40"=>"\xE8\xA5\xA6", + "\xE6\x41"=>"\xE8\xA5\xA4", + "\xE6\x42"=>"\xE8\xA5\xAD", + "\xE6\x43"=>"\xE8\xA5\xAA", + "\xE6\x44"=>"\xE8\xA5\xAF", + "\xE6\x45"=>"\xE8\xA5\xB4", + "\xE6\x46"=>"\xE8\xA5\xB7", + "\xE6\x47"=>"\xE8\xA5\xBE", + "\xE6\x48"=>"\xE8\xA6\x83", + "\xE6\x49"=>"\xE8\xA6\x88", + "\xE6\x4A"=>"\xE8\xA6\x8A", + "\xE6\x4B"=>"\xE8\xA6\x93", + "\xE6\x4C"=>"\xE8\xA6\x98", + "\xE6\x4D"=>"\xE8\xA6\xA1", + "\xE6\x4E"=>"\xE8\xA6\xA9", + "\xE6\x4F"=>"\xE8\xA6\xA6", + "\xE6\x50"=>"\xE8\xA6\xAC", + "\xE6\x51"=>"\xE8\xA6\xAF", + "\xE6\x52"=>"\xE8\xA6\xB2", + "\xE6\x53"=>"\xE8\xA6\xBA", + "\xE6\x54"=>"\xE8\xA6\xBD", + "\xE6\x55"=>"\xE8\xA6\xBF", + "\xE6\x56"=>"\xE8\xA7\x80", + "\xE6\x57"=>"\xE8\xA7\x9A", + "\xE6\x58"=>"\xE8\xA7\x9C", + "\xE6\x59"=>"\xE8\xA7\x9D", + "\xE6\x5A"=>"\xE8\xA7\xA7", + "\xE6\x5B"=>"\xE8\xA7\xB4", + "\xE6\x5C"=>"\xE8\xA7\xB8", + "\xE6\x5D"=>"\xE8\xA8\x83", + "\xE6\x5E"=>"\xE8\xA8\x96", + "\xE6\x5F"=>"\xE8\xA8\x90", + "\xE6\x60"=>"\xE8\xA8\x8C", + "\xE6\x61"=>"\xE8\xA8\x9B", + "\xE6\x62"=>"\xE8\xA8\x9D", + "\xE6\x63"=>"\xE8\xA8\xA5", + "\xE6\x64"=>"\xE8\xA8\xB6", + "\xE6\x65"=>"\xE8\xA9\x81", + "\xE6\x66"=>"\xE8\xA9\x9B", + "\xE6\x67"=>"\xE8\xA9\x92", + "\xE6\x68"=>"\xE8\xA9\x86", + "\xE6\x69"=>"\xE8\xA9\x88", + "\xE6\x6A"=>"\xE8\xA9\xBC", + "\xE6\x6B"=>"\xE8\xA9\xAD", + "\xE6\x6C"=>"\xE8\xA9\xAC", + "\xE6\x6D"=>"\xE8\xA9\xA2", + "\xE6\x6E"=>"\xE8\xAA\x85", + "\xE6\x6F"=>"\xE8\xAA\x82", + "\xE6\x70"=>"\xE8\xAA\x84", + "\xE6\x71"=>"\xE8\xAA\xA8", + "\xE6\x72"=>"\xE8\xAA\xA1", + "\xE6\x73"=>"\xE8\xAA\x91", + "\xE6\x74"=>"\xE8\xAA\xA5", + "\xE6\x75"=>"\xE8\xAA\xA6", + "\xE6\x76"=>"\xE8\xAA\x9A", + "\xE6\x77"=>"\xE8\xAA\xA3", + "\xE6\x78"=>"\xE8\xAB\x84", + "\xE6\x79"=>"\xE8\xAB\x8D", + "\xE6\x7A"=>"\xE8\xAB\x82", + "\xE6\x7B"=>"\xE8\xAB\x9A", + "\xE6\x7C"=>"\xE8\xAB\xAB", + "\xE6\x7D"=>"\xE8\xAB\xB3", + "\xE6\x7E"=>"\xE8\xAB\xA7", + "\xE6\x80"=>"\xE8\xAB\xA4", + "\xE6\x81"=>"\xE8\xAB\xB1", + "\xE6\x82"=>"\xE8\xAC\x94", + "\xE6\x83"=>"\xE8\xAB\xA0", + "\xE6\x84"=>"\xE8\xAB\xA2", + "\xE6\x85"=>"\xE8\xAB\xB7", + "\xE6\x86"=>"\xE8\xAB\x9E", + "\xE6\x87"=>"\xE8\xAB\x9B", + "\xE6\x88"=>"\xE8\xAC\x8C", + "\xE6\x89"=>"\xE8\xAC\x87", + "\xE6\x8A"=>"\xE8\xAC\x9A", + "\xE6\x8B"=>"\xE8\xAB\xA1", + "\xE6\x8C"=>"\xE8\xAC\x96", + "\xE6\x8D"=>"\xE8\xAC\x90", + "\xE6\x8E"=>"\xE8\xAC\x97", + "\xE6\x8F"=>"\xE8\xAC\xA0", + "\xE6\x90"=>"\xE8\xAC\xB3", + "\xE6\x91"=>"\xE9\x9E\xAB", + "\xE6\x92"=>"\xE8\xAC\xA6", + "\xE6\x93"=>"\xE8\xAC\xAB", + "\xE6\x94"=>"\xE8\xAC\xBE", + "\xE6\x95"=>"\xE8\xAC\xA8", + "\xE6\x96"=>"\xE8\xAD\x81", + "\xE6\x97"=>"\xE8\xAD\x8C", + "\xE6\x98"=>"\xE8\xAD\x8F", + "\xE6\x99"=>"\xE8\xAD\x8E", + "\xE6\x9A"=>"\xE8\xAD\x89", + "\xE6\x9B"=>"\xE8\xAD\x96", + "\xE6\x9C"=>"\xE8\xAD\x9B", + "\xE6\x9D"=>"\xE8\xAD\x9A", + "\xE6\x9E"=>"\xE8\xAD\xAB", + "\xE6\x9F"=>"\xE8\xAD\x9F", + "\xE6\xA0"=>"\xE8\xAD\xAC", + "\xE6\xA1"=>"\xE8\xAD\xAF", + "\xE6\xA2"=>"\xE8\xAD\xB4", + "\xE6\xA3"=>"\xE8\xAD\xBD", + "\xE6\xA4"=>"\xE8\xAE\x80", + "\xE6\xA5"=>"\xE8\xAE\x8C", + "\xE6\xA6"=>"\xE8\xAE\x8E", + "\xE6\xA7"=>"\xE8\xAE\x92", + "\xE6\xA8"=>"\xE8\xAE\x93", + "\xE6\xA9"=>"\xE8\xAE\x96", + "\xE6\xAA"=>"\xE8\xAE\x99", + "\xE6\xAB"=>"\xE8\xAE\x9A", + "\xE6\xAC"=>"\xE8\xB0\xBA", + "\xE6\xAD"=>"\xE8\xB1\x81", + "\xE6\xAE"=>"\xE8\xB0\xBF", + "\xE6\xAF"=>"\xE8\xB1\x88", + "\xE6\xB0"=>"\xE8\xB1\x8C", + "\xE6\xB1"=>"\xE8\xB1\x8E", + "\xE6\xB2"=>"\xE8\xB1\x90", + "\xE6\xB3"=>"\xE8\xB1\x95", + "\xE6\xB4"=>"\xE8\xB1\xA2", + "\xE6\xB5"=>"\xE8\xB1\xAC", + "\xE6\xB6"=>"\xE8\xB1\xB8", + "\xE6\xB7"=>"\xE8\xB1\xBA", + "\xE6\xB8"=>"\xE8\xB2\x82", + "\xE6\xB9"=>"\xE8\xB2\x89", + "\xE6\xBA"=>"\xE8\xB2\x85", + "\xE6\xBB"=>"\xE8\xB2\x8A", + "\xE6\xBC"=>"\xE8\xB2\x8D", + "\xE6\xBD"=>"\xE8\xB2\x8E", + "\xE6\xBE"=>"\xE8\xB2\x94", + "\xE6\xBF"=>"\xE8\xB1\xBC", + "\xE6\xC0"=>"\xE8\xB2\x98", + "\xE6\xC1"=>"\xE6\x88\x9D", + "\xE6\xC2"=>"\xE8\xB2\xAD", + "\xE6\xC3"=>"\xE8\xB2\xAA", + "\xE6\xC4"=>"\xE8\xB2\xBD", + "\xE6\xC5"=>"\xE8\xB2\xB2", + "\xE6\xC6"=>"\xE8\xB2\xB3", + "\xE6\xC7"=>"\xE8\xB2\xAE", + "\xE6\xC8"=>"\xE8\xB2\xB6", + "\xE6\xC9"=>"\xE8\xB3\x88", + "\xE6\xCA"=>"\xE8\xB3\x81", + "\xE6\xCB"=>"\xE8\xB3\xA4", + "\xE6\xCC"=>"\xE8\xB3\xA3", + "\xE6\xCD"=>"\xE8\xB3\x9A", + "\xE6\xCE"=>"\xE8\xB3\xBD", + "\xE6\xCF"=>"\xE8\xB3\xBA", + "\xE6\xD0"=>"\xE8\xB3\xBB", + "\xE6\xD1"=>"\xE8\xB4\x84", + "\xE6\xD2"=>"\xE8\xB4\x85", + "\xE6\xD3"=>"\xE8\xB4\x8A", + "\xE6\xD4"=>"\xE8\xB4\x87", + "\xE6\xD5"=>"\xE8\xB4\x8F", + "\xE6\xD6"=>"\xE8\xB4\x8D", + "\xE6\xD7"=>"\xE8\xB4\x90", + "\xE6\xD8"=>"\xE9\xBD\x8E", + "\xE6\xD9"=>"\xE8\xB4\x93", + "\xE6\xDA"=>"\xE8\xB3\x8D", + "\xE6\xDB"=>"\xE8\xB4\x94", + "\xE6\xDC"=>"\xE8\xB4\x96", + "\xE6\xDD"=>"\xE8\xB5\xA7", + "\xE6\xDE"=>"\xE8\xB5\xAD", + "\xE6\xDF"=>"\xE8\xB5\xB1", + "\xE6\xE0"=>"\xE8\xB5\xB3", + "\xE6\xE1"=>"\xE8\xB6\x81", + "\xE6\xE2"=>"\xE8\xB6\x99", + "\xE6\xE3"=>"\xE8\xB7\x82", + "\xE6\xE4"=>"\xE8\xB6\xBE", + "\xE6\xE5"=>"\xE8\xB6\xBA", + "\xE6\xE6"=>"\xE8\xB7\x8F", + "\xE6\xE7"=>"\xE8\xB7\x9A", + "\xE6\xE8"=>"\xE8\xB7\x96", + "\xE6\xE9"=>"\xE8\xB7\x8C", + "\xE6\xEA"=>"\xE8\xB7\x9B", + "\xE6\xEB"=>"\xE8\xB7\x8B", + "\xE6\xEC"=>"\xE8\xB7\xAA", + "\xE6\xED"=>"\xE8\xB7\xAB", + "\xE6\xEE"=>"\xE8\xB7\x9F", + "\xE6\xEF"=>"\xE8\xB7\xA3", + "\xE6\xF0"=>"\xE8\xB7\xBC", + "\xE6\xF1"=>"\xE8\xB8\x88", + "\xE6\xF2"=>"\xE8\xB8\x89", + "\xE6\xF3"=>"\xE8\xB7\xBF", + "\xE6\xF4"=>"\xE8\xB8\x9D", + "\xE6\xF5"=>"\xE8\xB8\x9E", + "\xE6\xF6"=>"\xE8\xB8\x90", + "\xE6\xF7"=>"\xE8\xB8\x9F", + "\xE6\xF8"=>"\xE8\xB9\x82", + "\xE6\xF9"=>"\xE8\xB8\xB5", + "\xE6\xFA"=>"\xE8\xB8\xB0", + "\xE6\xFB"=>"\xE8\xB8\xB4", + "\xE6\xFC"=>"\xE8\xB9\x8A", + "\xE7\x40"=>"\xE8\xB9\x87", + "\xE7\x41"=>"\xE8\xB9\x89", + "\xE7\x42"=>"\xE8\xB9\x8C", + "\xE7\x43"=>"\xE8\xB9\x90", + "\xE7\x44"=>"\xE8\xB9\x88", + "\xE7\x45"=>"\xE8\xB9\x99", + "\xE7\x46"=>"\xE8\xB9\xA4", + "\xE7\x47"=>"\xE8\xB9\xA0", + "\xE7\x48"=>"\xE8\xB8\xAA", + "\xE7\x49"=>"\xE8\xB9\xA3", + "\xE7\x4A"=>"\xE8\xB9\x95", + "\xE7\x4B"=>"\xE8\xB9\xB6", + "\xE7\x4C"=>"\xE8\xB9\xB2", + "\xE7\x4D"=>"\xE8\xB9\xBC", + "\xE7\x4E"=>"\xE8\xBA\x81", + "\xE7\x4F"=>"\xE8\xBA\x87", + "\xE7\x50"=>"\xE8\xBA\x85", + "\xE7\x51"=>"\xE8\xBA\x84", + "\xE7\x52"=>"\xE8\xBA\x8B", + "\xE7\x53"=>"\xE8\xBA\x8A", + "\xE7\x54"=>"\xE8\xBA\x93", + "\xE7\x55"=>"\xE8\xBA\x91", + "\xE7\x56"=>"\xE8\xBA\x94", + "\xE7\x57"=>"\xE8\xBA\x99", + "\xE7\x58"=>"\xE8\xBA\xAA", + "\xE7\x59"=>"\xE8\xBA\xA1", + "\xE7\x5A"=>"\xE8\xBA\xAC", + "\xE7\x5B"=>"\xE8\xBA\xB0", + "\xE7\x5C"=>"\xE8\xBB\x86", + "\xE7\x5D"=>"\xE8\xBA\xB1", + "\xE7\x5E"=>"\xE8\xBA\xBE", + "\xE7\x5F"=>"\xE8\xBB\x85", + "\xE7\x60"=>"\xE8\xBB\x88", + "\xE7\x61"=>"\xE8\xBB\x8B", + "\xE7\x62"=>"\xE8\xBB\x9B", + "\xE7\x63"=>"\xE8\xBB\xA3", + "\xE7\x64"=>"\xE8\xBB\xBC", + "\xE7\x65"=>"\xE8\xBB\xBB", + "\xE7\x66"=>"\xE8\xBB\xAB", + "\xE7\x67"=>"\xE8\xBB\xBE", + "\xE7\x68"=>"\xE8\xBC\x8A", + "\xE7\x69"=>"\xE8\xBC\x85", + "\xE7\x6A"=>"\xE8\xBC\x95", + "\xE7\x6B"=>"\xE8\xBC\x92", + "\xE7\x6C"=>"\xE8\xBC\x99", + "\xE7\x6D"=>"\xE8\xBC\x93", + "\xE7\x6E"=>"\xE8\xBC\x9C", + "\xE7\x6F"=>"\xE8\xBC\x9F", + "\xE7\x70"=>"\xE8\xBC\x9B", + "\xE7\x71"=>"\xE8\xBC\x8C", + "\xE7\x72"=>"\xE8\xBC\xA6", + "\xE7\x73"=>"\xE8\xBC\xB3", + "\xE7\x74"=>"\xE8\xBC\xBB", + "\xE7\x75"=>"\xE8\xBC\xB9", + "\xE7\x76"=>"\xE8\xBD\x85", + "\xE7\x77"=>"\xE8\xBD\x82", + "\xE7\x78"=>"\xE8\xBC\xBE", + "\xE7\x79"=>"\xE8\xBD\x8C", + "\xE7\x7A"=>"\xE8\xBD\x89", + "\xE7\x7B"=>"\xE8\xBD\x86", + "\xE7\x7C"=>"\xE8\xBD\x8E", + "\xE7\x7D"=>"\xE8\xBD\x97", + "\xE7\x7E"=>"\xE8\xBD\x9C", + "\xE7\x80"=>"\xE8\xBD\xA2", + "\xE7\x81"=>"\xE8\xBD\xA3", + "\xE7\x82"=>"\xE8\xBD\xA4", + "\xE7\x83"=>"\xE8\xBE\x9C", + "\xE7\x84"=>"\xE8\xBE\x9F", + "\xE7\x85"=>"\xE8\xBE\xA3", + "\xE7\x86"=>"\xE8\xBE\xAD", + "\xE7\x87"=>"\xE8\xBE\xAF", + "\xE7\x88"=>"\xE8\xBE\xB7", + "\xE7\x89"=>"\xE8\xBF\x9A", + "\xE7\x8A"=>"\xE8\xBF\xA5", + "\xE7\x8B"=>"\xE8\xBF\xA2", + "\xE7\x8C"=>"\xE8\xBF\xAA", + "\xE7\x8D"=>"\xE8\xBF\xAF", + "\xE7\x8E"=>"\xE9\x82\x87", + "\xE7\x8F"=>"\xE8\xBF\xB4", + "\xE7\x90"=>"\xE9\x80\x85", + "\xE7\x91"=>"\xE8\xBF\xB9", + "\xE7\x92"=>"\xE8\xBF\xBA", + "\xE7\x93"=>"\xE9\x80\x91", + "\xE7\x94"=>"\xE9\x80\x95", + "\xE7\x95"=>"\xE9\x80\xA1", + "\xE7\x96"=>"\xE9\x80\x8D", + "\xE7\x97"=>"\xE9\x80\x9E", + "\xE7\x98"=>"\xE9\x80\x96", + "\xE7\x99"=>"\xE9\x80\x8B", + "\xE7\x9A"=>"\xE9\x80\xA7", + "\xE7\x9B"=>"\xE9\x80\xB6", + "\xE7\x9C"=>"\xE9\x80\xB5", + "\xE7\x9D"=>"\xE9\x80\xB9", + "\xE7\x9E"=>"\xE8\xBF\xB8", + "\xE7\x9F"=>"\xE9\x81\x8F", + "\xE7\xA0"=>"\xE9\x81\x90", + "\xE7\xA1"=>"\xE9\x81\x91", + "\xE7\xA2"=>"\xE9\x81\x92", + "\xE7\xA3"=>"\xE9\x80\x8E", + "\xE7\xA4"=>"\xE9\x81\x89", + "\xE7\xA5"=>"\xE9\x80\xBE", + "\xE7\xA6"=>"\xE9\x81\x96", + "\xE7\xA7"=>"\xE9\x81\x98", + "\xE7\xA8"=>"\xE9\x81\x9E", + "\xE7\xA9"=>"\xE9\x81\xA8", + "\xE7\xAA"=>"\xE9\x81\xAF", + "\xE7\xAB"=>"\xE9\x81\xB6", + "\xE7\xAC"=>"\xE9\x9A\xA8", + "\xE7\xAD"=>"\xE9\x81\xB2", + "\xE7\xAE"=>"\xE9\x82\x82", + "\xE7\xAF"=>"\xE9\x81\xBD", + "\xE7\xB0"=>"\xE9\x82\x81", + "\xE7\xB1"=>"\xE9\x82\x80", + "\xE7\xB2"=>"\xE9\x82\x8A", + "\xE7\xB3"=>"\xE9\x82\x89", + "\xE7\xB4"=>"\xE9\x82\x8F", + "\xE7\xB5"=>"\xE9\x82\xA8", + "\xE7\xB6"=>"\xE9\x82\xAF", + "\xE7\xB7"=>"\xE9\x82\xB1", + "\xE7\xB8"=>"\xE9\x82\xB5", + "\xE7\xB9"=>"\xE9\x83\xA2", + "\xE7\xBA"=>"\xE9\x83\xA4", + "\xE7\xBB"=>"\xE6\x89\x88", + "\xE7\xBC"=>"\xE9\x83\x9B", + "\xE7\xBD"=>"\xE9\x84\x82", + "\xE7\xBE"=>"\xE9\x84\x92", + "\xE7\xBF"=>"\xE9\x84\x99", + "\xE7\xC0"=>"\xE9\x84\xB2", + "\xE7\xC1"=>"\xE9\x84\xB0", + "\xE7\xC2"=>"\xE9\x85\x8A", + "\xE7\xC3"=>"\xE9\x85\x96", + "\xE7\xC4"=>"\xE9\x85\x98", + "\xE7\xC5"=>"\xE9\x85\xA3", + "\xE7\xC6"=>"\xE9\x85\xA5", + "\xE7\xC7"=>"\xE9\x85\xA9", + "\xE7\xC8"=>"\xE9\x85\xB3", + "\xE7\xC9"=>"\xE9\x85\xB2", + "\xE7\xCA"=>"\xE9\x86\x8B", + "\xE7\xCB"=>"\xE9\x86\x89", + "\xE7\xCC"=>"\xE9\x86\x82", + "\xE7\xCD"=>"\xE9\x86\xA2", + "\xE7\xCE"=>"\xE9\x86\xAB", + "\xE7\xCF"=>"\xE9\x86\xAF", + "\xE7\xD0"=>"\xE9\x86\xAA", + "\xE7\xD1"=>"\xE9\x86\xB5", + "\xE7\xD2"=>"\xE9\x86\xB4", + "\xE7\xD3"=>"\xE9\x86\xBA", + "\xE7\xD4"=>"\xE9\x87\x80", + "\xE7\xD5"=>"\xE9\x87\x81", + "\xE7\xD6"=>"\xE9\x87\x89", + "\xE7\xD7"=>"\xE9\x87\x8B", + "\xE7\xD8"=>"\xE9\x87\x90", + "\xE7\xD9"=>"\xE9\x87\x96", + "\xE7\xDA"=>"\xE9\x87\x9F", + "\xE7\xDB"=>"\xE9\x87\xA1", + "\xE7\xDC"=>"\xE9\x87\x9B", + "\xE7\xDD"=>"\xE9\x87\xBC", + "\xE7\xDE"=>"\xE9\x87\xB5", + "\xE7\xDF"=>"\xE9\x87\xB6", + "\xE7\xE0"=>"\xE9\x88\x9E", + "\xE7\xE1"=>"\xE9\x87\xBF", + "\xE7\xE2"=>"\xE9\x88\x94", + "\xE7\xE3"=>"\xE9\x88\xAC", + "\xE7\xE4"=>"\xE9\x88\x95", + "\xE7\xE5"=>"\xE9\x88\x91", + "\xE7\xE6"=>"\xE9\x89\x9E", + "\xE7\xE7"=>"\xE9\x89\x97", + "\xE7\xE8"=>"\xE9\x89\x85", + "\xE7\xE9"=>"\xE9\x89\x89", + "\xE7\xEA"=>"\xE9\x89\xA4", + "\xE7\xEB"=>"\xE9\x89\x88", + "\xE7\xEC"=>"\xE9\x8A\x95", + "\xE7\xED"=>"\xE9\x88\xBF", + "\xE7\xEE"=>"\xE9\x89\x8B", + "\xE7\xEF"=>"\xE9\x89\x90", + "\xE7\xF0"=>"\xE9\x8A\x9C", + "\xE7\xF1"=>"\xE9\x8A\x96", + "\xE7\xF2"=>"\xE9\x8A\x93", + "\xE7\xF3"=>"\xE9\x8A\x9B", + "\xE7\xF4"=>"\xE9\x89\x9A", + "\xE7\xF5"=>"\xE9\x8B\x8F", + "\xE7\xF6"=>"\xE9\x8A\xB9", + "\xE7\xF7"=>"\xE9\x8A\xB7", + "\xE7\xF8"=>"\xE9\x8B\xA9", + "\xE7\xF9"=>"\xE9\x8C\x8F", + "\xE7\xFA"=>"\xE9\x8B\xBA", + "\xE7\xFB"=>"\xE9\x8D\x84", + "\xE7\xFC"=>"\xE9\x8C\xAE", + "\xE8\x40"=>"\xE9\x8C\x99", + "\xE8\x41"=>"\xE9\x8C\xA2", + "\xE8\x42"=>"\xE9\x8C\x9A", + "\xE8\x43"=>"\xE9\x8C\xA3", + "\xE8\x44"=>"\xE9\x8C\xBA", + "\xE8\x45"=>"\xE9\x8C\xB5", + "\xE8\x46"=>"\xE9\x8C\xBB", + "\xE8\x47"=>"\xE9\x8D\x9C", + "\xE8\x48"=>"\xE9\x8D\xA0", + "\xE8\x49"=>"\xE9\x8D\xBC", + "\xE8\x4A"=>"\xE9\x8D\xAE", + "\xE8\x4B"=>"\xE9\x8D\x96", + "\xE8\x4C"=>"\xE9\x8E\xB0", + "\xE8\x4D"=>"\xE9\x8E\xAC", + "\xE8\x4E"=>"\xE9\x8E\xAD", + "\xE8\x4F"=>"\xE9\x8E\x94", + "\xE8\x50"=>"\xE9\x8E\xB9", + "\xE8\x51"=>"\xE9\x8F\x96", + "\xE8\x52"=>"\xE9\x8F\x97", + "\xE8\x53"=>"\xE9\x8F\xA8", + "\xE8\x54"=>"\xE9\x8F\xA5", + "\xE8\x55"=>"\xE9\x8F\x98", + "\xE8\x56"=>"\xE9\x8F\x83", + "\xE8\x57"=>"\xE9\x8F\x9D", + "\xE8\x58"=>"\xE9\x8F\x90", + "\xE8\x59"=>"\xE9\x8F\x88", + "\xE8\x5A"=>"\xE9\x8F\xA4", + "\xE8\x5B"=>"\xE9\x90\x9A", + "\xE8\x5C"=>"\xE9\x90\x94", + "\xE8\x5D"=>"\xE9\x90\x93", + "\xE8\x5E"=>"\xE9\x90\x83", + "\xE8\x5F"=>"\xE9\x90\x87", + "\xE8\x60"=>"\xE9\x90\x90", + "\xE8\x61"=>"\xE9\x90\xB6", + "\xE8\x62"=>"\xE9\x90\xAB", + "\xE8\x63"=>"\xE9\x90\xB5", + "\xE8\x64"=>"\xE9\x90\xA1", + "\xE8\x65"=>"\xE9\x90\xBA", + "\xE8\x66"=>"\xE9\x91\x81", + "\xE8\x67"=>"\xE9\x91\x92", + "\xE8\x68"=>"\xE9\x91\x84", + "\xE8\x69"=>"\xE9\x91\x9B", + "\xE8\x6A"=>"\xE9\x91\xA0", + "\xE8\x6B"=>"\xE9\x91\xA2", + "\xE8\x6C"=>"\xE9\x91\x9E", + "\xE8\x6D"=>"\xE9\x91\xAA", + "\xE8\x6E"=>"\xE9\x88\xA9", + "\xE8\x6F"=>"\xE9\x91\xB0", + "\xE8\x70"=>"\xE9\x91\xB5", + "\xE8\x71"=>"\xE9\x91\xB7", + "\xE8\x72"=>"\xE9\x91\xBD", + "\xE8\x73"=>"\xE9\x91\x9A", + "\xE8\x74"=>"\xE9\x91\xBC", + "\xE8\x75"=>"\xE9\x91\xBE", + "\xE8\x76"=>"\xE9\x92\x81", + "\xE8\x77"=>"\xE9\x91\xBF", + "\xE8\x78"=>"\xE9\x96\x82", + "\xE8\x79"=>"\xE9\x96\x87", + "\xE8\x7A"=>"\xE9\x96\x8A", + "\xE8\x7B"=>"\xE9\x96\x94", + "\xE8\x7C"=>"\xE9\x96\x96", + "\xE8\x7D"=>"\xE9\x96\x98", + "\xE8\x7E"=>"\xE9\x96\x99", + "\xE8\x80"=>"\xE9\x96\xA0", + "\xE8\x81"=>"\xE9\x96\xA8", + "\xE8\x82"=>"\xE9\x96\xA7", + "\xE8\x83"=>"\xE9\x96\xAD", + "\xE8\x84"=>"\xE9\x96\xBC", + "\xE8\x85"=>"\xE9\x96\xBB", + "\xE8\x86"=>"\xE9\x96\xB9", + "\xE8\x87"=>"\xE9\x96\xBE", + "\xE8\x88"=>"\xE9\x97\x8A", + "\xE8\x89"=>"\xE6\xBF\xB6", + "\xE8\x8A"=>"\xE9\x97\x83", + "\xE8\x8B"=>"\xE9\x97\x8D", + "\xE8\x8C"=>"\xE9\x97\x8C", + "\xE8\x8D"=>"\xE9\x97\x95", + "\xE8\x8E"=>"\xE9\x97\x94", + "\xE8\x8F"=>"\xE9\x97\x96", + "\xE8\x90"=>"\xE9\x97\x9C", + "\xE8\x91"=>"\xE9\x97\xA1", + "\xE8\x92"=>"\xE9\x97\xA5", + "\xE8\x93"=>"\xE9\x97\xA2", + "\xE8\x94"=>"\xE9\x98\xA1", + "\xE8\x95"=>"\xE9\x98\xA8", + "\xE8\x96"=>"\xE9\x98\xAE", + "\xE8\x97"=>"\xE9\x98\xAF", + "\xE8\x98"=>"\xE9\x99\x82", + "\xE8\x99"=>"\xE9\x99\x8C", + "\xE8\x9A"=>"\xE9\x99\x8F", + "\xE8\x9B"=>"\xE9\x99\x8B", + "\xE8\x9C"=>"\xE9\x99\xB7", + "\xE8\x9D"=>"\xE9\x99\x9C", + "\xE8\x9E"=>"\xE9\x99\x9E", + "\xE8\x9F"=>"\xE9\x99\x9D", + "\xE8\xA0"=>"\xE9\x99\x9F", + "\xE8\xA1"=>"\xE9\x99\xA6", + "\xE8\xA2"=>"\xE9\x99\xB2", + "\xE8\xA3"=>"\xE9\x99\xAC", + "\xE8\xA4"=>"\xE9\x9A\x8D", + "\xE8\xA5"=>"\xE9\x9A\x98", + "\xE8\xA6"=>"\xE9\x9A\x95", + "\xE8\xA7"=>"\xE9\x9A\x97", + "\xE8\xA8"=>"\xE9\x9A\xAA", + "\xE8\xA9"=>"\xE9\x9A\xA7", + "\xE8\xAA"=>"\xE9\x9A\xB1", + "\xE8\xAB"=>"\xE9\x9A\xB2", + "\xE8\xAC"=>"\xE9\x9A\xB0", + "\xE8\xAD"=>"\xE9\x9A\xB4", + "\xE8\xAE"=>"\xE9\x9A\xB6", + "\xE8\xAF"=>"\xE9\x9A\xB8", + "\xE8\xB0"=>"\xE9\x9A\xB9", + "\xE8\xB1"=>"\xE9\x9B\x8E", + "\xE8\xB2"=>"\xE9\x9B\x8B", + "\xE8\xB3"=>"\xE9\x9B\x89", + "\xE8\xB4"=>"\xE9\x9B\x8D", + "\xE8\xB5"=>"\xE8\xA5\x8D", + "\xE8\xB6"=>"\xE9\x9B\x9C", + "\xE8\xB7"=>"\xE9\x9C\x8D", + "\xE8\xB8"=>"\xE9\x9B\x95", + "\xE8\xB9"=>"\xE9\x9B\xB9", + "\xE8\xBA"=>"\xE9\x9C\x84", + "\xE8\xBB"=>"\xE9\x9C\x86", + "\xE8\xBC"=>"\xE9\x9C\x88", + "\xE8\xBD"=>"\xE9\x9C\x93", + "\xE8\xBE"=>"\xE9\x9C\x8E", + "\xE8\xBF"=>"\xE9\x9C\x91", + "\xE8\xC0"=>"\xE9\x9C\x8F", + "\xE8\xC1"=>"\xE9\x9C\x96", + "\xE8\xC2"=>"\xE9\x9C\x99", + "\xE8\xC3"=>"\xE9\x9C\xA4", + "\xE8\xC4"=>"\xE9\x9C\xAA", + "\xE8\xC5"=>"\xE9\x9C\xB0", + "\xE8\xC6"=>"\xE9\x9C\xB9", + "\xE8\xC7"=>"\xE9\x9C\xBD", + "\xE8\xC8"=>"\xE9\x9C\xBE", + "\xE8\xC9"=>"\xE9\x9D\x84", + "\xE8\xCA"=>"\xE9\x9D\x86", + "\xE8\xCB"=>"\xE9\x9D\x88", + "\xE8\xCC"=>"\xE9\x9D\x82", + "\xE8\xCD"=>"\xE9\x9D\x89", + "\xE8\xCE"=>"\xE9\x9D\x9C", + "\xE8\xCF"=>"\xE9\x9D\xA0", + "\xE8\xD0"=>"\xE9\x9D\xA4", + "\xE8\xD1"=>"\xE9\x9D\xA6", + "\xE8\xD2"=>"\xE9\x9D\xA8", + "\xE8\xD3"=>"\xE5\x8B\x92", + "\xE8\xD4"=>"\xE9\x9D\xAB", + "\xE8\xD5"=>"\xE9\x9D\xB1", + "\xE8\xD6"=>"\xE9\x9D\xB9", + "\xE8\xD7"=>"\xE9\x9E\x85", + "\xE8\xD8"=>"\xE9\x9D\xBC", + "\xE8\xD9"=>"\xE9\x9E\x81", + "\xE8\xDA"=>"\xE9\x9D\xBA", + "\xE8\xDB"=>"\xE9\x9E\x86", + "\xE8\xDC"=>"\xE9\x9E\x8B", + "\xE8\xDD"=>"\xE9\x9E\x8F", + "\xE8\xDE"=>"\xE9\x9E\x90", + "\xE8\xDF"=>"\xE9\x9E\x9C", + "\xE8\xE0"=>"\xE9\x9E\xA8", + "\xE8\xE1"=>"\xE9\x9E\xA6", + "\xE8\xE2"=>"\xE9\x9E\xA3", + "\xE8\xE3"=>"\xE9\x9E\xB3", + "\xE8\xE4"=>"\xE9\x9E\xB4", + "\xE8\xE5"=>"\xE9\x9F\x83", + "\xE8\xE6"=>"\xE9\x9F\x86", + "\xE8\xE7"=>"\xE9\x9F\x88", + "\xE8\xE8"=>"\xE9\x9F\x8B", + "\xE8\xE9"=>"\xE9\x9F\x9C", + "\xE8\xEA"=>"\xE9\x9F\xAD", + "\xE8\xEB"=>"\xE9\xBD\x8F", + "\xE8\xEC"=>"\xE9\x9F\xB2", + "\xE8\xED"=>"\xE7\xAB\x9F", + "\xE8\xEE"=>"\xE9\x9F\xB6", + "\xE8\xEF"=>"\xE9\x9F\xB5", + "\xE8\xF0"=>"\xE9\xA0\x8F", + "\xE8\xF1"=>"\xE9\xA0\x8C", + "\xE8\xF2"=>"\xE9\xA0\xB8", + "\xE8\xF3"=>"\xE9\xA0\xA4", + "\xE8\xF4"=>"\xE9\xA0\xA1", + "\xE8\xF5"=>"\xE9\xA0\xB7", + "\xE8\xF6"=>"\xE9\xA0\xBD", + "\xE8\xF7"=>"\xE9\xA1\x86", + "\xE8\xF8"=>"\xE9\xA1\x8F", + "\xE8\xF9"=>"\xE9\xA1\x8B", + "\xE8\xFA"=>"\xE9\xA1\xAB", + "\xE8\xFB"=>"\xE9\xA1\xAF", + "\xE8\xFC"=>"\xE9\xA1\xB0", + "\xE9\x40"=>"\xE9\xA1\xB1", + "\xE9\x41"=>"\xE9\xA1\xB4", + "\xE9\x42"=>"\xE9\xA1\xB3", + "\xE9\x43"=>"\xE9\xA2\xAA", + "\xE9\x44"=>"\xE9\xA2\xAF", + "\xE9\x45"=>"\xE9\xA2\xB1", + "\xE9\x46"=>"\xE9\xA2\xB6", + "\xE9\x47"=>"\xE9\xA3\x84", + "\xE9\x48"=>"\xE9\xA3\x83", + "\xE9\x49"=>"\xE9\xA3\x86", + "\xE9\x4A"=>"\xE9\xA3\xA9", + "\xE9\x4B"=>"\xE9\xA3\xAB", + "\xE9\x4C"=>"\xE9\xA4\x83", + "\xE9\x4D"=>"\xE9\xA4\x89", + "\xE9\x4E"=>"\xE9\xA4\x92", + "\xE9\x4F"=>"\xE9\xA4\x94", + "\xE9\x50"=>"\xE9\xA4\x98", + "\xE9\x51"=>"\xE9\xA4\xA1", + "\xE9\x52"=>"\xE9\xA4\x9D", + "\xE9\x53"=>"\xE9\xA4\x9E", + "\xE9\x54"=>"\xE9\xA4\xA4", + "\xE9\x55"=>"\xE9\xA4\xA0", + "\xE9\x56"=>"\xE9\xA4\xAC", + "\xE9\x57"=>"\xE9\xA4\xAE", + "\xE9\x58"=>"\xE9\xA4\xBD", + "\xE9\x59"=>"\xE9\xA4\xBE", + "\xE9\x5A"=>"\xE9\xA5\x82", + "\xE9\x5B"=>"\xE9\xA5\x89", + "\xE9\x5C"=>"\xE9\xA5\x85", + "\xE9\x5D"=>"\xE9\xA5\x90", + "\xE9\x5E"=>"\xE9\xA5\x8B", + "\xE9\x5F"=>"\xE9\xA5\x91", + "\xE9\x60"=>"\xE9\xA5\x92", + "\xE9\x61"=>"\xE9\xA5\x8C", + "\xE9\x62"=>"\xE9\xA5\x95", + "\xE9\x63"=>"\xE9\xA6\x97", + "\xE9\x64"=>"\xE9\xA6\x98", + "\xE9\x65"=>"\xE9\xA6\xA5", + "\xE9\x66"=>"\xE9\xA6\xAD", + "\xE9\x67"=>"\xE9\xA6\xAE", + "\xE9\x68"=>"\xE9\xA6\xBC", + "\xE9\x69"=>"\xE9\xA7\x9F", + "\xE9\x6A"=>"\xE9\xA7\x9B", + "\xE9\x6B"=>"\xE9\xA7\x9D", + "\xE9\x6C"=>"\xE9\xA7\x98", + "\xE9\x6D"=>"\xE9\xA7\x91", + "\xE9\x6E"=>"\xE9\xA7\xAD", + "\xE9\x6F"=>"\xE9\xA7\xAE", + "\xE9\x70"=>"\xE9\xA7\xB1", + "\xE9\x71"=>"\xE9\xA7\xB2", + "\xE9\x72"=>"\xE9\xA7\xBB", + "\xE9\x73"=>"\xE9\xA7\xB8", + "\xE9\x74"=>"\xE9\xA8\x81", + "\xE9\x75"=>"\xE9\xA8\x8F", + "\xE9\x76"=>"\xE9\xA8\x85", + "\xE9\x77"=>"\xE9\xA7\xA2", + "\xE9\x78"=>"\xE9\xA8\x99", + "\xE9\x79"=>"\xE9\xA8\xAB", + "\xE9\x7A"=>"\xE9\xA8\xB7", + "\xE9\x7B"=>"\xE9\xA9\x85", + "\xE9\x7C"=>"\xE9\xA9\x82", + "\xE9\x7D"=>"\xE9\xA9\x80", + "\xE9\x7E"=>"\xE9\xA9\x83", + "\xE9\x80"=>"\xE9\xA8\xBE", + "\xE9\x81"=>"\xE9\xA9\x95", + "\xE9\x82"=>"\xE9\xA9\x8D", + "\xE9\x83"=>"\xE9\xA9\x9B", + "\xE9\x84"=>"\xE9\xA9\x97", + "\xE9\x85"=>"\xE9\xA9\x9F", + "\xE9\x86"=>"\xE9\xA9\xA2", + "\xE9\x87"=>"\xE9\xA9\xA5", + "\xE9\x88"=>"\xE9\xA9\xA4", + "\xE9\x89"=>"\xE9\xA9\xA9", + "\xE9\x8A"=>"\xE9\xA9\xAB", + "\xE9\x8B"=>"\xE9\xA9\xAA", + "\xE9\x8C"=>"\xE9\xAA\xAD", + "\xE9\x8D"=>"\xE9\xAA\xB0", + "\xE9\x8E"=>"\xE9\xAA\xBC", + "\xE9\x8F"=>"\xE9\xAB\x80", + "\xE9\x90"=>"\xE9\xAB\x8F", + "\xE9\x91"=>"\xE9\xAB\x91", + "\xE9\x92"=>"\xE9\xAB\x93", + "\xE9\x93"=>"\xE9\xAB\x94", + "\xE9\x94"=>"\xE9\xAB\x9E", + "\xE9\x95"=>"\xE9\xAB\x9F", + "\xE9\x96"=>"\xE9\xAB\xA2", + "\xE9\x97"=>"\xE9\xAB\xA3", + "\xE9\x98"=>"\xE9\xAB\xA6", + "\xE9\x99"=>"\xE9\xAB\xAF", + "\xE9\x9A"=>"\xE9\xAB\xAB", + "\xE9\x9B"=>"\xE9\xAB\xAE", + "\xE9\x9C"=>"\xE9\xAB\xB4", + "\xE9\x9D"=>"\xE9\xAB\xB1", + "\xE9\x9E"=>"\xE9\xAB\xB7", + "\xE9\x9F"=>"\xE9\xAB\xBB", + "\xE9\xA0"=>"\xE9\xAC\x86", + "\xE9\xA1"=>"\xE9\xAC\x98", + "\xE9\xA2"=>"\xE9\xAC\x9A", + "\xE9\xA3"=>"\xE9\xAC\x9F", + "\xE9\xA4"=>"\xE9\xAC\xA2", + "\xE9\xA5"=>"\xE9\xAC\xA3", + "\xE9\xA6"=>"\xE9\xAC\xA5", + "\xE9\xA7"=>"\xE9\xAC\xA7", + "\xE9\xA8"=>"\xE9\xAC\xA8", + "\xE9\xA9"=>"\xE9\xAC\xA9", + "\xE9\xAA"=>"\xE9\xAC\xAA", + "\xE9\xAB"=>"\xE9\xAC\xAE", + "\xE9\xAC"=>"\xE9\xAC\xAF", + "\xE9\xAD"=>"\xE9\xAC\xB2", + "\xE9\xAE"=>"\xE9\xAD\x84", + "\xE9\xAF"=>"\xE9\xAD\x83", + "\xE9\xB0"=>"\xE9\xAD\x8F", + "\xE9\xB1"=>"\xE9\xAD\x8D", + "\xE9\xB2"=>"\xE9\xAD\x8E", + "\xE9\xB3"=>"\xE9\xAD\x91", + "\xE9\xB4"=>"\xE9\xAD\x98", + "\xE9\xB5"=>"\xE9\xAD\xB4", + "\xE9\xB6"=>"\xE9\xAE\x93", + "\xE9\xB7"=>"\xE9\xAE\x83", + "\xE9\xB8"=>"\xE9\xAE\x91", + "\xE9\xB9"=>"\xE9\xAE\x96", + "\xE9\xBA"=>"\xE9\xAE\x97", + "\xE9\xBB"=>"\xE9\xAE\x9F", + "\xE9\xBC"=>"\xE9\xAE\xA0", + "\xE9\xBD"=>"\xE9\xAE\xA8", + "\xE9\xBE"=>"\xE9\xAE\xB4", + "\xE9\xBF"=>"\xE9\xAF\x80", + "\xE9\xC0"=>"\xE9\xAF\x8A", + "\xE9\xC1"=>"\xE9\xAE\xB9", + "\xE9\xC2"=>"\xE9\xAF\x86", + "\xE9\xC3"=>"\xE9\xAF\x8F", + "\xE9\xC4"=>"\xE9\xAF\x91", + "\xE9\xC5"=>"\xE9\xAF\x92", + "\xE9\xC6"=>"\xE9\xAF\xA3", + "\xE9\xC7"=>"\xE9\xAF\xA2", + "\xE9\xC8"=>"\xE9\xAF\xA4", + "\xE9\xC9"=>"\xE9\xAF\x94", + "\xE9\xCA"=>"\xE9\xAF\xA1", + "\xE9\xCB"=>"\xE9\xB0\xBA", + "\xE9\xCC"=>"\xE9\xAF\xB2", + "\xE9\xCD"=>"\xE9\xAF\xB1", + "\xE9\xCE"=>"\xE9\xAF\xB0", + "\xE9\xCF"=>"\xE9\xB0\x95", + "\xE9\xD0"=>"\xE9\xB0\x94", + "\xE9\xD1"=>"\xE9\xB0\x89", + "\xE9\xD2"=>"\xE9\xB0\x93", + "\xE9\xD3"=>"\xE9\xB0\x8C", + "\xE9\xD4"=>"\xE9\xB0\x86", + "\xE9\xD5"=>"\xE9\xB0\x88", + "\xE9\xD6"=>"\xE9\xB0\x92", + "\xE9\xD7"=>"\xE9\xB0\x8A", + "\xE9\xD8"=>"\xE9\xB0\x84", + "\xE9\xD9"=>"\xE9\xB0\xAE", + "\xE9\xDA"=>"\xE9\xB0\x9B", + "\xE9\xDB"=>"\xE9\xB0\xA5", + "\xE9\xDC"=>"\xE9\xB0\xA4", + "\xE9\xDD"=>"\xE9\xB0\xA1", + "\xE9\xDE"=>"\xE9\xB0\xB0", + "\xE9\xDF"=>"\xE9\xB1\x87", + "\xE9\xE0"=>"\xE9\xB0\xB2", + "\xE9\xE1"=>"\xE9\xB1\x86", + "\xE9\xE2"=>"\xE9\xB0\xBE", + "\xE9\xE3"=>"\xE9\xB1\x9A", + "\xE9\xE4"=>"\xE9\xB1\xA0", + "\xE9\xE5"=>"\xE9\xB1\xA7", + "\xE9\xE6"=>"\xE9\xB1\xB6", + "\xE9\xE7"=>"\xE9\xB1\xB8", + "\xE9\xE8"=>"\xE9\xB3\xA7", + "\xE9\xE9"=>"\xE9\xB3\xAC", + "\xE9\xEA"=>"\xE9\xB3\xB0", + "\xE9\xEB"=>"\xE9\xB4\x89", + "\xE9\xEC"=>"\xE9\xB4\x88", + "\xE9\xED"=>"\xE9\xB3\xAB", + "\xE9\xEE"=>"\xE9\xB4\x83", + "\xE9\xEF"=>"\xE9\xB4\x86", + "\xE9\xF0"=>"\xE9\xB4\xAA", + "\xE9\xF1"=>"\xE9\xB4\xA6", + "\xE9\xF2"=>"\xE9\xB6\xAF", + "\xE9\xF3"=>"\xE9\xB4\xA3", + "\xE9\xF4"=>"\xE9\xB4\x9F", + "\xE9\xF5"=>"\xE9\xB5\x84", + "\xE9\xF6"=>"\xE9\xB4\x95", + "\xE9\xF7"=>"\xE9\xB4\x92", + "\xE9\xF8"=>"\xE9\xB5\x81", + "\xE9\xF9"=>"\xE9\xB4\xBF", + "\xE9\xFA"=>"\xE9\xB4\xBE", + "\xE9\xFB"=>"\xE9\xB5\x86", + "\xE9\xFC"=>"\xE9\xB5\x88", + "\xEA\x40"=>"\xE9\xB5\x9D", + "\xEA\x41"=>"\xE9\xB5\x9E", + "\xEA\x42"=>"\xE9\xB5\xA4", + "\xEA\x43"=>"\xE9\xB5\x91", + "\xEA\x44"=>"\xE9\xB5\x90", + "\xEA\x45"=>"\xE9\xB5\x99", + "\xEA\x46"=>"\xE9\xB5\xB2", + "\xEA\x47"=>"\xE9\xB6\x89", + "\xEA\x48"=>"\xE9\xB6\x87", + "\xEA\x49"=>"\xE9\xB6\xAB", + "\xEA\x4A"=>"\xE9\xB5\xAF", + "\xEA\x4B"=>"\xE9\xB5\xBA", + "\xEA\x4C"=>"\xE9\xB6\x9A", + "\xEA\x4D"=>"\xE9\xB6\xA4", + "\xEA\x4E"=>"\xE9\xB6\xA9", + "\xEA\x4F"=>"\xE9\xB6\xB2", + "\xEA\x50"=>"\xE9\xB7\x84", + "\xEA\x51"=>"\xE9\xB7\x81", + "\xEA\x52"=>"\xE9\xB6\xBB", + "\xEA\x53"=>"\xE9\xB6\xB8", + "\xEA\x54"=>"\xE9\xB6\xBA", + "\xEA\x55"=>"\xE9\xB7\x86", + "\xEA\x56"=>"\xE9\xB7\x8F", + "\xEA\x57"=>"\xE9\xB7\x82", + "\xEA\x58"=>"\xE9\xB7\x99", + "\xEA\x59"=>"\xE9\xB7\x93", + "\xEA\x5A"=>"\xE9\xB7\xB8", + "\xEA\x5B"=>"\xE9\xB7\xA6", + "\xEA\x5C"=>"\xE9\xB7\xAD", + "\xEA\x5D"=>"\xE9\xB7\xAF", + "\xEA\x5E"=>"\xE9\xB7\xBD", + "\xEA\x5F"=>"\xE9\xB8\x9A", + "\xEA\x60"=>"\xE9\xB8\x9B", + "\xEA\x61"=>"\xE9\xB8\x9E", + "\xEA\x62"=>"\xE9\xB9\xB5", + "\xEA\x63"=>"\xE9\xB9\xB9", + "\xEA\x64"=>"\xE9\xB9\xBD", + "\xEA\x65"=>"\xE9\xBA\x81", + "\xEA\x66"=>"\xE9\xBA\x88", + "\xEA\x67"=>"\xE9\xBA\x8B", + "\xEA\x68"=>"\xE9\xBA\x8C", + "\xEA\x69"=>"\xE9\xBA\x92", + "\xEA\x6A"=>"\xE9\xBA\x95", + "\xEA\x6B"=>"\xE9\xBA\x91", + "\xEA\x6C"=>"\xE9\xBA\x9D", + "\xEA\x6D"=>"\xE9\xBA\xA5", + "\xEA\x6E"=>"\xE9\xBA\xA9", + "\xEA\x6F"=>"\xE9\xBA\xB8", + "\xEA\x70"=>"\xE9\xBA\xAA", + "\xEA\x71"=>"\xE9\xBA\xAD", + "\xEA\x72"=>"\xE9\x9D\xA1", + "\xEA\x73"=>"\xE9\xBB\x8C", + "\xEA\x74"=>"\xE9\xBB\x8E", + "\xEA\x75"=>"\xE9\xBB\x8F", + "\xEA\x76"=>"\xE9\xBB\x90", + "\xEA\x77"=>"\xE9\xBB\x94", + "\xEA\x78"=>"\xE9\xBB\x9C", + "\xEA\x79"=>"\xE9\xBB\x9E", + "\xEA\x7A"=>"\xE9\xBB\x9D", + "\xEA\x7B"=>"\xE9\xBB\xA0", + "\xEA\x7C"=>"\xE9\xBB\xA5", + "\xEA\x7D"=>"\xE9\xBB\xA8", + "\xEA\x7E"=>"\xE9\xBB\xAF", + "\xEA\x80"=>"\xE9\xBB\xB4", + "\xEA\x81"=>"\xE9\xBB\xB6", + "\xEA\x82"=>"\xE9\xBB\xB7", + "\xEA\x83"=>"\xE9\xBB\xB9", + "\xEA\x84"=>"\xE9\xBB\xBB", + "\xEA\x85"=>"\xE9\xBB\xBC", + "\xEA\x86"=>"\xE9\xBB\xBD", + "\xEA\x87"=>"\xE9\xBC\x87", + "\xEA\x88"=>"\xE9\xBC\x88", + "\xEA\x89"=>"\xE7\x9A\xB7", + "\xEA\x8A"=>"\xE9\xBC\x95", + "\xEA\x8B"=>"\xE9\xBC\xA1", + "\xEA\x8C"=>"\xE9\xBC\xAC", + "\xEA\x8D"=>"\xE9\xBC\xBE", + "\xEA\x8E"=>"\xE9\xBD\x8A", + "\xEA\x8F"=>"\xE9\xBD\x92", + "\xEA\x90"=>"\xE9\xBD\x94", + "\xEA\x91"=>"\xE9\xBD\xA3", + "\xEA\x92"=>"\xE9\xBD\x9F", + "\xEA\x93"=>"\xE9\xBD\xA0", + "\xEA\x94"=>"\xE9\xBD\xA1", + "\xEA\x95"=>"\xE9\xBD\xA6", + "\xEA\x96"=>"\xE9\xBD\xA7", + "\xEA\x97"=>"\xE9\xBD\xAC", + "\xEA\x98"=>"\xE9\xBD\xAA", + "\xEA\x99"=>"\xE9\xBD\xB7", + "\xEA\x9A"=>"\xE9\xBD\xB2", + "\xEA\x9B"=>"\xE9\xBD\xB6", + "\xEA\x9C"=>"\xE9\xBE\x95", + "\xEA\x9D"=>"\xE9\xBE\x9C", + "\xEA\x9E"=>"\xE9\xBE\xA0", + "\xEA\x9F"=>"\xE5\xA0\xAF", + "\xEA\xA0"=>"\xE6\xA7\x87", + "\xEA\xA1"=>"\xE9\x81\x99", + "\xEA\xA2"=>"\xE7\x91\xA4", + "\xEA\xA3"=>"\xE5\x87\x9C", + "\xEA\xA4"=>"\xE7\x86\x99" + ); + return strtr($string, $transform); +} + +function euc_kr($string) +{ + static $transform = array( + "\x5c" => "\xE2\x82\xA9", // KX X 1001 + "\x81\x41" => "\xEA\xB0\x82", + "\x81\x42" => "\xEA\xB0\x83", + "\x81\x43" => "\xEA\xB0\x85", + "\x81\x44" => "\xEA\xB0\x86", + "\x81\x45" => "\xEA\xB0\x8B", + "\x81\x46" => "\xEA\xB0\x8C", + "\x81\x47" => "\xEA\xB0\x8D", + "\x81\x48" => "\xEA\xB0\x8E", + "\x81\x49" => "\xEA\xB0\x8F", + "\x81\x4A" => "\xEA\xB0\x98", + "\x81\x4B" => "\xEA\xB0\x9E", + "\x81\x4C" => "\xEA\xB0\x9F", + "\x81\x4D" => "\xEA\xB0\xA1", + "\x81\x4E" => "\xEA\xB0\xA2", + "\x81\x4F" => "\xEA\xB0\xA3", + "\x81\x50" => "\xEA\xB0\xA5", + "\x81\x51" => "\xEA\xB0\xA6", + "\x81\x52" => "\xEA\xB0\xA7", + "\x81\x53" => "\xEA\xB0\xA8", + "\x81\x54" => "\xEA\xB0\xA9", + "\x81\x55" => "\xEA\xB0\xAA", + "\x81\x56" => "\xEA\xB0\xAB", + "\x81\x57" => "\xEA\xB0\xAE", + "\x81\x58" => "\xEA\xB0\xB2", + "\x81\x59" => "\xEA\xB0\xB3", + "\x81\x5A" => "\xEA\xB0\xB4", + "\x81\x61" => "\xEA\xB0\xB5", + "\x81\x62" => "\xEA\xB0\xB6", + "\x81\x63" => "\xEA\xB0\xB7", + "\x81\x64" => "\xEA\xB0\xBA", + "\x81\x65" => "\xEA\xB0\xBB", + "\x81\x66" => "\xEA\xB0\xBD", + "\x81\x67" => "\xEA\xB0\xBE", + "\x81\x68" => "\xEA\xB0\xBF", + "\x81\x69" => "\xEA\xB1\x81", + "\x81\x6A" => "\xEA\xB1\x82", + "\x81\x6B" => "\xEA\xB1\x83", + "\x81\x6C" => "\xEA\xB1\x84", + "\x81\x6D" => "\xEA\xB1\x85", + "\x81\x6E" => "\xEA\xB1\x86", + "\x81\x6F" => "\xEA\xB1\x87", + "\x81\x70" => "\xEA\xB1\x88", + "\x81\x71" => "\xEA\xB1\x89", + "\x81\x72" => "\xEA\xB1\x8A", + "\x81\x73" => "\xEA\xB1\x8C", + "\x81\x74" => "\xEA\xB1\x8E", + "\x81\x75" => "\xEA\xB1\x8F", + "\x81\x76" => "\xEA\xB1\x90", + "\x81\x77" => "\xEA\xB1\x91", + "\x81\x78" => "\xEA\xB1\x92", + "\x81\x79" => "\xEA\xB1\x93", + "\x81\x7A" => "\xEA\xB1\x95", + "\x81\x81" => "\xEA\xB1\x96", + "\x81\x82" => "\xEA\xB1\x97", + "\x81\x83" => "\xEA\xB1\x99", + "\x81\x84" => "\xEA\xB1\x9A", + "\x81\x85" => "\xEA\xB1\x9B", + "\x81\x86" => "\xEA\xB1\x9D", + "\x81\x87" => "\xEA\xB1\x9E", + "\x81\x88" => "\xEA\xB1\x9F", + "\x81\x89" => "\xEA\xB1\xA0", + "\x81\x8A" => "\xEA\xB1\xA1", + "\x81\x8B" => "\xEA\xB1\xA2", + "\x81\x8C" => "\xEA\xB1\xA3", + "\x81\x8D" => "\xEA\xB1\xA4", + "\x81\x8E" => "\xEA\xB1\xA5", + "\x81\x8F" => "\xEA\xB1\xA6", + "\x81\x90" => "\xEA\xB1\xA7", + "\x81\x91" => "\xEA\xB1\xA8", + "\x81\x92" => "\xEA\xB1\xA9", + "\x81\x93" => "\xEA\xB1\xAA", + "\x81\x94" => "\xEA\xB1\xAB", + "\x81\x95" => "\xEA\xB1\xAC", + "\x81\x96" => "\xEA\xB1\xAD", + "\x81\x97" => "\xEA\xB1\xAE", + "\x81\x98" => "\xEA\xB1\xAF", + "\x81\x99" => "\xEA\xB1\xB2", + "\x81\x9A" => "\xEA\xB1\xB3", + "\x81\x9B" => "\xEA\xB1\xB5", + "\x81\x9C" => "\xEA\xB1\xB6", + "\x81\x9D" => "\xEA\xB1\xB9", + "\x81\x9E" => "\xEA\xB1\xBB", + "\x81\x9F" => "\xEA\xB1\xBC", + "\x81\xA0" => "\xEA\xB1\xBD", + "\x81\xA1" => "\xEA\xB1\xBE", + "\x81\xA2" => "\xEA\xB1\xBF", + "\x81\xA3" => "\xEA\xB2\x82", + "\x81\xA4" => "\xEA\xB2\x87", + "\x81\xA5" => "\xEA\xB2\x88", + "\x81\xA6" => "\xEA\xB2\x8D", + "\x81\xA7" => "\xEA\xB2\x8E", + "\x81\xA8" => "\xEA\xB2\x8F", + "\x81\xA9" => "\xEA\xB2\x91", + "\x81\xAA" => "\xEA\xB2\x92", + "\x81\xAB" => "\xEA\xB2\x93", + "\x81\xAC" => "\xEA\xB2\x95", + "\x81\xAD" => "\xEA\xB2\x96", + "\x81\xAE" => "\xEA\xB2\x97", + "\x81\xAF" => "\xEA\xB2\x98", + "\x81\xB0" => "\xEA\xB2\x99", + "\x81\xB1" => "\xEA\xB2\x9A", + "\x81\xB2" => "\xEA\xB2\x9B", + "\x81\xB3" => "\xEA\xB2\x9E", + "\x81\xB4" => "\xEA\xB2\xA2", + "\x81\xB5" => "\xEA\xB2\xA3", + "\x81\xB6" => "\xEA\xB2\xA4", + "\x81\xB7" => "\xEA\xB2\xA5", + "\x81\xB8" => "\xEA\xB2\xA6", + "\x81\xB9" => "\xEA\xB2\xA7", + "\x81\xBA" => "\xEA\xB2\xAB", + "\x81\xBB" => "\xEA\xB2\xAD", + "\x81\xBC" => "\xEA\xB2\xAE", + "\x81\xBD" => "\xEA\xB2\xB1", + "\x81\xBE" => "\xEA\xB2\xB2", + "\x81\xBF" => "\xEA\xB2\xB3", + "\x81\xC0" => "\xEA\xB2\xB4", + "\x81\xC1" => "\xEA\xB2\xB5", + "\x81\xC2" => "\xEA\xB2\xB6", + "\x81\xC3" => "\xEA\xB2\xB7", + "\x81\xC4" => "\xEA\xB2\xBA", + "\x81\xC5" => "\xEA\xB2\xBE", + "\x81\xC6" => "\xEA\xB2\xBF", + "\x81\xC7" => "\xEA\xB3\x80", + "\x81\xC8" => "\xEA\xB3\x82", + "\x81\xC9" => "\xEA\xB3\x83", + "\x81\xCA" => "\xEA\xB3\x85", + "\x81\xCB" => "\xEA\xB3\x86", + "\x81\xCC" => "\xEA\xB3\x87", + "\x81\xCD" => "\xEA\xB3\x89", + "\x81\xCE" => "\xEA\xB3\x8A", + "\x81\xCF" => "\xEA\xB3\x8B", + "\x81\xD0" => "\xEA\xB3\x8D", + "\x81\xD1" => "\xEA\xB3\x8E", + "\x81\xD2" => "\xEA\xB3\x8F", + "\x81\xD3" => "\xEA\xB3\x90", + "\x81\xD4" => "\xEA\xB3\x91", + "\x81\xD5" => "\xEA\xB3\x92", + "\x81\xD6" => "\xEA\xB3\x93", + "\x81\xD7" => "\xEA\xB3\x94", + "\x81\xD8" => "\xEA\xB3\x96", + "\x81\xD9" => "\xEA\xB3\x98", + "\x81\xDA" => "\xEA\xB3\x99", + "\x81\xDB" => "\xEA\xB3\x9A", + "\x81\xDC" => "\xEA\xB3\x9B", + "\x81\xDD" => "\xEA\xB3\x9C", + "\x81\xDE" => "\xEA\xB3\x9D", + "\x81\xDF" => "\xEA\xB3\x9E", + "\x81\xE0" => "\xEA\xB3\x9F", + "\x81\xE1" => "\xEA\xB3\xA2", + "\x81\xE2" => "\xEA\xB3\xA3", + "\x81\xE3" => "\xEA\xB3\xA5", + "\x81\xE4" => "\xEA\xB3\xA6", + "\x81\xE5" => "\xEA\xB3\xA9", + "\x81\xE6" => "\xEA\xB3\xAB", + "\x81\xE7" => "\xEA\xB3\xAD", + "\x81\xE8" => "\xEA\xB3\xAE", + "\x81\xE9" => "\xEA\xB3\xB2", + "\x81\xEA" => "\xEA\xB3\xB4", + "\x81\xEB" => "\xEA\xB3\xB7", + "\x81\xEC" => "\xEA\xB3\xB8", + "\x81\xED" => "\xEA\xB3\xB9", + "\x81\xEE" => "\xEA\xB3\xBA", + "\x81\xEF" => "\xEA\xB3\xBB", + "\x81\xF0" => "\xEA\xB3\xBE", + "\x81\xF1" => "\xEA\xB3\xBF", + "\x81\xF2" => "\xEA\xB4\x81", + "\x81\xF3" => "\xEA\xB4\x82", + "\x81\xF4" => "\xEA\xB4\x83", + "\x81\xF5" => "\xEA\xB4\x85", + "\x81\xF6" => "\xEA\xB4\x87", + "\x81\xF7" => "\xEA\xB4\x88", + "\x81\xF8" => "\xEA\xB4\x89", + "\x81\xF9" => "\xEA\xB4\x8A", + "\x81\xFA" => "\xEA\xB4\x8B", + "\x81\xFB" => "\xEA\xB4\x8E", + "\x81\xFC" => "\xEA\xB4\x90", + "\x81\xFD" => "\xEA\xB4\x92", + "\x81\xFE" => "\xEA\xB4\x93", + "\x82\x41" => "\xEA\xB4\x94", + "\x82\x42" => "\xEA\xB4\x95", + "\x82\x43" => "\xEA\xB4\x96", + "\x82\x44" => "\xEA\xB4\x97", + "\x82\x45" => "\xEA\xB4\x99", + "\x82\x46" => "\xEA\xB4\x9A", + "\x82\x47" => "\xEA\xB4\x9B", + "\x82\x48" => "\xEA\xB4\x9D", + "\x82\x49" => "\xEA\xB4\x9E", + "\x82\x4A" => "\xEA\xB4\x9F", + "\x82\x4B" => "\xEA\xB4\xA1", + "\x82\x4C" => "\xEA\xB4\xA2", + "\x82\x4D" => "\xEA\xB4\xA3", + "\x82\x4E" => "\xEA\xB4\xA4", + "\x82\x4F" => "\xEA\xB4\xA5", + "\x82\x50" => "\xEA\xB4\xA6", + "\x82\x51" => "\xEA\xB4\xA7", + "\x82\x52" => "\xEA\xB4\xA8", + "\x82\x53" => "\xEA\xB4\xAA", + "\x82\x54" => "\xEA\xB4\xAB", + "\x82\x55" => "\xEA\xB4\xAE", + "\x82\x56" => "\xEA\xB4\xAF", + "\x82\x57" => "\xEA\xB4\xB0", + "\x82\x58" => "\xEA\xB4\xB1", + "\x82\x59" => "\xEA\xB4\xB2", + "\x82\x5A" => "\xEA\xB4\xB3", + "\x82\x61" => "\xEA\xB4\xB6", + "\x82\x62" => "\xEA\xB4\xB7", + "\x82\x63" => "\xEA\xB4\xB9", + "\x82\x64" => "\xEA\xB4\xBA", + "\x82\x65" => "\xEA\xB4\xBB", + "\x82\x66" => "\xEA\xB4\xBD", + "\x82\x67" => "\xEA\xB4\xBE", + "\x82\x68" => "\xEA\xB4\xBF", + "\x82\x69" => "\xEA\xB5\x80", + "\x82\x6A" => "\xEA\xB5\x81", + "\x82\x6B" => "\xEA\xB5\x82", + "\x82\x6C" => "\xEA\xB5\x83", + "\x82\x6D" => "\xEA\xB5\x86", + "\x82\x6E" => "\xEA\xB5\x88", + "\x82\x6F" => "\xEA\xB5\x8A", + "\x82\x70" => "\xEA\xB5\x8B", + "\x82\x71" => "\xEA\xB5\x8C", + "\x82\x72" => "\xEA\xB5\x8D", + "\x82\x73" => "\xEA\xB5\x8E", + "\x82\x74" => "\xEA\xB5\x8F", + "\x82\x75" => "\xEA\xB5\x91", + "\x82\x76" => "\xEA\xB5\x92", + "\x82\x77" => "\xEA\xB5\x93", + "\x82\x78" => "\xEA\xB5\x95", + "\x82\x79" => "\xEA\xB5\x96", + "\x82\x7A" => "\xEA\xB5\x97", + "\x82\x81" => "\xEA\xB5\x99", + "\x82\x82" => "\xEA\xB5\x9A", + "\x82\x83" => "\xEA\xB5\x9B", + "\x82\x84" => "\xEA\xB5\x9C", + "\x82\x85" => "\xEA\xB5\x9D", + "\x82\x86" => "\xEA\xB5\x9E", + "\x82\x87" => "\xEA\xB5\x9F", + "\x82\x88" => "\xEA\xB5\xA0", + "\x82\x89" => "\xEA\xB5\xA2", + "\x82\x8A" => "\xEA\xB5\xA4", + "\x82\x8B" => "\xEA\xB5\xA5", + "\x82\x8C" => "\xEA\xB5\xA6", + "\x82\x8D" => "\xEA\xB5\xA7", + "\x82\x8E" => "\xEA\xB5\xA8", + "\x82\x8F" => "\xEA\xB5\xA9", + "\x82\x90" => "\xEA\xB5\xAA", + "\x82\x91" => "\xEA\xB5\xAB", + "\x82\x92" => "\xEA\xB5\xAE", + "\x82\x93" => "\xEA\xB5\xAF", + "\x82\x94" => "\xEA\xB5\xB1", + "\x82\x95" => "\xEA\xB5\xB2", + "\x82\x96" => "\xEA\xB5\xB7", + "\x82\x97" => "\xEA\xB5\xB8", + "\x82\x98" => "\xEA\xB5\xB9", + "\x82\x99" => "\xEA\xB5\xBA", + "\x82\x9A" => "\xEA\xB5\xBE", + "\x82\x9B" => "\xEA\xB6\x80", + "\x82\x9C" => "\xEA\xB6\x83", + "\x82\x9D" => "\xEA\xB6\x84", + "\x82\x9E" => "\xEA\xB6\x85", + "\x82\x9F" => "\xEA\xB6\x86", + "\x82\xA0" => "\xEA\xB6\x87", + "\x82\xA1" => "\xEA\xB6\x8A", + "\x82\xA2" => "\xEA\xB6\x8B", + "\x82\xA3" => "\xEA\xB6\x8D", + "\x82\xA4" => "\xEA\xB6\x8E", + "\x82\xA5" => "\xEA\xB6\x8F", + "\x82\xA6" => "\xEA\xB6\x91", + "\x82\xA7" => "\xEA\xB6\x92", + "\x82\xA8" => "\xEA\xB6\x93", + "\x82\xA9" => "\xEA\xB6\x94", + "\x82\xAA" => "\xEA\xB6\x95", + "\x82\xAB" => "\xEA\xB6\x96", + "\x82\xAC" => "\xEA\xB6\x97", + "\x82\xAD" => "\xEA\xB6\x98", + "\x82\xAE" => "\xEA\xB6\x99", + "\x82\xAF" => "\xEA\xB6\x9A", + "\x82\xB0" => "\xEA\xB6\x9B", + "\x82\xB1" => "\xEA\xB6\x9E", + "\x82\xB2" => "\xEA\xB6\x9F", + "\x82\xB3" => "\xEA\xB6\xA0", + "\x82\xB4" => "\xEA\xB6\xA1", + "\x82\xB5" => "\xEA\xB6\xA2", + "\x82\xB6" => "\xEA\xB6\xA3", + "\x82\xB7" => "\xEA\xB6\xA5", + "\x82\xB8" => "\xEA\xB6\xA6", + "\x82\xB9" => "\xEA\xB6\xA7", + "\x82\xBA" => "\xEA\xB6\xA8", + "\x82\xBB" => "\xEA\xB6\xA9", + "\x82\xBC" => "\xEA\xB6\xAA", + "\x82\xBD" => "\xEA\xB6\xAB", + "\x82\xBE" => "\xEA\xB6\xAC", + "\x82\xBF" => "\xEA\xB6\xAD", + "\x82\xC0" => "\xEA\xB6\xAE", + "\x82\xC1" => "\xEA\xB6\xAF", + "\x82\xC2" => "\xEA\xB6\xB0", + "\x82\xC3" => "\xEA\xB6\xB1", + "\x82\xC4" => "\xEA\xB6\xB2", + "\x82\xC5" => "\xEA\xB6\xB3", + "\x82\xC6" => "\xEA\xB6\xB4", + "\x82\xC7" => "\xEA\xB6\xB5", + "\x82\xC8" => "\xEA\xB6\xB6", + "\x82\xC9" => "\xEA\xB6\xB8", + "\x82\xCA" => "\xEA\xB6\xB9", + "\x82\xCB" => "\xEA\xB6\xBA", + "\x82\xCC" => "\xEA\xB6\xBB", + "\x82\xCD" => "\xEA\xB6\xBC", + "\x82\xCE" => "\xEA\xB6\xBD", + "\x82\xCF" => "\xEA\xB6\xBE", + "\x82\xD0" => "\xEA\xB6\xBF", + "\x82\xD1" => "\xEA\xB7\x82", + "\x82\xD2" => "\xEA\xB7\x83", + "\x82\xD3" => "\xEA\xB7\x85", + "\x82\xD4" => "\xEA\xB7\x86", + "\x82\xD5" => "\xEA\xB7\x87", + "\x82\xD6" => "\xEA\xB7\x89", + "\x82\xD7" => "\xEA\xB7\x8A", + "\x82\xD8" => "\xEA\xB7\x8B", + "\x82\xD9" => "\xEA\xB7\x8C", + "\x82\xDA" => "\xEA\xB7\x8D", + "\x82\xDB" => "\xEA\xB7\x8E", + "\x82\xDC" => "\xEA\xB7\x8F", + "\x82\xDD" => "\xEA\xB7\x92", + "\x82\xDE" => "\xEA\xB7\x94", + "\x82\xDF" => "\xEA\xB7\x95", + "\x82\xE0" => "\xEA\xB7\x96", + "\x82\xE1" => "\xEA\xB7\x97", + "\x82\xE2" => "\xEA\xB7\x98", + "\x82\xE3" => "\xEA\xB7\x99", + "\x82\xE4" => "\xEA\xB7\x9A", + "\x82\xE5" => "\xEA\xB7\x9B", + "\x82\xE6" => "\xEA\xB7\x9D", + "\x82\xE7" => "\xEA\xB7\x9E", + "\x82\xE8" => "\xEA\xB7\x9F", + "\x82\xE9" => "\xEA\xB7\xA1", + "\x82\xEA" => "\xEA\xB7\xA2", + "\x82\xEB" => "\xEA\xB7\xA3", + "\x82\xEC" => "\xEA\xB7\xA5", + "\x82\xED" => "\xEA\xB7\xA6", + "\x82\xEE" => "\xEA\xB7\xA7", + "\x82\xEF" => "\xEA\xB7\xA8", + "\x82\xF0" => "\xEA\xB7\xA9", + "\x82\xF1" => "\xEA\xB7\xAA", + "\x82\xF2" => "\xEA\xB7\xAB", + "\x82\xF3" => "\xEA\xB7\xAC", + "\x82\xF4" => "\xEA\xB7\xAD", + "\x82\xF5" => "\xEA\xB7\xAE", + "\x82\xF6" => "\xEA\xB7\xAF", + "\x82\xF7" => "\xEA\xB7\xB0", + "\x82\xF8" => "\xEA\xB7\xB1", + "\x82\xF9" => "\xEA\xB7\xB2", + "\x82\xFA" => "\xEA\xB7\xB3", + "\x82\xFB" => "\xEA\xB7\xB4", + "\x82\xFC" => "\xEA\xB7\xB5", + "\x82\xFD" => "\xEA\xB7\xB6", + "\x82\xFE" => "\xEA\xB7\xB7", + "\x83\x41" => "\xEA\xB7\xBA", + "\x83\x42" => "\xEA\xB7\xBB", + "\x83\x43" => "\xEA\xB7\xBD", + "\x83\x44" => "\xEA\xB7\xBE", + "\x83\x45" => "\xEA\xB8\x82", + "\x83\x46" => "\xEA\xB8\x83", + "\x83\x47" => "\xEA\xB8\x84", + "\x83\x48" => "\xEA\xB8\x85", + "\x83\x49" => "\xEA\xB8\x86", + "\x83\x4A" => "\xEA\xB8\x87", + "\x83\x4B" => "\xEA\xB8\x8A", + "\x83\x4C" => "\xEA\xB8\x8C", + "\x83\x4D" => "\xEA\xB8\x8E", + "\x83\x4E" => "\xEA\xB8\x8F", + "\x83\x4F" => "\xEA\xB8\x90", + "\x83\x50" => "\xEA\xB8\x91", + "\x83\x51" => "\xEA\xB8\x92", + "\x83\x52" => "\xEA\xB8\x93", + "\x83\x53" => "\xEA\xB8\x95", + "\x83\x54" => "\xEA\xB8\x96", + "\x83\x55" => "\xEA\xB8\x97", + "\x83\x56" => "\xEA\xB8\x98", + "\x83\x57" => "\xEA\xB8\x99", + "\x83\x58" => "\xEA\xB8\x9A", + "\x83\x59" => "\xEA\xB8\x9B", + "\x83\x5A" => "\xEA\xB8\x9C", + "\x83\x61" => "\xEA\xB8\x9D", + "\x83\x62" => "\xEA\xB8\x9E", + "\x83\x63" => "\xEA\xB8\x9F", + "\x83\x64" => "\xEA\xB8\xA0", + "\x83\x65" => "\xEA\xB8\xA1", + "\x83\x66" => "\xEA\xB8\xA2", + "\x83\x67" => "\xEA\xB8\xA3", + "\x83\x68" => "\xEA\xB8\xA4", + "\x83\x69" => "\xEA\xB8\xA5", + "\x83\x6A" => "\xEA\xB8\xA6", + "\x83\x6B" => "\xEA\xB8\xA7", + "\x83\x6C" => "\xEA\xB8\xA8", + "\x83\x6D" => "\xEA\xB8\xA9", + "\x83\x6E" => "\xEA\xB8\xAA", + "\x83\x6F" => "\xEA\xB8\xAB", + "\x83\x70" => "\xEA\xB8\xAC", + "\x83\x71" => "\xEA\xB8\xAD", + "\x83\x72" => "\xEA\xB8\xAE", + "\x83\x73" => "\xEA\xB8\xAF", + "\x83\x74" => "\xEA\xB8\xB2", + "\x83\x75" => "\xEA\xB8\xB3", + "\x83\x76" => "\xEA\xB8\xB5", + "\x83\x77" => "\xEA\xB8\xB6", + "\x83\x78" => "\xEA\xB8\xB9", + "\x83\x79" => "\xEA\xB8\xBB", + "\x83\x7A" => "\xEA\xB8\xBC", + "\x83\x81" => "\xEA\xB8\xBD", + "\x83\x82" => "\xEA\xB8\xBE", + "\x83\x83" => "\xEA\xB8\xBF", + "\x83\x84" => "\xEA\xB9\x82", + "\x83\x85" => "\xEA\xB9\x84", + "\x83\x86" => "\xEA\xB9\x87", + "\x83\x87" => "\xEA\xB9\x88", + "\x83\x88" => "\xEA\xB9\x89", + "\x83\x89" => "\xEA\xB9\x8B", + "\x83\x8A" => "\xEA\xB9\x8F", + "\x83\x8B" => "\xEA\xB9\x91", + "\x83\x8C" => "\xEA\xB9\x92", + "\x83\x8D" => "\xEA\xB9\x93", + "\x83\x8E" => "\xEA\xB9\x95", + "\x83\x8F" => "\xEA\xB9\x97", + "\x83\x90" => "\xEA\xB9\x98", + "\x83\x91" => "\xEA\xB9\x99", + "\x83\x92" => "\xEA\xB9\x9A", + "\x83\x93" => "\xEA\xB9\x9B", + "\x83\x94" => "\xEA\xB9\x9E", + "\x83\x95" => "\xEA\xB9\xA2", + "\x83\x96" => "\xEA\xB9\xA3", + "\x83\x97" => "\xEA\xB9\xA4", + "\x83\x98" => "\xEA\xB9\xA6", + "\x83\x99" => "\xEA\xB9\xA7", + "\x83\x9A" => "\xEA\xB9\xAA", + "\x83\x9B" => "\xEA\xB9\xAB", + "\x83\x9C" => "\xEA\xB9\xAD", + "\x83\x9D" => "\xEA\xB9\xAE", + "\x83\x9E" => "\xEA\xB9\xAF", + "\x83\x9F" => "\xEA\xB9\xB1", + "\x83\xA0" => "\xEA\xB9\xB2", + "\x83\xA1" => "\xEA\xB9\xB3", + "\x83\xA2" => "\xEA\xB9\xB4", + "\x83\xA3" => "\xEA\xB9\xB5", + "\x83\xA4" => "\xEA\xB9\xB6", + "\x83\xA5" => "\xEA\xB9\xB7", + "\x83\xA6" => "\xEA\xB9\xBA", + "\x83\xA7" => "\xEA\xB9\xBE", + "\x83\xA8" => "\xEA\xB9\xBF", + "\x83\xA9" => "\xEA\xBA\x80", + "\x83\xAA" => "\xEA\xBA\x81", + "\x83\xAB" => "\xEA\xBA\x82", + "\x83\xAC" => "\xEA\xBA\x83", + "\x83\xAD" => "\xEA\xBA\x86", + "\x83\xAE" => "\xEA\xBA\x87", + "\x83\xAF" => "\xEA\xBA\x88", + "\x83\xB0" => "\xEA\xBA\x89", + "\x83\xB1" => "\xEA\xBA\x8A", + "\x83\xB2" => "\xEA\xBA\x8B", + "\x83\xB3" => "\xEA\xBA\x8D", + "\x83\xB4" => "\xEA\xBA\x8E", + "\x83\xB5" => "\xEA\xBA\x8F", + "\x83\xB6" => "\xEA\xBA\x90", + "\x83\xB7" => "\xEA\xBA\x91", + "\x83\xB8" => "\xEA\xBA\x92", + "\x83\xB9" => "\xEA\xBA\x93", + "\x83\xBA" => "\xEA\xBA\x94", + "\x83\xBB" => "\xEA\xBA\x95", + "\x83\xBC" => "\xEA\xBA\x96", + "\x83\xBD" => "\xEA\xBA\x97", + "\x83\xBE" => "\xEA\xBA\x98", + "\x83\xBF" => "\xEA\xBA\x99", + "\x83\xC0" => "\xEA\xBA\x9A", + "\x83\xC1" => "\xEA\xBA\x9B", + "\x83\xC2" => "\xEA\xBA\x9C", + "\x83\xC3" => "\xEA\xBA\x9D", + "\x83\xC4" => "\xEA\xBA\x9E", + "\x83\xC5" => "\xEA\xBA\x9F", + "\x83\xC6" => "\xEA\xBA\xA0", + "\x83\xC7" => "\xEA\xBA\xA1", + "\x83\xC8" => "\xEA\xBA\xA2", + "\x83\xC9" => "\xEA\xBA\xA3", + "\x83\xCA" => "\xEA\xBA\xA4", + "\x83\xCB" => "\xEA\xBA\xA5", + "\x83\xCC" => "\xEA\xBA\xA6", + "\x83\xCD" => "\xEA\xBA\xA7", + "\x83\xCE" => "\xEA\xBA\xA8", + "\x83\xCF" => "\xEA\xBA\xA9", + "\x83\xD0" => "\xEA\xBA\xAA", + "\x83\xD1" => "\xEA\xBA\xAB", + "\x83\xD2" => "\xEA\xBA\xAC", + "\x83\xD3" => "\xEA\xBA\xAD", + "\x83\xD4" => "\xEA\xBA\xAE", + "\x83\xD5" => "\xEA\xBA\xAF", + "\x83\xD6" => "\xEA\xBA\xB0", + "\x83\xD7" => "\xEA\xBA\xB1", + "\x83\xD8" => "\xEA\xBA\xB2", + "\x83\xD9" => "\xEA\xBA\xB3", + "\x83\xDA" => "\xEA\xBA\xB4", + "\x83\xDB" => "\xEA\xBA\xB5", + "\x83\xDC" => "\xEA\xBA\xB6", + "\x83\xDD" => "\xEA\xBA\xB7", + "\x83\xDE" => "\xEA\xBA\xB8", + "\x83\xDF" => "\xEA\xBA\xB9", + "\x83\xE0" => "\xEA\xBA\xBA", + "\x83\xE1" => "\xEA\xBA\xBB", + "\x83\xE2" => "\xEA\xBA\xBF", + "\x83\xE3" => "\xEA\xBB\x81", + "\x83\xE4" => "\xEA\xBB\x82", + "\x83\xE5" => "\xEA\xBB\x83", + "\x83\xE6" => "\xEA\xBB\x85", + "\x83\xE7" => "\xEA\xBB\x86", + "\x83\xE8" => "\xEA\xBB\x87", + "\x83\xE9" => "\xEA\xBB\x88", + "\x83\xEA" => "\xEA\xBB\x89", + "\x83\xEB" => "\xEA\xBB\x8A", + "\x83\xEC" => "\xEA\xBB\x8B", + "\x83\xED" => "\xEA\xBB\x8E", + "\x83\xEE" => "\xEA\xBB\x92", + "\x83\xEF" => "\xEA\xBB\x93", + "\x83\xF0" => "\xEA\xBB\x94", + "\x83\xF1" => "\xEA\xBB\x95", + "\x83\xF2" => "\xEA\xBB\x96", + "\x83\xF3" => "\xEA\xBB\x97", + "\x83\xF4" => "\xEA\xBB\x9A", + "\x83\xF5" => "\xEA\xBB\x9B", + "\x83\xF6" => "\xEA\xBB\x9D", + "\x83\xF7" => "\xEA\xBB\x9E", + "\x83\xF8" => "\xEA\xBB\x9F", + "\x83\xF9" => "\xEA\xBB\xA0", + "\x83\xFA" => "\xEA\xBB\xA1", + "\x83\xFB" => "\xEA\xBB\xA2", + "\x83\xFC" => "\xEA\xBB\xA3", + "\x83\xFD" => "\xEA\xBB\xA4", + "\x83\xFE" => "\xEA\xBB\xA5", + "\x84\x41" => "\xEA\xBB\xA6", + "\x84\x42" => "\xEA\xBB\xA7", + "\x84\x43" => "\xEA\xBB\xA9", + "\x84\x44" => "\xEA\xBB\xAA", + "\x84\x45" => "\xEA\xBB\xAC", + "\x84\x46" => "\xEA\xBB\xAE", + "\x84\x47" => "\xEA\xBB\xAF", + "\x84\x48" => "\xEA\xBB\xB0", + "\x84\x49" => "\xEA\xBB\xB1", + "\x84\x4A" => "\xEA\xBB\xB2", + "\x84\x4B" => "\xEA\xBB\xB3", + "\x84\x4C" => "\xEA\xBB\xB5", + "\x84\x4D" => "\xEA\xBB\xB6", + "\x84\x4E" => "\xEA\xBB\xB7", + "\x84\x4F" => "\xEA\xBB\xB9", + "\x84\x50" => "\xEA\xBB\xBA", + "\x84\x51" => "\xEA\xBB\xBB", + "\x84\x52" => "\xEA\xBB\xBD", + "\x84\x53" => "\xEA\xBB\xBE", + "\x84\x54" => "\xEA\xBB\xBF", + "\x84\x55" => "\xEA\xBC\x80", + "\x84\x56" => "\xEA\xBC\x81", + "\x84\x57" => "\xEA\xBC\x82", + "\x84\x58" => "\xEA\xBC\x83", + "\x84\x59" => "\xEA\xBC\x84", + "\x84\x5A" => "\xEA\xBC\x85", + "\x84\x61" => "\xEA\xBC\x86", + "\x84\x62" => "\xEA\xBC\x89", + "\x84\x63" => "\xEA\xBC\x8A", + "\x84\x64" => "\xEA\xBC\x8B", + "\x84\x65" => "\xEA\xBC\x8C", + "\x84\x66" => "\xEA\xBC\x8E", + "\x84\x67" => "\xEA\xBC\x8F", + "\x84\x68" => "\xEA\xBC\x91", + "\x84\x69" => "\xEA\xBC\x92", + "\x84\x6A" => "\xEA\xBC\x93", + "\x84\x6B" => "\xEA\xBC\x94", + "\x84\x6C" => "\xEA\xBC\x95", + "\x84\x6D" => "\xEA\xBC\x96", + "\x84\x6E" => "\xEA\xBC\x97", + "\x84\x6F" => "\xEA\xBC\x98", + "\x84\x70" => "\xEA\xBC\x99", + "\x84\x71" => "\xEA\xBC\x9A", + "\x84\x72" => "\xEA\xBC\x9B", + "\x84\x73" => "\xEA\xBC\x9C", + "\x84\x74" => "\xEA\xBC\x9D", + "\x84\x75" => "\xEA\xBC\x9E", + "\x84\x76" => "\xEA\xBC\x9F", + "\x84\x77" => "\xEA\xBC\xA0", + "\x84\x78" => "\xEA\xBC\xA1", + "\x84\x79" => "\xEA\xBC\xA2", + "\x84\x7A" => "\xEA\xBC\xA3", + "\x84\x81" => "\xEA\xBC\xA4", + "\x84\x82" => "\xEA\xBC\xA5", + "\x84\x83" => "\xEA\xBC\xA6", + "\x84\x84" => "\xEA\xBC\xA7", + "\x84\x85" => "\xEA\xBC\xA8", + "\x84\x86" => "\xEA\xBC\xA9", + "\x84\x87" => "\xEA\xBC\xAA", + "\x84\x88" => "\xEA\xBC\xAB", + "\x84\x89" => "\xEA\xBC\xAE", + "\x84\x8A" => "\xEA\xBC\xAF", + "\x84\x8B" => "\xEA\xBC\xB1", + "\x84\x8C" => "\xEA\xBC\xB3", + "\x84\x8D" => "\xEA\xBC\xB5", + "\x84\x8E" => "\xEA\xBC\xB6", + "\x84\x8F" => "\xEA\xBC\xB7", + "\x84\x90" => "\xEA\xBC\xB8", + "\x84\x91" => "\xEA\xBC\xB9", + "\x84\x92" => "\xEA\xBC\xBA", + "\x84\x93" => "\xEA\xBC\xBB", + "\x84\x94" => "\xEA\xBC\xBE", + "\x84\x95" => "\xEA\xBD\x80", + "\x84\x96" => "\xEA\xBD\x84", + "\x84\x97" => "\xEA\xBD\x85", + "\x84\x98" => "\xEA\xBD\x86", + "\x84\x99" => "\xEA\xBD\x87", + "\x84\x9A" => "\xEA\xBD\x8A", + "\x84\x9B" => "\xEA\xBD\x8B", + "\x84\x9C" => "\xEA\xBD\x8C", + "\x84\x9D" => "\xEA\xBD\x8D", + "\x84\x9E" => "\xEA\xBD\x8E", + "\x84\x9F" => "\xEA\xBD\x8F", + "\x84\xA0" => "\xEA\xBD\x91", + "\x84\xA1" => "\xEA\xBD\x92", + "\x84\xA2" => "\xEA\xBD\x93", + "\x84\xA3" => "\xEA\xBD\x94", + "\x84\xA4" => "\xEA\xBD\x95", + "\x84\xA5" => "\xEA\xBD\x96", + "\x84\xA6" => "\xEA\xBD\x97", + "\x84\xA7" => "\xEA\xBD\x98", + "\x84\xA8" => "\xEA\xBD\x99", + "\x84\xA9" => "\xEA\xBD\x9A", + "\x84\xAA" => "\xEA\xBD\x9B", + "\x84\xAB" => "\xEA\xBD\x9E", + "\x84\xAC" => "\xEA\xBD\x9F", + "\x84\xAD" => "\xEA\xBD\xA0", + "\x84\xAE" => "\xEA\xBD\xA1", + "\x84\xAF" => "\xEA\xBD\xA2", + "\x84\xB0" => "\xEA\xBD\xA3", + "\x84\xB1" => "\xEA\xBD\xA6", + "\x84\xB2" => "\xEA\xBD\xA7", + "\x84\xB3" => "\xEA\xBD\xA8", + "\x84\xB4" => "\xEA\xBD\xA9", + "\x84\xB5" => "\xEA\xBD\xAA", + "\x84\xB6" => "\xEA\xBD\xAB", + "\x84\xB7" => "\xEA\xBD\xAC", + "\x84\xB8" => "\xEA\xBD\xAD", + "\x84\xB9" => "\xEA\xBD\xAE", + "\x84\xBA" => "\xEA\xBD\xAF", + "\x84\xBB" => "\xEA\xBD\xB0", + "\x84\xBC" => "\xEA\xBD\xB1", + "\x84\xBD" => "\xEA\xBD\xB2", + "\x84\xBE" => "\xEA\xBD\xB3", + "\x84\xBF" => "\xEA\xBD\xB4", + "\x84\xC0" => "\xEA\xBD\xB5", + "\x84\xC1" => "\xEA\xBD\xB6", + "\x84\xC2" => "\xEA\xBD\xB7", + "\x84\xC3" => "\xEA\xBD\xB8", + "\x84\xC4" => "\xEA\xBD\xBA", + "\x84\xC5" => "\xEA\xBD\xBB", + "\x84\xC6" => "\xEA\xBD\xBC", + "\x84\xC7" => "\xEA\xBD\xBD", + "\x84\xC8" => "\xEA\xBD\xBE", + "\x84\xC9" => "\xEA\xBD\xBF", + "\x84\xCA" => "\xEA\xBE\x81", + "\x84\xCB" => "\xEA\xBE\x82", + "\x84\xCC" => "\xEA\xBE\x83", + "\x84\xCD" => "\xEA\xBE\x85", + "\x84\xCE" => "\xEA\xBE\x86", + "\x84\xCF" => "\xEA\xBE\x87", + "\x84\xD0" => "\xEA\xBE\x89", + "\x84\xD1" => "\xEA\xBE\x8A", + "\x84\xD2" => "\xEA\xBE\x8B", + "\x84\xD3" => "\xEA\xBE\x8C", + "\x84\xD4" => "\xEA\xBE\x8D", + "\x84\xD5" => "\xEA\xBE\x8E", + "\x84\xD6" => "\xEA\xBE\x8F", + "\x84\xD7" => "\xEA\xBE\x92", + "\x84\xD8" => "\xEA\xBE\x93", + "\x84\xD9" => "\xEA\xBE\x94", + "\x84\xDA" => "\xEA\xBE\x96", + "\x84\xDB" => "\xEA\xBE\x97", + "\x84\xDC" => "\xEA\xBE\x98", + "\x84\xDD" => "\xEA\xBE\x99", + "\x84\xDE" => "\xEA\xBE\x9A", + "\x84\xDF" => "\xEA\xBE\x9B", + "\x84\xE0" => "\xEA\xBE\x9D", + "\x84\xE1" => "\xEA\xBE\x9E", + "\x84\xE2" => "\xEA\xBE\x9F", + "\x84\xE3" => "\xEA\xBE\xA0", + "\x84\xE4" => "\xEA\xBE\xA1", + "\x84\xE5" => "\xEA\xBE\xA2", + "\x84\xE6" => "\xEA\xBE\xA3", + "\x84\xE7" => "\xEA\xBE\xA4", + "\x84\xE8" => "\xEA\xBE\xA5", + "\x84\xE9" => "\xEA\xBE\xA6", + "\x84\xEA" => "\xEA\xBE\xA7", + "\x84\xEB" => "\xEA\xBE\xA8", + "\x84\xEC" => "\xEA\xBE\xA9", + "\x84\xED" => "\xEA\xBE\xAA", + "\x84\xEE" => "\xEA\xBE\xAB", + "\x84\xEF" => "\xEA\xBE\xAC", + "\x84\xF0" => "\xEA\xBE\xAD", + "\x84\xF1" => "\xEA\xBE\xAE", + "\x84\xF2" => "\xEA\xBE\xAF", + "\x84\xF3" => "\xEA\xBE\xB0", + "\x84\xF4" => "\xEA\xBE\xB1", + "\x84\xF5" => "\xEA\xBE\xB2", + "\x84\xF6" => "\xEA\xBE\xB3", + "\x84\xF7" => "\xEA\xBE\xB4", + "\x84\xF8" => "\xEA\xBE\xB5", + "\x84\xF9" => "\xEA\xBE\xB6", + "\x84\xFA" => "\xEA\xBE\xB7", + "\x84\xFB" => "\xEA\xBE\xBA", + "\x84\xFC" => "\xEA\xBE\xBB", + "\x84\xFD" => "\xEA\xBE\xBD", + "\x84\xFE" => "\xEA\xBE\xBE", + "\x85\x41" => "\xEA\xBE\xBF", + "\x85\x42" => "\xEA\xBF\x81", + "\x85\x43" => "\xEA\xBF\x82", + "\x85\x44" => "\xEA\xBF\x83", + "\x85\x45" => "\xEA\xBF\x84", + "\x85\x46" => "\xEA\xBF\x85", + "\x85\x47" => "\xEA\xBF\x86", + "\x85\x48" => "\xEA\xBF\x8A", + "\x85\x49" => "\xEA\xBF\x8C", + "\x85\x4A" => "\xEA\xBF\x8F", + "\x85\x4B" => "\xEA\xBF\x90", + "\x85\x4C" => "\xEA\xBF\x91", + "\x85\x4D" => "\xEA\xBF\x92", + "\x85\x4E" => "\xEA\xBF\x93", + "\x85\x4F" => "\xEA\xBF\x95", + "\x85\x50" => "\xEA\xBF\x96", + "\x85\x51" => "\xEA\xBF\x97", + "\x85\x52" => "\xEA\xBF\x98", + "\x85\x53" => "\xEA\xBF\x99", + "\x85\x54" => "\xEA\xBF\x9A", + "\x85\x55" => "\xEA\xBF\x9B", + "\x85\x56" => "\xEA\xBF\x9D", + "\x85\x57" => "\xEA\xBF\x9E", + "\x85\x58" => "\xEA\xBF\x9F", + "\x85\x59" => "\xEA\xBF\xA0", + "\x85\x5A" => "\xEA\xBF\xA1", + "\x85\x61" => "\xEA\xBF\xA2", + "\x85\x62" => "\xEA\xBF\xA3", + "\x85\x63" => "\xEA\xBF\xA4", + "\x85\x64" => "\xEA\xBF\xA5", + "\x85\x65" => "\xEA\xBF\xA6", + "\x85\x66" => "\xEA\xBF\xA7", + "\x85\x67" => "\xEA\xBF\xAA", + "\x85\x68" => "\xEA\xBF\xAB", + "\x85\x69" => "\xEA\xBF\xAC", + "\x85\x6A" => "\xEA\xBF\xAD", + "\x85\x6B" => "\xEA\xBF\xAE", + "\x85\x6C" => "\xEA\xBF\xAF", + "\x85\x6D" => "\xEA\xBF\xB2", + "\x85\x6E" => "\xEA\xBF\xB3", + "\x85\x6F" => "\xEA\xBF\xB5", + "\x85\x70" => "\xEA\xBF\xB6", + "\x85\x71" => "\xEA\xBF\xB7", + "\x85\x72" => "\xEA\xBF\xB9", + "\x85\x73" => "\xEA\xBF\xBA", + "\x85\x74" => "\xEA\xBF\xBB", + "\x85\x75" => "\xEA\xBF\xBC", + "\x85\x76" => "\xEA\xBF\xBD", + "\x85\x77" => "\xEA\xBF\xBE", + "\x85\x78" => "\xEA\xBF\xBF", + "\x85\x79" => "\xEB\x80\x82", + "\x85\x7A" => "\xEB\x80\x83", + "\x85\x81" => "\xEB\x80\x85", + "\x85\x82" => "\xEB\x80\x86", + "\x85\x83" => "\xEB\x80\x87", + "\x85\x84" => "\xEB\x80\x88", + "\x85\x85" => "\xEB\x80\x89", + "\x85\x86" => "\xEB\x80\x8A", + "\x85\x87" => "\xEB\x80\x8B", + "\x85\x88" => "\xEB\x80\x8D", + "\x85\x89" => "\xEB\x80\x8E", + "\x85\x8A" => "\xEB\x80\x8F", + "\x85\x8B" => "\xEB\x80\x91", + "\x85\x8C" => "\xEB\x80\x92", + "\x85\x8D" => "\xEB\x80\x93", + "\x85\x8E" => "\xEB\x80\x95", + "\x85\x8F" => "\xEB\x80\x96", + "\x85\x90" => "\xEB\x80\x97", + "\x85\x91" => "\xEB\x80\x98", + "\x85\x92" => "\xEB\x80\x99", + "\x85\x93" => "\xEB\x80\x9A", + "\x85\x94" => "\xEB\x80\x9B", + "\x85\x95" => "\xEB\x80\x9E", + "\x85\x96" => "\xEB\x80\x9F", + "\x85\x97" => "\xEB\x80\xA0", + "\x85\x98" => "\xEB\x80\xA1", + "\x85\x99" => "\xEB\x80\xA2", + "\x85\x9A" => "\xEB\x80\xA3", + "\x85\x9B" => "\xEB\x80\xA4", + "\x85\x9C" => "\xEB\x80\xA5", + "\x85\x9D" => "\xEB\x80\xA6", + "\x85\x9E" => "\xEB\x80\xA7", + "\x85\x9F" => "\xEB\x80\xA9", + "\x85\xA0" => "\xEB\x80\xAA", + "\x85\xA1" => "\xEB\x80\xAB", + "\x85\xA2" => "\xEB\x80\xAC", + "\x85\xA3" => "\xEB\x80\xAD", + "\x85\xA4" => "\xEB\x80\xAE", + "\x85\xA5" => "\xEB\x80\xAF", + "\x85\xA6" => "\xEB\x80\xB0", + "\x85\xA7" => "\xEB\x80\xB1", + "\x85\xA8" => "\xEB\x80\xB2", + "\x85\xA9" => "\xEB\x80\xB3", + "\x85\xAA" => "\xEB\x80\xB4", + "\x85\xAB" => "\xEB\x80\xB5", + "\x85\xAC" => "\xEB\x80\xB6", + "\x85\xAD" => "\xEB\x80\xB7", + "\x85\xAE" => "\xEB\x80\xB8", + "\x85\xAF" => "\xEB\x80\xB9", + "\x85\xB0" => "\xEB\x80\xBA", + "\x85\xB1" => "\xEB\x80\xBB", + "\x85\xB2" => "\xEB\x80\xBC", + "\x85\xB3" => "\xEB\x80\xBD", + "\x85\xB4" => "\xEB\x80\xBE", + "\x85\xB5" => "\xEB\x80\xBF", + "\x85\xB6" => "\xEB\x81\x80", + "\x85\xB7" => "\xEB\x81\x81", + "\x85\xB8" => "\xEB\x81\x82", + "\x85\xB9" => "\xEB\x81\x83", + "\x85\xBA" => "\xEB\x81\x86", + "\x85\xBB" => "\xEB\x81\x87", + "\x85\xBC" => "\xEB\x81\x89", + "\x85\xBD" => "\xEB\x81\x8B", + "\x85\xBE" => "\xEB\x81\x8D", + "\x85\xBF" => "\xEB\x81\x8F", + "\x85\xC0" => "\xEB\x81\x90", + "\x85\xC1" => "\xEB\x81\x91", + "\x85\xC2" => "\xEB\x81\x92", + "\x85\xC3" => "\xEB\x81\x96", + "\x85\xC4" => "\xEB\x81\x98", + "\x85\xC5" => "\xEB\x81\x9A", + "\x85\xC6" => "\xEB\x81\x9B", + "\x85\xC7" => "\xEB\x81\x9C", + "\x85\xC8" => "\xEB\x81\x9E", + "\x85\xC9" => "\xEB\x81\x9F", + "\x85\xCA" => "\xEB\x81\xA0", + "\x85\xCB" => "\xEB\x81\xA1", + "\x85\xCC" => "\xEB\x81\xA2", + "\x85\xCD" => "\xEB\x81\xA3", + "\x85\xCE" => "\xEB\x81\xA4", + "\x85\xCF" => "\xEB\x81\xA5", + "\x85\xD0" => "\xEB\x81\xA6", + "\x85\xD1" => "\xEB\x81\xA7", + "\x85\xD2" => "\xEB\x81\xA8", + "\x85\xD3" => "\xEB\x81\xA9", + "\x85\xD4" => "\xEB\x81\xAA", + "\x85\xD5" => "\xEB\x81\xAB", + "\x85\xD6" => "\xEB\x81\xAC", + "\x85\xD7" => "\xEB\x81\xAD", + "\x85\xD8" => "\xEB\x81\xAE", + "\x85\xD9" => "\xEB\x81\xAF", + "\x85\xDA" => "\xEB\x81\xB0", + "\x85\xDB" => "\xEB\x81\xB1", + "\x85\xDC" => "\xEB\x81\xB2", + "\x85\xDD" => "\xEB\x81\xB3", + "\x85\xDE" => "\xEB\x81\xB4", + "\x85\xDF" => "\xEB\x81\xB5", + "\x85\xE0" => "\xEB\x81\xB6", + "\x85\xE1" => "\xEB\x81\xB7", + "\x85\xE2" => "\xEB\x81\xB8", + "\x85\xE3" => "\xEB\x81\xB9", + "\x85\xE4" => "\xEB\x81\xBA", + "\x85\xE5" => "\xEB\x81\xBB", + "\x85\xE6" => "\xEB\x81\xBE", + "\x85\xE7" => "\xEB\x81\xBF", + "\x85\xE8" => "\xEB\x82\x81", + "\x85\xE9" => "\xEB\x82\x82", + "\x85\xEA" => "\xEB\x82\x83", + "\x85\xEB" => "\xEB\x82\x85", + "\x85\xEC" => "\xEB\x82\x86", + "\x85\xED" => "\xEB\x82\x87", + "\x85\xEE" => "\xEB\x82\x88", + "\x85\xEF" => "\xEB\x82\x89", + "\x85\xF0" => "\xEB\x82\x8A", + "\x85\xF1" => "\xEB\x82\x8B", + "\x85\xF2" => "\xEB\x82\x8E", + "\x85\xF3" => "\xEB\x82\x90", + "\x85\xF4" => "\xEB\x82\x92", + "\x85\xF5" => "\xEB\x82\x93", + "\x85\xF6" => "\xEB\x82\x94", + "\x85\xF7" => "\xEB\x82\x95", + "\x85\xF8" => "\xEB\x82\x96", + "\x85\xF9" => "\xEB\x82\x97", + "\x85\xFA" => "\xEB\x82\x9B", + "\x85\xFB" => "\xEB\x82\x9D", + "\x85\xFC" => "\xEB\x82\x9E", + "\x85\xFD" => "\xEB\x82\xA3", + "\x85\xFE" => "\xEB\x82\xA4", + "\x86\x41" => "\xEB\x82\xA5", + "\x86\x42" => "\xEB\x82\xA6", + "\x86\x43" => "\xEB\x82\xA7", + "\x86\x44" => "\xEB\x82\xAA", + "\x86\x45" => "\xEB\x82\xB0", + "\x86\x46" => "\xEB\x82\xB2", + "\x86\x47" => "\xEB\x82\xB6", + "\x86\x48" => "\xEB\x82\xB7", + "\x86\x49" => "\xEB\x82\xB9", + "\x86\x4A" => "\xEB\x82\xBA", + "\x86\x4B" => "\xEB\x82\xBB", + "\x86\x4C" => "\xEB\x82\xBD", + "\x86\x4D" => "\xEB\x82\xBE", + "\x86\x4E" => "\xEB\x82\xBF", + "\x86\x4F" => "\xEB\x83\x80", + "\x86\x50" => "\xEB\x83\x81", + "\x86\x51" => "\xEB\x83\x82", + "\x86\x52" => "\xEB\x83\x83", + "\x86\x53" => "\xEB\x83\x86", + "\x86\x54" => "\xEB\x83\x8A", + "\x86\x55" => "\xEB\x83\x8B", + "\x86\x56" => "\xEB\x83\x8C", + "\x86\x57" => "\xEB\x83\x8D", + "\x86\x58" => "\xEB\x83\x8E", + "\x86\x59" => "\xEB\x83\x8F", + "\x86\x5A" => "\xEB\x83\x92", + "\x86\x61" => "\xEB\x83\x93", + "\x86\x62" => "\xEB\x83\x95", + "\x86\x63" => "\xEB\x83\x96", + "\x86\x64" => "\xEB\x83\x97", + "\x86\x65" => "\xEB\x83\x99", + "\x86\x66" => "\xEB\x83\x9A", + "\x86\x67" => "\xEB\x83\x9B", + "\x86\x68" => "\xEB\x83\x9C", + "\x86\x69" => "\xEB\x83\x9D", + "\x86\x6A" => "\xEB\x83\x9E", + "\x86\x6B" => "\xEB\x83\x9F", + "\x86\x6C" => "\xEB\x83\xA1", + "\x86\x6D" => "\xEB\x83\xA2", + "\x86\x6E" => "\xEB\x83\xA3", + "\x86\x6F" => "\xEB\x83\xA4", + "\x86\x70" => "\xEB\x83\xA6", + "\x86\x71" => "\xEB\x83\xA7", + "\x86\x72" => "\xEB\x83\xA8", + "\x86\x73" => "\xEB\x83\xA9", + "\x86\x74" => "\xEB\x83\xAA", + "\x86\x75" => "\xEB\x83\xAB", + "\x86\x76" => "\xEB\x83\xAC", + "\x86\x77" => "\xEB\x83\xAD", + "\x86\x78" => "\xEB\x83\xAE", + "\x86\x79" => "\xEB\x83\xAF", + "\x86\x7A" => "\xEB\x83\xB0", + "\x86\x81" => "\xEB\x83\xB1", + "\x86\x82" => "\xEB\x83\xB2", + "\x86\x83" => "\xEB\x83\xB3", + "\x86\x84" => "\xEB\x83\xB4", + "\x86\x85" => "\xEB\x83\xB5", + "\x86\x86" => "\xEB\x83\xB6", + "\x86\x87" => "\xEB\x83\xB7", + "\x86\x88" => "\xEB\x83\xB8", + "\x86\x89" => "\xEB\x83\xB9", + "\x86\x8A" => "\xEB\x83\xBA", + "\x86\x8B" => "\xEB\x83\xBB", + "\x86\x8C" => "\xEB\x83\xBC", + "\x86\x8D" => "\xEB\x83\xBD", + "\x86\x8E" => "\xEB\x83\xBE", + "\x86\x8F" => "\xEB\x83\xBF", + "\x86\x90" => "\xEB\x84\x80", + "\x86\x91" => "\xEB\x84\x81", + "\x86\x92" => "\xEB\x84\x82", + "\x86\x93" => "\xEB\x84\x83", + "\x86\x94" => "\xEB\x84\x84", + "\x86\x95" => "\xEB\x84\x85", + "\x86\x96" => "\xEB\x84\x86", + "\x86\x97" => "\xEB\x84\x87", + "\x86\x98" => "\xEB\x84\x8A", + "\x86\x99" => "\xEB\x84\x8D", + "\x86\x9A" => "\xEB\x84\x8E", + "\x86\x9B" => "\xEB\x84\x8F", + "\x86\x9C" => "\xEB\x84\x91", + "\x86\x9D" => "\xEB\x84\x94", + "\x86\x9E" => "\xEB\x84\x95", + "\x86\x9F" => "\xEB\x84\x96", + "\x86\xA0" => "\xEB\x84\x97", + "\x86\xA1" => "\xEB\x84\x9A", + "\x86\xA2" => "\xEB\x84\x9E", + "\x86\xA3" => "\xEB\x84\x9F", + "\x86\xA4" => "\xEB\x84\xA0", + "\x86\xA5" => "\xEB\x84\xA1", + "\x86\xA6" => "\xEB\x84\xA2", + "\x86\xA7" => "\xEB\x84\xA6", + "\x86\xA8" => "\xEB\x84\xA7", + "\x86\xA9" => "\xEB\x84\xA9", + "\x86\xAA" => "\xEB\x84\xAA", + "\x86\xAB" => "\xEB\x84\xAB", + "\x86\xAC" => "\xEB\x84\xAD", + "\x86\xAD" => "\xEB\x84\xAE", + "\x86\xAE" => "\xEB\x84\xAF", + "\x86\xAF" => "\xEB\x84\xB0", + "\x86\xB0" => "\xEB\x84\xB1", + "\x86\xB1" => "\xEB\x84\xB2", + "\x86\xB2" => "\xEB\x84\xB3", + "\x86\xB3" => "\xEB\x84\xB6", + "\x86\xB4" => "\xEB\x84\xBA", + "\x86\xB5" => "\xEB\x84\xBB", + "\x86\xB6" => "\xEB\x84\xBC", + "\x86\xB7" => "\xEB\x84\xBD", + "\x86\xB8" => "\xEB\x84\xBE", + "\x86\xB9" => "\xEB\x84\xBF", + "\x86\xBA" => "\xEB\x85\x82", + "\x86\xBB" => "\xEB\x85\x83", + "\x86\xBC" => "\xEB\x85\x85", + "\x86\xBD" => "\xEB\x85\x86", + "\x86\xBE" => "\xEB\x85\x87", + "\x86\xBF" => "\xEB\x85\x89", + "\x86\xC0" => "\xEB\x85\x8A", + "\x86\xC1" => "\xEB\x85\x8B", + "\x86\xC2" => "\xEB\x85\x8C", + "\x86\xC3" => "\xEB\x85\x8D", + "\x86\xC4" => "\xEB\x85\x8E", + "\x86\xC5" => "\xEB\x85\x8F", + "\x86\xC6" => "\xEB\x85\x92", + "\x86\xC7" => "\xEB\x85\x93", + "\x86\xC8" => "\xEB\x85\x96", + "\x86\xC9" => "\xEB\x85\x97", + "\x86\xCA" => "\xEB\x85\x99", + "\x86\xCB" => "\xEB\x85\x9A", + "\x86\xCC" => "\xEB\x85\x9B", + "\x86\xCD" => "\xEB\x85\x9D", + "\x86\xCE" => "\xEB\x85\x9E", + "\x86\xCF" => "\xEB\x85\x9F", + "\x86\xD0" => "\xEB\x85\xA1", + "\x86\xD1" => "\xEB\x85\xA2", + "\x86\xD2" => "\xEB\x85\xA3", + "\x86\xD3" => "\xEB\x85\xA4", + "\x86\xD4" => "\xEB\x85\xA5", + "\x86\xD5" => "\xEB\x85\xA6", + "\x86\xD6" => "\xEB\x85\xA7", + "\x86\xD7" => "\xEB\x85\xA8", + "\x86\xD8" => "\xEB\x85\xA9", + "\x86\xD9" => "\xEB\x85\xAA", + "\x86\xDA" => "\xEB\x85\xAB", + "\x86\xDB" => "\xEB\x85\xAC", + "\x86\xDC" => "\xEB\x85\xAD", + "\x86\xDD" => "\xEB\x85\xAE", + "\x86\xDE" => "\xEB\x85\xAF", + "\x86\xDF" => "\xEB\x85\xB0", + "\x86\xE0" => "\xEB\x85\xB1", + "\x86\xE1" => "\xEB\x85\xB2", + "\x86\xE2" => "\xEB\x85\xB3", + "\x86\xE3" => "\xEB\x85\xB4", + "\x86\xE4" => "\xEB\x85\xB5", + "\x86\xE5" => "\xEB\x85\xB6", + "\x86\xE6" => "\xEB\x85\xB7", + "\x86\xE7" => "\xEB\x85\xBA", + "\x86\xE8" => "\xEB\x85\xBB", + "\x86\xE9" => "\xEB\x85\xBD", + "\x86\xEA" => "\xEB\x85\xBE", + "\x86\xEB" => "\xEB\x85\xBF", + "\x86\xEC" => "\xEB\x86\x81", + "\x86\xED" => "\xEB\x86\x83", + "\x86\xEE" => "\xEB\x86\x84", + "\x86\xEF" => "\xEB\x86\x85", + "\x86\xF0" => "\xEB\x86\x86", + "\x86\xF1" => "\xEB\x86\x87", + "\x86\xF2" => "\xEB\x86\x8A", + "\x86\xF3" => "\xEB\x86\x8C", + "\x86\xF4" => "\xEB\x86\x8E", + "\x86\xF5" => "\xEB\x86\x8F", + "\x86\xF6" => "\xEB\x86\x90", + "\x86\xF7" => "\xEB\x86\x91", + "\x86\xF8" => "\xEB\x86\x95", + "\x86\xF9" => "\xEB\x86\x96", + "\x86\xFA" => "\xEB\x86\x97", + "\x86\xFB" => "\xEB\x86\x99", + "\x86\xFC" => "\xEB\x86\x9A", + "\x86\xFD" => "\xEB\x86\x9B", + "\x86\xFE" => "\xEB\x86\x9D", + "\x87\x41" => "\xEB\x86\x9E", + "\x87\x42" => "\xEB\x86\x9F", + "\x87\x43" => "\xEB\x86\xA0", + "\x87\x44" => "\xEB\x86\xA1", + "\x87\x45" => "\xEB\x86\xA2", + "\x87\x46" => "\xEB\x86\xA3", + "\x87\x47" => "\xEB\x86\xA4", + "\x87\x48" => "\xEB\x86\xA5", + "\x87\x49" => "\xEB\x86\xA6", + "\x87\x4A" => "\xEB\x86\xA7", + "\x87\x4B" => "\xEB\x86\xA9", + "\x87\x4C" => "\xEB\x86\xAA", + "\x87\x4D" => "\xEB\x86\xAB", + "\x87\x4E" => "\xEB\x86\xAC", + "\x87\x4F" => "\xEB\x86\xAD", + "\x87\x50" => "\xEB\x86\xAE", + "\x87\x51" => "\xEB\x86\xAF", + "\x87\x52" => "\xEB\x86\xB0", + "\x87\x53" => "\xEB\x86\xB1", + "\x87\x54" => "\xEB\x86\xB2", + "\x87\x55" => "\xEB\x86\xB3", + "\x87\x56" => "\xEB\x86\xB4", + "\x87\x57" => "\xEB\x86\xB5", + "\x87\x58" => "\xEB\x86\xB6", + "\x87\x59" => "\xEB\x86\xB7", + "\x87\x5A" => "\xEB\x86\xB8", + "\x87\x61" => "\xEB\x86\xB9", + "\x87\x62" => "\xEB\x86\xBA", + "\x87\x63" => "\xEB\x86\xBB", + "\x87\x64" => "\xEB\x86\xBC", + "\x87\x65" => "\xEB\x86\xBD", + "\x87\x66" => "\xEB\x86\xBE", + "\x87\x67" => "\xEB\x86\xBF", + "\x87\x68" => "\xEB\x87\x80", + "\x87\x69" => "\xEB\x87\x81", + "\x87\x6A" => "\xEB\x87\x82", + "\x87\x6B" => "\xEB\x87\x83", + "\x87\x6C" => "\xEB\x87\x84", + "\x87\x6D" => "\xEB\x87\x85", + "\x87\x6E" => "\xEB\x87\x86", + "\x87\x6F" => "\xEB\x87\x87", + "\x87\x70" => "\xEB\x87\x88", + "\x87\x71" => "\xEB\x87\x89", + "\x87\x72" => "\xEB\x87\x8A", + "\x87\x73" => "\xEB\x87\x8B", + "\x87\x74" => "\xEB\x87\x8D", + "\x87\x75" => "\xEB\x87\x8E", + "\x87\x76" => "\xEB\x87\x8F", + "\x87\x77" => "\xEB\x87\x91", + "\x87\x78" => "\xEB\x87\x92", + "\x87\x79" => "\xEB\x87\x93", + "\x87\x7A" => "\xEB\x87\x95", + "\x87\x81" => "\xEB\x87\x96", + "\x87\x82" => "\xEB\x87\x97", + "\x87\x83" => "\xEB\x87\x98", + "\x87\x84" => "\xEB\x87\x99", + "\x87\x85" => "\xEB\x87\x9A", + "\x87\x86" => "\xEB\x87\x9B", + "\x87\x87" => "\xEB\x87\x9E", + "\x87\x88" => "\xEB\x87\xA0", + "\x87\x89" => "\xEB\x87\xA1", + "\x87\x8A" => "\xEB\x87\xA2", + "\x87\x8B" => "\xEB\x87\xA3", + "\x87\x8C" => "\xEB\x87\xA4", + "\x87\x8D" => "\xEB\x87\xA5", + "\x87\x8E" => "\xEB\x87\xA6", + "\x87\x8F" => "\xEB\x87\xA7", + "\x87\x90" => "\xEB\x87\xAA", + "\x87\x91" => "\xEB\x87\xAB", + "\x87\x92" => "\xEB\x87\xAD", + "\x87\x93" => "\xEB\x87\xAE", + "\x87\x94" => "\xEB\x87\xAF", + "\x87\x95" => "\xEB\x87\xB1", + "\x87\x96" => "\xEB\x87\xB2", + "\x87\x97" => "\xEB\x87\xB3", + "\x87\x98" => "\xEB\x87\xB4", + "\x87\x99" => "\xEB\x87\xB5", + "\x87\x9A" => "\xEB\x87\xB6", + "\x87\x9B" => "\xEB\x87\xB7", + "\x87\x9C" => "\xEB\x87\xB8", + "\x87\x9D" => "\xEB\x87\xBA", + "\x87\x9E" => "\xEB\x87\xBC", + "\x87\x9F" => "\xEB\x87\xBE", + "\x87\xA0" => "\xEB\x87\xBF", + "\x87\xA1" => "\xEB\x88\x80", + "\x87\xA2" => "\xEB\x88\x81", + "\x87\xA3" => "\xEB\x88\x82", + "\x87\xA4" => "\xEB\x88\x83", + "\x87\xA5" => "\xEB\x88\x86", + "\x87\xA6" => "\xEB\x88\x87", + "\x87\xA7" => "\xEB\x88\x89", + "\x87\xA8" => "\xEB\x88\x8A", + "\x87\xA9" => "\xEB\x88\x8D", + "\x87\xAA" => "\xEB\x88\x8E", + "\x87\xAB" => "\xEB\x88\x8F", + "\x87\xAC" => "\xEB\x88\x90", + "\x87\xAD" => "\xEB\x88\x91", + "\x87\xAE" => "\xEB\x88\x92", + "\x87\xAF" => "\xEB\x88\x93", + "\x87\xB0" => "\xEB\x88\x96", + "\x87\xB1" => "\xEB\x88\x98", + "\x87\xB2" => "\xEB\x88\x9A", + "\x87\xB3" => "\xEB\x88\x9B", + "\x87\xB4" => "\xEB\x88\x9C", + "\x87\xB5" => "\xEB\x88\x9D", + "\x87\xB6" => "\xEB\x88\x9E", + "\x87\xB7" => "\xEB\x88\x9F", + "\x87\xB8" => "\xEB\x88\xA1", + "\x87\xB9" => "\xEB\x88\xA2", + "\x87\xBA" => "\xEB\x88\xA3", + "\x87\xBB" => "\xEB\x88\xA4", + "\x87\xBC" => "\xEB\x88\xA5", + "\x87\xBD" => "\xEB\x88\xA6", + "\x87\xBE" => "\xEB\x88\xA7", + "\x87\xBF" => "\xEB\x88\xA8", + "\x87\xC0" => "\xEB\x88\xA9", + "\x87\xC1" => "\xEB\x88\xAA", + "\x87\xC2" => "\xEB\x88\xAB", + "\x87\xC3" => "\xEB\x88\xAC", + "\x87\xC4" => "\xEB\x88\xAD", + "\x87\xC5" => "\xEB\x88\xAE", + "\x87\xC6" => "\xEB\x88\xAF", + "\x87\xC7" => "\xEB\x88\xB0", + "\x87\xC8" => "\xEB\x88\xB1", + "\x87\xC9" => "\xEB\x88\xB2", + "\x87\xCA" => "\xEB\x88\xB3", + "\x87\xCB" => "\xEB\x88\xB5", + "\x87\xCC" => "\xEB\x88\xB6", + "\x87\xCD" => "\xEB\x88\xB7", + "\x87\xCE" => "\xEB\x88\xB8", + "\x87\xCF" => "\xEB\x88\xB9", + "\x87\xD0" => "\xEB\x88\xBA", + "\x87\xD1" => "\xEB\x88\xBB", + "\x87\xD2" => "\xEB\x88\xBD", + "\x87\xD3" => "\xEB\x88\xBE", + "\x87\xD4" => "\xEB\x88\xBF", + "\x87\xD5" => "\xEB\x89\x80", + "\x87\xD6" => "\xEB\x89\x81", + "\x87\xD7" => "\xEB\x89\x82", + "\x87\xD8" => "\xEB\x89\x83", + "\x87\xD9" => "\xEB\x89\x84", + "\x87\xDA" => "\xEB\x89\x85", + "\x87\xDB" => "\xEB\x89\x86", + "\x87\xDC" => "\xEB\x89\x87", + "\x87\xDD" => "\xEB\x89\x88", + "\x87\xDE" => "\xEB\x89\x89", + "\x87\xDF" => "\xEB\x89\x8A", + "\x87\xE0" => "\xEB\x89\x8B", + "\x87\xE1" => "\xEB\x89\x8C", + "\x87\xE2" => "\xEB\x89\x8D", + "\x87\xE3" => "\xEB\x89\x8E", + "\x87\xE4" => "\xEB\x89\x8F", + "\x87\xE5" => "\xEB\x89\x90", + "\x87\xE6" => "\xEB\x89\x91", + "\x87\xE7" => "\xEB\x89\x92", + "\x87\xE8" => "\xEB\x89\x93", + "\x87\xE9" => "\xEB\x89\x94", + "\x87\xEA" => "\xEB\x89\x95", + "\x87\xEB" => "\xEB\x89\x96", + "\x87\xEC" => "\xEB\x89\x97", + "\x87\xED" => "\xEB\x89\x99", + "\x87\xEE" => "\xEB\x89\x9A", + "\x87\xEF" => "\xEB\x89\x9B", + "\x87\xF0" => "\xEB\x89\x9D", + "\x87\xF1" => "\xEB\x89\x9E", + "\x87\xF2" => "\xEB\x89\x9F", + "\x87\xF3" => "\xEB\x89\xA1", + "\x87\xF4" => "\xEB\x89\xA2", + "\x87\xF5" => "\xEB\x89\xA3", + "\x87\xF6" => "\xEB\x89\xA4", + "\x87\xF7" => "\xEB\x89\xA5", + "\x87\xF8" => "\xEB\x89\xA6", + "\x87\xF9" => "\xEB\x89\xA7", + "\x87\xFA" => "\xEB\x89\xAA", + "\x87\xFB" => "\xEB\x89\xAB", + "\x87\xFC" => "\xEB\x89\xAC", + "\x87\xFD" => "\xEB\x89\xAD", + "\x87\xFE" => "\xEB\x89\xAE", + "\x88\x41" => "\xEB\x89\xAF", + "\x88\x42" => "\xEB\x89\xB0", + "\x88\x43" => "\xEB\x89\xB1", + "\x88\x44" => "\xEB\x89\xB2", + "\x88\x45" => "\xEB\x89\xB3", + "\x88\x46" => "\xEB\x89\xB6", + "\x88\x47" => "\xEB\x89\xB7", + "\x88\x48" => "\xEB\x89\xB8", + "\x88\x49" => "\xEB\x89\xB9", + "\x88\x4A" => "\xEB\x89\xBA", + "\x88\x4B" => "\xEB\x89\xBB", + "\x88\x4C" => "\xEB\x89\xBD", + "\x88\x4D" => "\xEB\x89\xBE", + "\x88\x4E" => "\xEB\x89\xBF", + "\x88\x4F" => "\xEB\x8A\x80", + "\x88\x50" => "\xEB\x8A\x81", + "\x88\x51" => "\xEB\x8A\x82", + "\x88\x52" => "\xEB\x8A\x83", + "\x88\x53" => "\xEB\x8A\x86", + "\x88\x54" => "\xEB\x8A\x87", + "\x88\x55" => "\xEB\x8A\x88", + "\x88\x56" => "\xEB\x8A\x8A", + "\x88\x57" => "\xEB\x8A\x8B", + "\x88\x58" => "\xEB\x8A\x8C", + "\x88\x59" => "\xEB\x8A\x8D", + "\x88\x5A" => "\xEB\x8A\x8E", + "\x88\x61" => "\xEB\x8A\x8F", + "\x88\x62" => "\xEB\x8A\x92", + "\x88\x63" => "\xEB\x8A\x93", + "\x88\x64" => "\xEB\x8A\x95", + "\x88\x65" => "\xEB\x8A\x96", + "\x88\x66" => "\xEB\x8A\x97", + "\x88\x67" => "\xEB\x8A\x9B", + "\x88\x68" => "\xEB\x8A\x9C", + "\x88\x69" => "\xEB\x8A\x9D", + "\x88\x6A" => "\xEB\x8A\x9E", + "\x88\x6B" => "\xEB\x8A\x9F", + "\x88\x6C" => "\xEB\x8A\xA2", + "\x88\x6D" => "\xEB\x8A\xA4", + "\x88\x6E" => "\xEB\x8A\xA7", + "\x88\x6F" => "\xEB\x8A\xA8", + "\x88\x70" => "\xEB\x8A\xA9", + "\x88\x71" => "\xEB\x8A\xAB", + "\x88\x72" => "\xEB\x8A\xAD", + "\x88\x73" => "\xEB\x8A\xAE", + "\x88\x74" => "\xEB\x8A\xAF", + "\x88\x75" => "\xEB\x8A\xB1", + "\x88\x76" => "\xEB\x8A\xB2", + "\x88\x77" => "\xEB\x8A\xB3", + "\x88\x78" => "\xEB\x8A\xB5", + "\x88\x79" => "\xEB\x8A\xB6", + "\x88\x7A" => "\xEB\x8A\xB7", + "\x88\x81" => "\xEB\x8A\xB8", + "\x88\x82" => "\xEB\x8A\xB9", + "\x88\x83" => "\xEB\x8A\xBA", + "\x88\x84" => "\xEB\x8A\xBB", + "\x88\x85" => "\xEB\x8A\xBC", + "\x88\x86" => "\xEB\x8A\xBD", + "\x88\x87" => "\xEB\x8A\xBE", + "\x88\x88" => "\xEB\x8A\xBF", + "\x88\x89" => "\xEB\x8B\x80", + "\x88\x8A" => "\xEB\x8B\x81", + "\x88\x8B" => "\xEB\x8B\x82", + "\x88\x8C" => "\xEB\x8B\x83", + "\x88\x8D" => "\xEB\x8B\x84", + "\x88\x8E" => "\xEB\x8B\x85", + "\x88\x8F" => "\xEB\x8B\x86", + "\x88\x90" => "\xEB\x8B\x87", + "\x88\x91" => "\xEB\x8B\x8A", + "\x88\x92" => "\xEB\x8B\x8B", + "\x88\x93" => "\xEB\x8B\x8D", + "\x88\x94" => "\xEB\x8B\x8E", + "\x88\x95" => "\xEB\x8B\x8F", + "\x88\x96" => "\xEB\x8B\x91", + "\x88\x97" => "\xEB\x8B\x93", + "\x88\x98" => "\xEB\x8B\x94", + "\x88\x99" => "\xEB\x8B\x95", + "\x88\x9A" => "\xEB\x8B\x96", + "\x88\x9B" => "\xEB\x8B\x97", + "\x88\x9C" => "\xEB\x8B\x9A", + "\x88\x9D" => "\xEB\x8B\x9C", + "\x88\x9E" => "\xEB\x8B\x9E", + "\x88\x9F" => "\xEB\x8B\x9F", + "\x88\xA0" => "\xEB\x8B\xA0", + "\x88\xA1" => "\xEB\x8B\xA1", + "\x88\xA2" => "\xEB\x8B\xA3", + "\x88\xA3" => "\xEB\x8B\xA7", + "\x88\xA4" => "\xEB\x8B\xA9", + "\x88\xA5" => "\xEB\x8B\xAA", + "\x88\xA6" => "\xEB\x8B\xB0", + "\x88\xA7" => "\xEB\x8B\xB1", + "\x88\xA8" => "\xEB\x8B\xB2", + "\x88\xA9" => "\xEB\x8B\xB6", + "\x88\xAA" => "\xEB\x8B\xBC", + "\x88\xAB" => "\xEB\x8B\xBD", + "\x88\xAC" => "\xEB\x8B\xBE", + "\x88\xAD" => "\xEB\x8C\x82", + "\x88\xAE" => "\xEB\x8C\x83", + "\x88\xAF" => "\xEB\x8C\x85", + "\x88\xB0" => "\xEB\x8C\x86", + "\x88\xB1" => "\xEB\x8C\x87", + "\x88\xB2" => "\xEB\x8C\x89", + "\x88\xB3" => "\xEB\x8C\x8A", + "\x88\xB4" => "\xEB\x8C\x8B", + "\x88\xB5" => "\xEB\x8C\x8C", + "\x88\xB6" => "\xEB\x8C\x8D", + "\x88\xB7" => "\xEB\x8C\x8E", + "\x88\xB8" => "\xEB\x8C\x8F", + "\x88\xB9" => "\xEB\x8C\x92", + "\x88\xBA" => "\xEB\x8C\x96", + "\x88\xBB" => "\xEB\x8C\x97", + "\x88\xBC" => "\xEB\x8C\x98", + "\x88\xBD" => "\xEB\x8C\x99", + "\x88\xBE" => "\xEB\x8C\x9A", + "\x88\xBF" => "\xEB\x8C\x9B", + "\x88\xC0" => "\xEB\x8C\x9D", + "\x88\xC1" => "\xEB\x8C\x9E", + "\x88\xC2" => "\xEB\x8C\x9F", + "\x88\xC3" => "\xEB\x8C\xA0", + "\x88\xC4" => "\xEB\x8C\xA1", + "\x88\xC5" => "\xEB\x8C\xA2", + "\x88\xC6" => "\xEB\x8C\xA3", + "\x88\xC7" => "\xEB\x8C\xA4", + "\x88\xC8" => "\xEB\x8C\xA5", + "\x88\xC9" => "\xEB\x8C\xA6", + "\x88\xCA" => "\xEB\x8C\xA7", + "\x88\xCB" => "\xEB\x8C\xA8", + "\x88\xCC" => "\xEB\x8C\xA9", + "\x88\xCD" => "\xEB\x8C\xAA", + "\x88\xCE" => "\xEB\x8C\xAB", + "\x88\xCF" => "\xEB\x8C\xAC", + "\x88\xD0" => "\xEB\x8C\xAD", + "\x88\xD1" => "\xEB\x8C\xAE", + "\x88\xD2" => "\xEB\x8C\xAF", + "\x88\xD3" => "\xEB\x8C\xB0", + "\x88\xD4" => "\xEB\x8C\xB1", + "\x88\xD5" => "\xEB\x8C\xB2", + "\x88\xD6" => "\xEB\x8C\xB3", + "\x88\xD7" => "\xEB\x8C\xB4", + "\x88\xD8" => "\xEB\x8C\xB5", + "\x88\xD9" => "\xEB\x8C\xB6", + "\x88\xDA" => "\xEB\x8C\xB7", + "\x88\xDB" => "\xEB\x8C\xB8", + "\x88\xDC" => "\xEB\x8C\xB9", + "\x88\xDD" => "\xEB\x8C\xBA", + "\x88\xDE" => "\xEB\x8C\xBB", + "\x88\xDF" => "\xEB\x8C\xBC", + "\x88\xE0" => "\xEB\x8C\xBD", + "\x88\xE1" => "\xEB\x8C\xBE", + "\x88\xE2" => "\xEB\x8C\xBF", + "\x88\xE3" => "\xEB\x8D\x80", + "\x88\xE4" => "\xEB\x8D\x81", + "\x88\xE5" => "\xEB\x8D\x82", + "\x88\xE6" => "\xEB\x8D\x83", + "\x88\xE7" => "\xEB\x8D\x84", + "\x88\xE8" => "\xEB\x8D\x85", + "\x88\xE9" => "\xEB\x8D\x86", + "\x88\xEA" => "\xEB\x8D\x87", + "\x88\xEB" => "\xEB\x8D\x88", + "\x88\xEC" => "\xEB\x8D\x89", + "\x88\xED" => "\xEB\x8D\x8A", + "\x88\xEE" => "\xEB\x8D\x8B", + "\x88\xEF" => "\xEB\x8D\x8C", + "\x88\xF0" => "\xEB\x8D\x8D", + "\x88\xF1" => "\xEB\x8D\x8E", + "\x88\xF2" => "\xEB\x8D\x8F", + "\x88\xF3" => "\xEB\x8D\x90", + "\x88\xF4" => "\xEB\x8D\x91", + "\x88\xF5" => "\xEB\x8D\x92", + "\x88\xF6" => "\xEB\x8D\x93", + "\x88\xF7" => "\xEB\x8D\x97", + "\x88\xF8" => "\xEB\x8D\x99", + "\x88\xF9" => "\xEB\x8D\x9A", + "\x88\xFA" => "\xEB\x8D\x9D", + "\x88\xFB" => "\xEB\x8D\xA0", + "\x88\xFC" => "\xEB\x8D\xA1", + "\x88\xFD" => "\xEB\x8D\xA2", + "\x88\xFE" => "\xEB\x8D\xA3", + "\x89\x41" => "\xEB\x8D\xA6", + "\x89\x42" => "\xEB\x8D\xA8", + "\x89\x43" => "\xEB\x8D\xAA", + "\x89\x44" => "\xEB\x8D\xAC", + "\x89\x45" => "\xEB\x8D\xAD", + "\x89\x46" => "\xEB\x8D\xAF", + "\x89\x47" => "\xEB\x8D\xB2", + "\x89\x48" => "\xEB\x8D\xB3", + "\x89\x49" => "\xEB\x8D\xB5", + "\x89\x4A" => "\xEB\x8D\xB6", + "\x89\x4B" => "\xEB\x8D\xB7", + "\x89\x4C" => "\xEB\x8D\xB9", + "\x89\x4D" => "\xEB\x8D\xBA", + "\x89\x4E" => "\xEB\x8D\xBB", + "\x89\x4F" => "\xEB\x8D\xBC", + "\x89\x50" => "\xEB\x8D\xBD", + "\x89\x51" => "\xEB\x8D\xBE", + "\x89\x52" => "\xEB\x8D\xBF", + "\x89\x53" => "\xEB\x8E\x82", + "\x89\x54" => "\xEB\x8E\x86", + "\x89\x55" => "\xEB\x8E\x87", + "\x89\x56" => "\xEB\x8E\x88", + "\x89\x57" => "\xEB\x8E\x89", + "\x89\x58" => "\xEB\x8E\x8A", + "\x89\x59" => "\xEB\x8E\x8B", + "\x89\x5A" => "\xEB\x8E\x8D", + "\x89\x61" => "\xEB\x8E\x8E", + "\x89\x62" => "\xEB\x8E\x8F", + "\x89\x63" => "\xEB\x8E\x91", + "\x89\x64" => "\xEB\x8E\x92", + "\x89\x65" => "\xEB\x8E\x93", + "\x89\x66" => "\xEB\x8E\x95", + "\x89\x67" => "\xEB\x8E\x96", + "\x89\x68" => "\xEB\x8E\x97", + "\x89\x69" => "\xEB\x8E\x98", + "\x89\x6A" => "\xEB\x8E\x99", + "\x89\x6B" => "\xEB\x8E\x9A", + "\x89\x6C" => "\xEB\x8E\x9B", + "\x89\x6D" => "\xEB\x8E\x9C", + "\x89\x6E" => "\xEB\x8E\x9D", + "\x89\x6F" => "\xEB\x8E\x9E", + "\x89\x70" => "\xEB\x8E\x9F", + "\x89\x71" => "\xEB\x8E\xA2", + "\x89\x72" => "\xEB\x8E\xA3", + "\x89\x73" => "\xEB\x8E\xA4", + "\x89\x74" => "\xEB\x8E\xA5", + "\x89\x75" => "\xEB\x8E\xA6", + "\x89\x76" => "\xEB\x8E\xA7", + "\x89\x77" => "\xEB\x8E\xA9", + "\x89\x78" => "\xEB\x8E\xAA", + "\x89\x79" => "\xEB\x8E\xAB", + "\x89\x7A" => "\xEB\x8E\xAD", + "\x89\x81" => "\xEB\x8E\xAE", + "\x89\x82" => "\xEB\x8E\xAF", + "\x89\x83" => "\xEB\x8E\xB0", + "\x89\x84" => "\xEB\x8E\xB1", + "\x89\x85" => "\xEB\x8E\xB2", + "\x89\x86" => "\xEB\x8E\xB3", + "\x89\x87" => "\xEB\x8E\xB4", + "\x89\x88" => "\xEB\x8E\xB5", + "\x89\x89" => "\xEB\x8E\xB6", + "\x89\x8A" => "\xEB\x8E\xB7", + "\x89\x8B" => "\xEB\x8E\xB8", + "\x89\x8C" => "\xEB\x8E\xB9", + "\x89\x8D" => "\xEB\x8E\xBA", + "\x89\x8E" => "\xEB\x8E\xBB", + "\x89\x8F" => "\xEB\x8E\xBC", + "\x89\x90" => "\xEB\x8E\xBD", + "\x89\x91" => "\xEB\x8E\xBE", + "\x89\x92" => "\xEB\x8E\xBF", + "\x89\x93" => "\xEB\x8F\x80", + "\x89\x94" => "\xEB\x8F\x81", + "\x89\x95" => "\xEB\x8F\x82", + "\x89\x96" => "\xEB\x8F\x83", + "\x89\x97" => "\xEB\x8F\x86", + "\x89\x98" => "\xEB\x8F\x87", + "\x89\x99" => "\xEB\x8F\x89", + "\x89\x9A" => "\xEB\x8F\x8A", + "\x89\x9B" => "\xEB\x8F\x8D", + "\x89\x9C" => "\xEB\x8F\x8F", + "\x89\x9D" => "\xEB\x8F\x91", + "\x89\x9E" => "\xEB\x8F\x92", + "\x89\x9F" => "\xEB\x8F\x93", + "\x89\xA0" => "\xEB\x8F\x96", + "\x89\xA1" => "\xEB\x8F\x98", + "\x89\xA2" => "\xEB\x8F\x9A", + "\x89\xA3" => "\xEB\x8F\x9C", + "\x89\xA4" => "\xEB\x8F\x9E", + "\x89\xA5" => "\xEB\x8F\x9F", + "\x89\xA6" => "\xEB\x8F\xA1", + "\x89\xA7" => "\xEB\x8F\xA2", + "\x89\xA8" => "\xEB\x8F\xA3", + "\x89\xA9" => "\xEB\x8F\xA5", + "\x89\xAA" => "\xEB\x8F\xA6", + "\x89\xAB" => "\xEB\x8F\xA7", + "\x89\xAC" => "\xEB\x8F\xA9", + "\x89\xAD" => "\xEB\x8F\xAA", + "\x89\xAE" => "\xEB\x8F\xAB", + "\x89\xAF" => "\xEB\x8F\xAC", + "\x89\xB0" => "\xEB\x8F\xAD", + "\x89\xB1" => "\xEB\x8F\xAE", + "\x89\xB2" => "\xEB\x8F\xAF", + "\x89\xB3" => "\xEB\x8F\xB0", + "\x89\xB4" => "\xEB\x8F\xB1", + "\x89\xB5" => "\xEB\x8F\xB2", + "\x89\xB6" => "\xEB\x8F\xB3", + "\x89\xB7" => "\xEB\x8F\xB4", + "\x89\xB8" => "\xEB\x8F\xB5", + "\x89\xB9" => "\xEB\x8F\xB6", + "\x89\xBA" => "\xEB\x8F\xB7", + "\x89\xBB" => "\xEB\x8F\xB8", + "\x89\xBC" => "\xEB\x8F\xB9", + "\x89\xBD" => "\xEB\x8F\xBA", + "\x89\xBE" => "\xEB\x8F\xBB", + "\x89\xBF" => "\xEB\x8F\xBD", + "\x89\xC0" => "\xEB\x8F\xBE", + "\x89\xC1" => "\xEB\x8F\xBF", + "\x89\xC2" => "\xEB\x90\x80", + "\x89\xC3" => "\xEB\x90\x81", + "\x89\xC4" => "\xEB\x90\x82", + "\x89\xC5" => "\xEB\x90\x83", + "\x89\xC6" => "\xEB\x90\x84", + "\x89\xC7" => "\xEB\x90\x85", + "\x89\xC8" => "\xEB\x90\x86", + "\x89\xC9" => "\xEB\x90\x87", + "\x89\xCA" => "\xEB\x90\x88", + "\x89\xCB" => "\xEB\x90\x89", + "\x89\xCC" => "\xEB\x90\x8A", + "\x89\xCD" => "\xEB\x90\x8B", + "\x89\xCE" => "\xEB\x90\x8C", + "\x89\xCF" => "\xEB\x90\x8D", + "\x89\xD0" => "\xEB\x90\x8E", + "\x89\xD1" => "\xEB\x90\x8F", + "\x89\xD2" => "\xEB\x90\x91", + "\x89\xD3" => "\xEB\x90\x92", + "\x89\xD4" => "\xEB\x90\x93", + "\x89\xD5" => "\xEB\x90\x94", + "\x89\xD6" => "\xEB\x90\x95", + "\x89\xD7" => "\xEB\x90\x96", + "\x89\xD8" => "\xEB\x90\x97", + "\x89\xD9" => "\xEB\x90\x99", + "\x89\xDA" => "\xEB\x90\x9A", + "\x89\xDB" => "\xEB\x90\x9B", + "\x89\xDC" => "\xEB\x90\x9D", + "\x89\xDD" => "\xEB\x90\x9E", + "\x89\xDE" => "\xEB\x90\x9F", + "\x89\xDF" => "\xEB\x90\xA1", + "\x89\xE0" => "\xEB\x90\xA2", + "\x89\xE1" => "\xEB\x90\xA3", + "\x89\xE2" => "\xEB\x90\xA4", + "\x89\xE3" => "\xEB\x90\xA5", + "\x89\xE4" => "\xEB\x90\xA6", + "\x89\xE5" => "\xEB\x90\xA7", + "\x89\xE6" => "\xEB\x90\xAA", + "\x89\xE7" => "\xEB\x90\xAC", + "\x89\xE8" => "\xEB\x90\xAD", + "\x89\xE9" => "\xEB\x90\xAE", + "\x89\xEA" => "\xEB\x90\xAF", + "\x89\xEB" => "\xEB\x90\xB0", + "\x89\xEC" => "\xEB\x90\xB1", + "\x89\xED" => "\xEB\x90\xB2", + "\x89\xEE" => "\xEB\x90\xB3", + "\x89\xEF" => "\xEB\x90\xB5", + "\x89\xF0" => "\xEB\x90\xB6", + "\x89\xF1" => "\xEB\x90\xB7", + "\x89\xF2" => "\xEB\x90\xB8", + "\x89\xF3" => "\xEB\x90\xB9", + "\x89\xF4" => "\xEB\x90\xBA", + "\x89\xF5" => "\xEB\x90\xBB", + "\x89\xF6" => "\xEB\x90\xBC", + "\x89\xF7" => "\xEB\x90\xBD", + "\x89\xF8" => "\xEB\x90\xBE", + "\x89\xF9" => "\xEB\x90\xBF", + "\x89\xFA" => "\xEB\x91\x80", + "\x89\xFB" => "\xEB\x91\x81", + "\x89\xFC" => "\xEB\x91\x82", + "\x89\xFD" => "\xEB\x91\x83", + "\x89\xFE" => "\xEB\x91\x84", + "\x8A\x41" => "\xEB\x91\x85", + "\x8A\x42" => "\xEB\x91\x86", + "\x8A\x43" => "\xEB\x91\x87", + "\x8A\x44" => "\xEB\x91\x88", + "\x8A\x45" => "\xEB\x91\x89", + "\x8A\x46" => "\xEB\x91\x8A", + "\x8A\x47" => "\xEB\x91\x8B", + "\x8A\x48" => "\xEB\x91\x8C", + "\x8A\x49" => "\xEB\x91\x8D", + "\x8A\x4A" => "\xEB\x91\x8E", + "\x8A\x4B" => "\xEB\x91\x8F", + "\x8A\x4C" => "\xEB\x91\x92", + "\x8A\x4D" => "\xEB\x91\x93", + "\x8A\x4E" => "\xEB\x91\x95", + "\x8A\x4F" => "\xEB\x91\x96", + "\x8A\x50" => "\xEB\x91\x97", + "\x8A\x51" => "\xEB\x91\x99", + "\x8A\x52" => "\xEB\x91\x9A", + "\x8A\x53" => "\xEB\x91\x9B", + "\x8A\x54" => "\xEB\x91\x9C", + "\x8A\x55" => "\xEB\x91\x9D", + "\x8A\x56" => "\xEB\x91\x9E", + "\x8A\x57" => "\xEB\x91\x9F", + "\x8A\x58" => "\xEB\x91\xA2", + "\x8A\x59" => "\xEB\x91\xA4", + "\x8A\x5A" => "\xEB\x91\xA6", + "\x8A\x61" => "\xEB\x91\xA7", + "\x8A\x62" => "\xEB\x91\xA8", + "\x8A\x63" => "\xEB\x91\xA9", + "\x8A\x64" => "\xEB\x91\xAA", + "\x8A\x65" => "\xEB\x91\xAB", + "\x8A\x66" => "\xEB\x91\xAD", + "\x8A\x67" => "\xEB\x91\xAE", + "\x8A\x68" => "\xEB\x91\xAF", + "\x8A\x69" => "\xEB\x91\xB0", + "\x8A\x6A" => "\xEB\x91\xB1", + "\x8A\x6B" => "\xEB\x91\xB2", + "\x8A\x6C" => "\xEB\x91\xB3", + "\x8A\x6D" => "\xEB\x91\xB4", + "\x8A\x6E" => "\xEB\x91\xB5", + "\x8A\x6F" => "\xEB\x91\xB6", + "\x8A\x70" => "\xEB\x91\xB7", + "\x8A\x71" => "\xEB\x91\xB8", + "\x8A\x72" => "\xEB\x91\xB9", + "\x8A\x73" => "\xEB\x91\xBA", + "\x8A\x74" => "\xEB\x91\xBB", + "\x8A\x75" => "\xEB\x91\xBC", + "\x8A\x76" => "\xEB\x91\xBD", + "\x8A\x77" => "\xEB\x91\xBE", + "\x8A\x78" => "\xEB\x91\xBF", + "\x8A\x79" => "\xEB\x92\x81", + "\x8A\x7A" => "\xEB\x92\x82", + "\x8A\x81" => "\xEB\x92\x83", + "\x8A\x82" => "\xEB\x92\x84", + "\x8A\x83" => "\xEB\x92\x85", + "\x8A\x84" => "\xEB\x92\x86", + "\x8A\x85" => "\xEB\x92\x87", + "\x8A\x86" => "\xEB\x92\x89", + "\x8A\x87" => "\xEB\x92\x8A", + "\x8A\x88" => "\xEB\x92\x8B", + "\x8A\x89" => "\xEB\x92\x8C", + "\x8A\x8A" => "\xEB\x92\x8D", + "\x8A\x8B" => "\xEB\x92\x8E", + "\x8A\x8C" => "\xEB\x92\x8F", + "\x8A\x8D" => "\xEB\x92\x90", + "\x8A\x8E" => "\xEB\x92\x91", + "\x8A\x8F" => "\xEB\x92\x92", + "\x8A\x90" => "\xEB\x92\x93", + "\x8A\x91" => "\xEB\x92\x94", + "\x8A\x92" => "\xEB\x92\x95", + "\x8A\x93" => "\xEB\x92\x96", + "\x8A\x94" => "\xEB\x92\x97", + "\x8A\x95" => "\xEB\x92\x98", + "\x8A\x96" => "\xEB\x92\x99", + "\x8A\x97" => "\xEB\x92\x9A", + "\x8A\x98" => "\xEB\x92\x9B", + "\x8A\x99" => "\xEB\x92\x9C", + "\x8A\x9A" => "\xEB\x92\x9E", + "\x8A\x9B" => "\xEB\x92\x9F", + "\x8A\x9C" => "\xEB\x92\xA0", + "\x8A\x9D" => "\xEB\x92\xA1", + "\x8A\x9E" => "\xEB\x92\xA2", + "\x8A\x9F" => "\xEB\x92\xA3", + "\x8A\xA0" => "\xEB\x92\xA5", + "\x8A\xA1" => "\xEB\x92\xA6", + "\x8A\xA2" => "\xEB\x92\xA7", + "\x8A\xA3" => "\xEB\x92\xA9", + "\x8A\xA4" => "\xEB\x92\xAA", + "\x8A\xA5" => "\xEB\x92\xAB", + "\x8A\xA6" => "\xEB\x92\xAD", + "\x8A\xA7" => "\xEB\x92\xAE", + "\x8A\xA8" => "\xEB\x92\xAF", + "\x8A\xA9" => "\xEB\x92\xB0", + "\x8A\xAA" => "\xEB\x92\xB1", + "\x8A\xAB" => "\xEB\x92\xB2", + "\x8A\xAC" => "\xEB\x92\xB3", + "\x8A\xAD" => "\xEB\x92\xB4", + "\x8A\xAE" => "\xEB\x92\xB6", + "\x8A\xAF" => "\xEB\x92\xB8", + "\x8A\xB0" => "\xEB\x92\xBA", + "\x8A\xB1" => "\xEB\x92\xBB", + "\x8A\xB2" => "\xEB\x92\xBC", + "\x8A\xB3" => "\xEB\x92\xBD", + "\x8A\xB4" => "\xEB\x92\xBE", + "\x8A\xB5" => "\xEB\x92\xBF", + "\x8A\xB6" => "\xEB\x93\x81", + "\x8A\xB7" => "\xEB\x93\x82", + "\x8A\xB8" => "\xEB\x93\x83", + "\x8A\xB9" => "\xEB\x93\x85", + "\x8A\xBA" => "\xEB\x93\x86", + "\x8A\xBB" => "\xEB\x93\x87", + "\x8A\xBC" => "\xEB\x93\x89", + "\x8A\xBD" => "\xEB\x93\x8A", + "\x8A\xBE" => "\xEB\x93\x8B", + "\x8A\xBF" => "\xEB\x93\x8C", + "\x8A\xC0" => "\xEB\x93\x8D", + "\x8A\xC1" => "\xEB\x93\x8E", + "\x8A\xC2" => "\xEB\x93\x8F", + "\x8A\xC3" => "\xEB\x93\x91", + "\x8A\xC4" => "\xEB\x93\x92", + "\x8A\xC5" => "\xEB\x93\x93", + "\x8A\xC6" => "\xEB\x93\x94", + "\x8A\xC7" => "\xEB\x93\x96", + "\x8A\xC8" => "\xEB\x93\x97", + "\x8A\xC9" => "\xEB\x93\x98", + "\x8A\xCA" => "\xEB\x93\x99", + "\x8A\xCB" => "\xEB\x93\x9A", + "\x8A\xCC" => "\xEB\x93\x9B", + "\x8A\xCD" => "\xEB\x93\x9E", + "\x8A\xCE" => "\xEB\x93\x9F", + "\x8A\xCF" => "\xEB\x93\xA1", + "\x8A\xD0" => "\xEB\x93\xA2", + "\x8A\xD1" => "\xEB\x93\xA5", + "\x8A\xD2" => "\xEB\x93\xA7", + "\x8A\xD3" => "\xEB\x93\xA8", + "\x8A\xD4" => "\xEB\x93\xA9", + "\x8A\xD5" => "\xEB\x93\xAA", + "\x8A\xD6" => "\xEB\x93\xAB", + "\x8A\xD7" => "\xEB\x93\xAE", + "\x8A\xD8" => "\xEB\x93\xB0", + "\x8A\xD9" => "\xEB\x93\xB2", + "\x8A\xDA" => "\xEB\x93\xB3", + "\x8A\xDB" => "\xEB\x93\xB4", + "\x8A\xDC" => "\xEB\x93\xB5", + "\x8A\xDD" => "\xEB\x93\xB6", + "\x8A\xDE" => "\xEB\x93\xB7", + "\x8A\xDF" => "\xEB\x93\xB9", + "\x8A\xE0" => "\xEB\x93\xBA", + "\x8A\xE1" => "\xEB\x93\xBB", + "\x8A\xE2" => "\xEB\x93\xBC", + "\x8A\xE3" => "\xEB\x93\xBD", + "\x8A\xE4" => "\xEB\x93\xBE", + "\x8A\xE5" => "\xEB\x93\xBF", + "\x8A\xE6" => "\xEB\x94\x80", + "\x8A\xE7" => "\xEB\x94\x81", + "\x8A\xE8" => "\xEB\x94\x82", + "\x8A\xE9" => "\xEB\x94\x83", + "\x8A\xEA" => "\xEB\x94\x84", + "\x8A\xEB" => "\xEB\x94\x85", + "\x8A\xEC" => "\xEB\x94\x86", + "\x8A\xED" => "\xEB\x94\x87", + "\x8A\xEE" => "\xEB\x94\x88", + "\x8A\xEF" => "\xEB\x94\x89", + "\x8A\xF0" => "\xEB\x94\x8A", + "\x8A\xF1" => "\xEB\x94\x8B", + "\x8A\xF2" => "\xEB\x94\x8C", + "\x8A\xF3" => "\xEB\x94\x8D", + "\x8A\xF4" => "\xEB\x94\x8E", + "\x8A\xF5" => "\xEB\x94\x8F", + "\x8A\xF6" => "\xEB\x94\x90", + "\x8A\xF7" => "\xEB\x94\x91", + "\x8A\xF8" => "\xEB\x94\x92", + "\x8A\xF9" => "\xEB\x94\x93", + "\x8A\xFA" => "\xEB\x94\x96", + "\x8A\xFB" => "\xEB\x94\x97", + "\x8A\xFC" => "\xEB\x94\x99", + "\x8A\xFD" => "\xEB\x94\x9A", + "\x8A\xFE" => "\xEB\x94\x9D", + "\x8B\x41" => "\xEB\x94\x9E", + "\x8B\x42" => "\xEB\x94\x9F", + "\x8B\x43" => "\xEB\x94\xA0", + "\x8B\x44" => "\xEB\x94\xA1", + "\x8B\x45" => "\xEB\x94\xA2", + "\x8B\x46" => "\xEB\x94\xA3", + "\x8B\x47" => "\xEB\x94\xA6", + "\x8B\x48" => "\xEB\x94\xAB", + "\x8B\x49" => "\xEB\x94\xAC", + "\x8B\x4A" => "\xEB\x94\xAD", + "\x8B\x4B" => "\xEB\x94\xAE", + "\x8B\x4C" => "\xEB\x94\xAF", + "\x8B\x4D" => "\xEB\x94\xB2", + "\x8B\x4E" => "\xEB\x94\xB3", + "\x8B\x4F" => "\xEB\x94\xB5", + "\x8B\x50" => "\xEB\x94\xB6", + "\x8B\x51" => "\xEB\x94\xB7", + "\x8B\x52" => "\xEB\x94\xB9", + "\x8B\x53" => "\xEB\x94\xBA", + "\x8B\x54" => "\xEB\x94\xBB", + "\x8B\x55" => "\xEB\x94\xBC", + "\x8B\x56" => "\xEB\x94\xBD", + "\x8B\x57" => "\xEB\x94\xBE", + "\x8B\x58" => "\xEB\x94\xBF", + "\x8B\x59" => "\xEB\x95\x82", + "\x8B\x5A" => "\xEB\x95\x86", + "\x8B\x61" => "\xEB\x95\x87", + "\x8B\x62" => "\xEB\x95\x88", + "\x8B\x63" => "\xEB\x95\x89", + "\x8B\x64" => "\xEB\x95\x8A", + "\x8B\x65" => "\xEB\x95\x8E", + "\x8B\x66" => "\xEB\x95\x8F", + "\x8B\x67" => "\xEB\x95\x91", + "\x8B\x68" => "\xEB\x95\x92", + "\x8B\x69" => "\xEB\x95\x93", + "\x8B\x6A" => "\xEB\x95\x95", + "\x8B\x6B" => "\xEB\x95\x96", + "\x8B\x6C" => "\xEB\x95\x97", + "\x8B\x6D" => "\xEB\x95\x98", + "\x8B\x6E" => "\xEB\x95\x99", + "\x8B\x6F" => "\xEB\x95\x9A", + "\x8B\x70" => "\xEB\x95\x9B", + "\x8B\x71" => "\xEB\x95\x9E", + "\x8B\x72" => "\xEB\x95\xA2", + "\x8B\x73" => "\xEB\x95\xA3", + "\x8B\x74" => "\xEB\x95\xA4", + "\x8B\x75" => "\xEB\x95\xA5", + "\x8B\x76" => "\xEB\x95\xA6", + "\x8B\x77" => "\xEB\x95\xA7", + "\x8B\x78" => "\xEB\x95\xA8", + "\x8B\x79" => "\xEB\x95\xA9", + "\x8B\x7A" => "\xEB\x95\xAA", + "\x8B\x81" => "\xEB\x95\xAB", + "\x8B\x82" => "\xEB\x95\xAC", + "\x8B\x83" => "\xEB\x95\xAD", + "\x8B\x84" => "\xEB\x95\xAE", + "\x8B\x85" => "\xEB\x95\xAF", + "\x8B\x86" => "\xEB\x95\xB0", + "\x8B\x87" => "\xEB\x95\xB1", + "\x8B\x88" => "\xEB\x95\xB2", + "\x8B\x89" => "\xEB\x95\xB3", + "\x8B\x8A" => "\xEB\x95\xB4", + "\x8B\x8B" => "\xEB\x95\xB5", + "\x8B\x8C" => "\xEB\x95\xB6", + "\x8B\x8D" => "\xEB\x95\xB7", + "\x8B\x8E" => "\xEB\x95\xB8", + "\x8B\x8F" => "\xEB\x95\xB9", + "\x8B\x90" => "\xEB\x95\xBA", + "\x8B\x91" => "\xEB\x95\xBB", + "\x8B\x92" => "\xEB\x95\xBC", + "\x8B\x93" => "\xEB\x95\xBD", + "\x8B\x94" => "\xEB\x95\xBE", + "\x8B\x95" => "\xEB\x95\xBF", + "\x8B\x96" => "\xEB\x96\x80", + "\x8B\x97" => "\xEB\x96\x81", + "\x8B\x98" => "\xEB\x96\x82", + "\x8B\x99" => "\xEB\x96\x83", + "\x8B\x9A" => "\xEB\x96\x84", + "\x8B\x9B" => "\xEB\x96\x85", + "\x8B\x9C" => "\xEB\x96\x86", + "\x8B\x9D" => "\xEB\x96\x87", + "\x8B\x9E" => "\xEB\x96\x88", + "\x8B\x9F" => "\xEB\x96\x89", + "\x8B\xA0" => "\xEB\x96\x8A", + "\x8B\xA1" => "\xEB\x96\x8B", + "\x8B\xA2" => "\xEB\x96\x8C", + "\x8B\xA3" => "\xEB\x96\x8D", + "\x8B\xA4" => "\xEB\x96\x8E", + "\x8B\xA5" => "\xEB\x96\x8F", + "\x8B\xA6" => "\xEB\x96\x90", + "\x8B\xA7" => "\xEB\x96\x91", + "\x8B\xA8" => "\xEB\x96\x92", + "\x8B\xA9" => "\xEB\x96\x93", + "\x8B\xAA" => "\xEB\x96\x94", + "\x8B\xAB" => "\xEB\x96\x95", + "\x8B\xAC" => "\xEB\x96\x96", + "\x8B\xAD" => "\xEB\x96\x97", + "\x8B\xAE" => "\xEB\x96\x98", + "\x8B\xAF" => "\xEB\x96\x99", + "\x8B\xB0" => "\xEB\x96\x9A", + "\x8B\xB1" => "\xEB\x96\x9B", + "\x8B\xB2" => "\xEB\x96\x9C", + "\x8B\xB3" => "\xEB\x96\x9D", + "\x8B\xB4" => "\xEB\x96\x9E", + "\x8B\xB5" => "\xEB\x96\x9F", + "\x8B\xB6" => "\xEB\x96\xA2", + "\x8B\xB7" => "\xEB\x96\xA3", + "\x8B\xB8" => "\xEB\x96\xA5", + "\x8B\xB9" => "\xEB\x96\xA6", + "\x8B\xBA" => "\xEB\x96\xA7", + "\x8B\xBB" => "\xEB\x96\xA9", + "\x8B\xBC" => "\xEB\x96\xAC", + "\x8B\xBD" => "\xEB\x96\xAD", + "\x8B\xBE" => "\xEB\x96\xAE", + "\x8B\xBF" => "\xEB\x96\xAF", + "\x8B\xC0" => "\xEB\x96\xB2", + "\x8B\xC1" => "\xEB\x96\xB6", + "\x8B\xC2" => "\xEB\x96\xB7", + "\x8B\xC3" => "\xEB\x96\xB8", + "\x8B\xC4" => "\xEB\x96\xB9", + "\x8B\xC5" => "\xEB\x96\xBA", + "\x8B\xC6" => "\xEB\x96\xBE", + "\x8B\xC7" => "\xEB\x96\xBF", + "\x8B\xC8" => "\xEB\x97\x81", + "\x8B\xC9" => "\xEB\x97\x82", + "\x8B\xCA" => "\xEB\x97\x83", + "\x8B\xCB" => "\xEB\x97\x85", + "\x8B\xCC" => "\xEB\x97\x86", + "\x8B\xCD" => "\xEB\x97\x87", + "\x8B\xCE" => "\xEB\x97\x88", + "\x8B\xCF" => "\xEB\x97\x89", + "\x8B\xD0" => "\xEB\x97\x8A", + "\x8B\xD1" => "\xEB\x97\x8B", + "\x8B\xD2" => "\xEB\x97\x8E", + "\x8B\xD3" => "\xEB\x97\x92", + "\x8B\xD4" => "\xEB\x97\x93", + "\x8B\xD5" => "\xEB\x97\x94", + "\x8B\xD6" => "\xEB\x97\x95", + "\x8B\xD7" => "\xEB\x97\x96", + "\x8B\xD8" => "\xEB\x97\x97", + "\x8B\xD9" => "\xEB\x97\x99", + "\x8B\xDA" => "\xEB\x97\x9A", + "\x8B\xDB" => "\xEB\x97\x9B", + "\x8B\xDC" => "\xEB\x97\x9C", + "\x8B\xDD" => "\xEB\x97\x9D", + "\x8B\xDE" => "\xEB\x97\x9E", + "\x8B\xDF" => "\xEB\x97\x9F", + "\x8B\xE0" => "\xEB\x97\xA0", + "\x8B\xE1" => "\xEB\x97\xA1", + "\x8B\xE2" => "\xEB\x97\xA2", + "\x8B\xE3" => "\xEB\x97\xA3", + "\x8B\xE4" => "\xEB\x97\xA4", + "\x8B\xE5" => "\xEB\x97\xA5", + "\x8B\xE6" => "\xEB\x97\xA6", + "\x8B\xE7" => "\xEB\x97\xA7", + "\x8B\xE8" => "\xEB\x97\xA8", + "\x8B\xE9" => "\xEB\x97\xA9", + "\x8B\xEA" => "\xEB\x97\xAA", + "\x8B\xEB" => "\xEB\x97\xAB", + "\x8B\xEC" => "\xEB\x97\xAD", + "\x8B\xED" => "\xEB\x97\xAE", + "\x8B\xEE" => "\xEB\x97\xAF", + "\x8B\xEF" => "\xEB\x97\xB0", + "\x8B\xF0" => "\xEB\x97\xB1", + "\x8B\xF1" => "\xEB\x97\xB2", + "\x8B\xF2" => "\xEB\x97\xB3", + "\x8B\xF3" => "\xEB\x97\xB4", + "\x8B\xF4" => "\xEB\x97\xB5", + "\x8B\xF5" => "\xEB\x97\xB6", + "\x8B\xF6" => "\xEB\x97\xB7", + "\x8B\xF7" => "\xEB\x97\xB8", + "\x8B\xF8" => "\xEB\x97\xB9", + "\x8B\xF9" => "\xEB\x97\xBA", + "\x8B\xFA" => "\xEB\x97\xBB", + "\x8B\xFB" => "\xEB\x97\xBC", + "\x8B\xFC" => "\xEB\x97\xBD", + "\x8B\xFD" => "\xEB\x97\xBE", + "\x8B\xFE" => "\xEB\x97\xBF", + "\x8C\x41" => "\xEB\x98\x80", + "\x8C\x42" => "\xEB\x98\x81", + "\x8C\x43" => "\xEB\x98\x82", + "\x8C\x44" => "\xEB\x98\x83", + "\x8C\x45" => "\xEB\x98\x84", + "\x8C\x46" => "\xEB\x98\x85", + "\x8C\x47" => "\xEB\x98\x86", + "\x8C\x48" => "\xEB\x98\x87", + "\x8C\x49" => "\xEB\x98\x88", + "\x8C\x4A" => "\xEB\x98\x89", + "\x8C\x4B" => "\xEB\x98\x8A", + "\x8C\x4C" => "\xEB\x98\x8B", + "\x8C\x4D" => "\xEB\x98\x8C", + "\x8C\x4E" => "\xEB\x98\x8D", + "\x8C\x4F" => "\xEB\x98\x8E", + "\x8C\x50" => "\xEB\x98\x8F", + "\x8C\x51" => "\xEB\x98\x92", + "\x8C\x52" => "\xEB\x98\x93", + "\x8C\x53" => "\xEB\x98\x95", + "\x8C\x54" => "\xEB\x98\x96", + "\x8C\x55" => "\xEB\x98\x97", + "\x8C\x56" => "\xEB\x98\x99", + "\x8C\x57" => "\xEB\x98\x9A", + "\x8C\x58" => "\xEB\x98\x9B", + "\x8C\x59" => "\xEB\x98\x9C", + "\x8C\x5A" => "\xEB\x98\x9D", + "\x8C\x61" => "\xEB\x98\x9E", + "\x8C\x62" => "\xEB\x98\x9F", + "\x8C\x63" => "\xEB\x98\xA0", + "\x8C\x64" => "\xEB\x98\xA1", + "\x8C\x65" => "\xEB\x98\xA2", + "\x8C\x66" => "\xEB\x98\xA3", + "\x8C\x67" => "\xEB\x98\xA4", + "\x8C\x68" => "\xEB\x98\xA6", + "\x8C\x69" => "\xEB\x98\xA7", + "\x8C\x6A" => "\xEB\x98\xA8", + "\x8C\x6B" => "\xEB\x98\xA9", + "\x8C\x6C" => "\xEB\x98\xAA", + "\x8C\x6D" => "\xEB\x98\xAB", + "\x8C\x6E" => "\xEB\x98\xAD", + "\x8C\x6F" => "\xEB\x98\xAE", + "\x8C\x70" => "\xEB\x98\xAF", + "\x8C\x71" => "\xEB\x98\xB0", + "\x8C\x72" => "\xEB\x98\xB1", + "\x8C\x73" => "\xEB\x98\xB2", + "\x8C\x74" => "\xEB\x98\xB3", + "\x8C\x75" => "\xEB\x98\xB5", + "\x8C\x76" => "\xEB\x98\xB6", + "\x8C\x77" => "\xEB\x98\xB7", + "\x8C\x78" => "\xEB\x98\xB8", + "\x8C\x79" => "\xEB\x98\xB9", + "\x8C\x7A" => "\xEB\x98\xBA", + "\x8C\x81" => "\xEB\x98\xBB", + "\x8C\x82" => "\xEB\x98\xBC", + "\x8C\x83" => "\xEB\x98\xBD", + "\x8C\x84" => "\xEB\x98\xBE", + "\x8C\x85" => "\xEB\x98\xBF", + "\x8C\x86" => "\xEB\x99\x80", + "\x8C\x87" => "\xEB\x99\x81", + "\x8C\x88" => "\xEB\x99\x82", + "\x8C\x89" => "\xEB\x99\x83", + "\x8C\x8A" => "\xEB\x99\x84", + "\x8C\x8B" => "\xEB\x99\x85", + "\x8C\x8C" => "\xEB\x99\x86", + "\x8C\x8D" => "\xEB\x99\x87", + "\x8C\x8E" => "\xEB\x99\x89", + "\x8C\x8F" => "\xEB\x99\x8A", + "\x8C\x90" => "\xEB\x99\x8B", + "\x8C\x91" => "\xEB\x99\x8C", + "\x8C\x92" => "\xEB\x99\x8D", + "\x8C\x93" => "\xEB\x99\x8E", + "\x8C\x94" => "\xEB\x99\x8F", + "\x8C\x95" => "\xEB\x99\x90", + "\x8C\x96" => "\xEB\x99\x91", + "\x8C\x97" => "\xEB\x99\x92", + "\x8C\x98" => "\xEB\x99\x93", + "\x8C\x99" => "\xEB\x99\x94", + "\x8C\x9A" => "\xEB\x99\x95", + "\x8C\x9B" => "\xEB\x99\x96", + "\x8C\x9C" => "\xEB\x99\x97", + "\x8C\x9D" => "\xEB\x99\x98", + "\x8C\x9E" => "\xEB\x99\x99", + "\x8C\x9F" => "\xEB\x99\x9A", + "\x8C\xA0" => "\xEB\x99\x9B", + "\x8C\xA1" => "\xEB\x99\x9C", + "\x8C\xA2" => "\xEB\x99\x9D", + "\x8C\xA3" => "\xEB\x99\x9E", + "\x8C\xA4" => "\xEB\x99\x9F", + "\x8C\xA5" => "\xEB\x99\xA0", + "\x8C\xA6" => "\xEB\x99\xA1", + "\x8C\xA7" => "\xEB\x99\xA2", + "\x8C\xA8" => "\xEB\x99\xA3", + "\x8C\xA9" => "\xEB\x99\xA5", + "\x8C\xAA" => "\xEB\x99\xA6", + "\x8C\xAB" => "\xEB\x99\xA7", + "\x8C\xAC" => "\xEB\x99\xA9", + "\x8C\xAD" => "\xEB\x99\xAA", + "\x8C\xAE" => "\xEB\x99\xAB", + "\x8C\xAF" => "\xEB\x99\xAC", + "\x8C\xB0" => "\xEB\x99\xAD", + "\x8C\xB1" => "\xEB\x99\xAE", + "\x8C\xB2" => "\xEB\x99\xAF", + "\x8C\xB3" => "\xEB\x99\xB0", + "\x8C\xB4" => "\xEB\x99\xB1", + "\x8C\xB5" => "\xEB\x99\xB2", + "\x8C\xB6" => "\xEB\x99\xB3", + "\x8C\xB7" => "\xEB\x99\xB4", + "\x8C\xB8" => "\xEB\x99\xB5", + "\x8C\xB9" => "\xEB\x99\xB6", + "\x8C\xBA" => "\xEB\x99\xB7", + "\x8C\xBB" => "\xEB\x99\xB8", + "\x8C\xBC" => "\xEB\x99\xB9", + "\x8C\xBD" => "\xEB\x99\xBA", + "\x8C\xBE" => "\xEB\x99\xBB", + "\x8C\xBF" => "\xEB\x99\xBC", + "\x8C\xC0" => "\xEB\x99\xBD", + "\x8C\xC1" => "\xEB\x99\xBE", + "\x8C\xC2" => "\xEB\x99\xBF", + "\x8C\xC3" => "\xEB\x9A\x80", + "\x8C\xC4" => "\xEB\x9A\x81", + "\x8C\xC5" => "\xEB\x9A\x82", + "\x8C\xC6" => "\xEB\x9A\x83", + "\x8C\xC7" => "\xEB\x9A\x84", + "\x8C\xC8" => "\xEB\x9A\x85", + "\x8C\xC9" => "\xEB\x9A\x86", + "\x8C\xCA" => "\xEB\x9A\x87", + "\x8C\xCB" => "\xEB\x9A\x88", + "\x8C\xCC" => "\xEB\x9A\x89", + "\x8C\xCD" => "\xEB\x9A\x8A", + "\x8C\xCE" => "\xEB\x9A\x8B", + "\x8C\xCF" => "\xEB\x9A\x8C", + "\x8C\xD0" => "\xEB\x9A\x8D", + "\x8C\xD1" => "\xEB\x9A\x8E", + "\x8C\xD2" => "\xEB\x9A\x8F", + "\x8C\xD3" => "\xEB\x9A\x90", + "\x8C\xD4" => "\xEB\x9A\x91", + "\x8C\xD5" => "\xEB\x9A\x92", + "\x8C\xD6" => "\xEB\x9A\x93", + "\x8C\xD7" => "\xEB\x9A\x94", + "\x8C\xD8" => "\xEB\x9A\x95", + "\x8C\xD9" => "\xEB\x9A\x96", + "\x8C\xDA" => "\xEB\x9A\x97", + "\x8C\xDB" => "\xEB\x9A\x98", + "\x8C\xDC" => "\xEB\x9A\x99", + "\x8C\xDD" => "\xEB\x9A\x9A", + "\x8C\xDE" => "\xEB\x9A\x9B", + "\x8C\xDF" => "\xEB\x9A\x9E", + "\x8C\xE0" => "\xEB\x9A\x9F", + "\x8C\xE1" => "\xEB\x9A\xA1", + "\x8C\xE2" => "\xEB\x9A\xA2", + "\x8C\xE3" => "\xEB\x9A\xA3", + "\x8C\xE4" => "\xEB\x9A\xA5", + "\x8C\xE5" => "\xEB\x9A\xA6", + "\x8C\xE6" => "\xEB\x9A\xA7", + "\x8C\xE7" => "\xEB\x9A\xA8", + "\x8C\xE8" => "\xEB\x9A\xA9", + "\x8C\xE9" => "\xEB\x9A\xAA", + "\x8C\xEA" => "\xEB\x9A\xAD", + "\x8C\xEB" => "\xEB\x9A\xAE", + "\x8C\xEC" => "\xEB\x9A\xAF", + "\x8C\xED" => "\xEB\x9A\xB0", + "\x8C\xEE" => "\xEB\x9A\xB2", + "\x8C\xEF" => "\xEB\x9A\xB3", + "\x8C\xF0" => "\xEB\x9A\xB4", + "\x8C\xF1" => "\xEB\x9A\xB5", + "\x8C\xF2" => "\xEB\x9A\xB6", + "\x8C\xF3" => "\xEB\x9A\xB7", + "\x8C\xF4" => "\xEB\x9A\xB8", + "\x8C\xF5" => "\xEB\x9A\xB9", + "\x8C\xF6" => "\xEB\x9A\xBA", + "\x8C\xF7" => "\xEB\x9A\xBB", + "\x8C\xF8" => "\xEB\x9A\xBC", + "\x8C\xF9" => "\xEB\x9A\xBD", + "\x8C\xFA" => "\xEB\x9A\xBE", + "\x8C\xFB" => "\xEB\x9A\xBF", + "\x8C\xFC" => "\xEB\x9B\x80", + "\x8C\xFD" => "\xEB\x9B\x81", + "\x8C\xFE" => "\xEB\x9B\x82", + "\x8D\x41" => "\xEB\x9B\x83", + "\x8D\x42" => "\xEB\x9B\x84", + "\x8D\x43" => "\xEB\x9B\x85", + "\x8D\x44" => "\xEB\x9B\x86", + "\x8D\x45" => "\xEB\x9B\x87", + "\x8D\x46" => "\xEB\x9B\x88", + "\x8D\x47" => "\xEB\x9B\x89", + "\x8D\x48" => "\xEB\x9B\x8A", + "\x8D\x49" => "\xEB\x9B\x8B", + "\x8D\x4A" => "\xEB\x9B\x8C", + "\x8D\x4B" => "\xEB\x9B\x8D", + "\x8D\x4C" => "\xEB\x9B\x8E", + "\x8D\x4D" => "\xEB\x9B\x8F", + "\x8D\x4E" => "\xEB\x9B\x90", + "\x8D\x4F" => "\xEB\x9B\x91", + "\x8D\x50" => "\xEB\x9B\x92", + "\x8D\x51" => "\xEB\x9B\x93", + "\x8D\x52" => "\xEB\x9B\x95", + "\x8D\x53" => "\xEB\x9B\x96", + "\x8D\x54" => "\xEB\x9B\x97", + "\x8D\x55" => "\xEB\x9B\x98", + "\x8D\x56" => "\xEB\x9B\x99", + "\x8D\x57" => "\xEB\x9B\x9A", + "\x8D\x58" => "\xEB\x9B\x9B", + "\x8D\x59" => "\xEB\x9B\x9C", + "\x8D\x5A" => "\xEB\x9B\x9D", + "\x8D\x61" => "\xEB\x9B\x9E", + "\x8D\x62" => "\xEB\x9B\x9F", + "\x8D\x63" => "\xEB\x9B\xA0", + "\x8D\x64" => "\xEB\x9B\xA1", + "\x8D\x65" => "\xEB\x9B\xA2", + "\x8D\x66" => "\xEB\x9B\xA3", + "\x8D\x67" => "\xEB\x9B\xA4", + "\x8D\x68" => "\xEB\x9B\xA5", + "\x8D\x69" => "\xEB\x9B\xA6", + "\x8D\x6A" => "\xEB\x9B\xA7", + "\x8D\x6B" => "\xEB\x9B\xA8", + "\x8D\x6C" => "\xEB\x9B\xA9", + "\x8D\x6D" => "\xEB\x9B\xAA", + "\x8D\x6E" => "\xEB\x9B\xAB", + "\x8D\x6F" => "\xEB\x9B\xAC", + "\x8D\x70" => "\xEB\x9B\xAD", + "\x8D\x71" => "\xEB\x9B\xAE", + "\x8D\x72" => "\xEB\x9B\xAF", + "\x8D\x73" => "\xEB\x9B\xB1", + "\x8D\x74" => "\xEB\x9B\xB2", + "\x8D\x75" => "\xEB\x9B\xB3", + "\x8D\x76" => "\xEB\x9B\xB5", + "\x8D\x77" => "\xEB\x9B\xB6", + "\x8D\x78" => "\xEB\x9B\xB7", + "\x8D\x79" => "\xEB\x9B\xB9", + "\x8D\x7A" => "\xEB\x9B\xBA", + "\x8D\x81" => "\xEB\x9B\xBB", + "\x8D\x82" => "\xEB\x9B\xBC", + "\x8D\x83" => "\xEB\x9B\xBD", + "\x8D\x84" => "\xEB\x9B\xBE", + "\x8D\x85" => "\xEB\x9B\xBF", + "\x8D\x86" => "\xEB\x9C\x82", + "\x8D\x87" => "\xEB\x9C\x83", + "\x8D\x88" => "\xEB\x9C\x84", + "\x8D\x89" => "\xEB\x9C\x86", + "\x8D\x8A" => "\xEB\x9C\x87", + "\x8D\x8B" => "\xEB\x9C\x88", + "\x8D\x8C" => "\xEB\x9C\x89", + "\x8D\x8D" => "\xEB\x9C\x8A", + "\x8D\x8E" => "\xEB\x9C\x8B", + "\x8D\x8F" => "\xEB\x9C\x8C", + "\x8D\x90" => "\xEB\x9C\x8D", + "\x8D\x91" => "\xEB\x9C\x8E", + "\x8D\x92" => "\xEB\x9C\x8F", + "\x8D\x93" => "\xEB\x9C\x90", + "\x8D\x94" => "\xEB\x9C\x91", + "\x8D\x95" => "\xEB\x9C\x92", + "\x8D\x96" => "\xEB\x9C\x93", + "\x8D\x97" => "\xEB\x9C\x94", + "\x8D\x98" => "\xEB\x9C\x95", + "\x8D\x99" => "\xEB\x9C\x96", + "\x8D\x9A" => "\xEB\x9C\x97", + "\x8D\x9B" => "\xEB\x9C\x98", + "\x8D\x9C" => "\xEB\x9C\x99", + "\x8D\x9D" => "\xEB\x9C\x9A", + "\x8D\x9E" => "\xEB\x9C\x9B", + "\x8D\x9F" => "\xEB\x9C\x9C", + "\x8D\xA0" => "\xEB\x9C\x9D", + "\x8D\xA1" => "\xEB\x9C\x9E", + "\x8D\xA2" => "\xEB\x9C\x9F", + "\x8D\xA3" => "\xEB\x9C\xA0", + "\x8D\xA4" => "\xEB\x9C\xA1", + "\x8D\xA5" => "\xEB\x9C\xA2", + "\x8D\xA6" => "\xEB\x9C\xA3", + "\x8D\xA7" => "\xEB\x9C\xA4", + "\x8D\xA8" => "\xEB\x9C\xA5", + "\x8D\xA9" => "\xEB\x9C\xA6", + "\x8D\xAA" => "\xEB\x9C\xA7", + "\x8D\xAB" => "\xEB\x9C\xAA", + "\x8D\xAC" => "\xEB\x9C\xAB", + "\x8D\xAD" => "\xEB\x9C\xAD", + "\x8D\xAE" => "\xEB\x9C\xAE", + "\x8D\xAF" => "\xEB\x9C\xB1", + "\x8D\xB0" => "\xEB\x9C\xB2", + "\x8D\xB1" => "\xEB\x9C\xB3", + "\x8D\xB2" => "\xEB\x9C\xB4", + "\x8D\xB3" => "\xEB\x9C\xB5", + "\x8D\xB4" => "\xEB\x9C\xB6", + "\x8D\xB5" => "\xEB\x9C\xB7", + "\x8D\xB6" => "\xEB\x9C\xBA", + "\x8D\xB7" => "\xEB\x9C\xBC", + "\x8D\xB8" => "\xEB\x9C\xBD", + "\x8D\xB9" => "\xEB\x9C\xBE", + "\x8D\xBA" => "\xEB\x9C\xBF", + "\x8D\xBB" => "\xEB\x9D\x80", + "\x8D\xBC" => "\xEB\x9D\x81", + "\x8D\xBD" => "\xEB\x9D\x82", + "\x8D\xBE" => "\xEB\x9D\x83", + "\x8D\xBF" => "\xEB\x9D\x85", + "\x8D\xC0" => "\xEB\x9D\x86", + "\x8D\xC1" => "\xEB\x9D\x87", + "\x8D\xC2" => "\xEB\x9D\x89", + "\x8D\xC3" => "\xEB\x9D\x8A", + "\x8D\xC4" => "\xEB\x9D\x8B", + "\x8D\xC5" => "\xEB\x9D\x8D", + "\x8D\xC6" => "\xEB\x9D\x8E", + "\x8D\xC7" => "\xEB\x9D\x8F", + "\x8D\xC8" => "\xEB\x9D\x90", + "\x8D\xC9" => "\xEB\x9D\x91", + "\x8D\xCA" => "\xEB\x9D\x92", + "\x8D\xCB" => "\xEB\x9D\x93", + "\x8D\xCC" => "\xEB\x9D\x96", + "\x8D\xCD" => "\xEB\x9D\x97", + "\x8D\xCE" => "\xEB\x9D\x98", + "\x8D\xCF" => "\xEB\x9D\x99", + "\x8D\xD0" => "\xEB\x9D\x9A", + "\x8D\xD1" => "\xEB\x9D\x9B", + "\x8D\xD2" => "\xEB\x9D\x9C", + "\x8D\xD3" => "\xEB\x9D\x9D", + "\x8D\xD4" => "\xEB\x9D\x9E", + "\x8D\xD5" => "\xEB\x9D\x9F", + "\x8D\xD6" => "\xEB\x9D\xA1", + "\x8D\xD7" => "\xEB\x9D\xA2", + "\x8D\xD8" => "\xEB\x9D\xA3", + "\x8D\xD9" => "\xEB\x9D\xA5", + "\x8D\xDA" => "\xEB\x9D\xA6", + "\x8D\xDB" => "\xEB\x9D\xA7", + "\x8D\xDC" => "\xEB\x9D\xA9", + "\x8D\xDD" => "\xEB\x9D\xAA", + "\x8D\xDE" => "\xEB\x9D\xAB", + "\x8D\xDF" => "\xEB\x9D\xAC", + "\x8D\xE0" => "\xEB\x9D\xAD", + "\x8D\xE1" => "\xEB\x9D\xAE", + "\x8D\xE2" => "\xEB\x9D\xAF", + "\x8D\xE3" => "\xEB\x9D\xB2", + "\x8D\xE4" => "\xEB\x9D\xB4", + "\x8D\xE5" => "\xEB\x9D\xB6", + "\x8D\xE6" => "\xEB\x9D\xB7", + "\x8D\xE7" => "\xEB\x9D\xB8", + "\x8D\xE8" => "\xEB\x9D\xB9", + "\x8D\xE9" => "\xEB\x9D\xBA", + "\x8D\xEA" => "\xEB\x9D\xBB", + "\x8D\xEB" => "\xEB\x9D\xBE", + "\x8D\xEC" => "\xEB\x9D\xBF", + "\x8D\xED" => "\xEB\x9E\x81", + "\x8D\xEE" => "\xEB\x9E\x82", + "\x8D\xEF" => "\xEB\x9E\x83", + "\x8D\xF0" => "\xEB\x9E\x85", + "\x8D\xF1" => "\xEB\x9E\x86", + "\x8D\xF2" => "\xEB\x9E\x87", + "\x8D\xF3" => "\xEB\x9E\x88", + "\x8D\xF4" => "\xEB\x9E\x89", + "\x8D\xF5" => "\xEB\x9E\x8A", + "\x8D\xF6" => "\xEB\x9E\x8B", + "\x8D\xF7" => "\xEB\x9E\x8E", + "\x8D\xF8" => "\xEB\x9E\x93", + "\x8D\xF9" => "\xEB\x9E\x94", + "\x8D\xFA" => "\xEB\x9E\x95", + "\x8D\xFB" => "\xEB\x9E\x9A", + "\x8D\xFC" => "\xEB\x9E\x9B", + "\x8D\xFD" => "\xEB\x9E\x9D", + "\x8D\xFE" => "\xEB\x9E\x9E", + "\x8E\x41" => "\xEB\x9E\x9F", + "\x8E\x42" => "\xEB\x9E\xA1", + "\x8E\x43" => "\xEB\x9E\xA2", + "\x8E\x44" => "\xEB\x9E\xA3", + "\x8E\x45" => "\xEB\x9E\xA4", + "\x8E\x46" => "\xEB\x9E\xA5", + "\x8E\x47" => "\xEB\x9E\xA6", + "\x8E\x48" => "\xEB\x9E\xA7", + "\x8E\x49" => "\xEB\x9E\xAA", + "\x8E\x4A" => "\xEB\x9E\xAE", + "\x8E\x4B" => "\xEB\x9E\xAF", + "\x8E\x4C" => "\xEB\x9E\xB0", + "\x8E\x4D" => "\xEB\x9E\xB1", + "\x8E\x4E" => "\xEB\x9E\xB2", + "\x8E\x4F" => "\xEB\x9E\xB3", + "\x8E\x50" => "\xEB\x9E\xB6", + "\x8E\x51" => "\xEB\x9E\xB7", + "\x8E\x52" => "\xEB\x9E\xB9", + "\x8E\x53" => "\xEB\x9E\xBA", + "\x8E\x54" => "\xEB\x9E\xBB", + "\x8E\x55" => "\xEB\x9E\xBC", + "\x8E\x56" => "\xEB\x9E\xBD", + "\x8E\x57" => "\xEB\x9E\xBE", + "\x8E\x58" => "\xEB\x9E\xBF", + "\x8E\x59" => "\xEB\x9F\x80", + "\x8E\x5A" => "\xEB\x9F\x81", + "\x8E\x61" => "\xEB\x9F\x82", + "\x8E\x62" => "\xEB\x9F\x83", + "\x8E\x63" => "\xEB\x9F\x84", + "\x8E\x64" => "\xEB\x9F\x85", + "\x8E\x65" => "\xEB\x9F\x86", + "\x8E\x66" => "\xEB\x9F\x88", + "\x8E\x67" => "\xEB\x9F\x8A", + "\x8E\x68" => "\xEB\x9F\x8B", + "\x8E\x69" => "\xEB\x9F\x8C", + "\x8E\x6A" => "\xEB\x9F\x8D", + "\x8E\x6B" => "\xEB\x9F\x8E", + "\x8E\x6C" => "\xEB\x9F\x8F", + "\x8E\x6D" => "\xEB\x9F\x90", + "\x8E\x6E" => "\xEB\x9F\x91", + "\x8E\x6F" => "\xEB\x9F\x92", + "\x8E\x70" => "\xEB\x9F\x93", + "\x8E\x71" => "\xEB\x9F\x94", + "\x8E\x72" => "\xEB\x9F\x95", + "\x8E\x73" => "\xEB\x9F\x96", + "\x8E\x74" => "\xEB\x9F\x97", + "\x8E\x75" => "\xEB\x9F\x98", + "\x8E\x76" => "\xEB\x9F\x99", + "\x8E\x77" => "\xEB\x9F\x9A", + "\x8E\x78" => "\xEB\x9F\x9B", + "\x8E\x79" => "\xEB\x9F\x9C", + "\x8E\x7A" => "\xEB\x9F\x9D", + "\x8E\x81" => "\xEB\x9F\x9E", + "\x8E\x82" => "\xEB\x9F\x9F", + "\x8E\x83" => "\xEB\x9F\xA0", + "\x8E\x84" => "\xEB\x9F\xA1", + "\x8E\x85" => "\xEB\x9F\xA2", + "\x8E\x86" => "\xEB\x9F\xA3", + "\x8E\x87" => "\xEB\x9F\xA4", + "\x8E\x88" => "\xEB\x9F\xA5", + "\x8E\x89" => "\xEB\x9F\xA6", + "\x8E\x8A" => "\xEB\x9F\xA7", + "\x8E\x8B" => "\xEB\x9F\xA8", + "\x8E\x8C" => "\xEB\x9F\xA9", + "\x8E\x8D" => "\xEB\x9F\xAA", + "\x8E\x8E" => "\xEB\x9F\xAB", + "\x8E\x8F" => "\xEB\x9F\xAE", + "\x8E\x90" => "\xEB\x9F\xAF", + "\x8E\x91" => "\xEB\x9F\xB1", + "\x8E\x92" => "\xEB\x9F\xB2", + "\x8E\x93" => "\xEB\x9F\xB3", + "\x8E\x94" => "\xEB\x9F\xB5", + "\x8E\x95" => "\xEB\x9F\xB6", + "\x8E\x96" => "\xEB\x9F\xB7", + "\x8E\x97" => "\xEB\x9F\xB8", + "\x8E\x98" => "\xEB\x9F\xB9", + "\x8E\x99" => "\xEB\x9F\xBA", + "\x8E\x9A" => "\xEB\x9F\xBB", + "\x8E\x9B" => "\xEB\x9F\xBE", + "\x8E\x9C" => "\xEB\xA0\x82", + "\x8E\x9D" => "\xEB\xA0\x83", + "\x8E\x9E" => "\xEB\xA0\x84", + "\x8E\x9F" => "\xEB\xA0\x85", + "\x8E\xA0" => "\xEB\xA0\x86", + "\x8E\xA1" => "\xEB\xA0\x8A", + "\x8E\xA2" => "\xEB\xA0\x8B", + "\x8E\xA3" => "\xEB\xA0\x8D", + "\x8E\xA4" => "\xEB\xA0\x8E", + "\x8E\xA5" => "\xEB\xA0\x8F", + "\x8E\xA6" => "\xEB\xA0\x91", + "\x8E\xA7" => "\xEB\xA0\x92", + "\x8E\xA8" => "\xEB\xA0\x93", + "\x8E\xA9" => "\xEB\xA0\x94", + "\x8E\xAA" => "\xEB\xA0\x95", + "\x8E\xAB" => "\xEB\xA0\x96", + "\x8E\xAC" => "\xEB\xA0\x97", + "\x8E\xAD" => "\xEB\xA0\x9A", + "\x8E\xAE" => "\xEB\xA0\x9C", + "\x8E\xAF" => "\xEB\xA0\x9E", + "\x8E\xB0" => "\xEB\xA0\x9F", + "\x8E\xB1" => "\xEB\xA0\xA0", + "\x8E\xB2" => "\xEB\xA0\xA1", + "\x8E\xB3" => "\xEB\xA0\xA2", + "\x8E\xB4" => "\xEB\xA0\xA3", + "\x8E\xB5" => "\xEB\xA0\xA6", + "\x8E\xB6" => "\xEB\xA0\xA7", + "\x8E\xB7" => "\xEB\xA0\xA9", + "\x8E\xB8" => "\xEB\xA0\xAA", + "\x8E\xB9" => "\xEB\xA0\xAB", + "\x8E\xBA" => "\xEB\xA0\xAD", + "\x8E\xBB" => "\xEB\xA0\xAE", + "\x8E\xBC" => "\xEB\xA0\xAF", + "\x8E\xBD" => "\xEB\xA0\xB0", + "\x8E\xBE" => "\xEB\xA0\xB1", + "\x8E\xBF" => "\xEB\xA0\xB2", + "\x8E\xC0" => "\xEB\xA0\xB3", + "\x8E\xC1" => "\xEB\xA0\xB6", + "\x8E\xC2" => "\xEB\xA0\xBA", + "\x8E\xC3" => "\xEB\xA0\xBB", + "\x8E\xC4" => "\xEB\xA0\xBC", + "\x8E\xC5" => "\xEB\xA0\xBD", + "\x8E\xC6" => "\xEB\xA0\xBE", + "\x8E\xC7" => "\xEB\xA0\xBF", + "\x8E\xC8" => "\xEB\xA1\x81", + "\x8E\xC9" => "\xEB\xA1\x82", + "\x8E\xCA" => "\xEB\xA1\x83", + "\x8E\xCB" => "\xEB\xA1\x85", + "\x8E\xCC" => "\xEB\xA1\x86", + "\x8E\xCD" => "\xEB\xA1\x87", + "\x8E\xCE" => "\xEB\xA1\x88", + "\x8E\xCF" => "\xEB\xA1\x89", + "\x8E\xD0" => "\xEB\xA1\x8A", + "\x8E\xD1" => "\xEB\xA1\x8B", + "\x8E\xD2" => "\xEB\xA1\x8C", + "\x8E\xD3" => "\xEB\xA1\x8D", + "\x8E\xD4" => "\xEB\xA1\x8E", + "\x8E\xD5" => "\xEB\xA1\x8F", + "\x8E\xD6" => "\xEB\xA1\x90", + "\x8E\xD7" => "\xEB\xA1\x92", + "\x8E\xD8" => "\xEB\xA1\x94", + "\x8E\xD9" => "\xEB\xA1\x95", + "\x8E\xDA" => "\xEB\xA1\x96", + "\x8E\xDB" => "\xEB\xA1\x97", + "\x8E\xDC" => "\xEB\xA1\x98", + "\x8E\xDD" => "\xEB\xA1\x99", + "\x8E\xDE" => "\xEB\xA1\x9A", + "\x8E\xDF" => "\xEB\xA1\x9B", + "\x8E\xE0" => "\xEB\xA1\x9E", + "\x8E\xE1" => "\xEB\xA1\x9F", + "\x8E\xE2" => "\xEB\xA1\xA1", + "\x8E\xE3" => "\xEB\xA1\xA2", + "\x8E\xE4" => "\xEB\xA1\xA3", + "\x8E\xE5" => "\xEB\xA1\xA5", + "\x8E\xE6" => "\xEB\xA1\xA6", + "\x8E\xE7" => "\xEB\xA1\xA7", + "\x8E\xE8" => "\xEB\xA1\xA8", + "\x8E\xE9" => "\xEB\xA1\xA9", + "\x8E\xEA" => "\xEB\xA1\xAA", + "\x8E\xEB" => "\xEB\xA1\xAB", + "\x8E\xEC" => "\xEB\xA1\xAE", + "\x8E\xED" => "\xEB\xA1\xB0", + "\x8E\xEE" => "\xEB\xA1\xB2", + "\x8E\xEF" => "\xEB\xA1\xB3", + "\x8E\xF0" => "\xEB\xA1\xB4", + "\x8E\xF1" => "\xEB\xA1\xB5", + "\x8E\xF2" => "\xEB\xA1\xB6", + "\x8E\xF3" => "\xEB\xA1\xB7", + "\x8E\xF4" => "\xEB\xA1\xB9", + "\x8E\xF5" => "\xEB\xA1\xBA", + "\x8E\xF6" => "\xEB\xA1\xBB", + "\x8E\xF7" => "\xEB\xA1\xBD", + "\x8E\xF8" => "\xEB\xA1\xBE", + "\x8E\xF9" => "\xEB\xA1\xBF", + "\x8E\xFA" => "\xEB\xA2\x80", + "\x8E\xFB" => "\xEB\xA2\x81", + "\x8E\xFC" => "\xEB\xA2\x82", + "\x8E\xFD" => "\xEB\xA2\x83", + "\x8E\xFE" => "\xEB\xA2\x84", + "\x8F\x41" => "\xEB\xA2\x85", + "\x8F\x42" => "\xEB\xA2\x86", + "\x8F\x43" => "\xEB\xA2\x87", + "\x8F\x44" => "\xEB\xA2\x88", + "\x8F\x45" => "\xEB\xA2\x89", + "\x8F\x46" => "\xEB\xA2\x8A", + "\x8F\x47" => "\xEB\xA2\x8B", + "\x8F\x48" => "\xEB\xA2\x8C", + "\x8F\x49" => "\xEB\xA2\x8E", + "\x8F\x4A" => "\xEB\xA2\x8F", + "\x8F\x4B" => "\xEB\xA2\x90", + "\x8F\x4C" => "\xEB\xA2\x91", + "\x8F\x4D" => "\xEB\xA2\x92", + "\x8F\x4E" => "\xEB\xA2\x93", + "\x8F\x4F" => "\xEB\xA2\x94", + "\x8F\x50" => "\xEB\xA2\x95", + "\x8F\x51" => "\xEB\xA2\x96", + "\x8F\x52" => "\xEB\xA2\x97", + "\x8F\x53" => "\xEB\xA2\x98", + "\x8F\x54" => "\xEB\xA2\x99", + "\x8F\x55" => "\xEB\xA2\x9A", + "\x8F\x56" => "\xEB\xA2\x9B", + "\x8F\x57" => "\xEB\xA2\x9C", + "\x8F\x58" => "\xEB\xA2\x9D", + "\x8F\x59" => "\xEB\xA2\x9E", + "\x8F\x5A" => "\xEB\xA2\x9F", + "\x8F\x61" => "\xEB\xA2\xA0", + "\x8F\x62" => "\xEB\xA2\xA1", + "\x8F\x63" => "\xEB\xA2\xA2", + "\x8F\x64" => "\xEB\xA2\xA3", + "\x8F\x65" => "\xEB\xA2\xA4", + "\x8F\x66" => "\xEB\xA2\xA5", + "\x8F\x67" => "\xEB\xA2\xA6", + "\x8F\x68" => "\xEB\xA2\xA7", + "\x8F\x69" => "\xEB\xA2\xA9", + "\x8F\x6A" => "\xEB\xA2\xAA", + "\x8F\x6B" => "\xEB\xA2\xAB", + "\x8F\x6C" => "\xEB\xA2\xAC", + "\x8F\x6D" => "\xEB\xA2\xAD", + "\x8F\x6E" => "\xEB\xA2\xAE", + "\x8F\x6F" => "\xEB\xA2\xAF", + "\x8F\x70" => "\xEB\xA2\xB1", + "\x8F\x71" => "\xEB\xA2\xB2", + "\x8F\x72" => "\xEB\xA2\xB3", + "\x8F\x73" => "\xEB\xA2\xB5", + "\x8F\x74" => "\xEB\xA2\xB6", + "\x8F\x75" => "\xEB\xA2\xB7", + "\x8F\x76" => "\xEB\xA2\xB9", + "\x8F\x77" => "\xEB\xA2\xBA", + "\x8F\x78" => "\xEB\xA2\xBB", + "\x8F\x79" => "\xEB\xA2\xBC", + "\x8F\x7A" => "\xEB\xA2\xBD", + "\x8F\x81" => "\xEB\xA2\xBE", + "\x8F\x82" => "\xEB\xA2\xBF", + "\x8F\x83" => "\xEB\xA3\x82", + "\x8F\x84" => "\xEB\xA3\x84", + "\x8F\x85" => "\xEB\xA3\x86", + "\x8F\x86" => "\xEB\xA3\x87", + "\x8F\x87" => "\xEB\xA3\x88", + "\x8F\x88" => "\xEB\xA3\x89", + "\x8F\x89" => "\xEB\xA3\x8A", + "\x8F\x8A" => "\xEB\xA3\x8B", + "\x8F\x8B" => "\xEB\xA3\x8D", + "\x8F\x8C" => "\xEB\xA3\x8E", + "\x8F\x8D" => "\xEB\xA3\x8F", + "\x8F\x8E" => "\xEB\xA3\x91", + "\x8F\x8F" => "\xEB\xA3\x92", + "\x8F\x90" => "\xEB\xA3\x93", + "\x8F\x91" => "\xEB\xA3\x95", + "\x8F\x92" => "\xEB\xA3\x96", + "\x8F\x93" => "\xEB\xA3\x97", + "\x8F\x94" => "\xEB\xA3\x98", + "\x8F\x95" => "\xEB\xA3\x99", + "\x8F\x96" => "\xEB\xA3\x9A", + "\x8F\x97" => "\xEB\xA3\x9B", + "\x8F\x98" => "\xEB\xA3\x9C", + "\x8F\x99" => "\xEB\xA3\x9E", + "\x8F\x9A" => "\xEB\xA3\xA0", + "\x8F\x9B" => "\xEB\xA3\xA2", + "\x8F\x9C" => "\xEB\xA3\xA3", + "\x8F\x9D" => "\xEB\xA3\xA4", + "\x8F\x9E" => "\xEB\xA3\xA5", + "\x8F\x9F" => "\xEB\xA3\xA6", + "\x8F\xA0" => "\xEB\xA3\xA7", + "\x8F\xA1" => "\xEB\xA3\xAA", + "\x8F\xA2" => "\xEB\xA3\xAB", + "\x8F\xA3" => "\xEB\xA3\xAD", + "\x8F\xA4" => "\xEB\xA3\xAE", + "\x8F\xA5" => "\xEB\xA3\xAF", + "\x8F\xA6" => "\xEB\xA3\xB1", + "\x8F\xA7" => "\xEB\xA3\xB2", + "\x8F\xA8" => "\xEB\xA3\xB3", + "\x8F\xA9" => "\xEB\xA3\xB4", + "\x8F\xAA" => "\xEB\xA3\xB5", + "\x8F\xAB" => "\xEB\xA3\xB6", + "\x8F\xAC" => "\xEB\xA3\xB7", + "\x8F\xAD" => "\xEB\xA3\xBA", + "\x8F\xAE" => "\xEB\xA3\xBC", + "\x8F\xAF" => "\xEB\xA3\xBE", + "\x8F\xB0" => "\xEB\xA3\xBF", + "\x8F\xB1" => "\xEB\xA4\x80", + "\x8F\xB2" => "\xEB\xA4\x81", + "\x8F\xB3" => "\xEB\xA4\x82", + "\x8F\xB4" => "\xEB\xA4\x83", + "\x8F\xB5" => "\xEB\xA4\x85", + "\x8F\xB6" => "\xEB\xA4\x86", + "\x8F\xB7" => "\xEB\xA4\x87", + "\x8F\xB8" => "\xEB\xA4\x88", + "\x8F\xB9" => "\xEB\xA4\x89", + "\x8F\xBA" => "\xEB\xA4\x8A", + "\x8F\xBB" => "\xEB\xA4\x8B", + "\x8F\xBC" => "\xEB\xA4\x8C", + "\x8F\xBD" => "\xEB\xA4\x8D", + "\x8F\xBE" => "\xEB\xA4\x8E", + "\x8F\xBF" => "\xEB\xA4\x8F", + "\x8F\xC0" => "\xEB\xA4\x90", + "\x8F\xC1" => "\xEB\xA4\x91", + "\x8F\xC2" => "\xEB\xA4\x92", + "\x8F\xC3" => "\xEB\xA4\x93", + "\x8F\xC4" => "\xEB\xA4\x94", + "\x8F\xC5" => "\xEB\xA4\x95", + "\x8F\xC6" => "\xEB\xA4\x96", + "\x8F\xC7" => "\xEB\xA4\x97", + "\x8F\xC8" => "\xEB\xA4\x99", + "\x8F\xC9" => "\xEB\xA4\x9A", + "\x8F\xCA" => "\xEB\xA4\x9B", + "\x8F\xCB" => "\xEB\xA4\x9C", + "\x8F\xCC" => "\xEB\xA4\x9D", + "\x8F\xCD" => "\xEB\xA4\x9E", + "\x8F\xCE" => "\xEB\xA4\x9F", + "\x8F\xCF" => "\xEB\xA4\xA1", + "\x8F\xD0" => "\xEB\xA4\xA2", + "\x8F\xD1" => "\xEB\xA4\xA3", + "\x8F\xD2" => "\xEB\xA4\xA4", + "\x8F\xD3" => "\xEB\xA4\xA5", + "\x8F\xD4" => "\xEB\xA4\xA6", + "\x8F\xD5" => "\xEB\xA4\xA7", + "\x8F\xD6" => "\xEB\xA4\xA8", + "\x8F\xD7" => "\xEB\xA4\xA9", + "\x8F\xD8" => "\xEB\xA4\xAA", + "\x8F\xD9" => "\xEB\xA4\xAB", + "\x8F\xDA" => "\xEB\xA4\xAC", + "\x8F\xDB" => "\xEB\xA4\xAD", + "\x8F\xDC" => "\xEB\xA4\xAE", + "\x8F\xDD" => "\xEB\xA4\xAF", + "\x8F\xDE" => "\xEB\xA4\xB0", + "\x8F\xDF" => "\xEB\xA4\xB1", + "\x8F\xE0" => "\xEB\xA4\xB2", + "\x8F\xE1" => "\xEB\xA4\xB3", + "\x8F\xE2" => "\xEB\xA4\xB4", + "\x8F\xE3" => "\xEB\xA4\xB5", + "\x8F\xE4" => "\xEB\xA4\xB6", + "\x8F\xE5" => "\xEB\xA4\xB7", + "\x8F\xE6" => "\xEB\xA4\xB8", + "\x8F\xE7" => "\xEB\xA4\xB9", + "\x8F\xE8" => "\xEB\xA4\xBA", + "\x8F\xE9" => "\xEB\xA4\xBB", + "\x8F\xEA" => "\xEB\xA4\xBE", + "\x8F\xEB" => "\xEB\xA4\xBF", + "\x8F\xEC" => "\xEB\xA5\x81", + "\x8F\xED" => "\xEB\xA5\x82", + "\x8F\xEE" => "\xEB\xA5\x83", + "\x8F\xEF" => "\xEB\xA5\x85", + "\x8F\xF0" => "\xEB\xA5\x86", + "\x8F\xF1" => "\xEB\xA5\x87", + "\x8F\xF2" => "\xEB\xA5\x88", + "\x8F\xF3" => "\xEB\xA5\x89", + "\x8F\xF4" => "\xEB\xA5\x8A", + "\x8F\xF5" => "\xEB\xA5\x8B", + "\x8F\xF6" => "\xEB\xA5\x8D", + "\x8F\xF7" => "\xEB\xA5\x8E", + "\x8F\xF8" => "\xEB\xA5\x90", + "\x8F\xF9" => "\xEB\xA5\x92", + "\x8F\xFA" => "\xEB\xA5\x93", + "\x8F\xFB" => "\xEB\xA5\x94", + "\x8F\xFC" => "\xEB\xA5\x95", + "\x8F\xFD" => "\xEB\xA5\x96", + "\x8F\xFE" => "\xEB\xA5\x97", + "\x90\x41" => "\xEB\xA5\x9A", + "\x90\x42" => "\xEB\xA5\x9B", + "\x90\x43" => "\xEB\xA5\x9D", + "\x90\x44" => "\xEB\xA5\x9E", + "\x90\x45" => "\xEB\xA5\x9F", + "\x90\x46" => "\xEB\xA5\xA1", + "\x90\x47" => "\xEB\xA5\xA2", + "\x90\x48" => "\xEB\xA5\xA3", + "\x90\x49" => "\xEB\xA5\xA4", + "\x90\x4A" => "\xEB\xA5\xA5", + "\x90\x4B" => "\xEB\xA5\xA6", + "\x90\x4C" => "\xEB\xA5\xA7", + "\x90\x4D" => "\xEB\xA5\xAA", + "\x90\x4E" => "\xEB\xA5\xAC", + "\x90\x4F" => "\xEB\xA5\xAE", + "\x90\x50" => "\xEB\xA5\xAF", + "\x90\x51" => "\xEB\xA5\xB0", + "\x90\x52" => "\xEB\xA5\xB1", + "\x90\x53" => "\xEB\xA5\xB2", + "\x90\x54" => "\xEB\xA5\xB3", + "\x90\x55" => "\xEB\xA5\xB6", + "\x90\x56" => "\xEB\xA5\xB7", + "\x90\x57" => "\xEB\xA5\xB9", + "\x90\x58" => "\xEB\xA5\xBA", + "\x90\x59" => "\xEB\xA5\xBB", + "\x90\x5A" => "\xEB\xA5\xBD", + "\x90\x61" => "\xEB\xA5\xBE", + "\x90\x62" => "\xEB\xA5\xBF", + "\x90\x63" => "\xEB\xA6\x80", + "\x90\x64" => "\xEB\xA6\x81", + "\x90\x65" => "\xEB\xA6\x82", + "\x90\x66" => "\xEB\xA6\x83", + "\x90\x67" => "\xEB\xA6\x86", + "\x90\x68" => "\xEB\xA6\x88", + "\x90\x69" => "\xEB\xA6\x8B", + "\x90\x6A" => "\xEB\xA6\x8C", + "\x90\x6B" => "\xEB\xA6\x8F", + "\x90\x6C" => "\xEB\xA6\x90", + "\x90\x6D" => "\xEB\xA6\x91", + "\x90\x6E" => "\xEB\xA6\x92", + "\x90\x6F" => "\xEB\xA6\x93", + "\x90\x70" => "\xEB\xA6\x94", + "\x90\x71" => "\xEB\xA6\x95", + "\x90\x72" => "\xEB\xA6\x96", + "\x90\x73" => "\xEB\xA6\x97", + "\x90\x74" => "\xEB\xA6\x98", + "\x90\x75" => "\xEB\xA6\x99", + "\x90\x76" => "\xEB\xA6\x9A", + "\x90\x77" => "\xEB\xA6\x9B", + "\x90\x78" => "\xEB\xA6\x9C", + "\x90\x79" => "\xEB\xA6\x9D", + "\x90\x7A" => "\xEB\xA6\x9E", + "\x90\x81" => "\xEB\xA6\x9F", + "\x90\x82" => "\xEB\xA6\xA0", + "\x90\x83" => "\xEB\xA6\xA1", + "\x90\x84" => "\xEB\xA6\xA2", + "\x90\x85" => "\xEB\xA6\xA3", + "\x90\x86" => "\xEB\xA6\xA4", + "\x90\x87" => "\xEB\xA6\xA5", + "\x90\x88" => "\xEB\xA6\xA6", + "\x90\x89" => "\xEB\xA6\xA7", + "\x90\x8A" => "\xEB\xA6\xA8", + "\x90\x8B" => "\xEB\xA6\xA9", + "\x90\x8C" => "\xEB\xA6\xAA", + "\x90\x8D" => "\xEB\xA6\xAB", + "\x90\x8E" => "\xEB\xA6\xAE", + "\x90\x8F" => "\xEB\xA6\xAF", + "\x90\x90" => "\xEB\xA6\xB1", + "\x90\x91" => "\xEB\xA6\xB2", + "\x90\x92" => "\xEB\xA6\xB3", + "\x90\x93" => "\xEB\xA6\xB5", + "\x90\x94" => "\xEB\xA6\xB6", + "\x90\x95" => "\xEB\xA6\xB7", + "\x90\x96" => "\xEB\xA6\xB8", + "\x90\x97" => "\xEB\xA6\xB9", + "\x90\x98" => "\xEB\xA6\xBA", + "\x90\x99" => "\xEB\xA6\xBB", + "\x90\x9A" => "\xEB\xA6\xBE", + "\x90\x9B" => "\xEB\xA7\x80", + "\x90\x9C" => "\xEB\xA7\x82", + "\x90\x9D" => "\xEB\xA7\x83", + "\x90\x9E" => "\xEB\xA7\x84", + "\x90\x9F" => "\xEB\xA7\x85", + "\x90\xA0" => "\xEB\xA7\x86", + "\x90\xA1" => "\xEB\xA7\x87", + "\x90\xA2" => "\xEB\xA7\x8A", + "\x90\xA3" => "\xEB\xA7\x8B", + "\x90\xA4" => "\xEB\xA7\x8D", + "\x90\xA5" => "\xEB\xA7\x93", + "\x90\xA6" => "\xEB\xA7\x94", + "\x90\xA7" => "\xEB\xA7\x95", + "\x90\xA8" => "\xEB\xA7\x96", + "\x90\xA9" => "\xEB\xA7\x97", + "\x90\xAA" => "\xEB\xA7\x9A", + "\x90\xAB" => "\xEB\xA7\x9C", + "\x90\xAC" => "\xEB\xA7\x9F", + "\x90\xAD" => "\xEB\xA7\xA0", + "\x90\xAE" => "\xEB\xA7\xA2", + "\x90\xAF" => "\xEB\xA7\xA6", + "\x90\xB0" => "\xEB\xA7\xA7", + "\x90\xB1" => "\xEB\xA7\xA9", + "\x90\xB2" => "\xEB\xA7\xAA", + "\x90\xB3" => "\xEB\xA7\xAB", + "\x90\xB4" => "\xEB\xA7\xAD", + "\x90\xB5" => "\xEB\xA7\xAE", + "\x90\xB6" => "\xEB\xA7\xAF", + "\x90\xB7" => "\xEB\xA7\xB0", + "\x90\xB8" => "\xEB\xA7\xB1", + "\x90\xB9" => "\xEB\xA7\xB2", + "\x90\xBA" => "\xEB\xA7\xB3", + "\x90\xBB" => "\xEB\xA7\xB6", + "\x90\xBC" => "\xEB\xA7\xBB", + "\x90\xBD" => "\xEB\xA7\xBC", + "\x90\xBE" => "\xEB\xA7\xBD", + "\x90\xBF" => "\xEB\xA7\xBE", + "\x90\xC0" => "\xEB\xA7\xBF", + "\x90\xC1" => "\xEB\xA8\x82", + "\x90\xC2" => "\xEB\xA8\x83", + "\x90\xC3" => "\xEB\xA8\x84", + "\x90\xC4" => "\xEB\xA8\x85", + "\x90\xC5" => "\xEB\xA8\x86", + "\x90\xC6" => "\xEB\xA8\x87", + "\x90\xC7" => "\xEB\xA8\x89", + "\x90\xC8" => "\xEB\xA8\x8A", + "\x90\xC9" => "\xEB\xA8\x8B", + "\x90\xCA" => "\xEB\xA8\x8C", + "\x90\xCB" => "\xEB\xA8\x8D", + "\x90\xCC" => "\xEB\xA8\x8E", + "\x90\xCD" => "\xEB\xA8\x8F", + "\x90\xCE" => "\xEB\xA8\x90", + "\x90\xCF" => "\xEB\xA8\x91", + "\x90\xD0" => "\xEB\xA8\x92", + "\x90\xD1" => "\xEB\xA8\x93", + "\x90\xD2" => "\xEB\xA8\x94", + "\x90\xD3" => "\xEB\xA8\x96", + "\x90\xD4" => "\xEB\xA8\x97", + "\x90\xD5" => "\xEB\xA8\x98", + "\x90\xD6" => "\xEB\xA8\x99", + "\x90\xD7" => "\xEB\xA8\x9A", + "\x90\xD8" => "\xEB\xA8\x9B", + "\x90\xD9" => "\xEB\xA8\x9C", + "\x90\xDA" => "\xEB\xA8\x9D", + "\x90\xDB" => "\xEB\xA8\x9E", + "\x90\xDC" => "\xEB\xA8\x9F", + "\x90\xDD" => "\xEB\xA8\xA0", + "\x90\xDE" => "\xEB\xA8\xA1", + "\x90\xDF" => "\xEB\xA8\xA2", + "\x90\xE0" => "\xEB\xA8\xA3", + "\x90\xE1" => "\xEB\xA8\xA4", + "\x90\xE2" => "\xEB\xA8\xA5", + "\x90\xE3" => "\xEB\xA8\xA6", + "\x90\xE4" => "\xEB\xA8\xA7", + "\x90\xE5" => "\xEB\xA8\xA8", + "\x90\xE6" => "\xEB\xA8\xA9", + "\x90\xE7" => "\xEB\xA8\xAA", + "\x90\xE8" => "\xEB\xA8\xAB", + "\x90\xE9" => "\xEB\xA8\xAC", + "\x90\xEA" => "\xEB\xA8\xAD", + "\x90\xEB" => "\xEB\xA8\xAE", + "\x90\xEC" => "\xEB\xA8\xAF", + "\x90\xED" => "\xEB\xA8\xB0", + "\x90\xEE" => "\xEB\xA8\xB1", + "\x90\xEF" => "\xEB\xA8\xB2", + "\x90\xF0" => "\xEB\xA8\xB3", + "\x90\xF1" => "\xEB\xA8\xB4", + "\x90\xF2" => "\xEB\xA8\xB5", + "\x90\xF3" => "\xEB\xA8\xB6", + "\x90\xF4" => "\xEB\xA8\xB7", + "\x90\xF5" => "\xEB\xA8\xBA", + "\x90\xF6" => "\xEB\xA8\xBB", + "\x90\xF7" => "\xEB\xA8\xBD", + "\x90\xF8" => "\xEB\xA8\xBE", + "\x90\xF9" => "\xEB\xA8\xBF", + "\x90\xFA" => "\xEB\xA9\x81", + "\x90\xFB" => "\xEB\xA9\x83", + "\x90\xFC" => "\xEB\xA9\x84", + "\x90\xFD" => "\xEB\xA9\x85", + "\x90\xFE" => "\xEB\xA9\x86", + "\x91\x41" => "\xEB\xA9\x87", + "\x91\x42" => "\xEB\xA9\x8A", + "\x91\x43" => "\xEB\xA9\x8C", + "\x91\x44" => "\xEB\xA9\x8F", + "\x91\x45" => "\xEB\xA9\x90", + "\x91\x46" => "\xEB\xA9\x91", + "\x91\x47" => "\xEB\xA9\x92", + "\x91\x48" => "\xEB\xA9\x96", + "\x91\x49" => "\xEB\xA9\x97", + "\x91\x4A" => "\xEB\xA9\x99", + "\x91\x4B" => "\xEB\xA9\x9A", + "\x91\x4C" => "\xEB\xA9\x9B", + "\x91\x4D" => "\xEB\xA9\x9D", + "\x91\x4E" => "\xEB\xA9\x9E", + "\x91\x4F" => "\xEB\xA9\x9F", + "\x91\x50" => "\xEB\xA9\xA0", + "\x91\x51" => "\xEB\xA9\xA1", + "\x91\x52" => "\xEB\xA9\xA2", + "\x91\x53" => "\xEB\xA9\xA3", + "\x91\x54" => "\xEB\xA9\xA6", + "\x91\x55" => "\xEB\xA9\xAA", + "\x91\x56" => "\xEB\xA9\xAB", + "\x91\x57" => "\xEB\xA9\xAC", + "\x91\x58" => "\xEB\xA9\xAD", + "\x91\x59" => "\xEB\xA9\xAE", + "\x91\x5A" => "\xEB\xA9\xAF", + "\x91\x61" => "\xEB\xA9\xB2", + "\x91\x62" => "\xEB\xA9\xB3", + "\x91\x63" => "\xEB\xA9\xB5", + "\x91\x64" => "\xEB\xA9\xB6", + "\x91\x65" => "\xEB\xA9\xB7", + "\x91\x66" => "\xEB\xA9\xB9", + "\x91\x67" => "\xEB\xA9\xBA", + "\x91\x68" => "\xEB\xA9\xBB", + "\x91\x69" => "\xEB\xA9\xBC", + "\x91\x6A" => "\xEB\xA9\xBD", + "\x91\x6B" => "\xEB\xA9\xBE", + "\x91\x6C" => "\xEB\xA9\xBF", + "\x91\x6D" => "\xEB\xAA\x80", + "\x91\x6E" => "\xEB\xAA\x81", + "\x91\x6F" => "\xEB\xAA\x82", + "\x91\x70" => "\xEB\xAA\x86", + "\x91\x71" => "\xEB\xAA\x88", + "\x91\x72" => "\xEB\xAA\x89", + "\x91\x73" => "\xEB\xAA\x8A", + "\x91\x74" => "\xEB\xAA\x8B", + "\x91\x75" => "\xEB\xAA\x8D", + "\x91\x76" => "\xEB\xAA\x8E", + "\x91\x77" => "\xEB\xAA\x8F", + "\x91\x78" => "\xEB\xAA\x90", + "\x91\x79" => "\xEB\xAA\x91", + "\x91\x7A" => "\xEB\xAA\x92", + "\x91\x81" => "\xEB\xAA\x93", + "\x91\x82" => "\xEB\xAA\x94", + "\x91\x83" => "\xEB\xAA\x95", + "\x91\x84" => "\xEB\xAA\x96", + "\x91\x85" => "\xEB\xAA\x97", + "\x91\x86" => "\xEB\xAA\x98", + "\x91\x87" => "\xEB\xAA\x99", + "\x91\x88" => "\xEB\xAA\x9A", + "\x91\x89" => "\xEB\xAA\x9B", + "\x91\x8A" => "\xEB\xAA\x9C", + "\x91\x8B" => "\xEB\xAA\x9D", + "\x91\x8C" => "\xEB\xAA\x9E", + "\x91\x8D" => "\xEB\xAA\x9F", + "\x91\x8E" => "\xEB\xAA\xA0", + "\x91\x8F" => "\xEB\xAA\xA1", + "\x91\x90" => "\xEB\xAA\xA2", + "\x91\x91" => "\xEB\xAA\xA3", + "\x91\x92" => "\xEB\xAA\xA4", + "\x91\x93" => "\xEB\xAA\xA5", + "\x91\x94" => "\xEB\xAA\xA6", + "\x91\x95" => "\xEB\xAA\xA7", + "\x91\x96" => "\xEB\xAA\xAA", + "\x91\x97" => "\xEB\xAA\xAD", + "\x91\x98" => "\xEB\xAA\xAE", + "\x91\x99" => "\xEB\xAA\xAF", + "\x91\x9A" => "\xEB\xAA\xB1", + "\x91\x9B" => "\xEB\xAA\xB3", + "\x91\x9C" => "\xEB\xAA\xB4", + "\x91\x9D" => "\xEB\xAA\xB5", + "\x91\x9E" => "\xEB\xAA\xB6", + "\x91\x9F" => "\xEB\xAA\xB7", + "\x91\xA0" => "\xEB\xAA\xBA", + "\x91\xA1" => "\xEB\xAA\xBC", + "\x91\xA2" => "\xEB\xAA\xBE", + "\x91\xA3" => "\xEB\xAA\xBF", + "\x91\xA4" => "\xEB\xAB\x80", + "\x91\xA5" => "\xEB\xAB\x81", + "\x91\xA6" => "\xEB\xAB\x82", + "\x91\xA7" => "\xEB\xAB\x83", + "\x91\xA8" => "\xEB\xAB\x85", + "\x91\xA9" => "\xEB\xAB\x86", + "\x91\xAA" => "\xEB\xAB\x87", + "\x91\xAB" => "\xEB\xAB\x89", + "\x91\xAC" => "\xEB\xAB\x8A", + "\x91\xAD" => "\xEB\xAB\x8B", + "\x91\xAE" => "\xEB\xAB\x8C", + "\x91\xAF" => "\xEB\xAB\x8D", + "\x91\xB0" => "\xEB\xAB\x8E", + "\x91\xB1" => "\xEB\xAB\x8F", + "\x91\xB2" => "\xEB\xAB\x90", + "\x91\xB3" => "\xEB\xAB\x91", + "\x91\xB4" => "\xEB\xAB\x92", + "\x91\xB5" => "\xEB\xAB\x93", + "\x91\xB6" => "\xEB\xAB\x94", + "\x91\xB7" => "\xEB\xAB\x95", + "\x91\xB8" => "\xEB\xAB\x96", + "\x91\xB9" => "\xEB\xAB\x97", + "\x91\xBA" => "\xEB\xAB\x9A", + "\x91\xBB" => "\xEB\xAB\x9B", + "\x91\xBC" => "\xEB\xAB\x9C", + "\x91\xBD" => "\xEB\xAB\x9D", + "\x91\xBE" => "\xEB\xAB\x9E", + "\x91\xBF" => "\xEB\xAB\x9F", + "\x91\xC0" => "\xEB\xAB\xA0", + "\x91\xC1" => "\xEB\xAB\xA1", + "\x91\xC2" => "\xEB\xAB\xA2", + "\x91\xC3" => "\xEB\xAB\xA3", + "\x91\xC4" => "\xEB\xAB\xA4", + "\x91\xC5" => "\xEB\xAB\xA5", + "\x91\xC6" => "\xEB\xAB\xA6", + "\x91\xC7" => "\xEB\xAB\xA7", + "\x91\xC8" => "\xEB\xAB\xA8", + "\x91\xC9" => "\xEB\xAB\xA9", + "\x91\xCA" => "\xEB\xAB\xAA", + "\x91\xCB" => "\xEB\xAB\xAB", + "\x91\xCC" => "\xEB\xAB\xAC", + "\x91\xCD" => "\xEB\xAB\xAD", + "\x91\xCE" => "\xEB\xAB\xAE", + "\x91\xCF" => "\xEB\xAB\xAF", + "\x91\xD0" => "\xEB\xAB\xB0", + "\x91\xD1" => "\xEB\xAB\xB1", + "\x91\xD2" => "\xEB\xAB\xB2", + "\x91\xD3" => "\xEB\xAB\xB3", + "\x91\xD4" => "\xEB\xAB\xB4", + "\x91\xD5" => "\xEB\xAB\xB5", + "\x91\xD6" => "\xEB\xAB\xB6", + "\x91\xD7" => "\xEB\xAB\xB7", + "\x91\xD8" => "\xEB\xAB\xB8", + "\x91\xD9" => "\xEB\xAB\xB9", + "\x91\xDA" => "\xEB\xAB\xBA", + "\x91\xDB" => "\xEB\xAB\xBB", + "\x91\xDC" => "\xEB\xAB\xBD", + "\x91\xDD" => "\xEB\xAB\xBE", + "\x91\xDE" => "\xEB\xAB\xBF", + "\x91\xDF" => "\xEB\xAC\x81", + "\x91\xE0" => "\xEB\xAC\x82", + "\x91\xE1" => "\xEB\xAC\x83", + "\x91\xE2" => "\xEB\xAC\x85", + "\x91\xE3" => "\xEB\xAC\x86", + "\x91\xE4" => "\xEB\xAC\x87", + "\x91\xE5" => "\xEB\xAC\x88", + "\x91\xE6" => "\xEB\xAC\x89", + "\x91\xE7" => "\xEB\xAC\x8A", + "\x91\xE8" => "\xEB\xAC\x8B", + "\x91\xE9" => "\xEB\xAC\x8C", + "\x91\xEA" => "\xEB\xAC\x8E", + "\x91\xEB" => "\xEB\xAC\x90", + "\x91\xEC" => "\xEB\xAC\x92", + "\x91\xED" => "\xEB\xAC\x93", + "\x91\xEE" => "\xEB\xAC\x94", + "\x91\xEF" => "\xEB\xAC\x95", + "\x91\xF0" => "\xEB\xAC\x96", + "\x91\xF1" => "\xEB\xAC\x97", + "\x91\xF2" => "\xEB\xAC\x99", + "\x91\xF3" => "\xEB\xAC\x9A", + "\x91\xF4" => "\xEB\xAC\x9B", + "\x91\xF5" => "\xEB\xAC\x9D", + "\x91\xF6" => "\xEB\xAC\x9E", + "\x91\xF7" => "\xEB\xAC\x9F", + "\x91\xF8" => "\xEB\xAC\xA1", + "\x91\xF9" => "\xEB\xAC\xA2", + "\x91\xFA" => "\xEB\xAC\xA3", + "\x91\xFB" => "\xEB\xAC\xA4", + "\x91\xFC" => "\xEB\xAC\xA5", + "\x91\xFD" => "\xEB\xAC\xA6", + "\x91\xFE" => "\xEB\xAC\xA7", + "\x92\x41" => "\xEB\xAC\xA8", + "\x92\x42" => "\xEB\xAC\xAA", + "\x92\x43" => "\xEB\xAC\xAC", + "\x92\x44" => "\xEB\xAC\xAD", + "\x92\x45" => "\xEB\xAC\xAE", + "\x92\x46" => "\xEB\xAC\xAF", + "\x92\x47" => "\xEB\xAC\xB0", + "\x92\x48" => "\xEB\xAC\xB1", + "\x92\x49" => "\xEB\xAC\xB2", + "\x92\x4A" => "\xEB\xAC\xB3", + "\x92\x4B" => "\xEB\xAC\xB7", + "\x92\x4C" => "\xEB\xAC\xB9", + "\x92\x4D" => "\xEB\xAC\xBA", + "\x92\x4E" => "\xEB\xAC\xBF", + "\x92\x4F" => "\xEB\xAD\x80", + "\x92\x50" => "\xEB\xAD\x81", + "\x92\x51" => "\xEB\xAD\x82", + "\x92\x52" => "\xEB\xAD\x83", + "\x92\x53" => "\xEB\xAD\x86", + "\x92\x54" => "\xEB\xAD\x88", + "\x92\x55" => "\xEB\xAD\x8A", + "\x92\x56" => "\xEB\xAD\x8B", + "\x92\x57" => "\xEB\xAD\x8C", + "\x92\x58" => "\xEB\xAD\x8E", + "\x92\x59" => "\xEB\xAD\x91", + "\x92\x5A" => "\xEB\xAD\x92", + "\x92\x61" => "\xEB\xAD\x93", + "\x92\x62" => "\xEB\xAD\x95", + "\x92\x63" => "\xEB\xAD\x96", + "\x92\x64" => "\xEB\xAD\x97", + "\x92\x65" => "\xEB\xAD\x99", + "\x92\x66" => "\xEB\xAD\x9A", + "\x92\x67" => "\xEB\xAD\x9B", + "\x92\x68" => "\xEB\xAD\x9C", + "\x92\x69" => "\xEB\xAD\x9D", + "\x92\x6A" => "\xEB\xAD\x9E", + "\x92\x6B" => "\xEB\xAD\x9F", + "\x92\x6C" => "\xEB\xAD\xA0", + "\x92\x6D" => "\xEB\xAD\xA2", + "\x92\x6E" => "\xEB\xAD\xA4", + "\x92\x6F" => "\xEB\xAD\xA5", + "\x92\x70" => "\xEB\xAD\xA6", + "\x92\x71" => "\xEB\xAD\xA7", + "\x92\x72" => "\xEB\xAD\xA8", + "\x92\x73" => "\xEB\xAD\xA9", + "\x92\x74" => "\xEB\xAD\xAA", + "\x92\x75" => "\xEB\xAD\xAB", + "\x92\x76" => "\xEB\xAD\xAD", + "\x92\x77" => "\xEB\xAD\xAE", + "\x92\x78" => "\xEB\xAD\xAF", + "\x92\x79" => "\xEB\xAD\xB0", + "\x92\x7A" => "\xEB\xAD\xB1", + "\x92\x81" => "\xEB\xAD\xB2", + "\x92\x82" => "\xEB\xAD\xB3", + "\x92\x83" => "\xEB\xAD\xB4", + "\x92\x84" => "\xEB\xAD\xB5", + "\x92\x85" => "\xEB\xAD\xB6", + "\x92\x86" => "\xEB\xAD\xB7", + "\x92\x87" => "\xEB\xAD\xB8", + "\x92\x88" => "\xEB\xAD\xB9", + "\x92\x89" => "\xEB\xAD\xBA", + "\x92\x8A" => "\xEB\xAD\xBB", + "\x92\x8B" => "\xEB\xAD\xBC", + "\x92\x8C" => "\xEB\xAD\xBD", + "\x92\x8D" => "\xEB\xAD\xBE", + "\x92\x8E" => "\xEB\xAD\xBF", + "\x92\x8F" => "\xEB\xAE\x80", + "\x92\x90" => "\xEB\xAE\x81", + "\x92\x91" => "\xEB\xAE\x82", + "\x92\x92" => "\xEB\xAE\x83", + "\x92\x93" => "\xEB\xAE\x84", + "\x92\x94" => "\xEB\xAE\x85", + "\x92\x95" => "\xEB\xAE\x86", + "\x92\x96" => "\xEB\xAE\x87", + "\x92\x97" => "\xEB\xAE\x89", + "\x92\x98" => "\xEB\xAE\x8A", + "\x92\x99" => "\xEB\xAE\x8B", + "\x92\x9A" => "\xEB\xAE\x8D", + "\x92\x9B" => "\xEB\xAE\x8E", + "\x92\x9C" => "\xEB\xAE\x8F", + "\x92\x9D" => "\xEB\xAE\x91", + "\x92\x9E" => "\xEB\xAE\x92", + "\x92\x9F" => "\xEB\xAE\x93", + "\x92\xA0" => "\xEB\xAE\x94", + "\x92\xA1" => "\xEB\xAE\x95", + "\x92\xA2" => "\xEB\xAE\x96", + "\x92\xA3" => "\xEB\xAE\x97", + "\x92\xA4" => "\xEB\xAE\x98", + "\x92\xA5" => "\xEB\xAE\x99", + "\x92\xA6" => "\xEB\xAE\x9A", + "\x92\xA7" => "\xEB\xAE\x9B", + "\x92\xA8" => "\xEB\xAE\x9C", + "\x92\xA9" => "\xEB\xAE\x9D", + "\x92\xAA" => "\xEB\xAE\x9E", + "\x92\xAB" => "\xEB\xAE\x9F", + "\x92\xAC" => "\xEB\xAE\xA0", + "\x92\xAD" => "\xEB\xAE\xA1", + "\x92\xAE" => "\xEB\xAE\xA2", + "\x92\xAF" => "\xEB\xAE\xA3", + "\x92\xB0" => "\xEB\xAE\xA5", + "\x92\xB1" => "\xEB\xAE\xA6", + "\x92\xB2" => "\xEB\xAE\xA7", + "\x92\xB3" => "\xEB\xAE\xA9", + "\x92\xB4" => "\xEB\xAE\xAA", + "\x92\xB5" => "\xEB\xAE\xAB", + "\x92\xB6" => "\xEB\xAE\xAD", + "\x92\xB7" => "\xEB\xAE\xAE", + "\x92\xB8" => "\xEB\xAE\xAF", + "\x92\xB9" => "\xEB\xAE\xB0", + "\x92\xBA" => "\xEB\xAE\xB1", + "\x92\xBB" => "\xEB\xAE\xB2", + "\x92\xBC" => "\xEB\xAE\xB3", + "\x92\xBD" => "\xEB\xAE\xB5", + "\x92\xBE" => "\xEB\xAE\xB6", + "\x92\xBF" => "\xEB\xAE\xB8", + "\x92\xC0" => "\xEB\xAE\xB9", + "\x92\xC1" => "\xEB\xAE\xBA", + "\x92\xC2" => "\xEB\xAE\xBB", + "\x92\xC3" => "\xEB\xAE\xBC", + "\x92\xC4" => "\xEB\xAE\xBD", + "\x92\xC5" => "\xEB\xAE\xBE", + "\x92\xC6" => "\xEB\xAE\xBF", + "\x92\xC7" => "\xEB\xAF\x81", + "\x92\xC8" => "\xEB\xAF\x82", + "\x92\xC9" => "\xEB\xAF\x83", + "\x92\xCA" => "\xEB\xAF\x85", + "\x92\xCB" => "\xEB\xAF\x86", + "\x92\xCC" => "\xEB\xAF\x87", + "\x92\xCD" => "\xEB\xAF\x89", + "\x92\xCE" => "\xEB\xAF\x8A", + "\x92\xCF" => "\xEB\xAF\x8B", + "\x92\xD0" => "\xEB\xAF\x8C", + "\x92\xD1" => "\xEB\xAF\x8D", + "\x92\xD2" => "\xEB\xAF\x8E", + "\x92\xD3" => "\xEB\xAF\x8F", + "\x92\xD4" => "\xEB\xAF\x91", + "\x92\xD5" => "\xEB\xAF\x92", + "\x92\xD6" => "\xEB\xAF\x94", + "\x92\xD7" => "\xEB\xAF\x95", + "\x92\xD8" => "\xEB\xAF\x96", + "\x92\xD9" => "\xEB\xAF\x97", + "\x92\xDA" => "\xEB\xAF\x98", + "\x92\xDB" => "\xEB\xAF\x99", + "\x92\xDC" => "\xEB\xAF\x9A", + "\x92\xDD" => "\xEB\xAF\x9B", + "\x92\xDE" => "\xEB\xAF\x9C", + "\x92\xDF" => "\xEB\xAF\x9D", + "\x92\xE0" => "\xEB\xAF\x9E", + "\x92\xE1" => "\xEB\xAF\x9F", + "\x92\xE2" => "\xEB\xAF\xA0", + "\x92\xE3" => "\xEB\xAF\xA1", + "\x92\xE4" => "\xEB\xAF\xA2", + "\x92\xE5" => "\xEB\xAF\xA3", + "\x92\xE6" => "\xEB\xAF\xA4", + "\x92\xE7" => "\xEB\xAF\xA5", + "\x92\xE8" => "\xEB\xAF\xA6", + "\x92\xE9" => "\xEB\xAF\xA7", + "\x92\xEA" => "\xEB\xAF\xA8", + "\x92\xEB" => "\xEB\xAF\xA9", + "\x92\xEC" => "\xEB\xAF\xAA", + "\x92\xED" => "\xEB\xAF\xAB", + "\x92\xEE" => "\xEB\xAF\xAC", + "\x92\xEF" => "\xEB\xAF\xAD", + "\x92\xF0" => "\xEB\xAF\xAE", + "\x92\xF1" => "\xEB\xAF\xAF", + "\x92\xF2" => "\xEB\xAF\xB0", + "\x92\xF3" => "\xEB\xAF\xB1", + "\x92\xF4" => "\xEB\xAF\xB2", + "\x92\xF5" => "\xEB\xAF\xB3", + "\x92\xF6" => "\xEB\xAF\xB4", + "\x92\xF7" => "\xEB\xAF\xB5", + "\x92\xF8" => "\xEB\xAF\xB6", + "\x92\xF9" => "\xEB\xAF\xB7", + "\x92\xFA" => "\xEB\xAF\xBA", + "\x92\xFB" => "\xEB\xAF\xBB", + "\x92\xFC" => "\xEB\xAF\xBD", + "\x92\xFD" => "\xEB\xAF\xBE", + "\x92\xFE" => "\xEB\xB0\x81", + "\x93\x41" => "\xEB\xB0\x83", + "\x93\x42" => "\xEB\xB0\x84", + "\x93\x43" => "\xEB\xB0\x85", + "\x93\x44" => "\xEB\xB0\x86", + "\x93\x45" => "\xEB\xB0\x87", + "\x93\x46" => "\xEB\xB0\x8A", + "\x93\x47" => "\xEB\xB0\x8E", + "\x93\x48" => "\xEB\xB0\x90", + "\x93\x49" => "\xEB\xB0\x92", + "\x93\x4A" => "\xEB\xB0\x93", + "\x93\x4B" => "\xEB\xB0\x99", + "\x93\x4C" => "\xEB\xB0\x9A", + "\x93\x4D" => "\xEB\xB0\xA0", + "\x93\x4E" => "\xEB\xB0\xA1", + "\x93\x4F" => "\xEB\xB0\xA2", + "\x93\x50" => "\xEB\xB0\xA3", + "\x93\x51" => "\xEB\xB0\xA6", + "\x93\x52" => "\xEB\xB0\xA8", + "\x93\x53" => "\xEB\xB0\xAA", + "\x93\x54" => "\xEB\xB0\xAB", + "\x93\x55" => "\xEB\xB0\xAC", + "\x93\x56" => "\xEB\xB0\xAE", + "\x93\x57" => "\xEB\xB0\xAF", + "\x93\x58" => "\xEB\xB0\xB2", + "\x93\x59" => "\xEB\xB0\xB3", + "\x93\x5A" => "\xEB\xB0\xB5", + "\x93\x61" => "\xEB\xB0\xB6", + "\x93\x62" => "\xEB\xB0\xB7", + "\x93\x63" => "\xEB\xB0\xB9", + "\x93\x64" => "\xEB\xB0\xBA", + "\x93\x65" => "\xEB\xB0\xBB", + "\x93\x66" => "\xEB\xB0\xBC", + "\x93\x67" => "\xEB\xB0\xBD", + "\x93\x68" => "\xEB\xB0\xBE", + "\x93\x69" => "\xEB\xB0\xBF", + "\x93\x6A" => "\xEB\xB1\x82", + "\x93\x6B" => "\xEB\xB1\x86", + "\x93\x6C" => "\xEB\xB1\x87", + "\x93\x6D" => "\xEB\xB1\x88", + "\x93\x6E" => "\xEB\xB1\x8A", + "\x93\x6F" => "\xEB\xB1\x8B", + "\x93\x70" => "\xEB\xB1\x8E", + "\x93\x71" => "\xEB\xB1\x8F", + "\x93\x72" => "\xEB\xB1\x91", + "\x93\x73" => "\xEB\xB1\x92", + "\x93\x74" => "\xEB\xB1\x93", + "\x93\x75" => "\xEB\xB1\x94", + "\x93\x76" => "\xEB\xB1\x95", + "\x93\x77" => "\xEB\xB1\x96", + "\x93\x78" => "\xEB\xB1\x97", + "\x93\x79" => "\xEB\xB1\x98", + "\x93\x7A" => "\xEB\xB1\x99", + "\x93\x81" => "\xEB\xB1\x9A", + "\x93\x82" => "\xEB\xB1\x9B", + "\x93\x83" => "\xEB\xB1\x9C", + "\x93\x84" => "\xEB\xB1\x9E", + "\x93\x85" => "\xEB\xB1\x9F", + "\x93\x86" => "\xEB\xB1\xA0", + "\x93\x87" => "\xEB\xB1\xA1", + "\x93\x88" => "\xEB\xB1\xA2", + "\x93\x89" => "\xEB\xB1\xA3", + "\x93\x8A" => "\xEB\xB1\xA4", + "\x93\x8B" => "\xEB\xB1\xA5", + "\x93\x8C" => "\xEB\xB1\xA6", + "\x93\x8D" => "\xEB\xB1\xA7", + "\x93\x8E" => "\xEB\xB1\xA8", + "\x93\x8F" => "\xEB\xB1\xA9", + "\x93\x90" => "\xEB\xB1\xAA", + "\x93\x91" => "\xEB\xB1\xAB", + "\x93\x92" => "\xEB\xB1\xAC", + "\x93\x93" => "\xEB\xB1\xAD", + "\x93\x94" => "\xEB\xB1\xAE", + "\x93\x95" => "\xEB\xB1\xAF", + "\x93\x96" => "\xEB\xB1\xB0", + "\x93\x97" => "\xEB\xB1\xB1", + "\x93\x98" => "\xEB\xB1\xB2", + "\x93\x99" => "\xEB\xB1\xB3", + "\x93\x9A" => "\xEB\xB1\xB4", + "\x93\x9B" => "\xEB\xB1\xB5", + "\x93\x9C" => "\xEB\xB1\xB6", + "\x93\x9D" => "\xEB\xB1\xB7", + "\x93\x9E" => "\xEB\xB1\xB8", + "\x93\x9F" => "\xEB\xB1\xB9", + "\x93\xA0" => "\xEB\xB1\xBA", + "\x93\xA1" => "\xEB\xB1\xBB", + "\x93\xA2" => "\xEB\xB1\xBC", + "\x93\xA3" => "\xEB\xB1\xBD", + "\x93\xA4" => "\xEB\xB1\xBE", + "\x93\xA5" => "\xEB\xB1\xBF", + "\x93\xA6" => "\xEB\xB2\x80", + "\x93\xA7" => "\xEB\xB2\x81", + "\x93\xA8" => "\xEB\xB2\x82", + "\x93\xA9" => "\xEB\xB2\x83", + "\x93\xAA" => "\xEB\xB2\x86", + "\x93\xAB" => "\xEB\xB2\x87", + "\x93\xAC" => "\xEB\xB2\x89", + "\x93\xAD" => "\xEB\xB2\x8A", + "\x93\xAE" => "\xEB\xB2\x8D", + "\x93\xAF" => "\xEB\xB2\x8F", + "\x93\xB0" => "\xEB\xB2\x90", + "\x93\xB1" => "\xEB\xB2\x91", + "\x93\xB2" => "\xEB\xB2\x92", + "\x93\xB3" => "\xEB\xB2\x93", + "\x93\xB4" => "\xEB\xB2\x96", + "\x93\xB5" => "\xEB\xB2\x98", + "\x93\xB6" => "\xEB\xB2\x9B", + "\x93\xB7" => "\xEB\xB2\x9C", + "\x93\xB8" => "\xEB\xB2\x9D", + "\x93\xB9" => "\xEB\xB2\x9E", + "\x93\xBA" => "\xEB\xB2\x9F", + "\x93\xBB" => "\xEB\xB2\xA2", + "\x93\xBC" => "\xEB\xB2\xA3", + "\x93\xBD" => "\xEB\xB2\xA5", + "\x93\xBE" => "\xEB\xB2\xA6", + "\x93\xBF" => "\xEB\xB2\xA9", + "\x93\xC0" => "\xEB\xB2\xAA", + "\x93\xC1" => "\xEB\xB2\xAB", + "\x93\xC2" => "\xEB\xB2\xAC", + "\x93\xC3" => "\xEB\xB2\xAD", + "\x93\xC4" => "\xEB\xB2\xAE", + "\x93\xC5" => "\xEB\xB2\xAF", + "\x93\xC6" => "\xEB\xB2\xB2", + "\x93\xC7" => "\xEB\xB2\xB6", + "\x93\xC8" => "\xEB\xB2\xB7", + "\x93\xC9" => "\xEB\xB2\xB8", + "\x93\xCA" => "\xEB\xB2\xB9", + "\x93\xCB" => "\xEB\xB2\xBA", + "\x93\xCC" => "\xEB\xB2\xBB", + "\x93\xCD" => "\xEB\xB2\xBE", + "\x93\xCE" => "\xEB\xB2\xBF", + "\x93\xCF" => "\xEB\xB3\x81", + "\x93\xD0" => "\xEB\xB3\x82", + "\x93\xD1" => "\xEB\xB3\x83", + "\x93\xD2" => "\xEB\xB3\x85", + "\x93\xD3" => "\xEB\xB3\x86", + "\x93\xD4" => "\xEB\xB3\x87", + "\x93\xD5" => "\xEB\xB3\x88", + "\x93\xD6" => "\xEB\xB3\x89", + "\x93\xD7" => "\xEB\xB3\x8A", + "\x93\xD8" => "\xEB\xB3\x8B", + "\x93\xD9" => "\xEB\xB3\x8C", + "\x93\xDA" => "\xEB\xB3\x8E", + "\x93\xDB" => "\xEB\xB3\x92", + "\x93\xDC" => "\xEB\xB3\x93", + "\x93\xDD" => "\xEB\xB3\x94", + "\x93\xDE" => "\xEB\xB3\x96", + "\x93\xDF" => "\xEB\xB3\x97", + "\x93\xE0" => "\xEB\xB3\x99", + "\x93\xE1" => "\xEB\xB3\x9A", + "\x93\xE2" => "\xEB\xB3\x9B", + "\x93\xE3" => "\xEB\xB3\x9D", + "\x93\xE4" => "\xEB\xB3\x9E", + "\x93\xE5" => "\xEB\xB3\x9F", + "\x93\xE6" => "\xEB\xB3\xA0", + "\x93\xE7" => "\xEB\xB3\xA1", + "\x93\xE8" => "\xEB\xB3\xA2", + "\x93\xE9" => "\xEB\xB3\xA3", + "\x93\xEA" => "\xEB\xB3\xA4", + "\x93\xEB" => "\xEB\xB3\xA5", + "\x93\xEC" => "\xEB\xB3\xA6", + "\x93\xED" => "\xEB\xB3\xA7", + "\x93\xEE" => "\xEB\xB3\xA8", + "\x93\xEF" => "\xEB\xB3\xA9", + "\x93\xF0" => "\xEB\xB3\xAA", + "\x93\xF1" => "\xEB\xB3\xAB", + "\x93\xF2" => "\xEB\xB3\xAC", + "\x93\xF3" => "\xEB\xB3\xAD", + "\x93\xF4" => "\xEB\xB3\xAE", + "\x93\xF5" => "\xEB\xB3\xAF", + "\x93\xF6" => "\xEB\xB3\xB0", + "\x93\xF7" => "\xEB\xB3\xB1", + "\x93\xF8" => "\xEB\xB3\xB2", + "\x93\xF9" => "\xEB\xB3\xB3", + "\x93\xFA" => "\xEB\xB3\xB7", + "\x93\xFB" => "\xEB\xB3\xB9", + "\x93\xFC" => "\xEB\xB3\xBA", + "\x93\xFD" => "\xEB\xB3\xBB", + "\x93\xFE" => "\xEB\xB3\xBD", + "\x94\x41" => "\xEB\xB3\xBE", + "\x94\x42" => "\xEB\xB3\xBF", + "\x94\x43" => "\xEB\xB4\x80", + "\x94\x44" => "\xEB\xB4\x81", + "\x94\x45" => "\xEB\xB4\x82", + "\x94\x46" => "\xEB\xB4\x83", + "\x94\x47" => "\xEB\xB4\x86", + "\x94\x48" => "\xEB\xB4\x88", + "\x94\x49" => "\xEB\xB4\x8A", + "\x94\x4A" => "\xEB\xB4\x8B", + "\x94\x4B" => "\xEB\xB4\x8C", + "\x94\x4C" => "\xEB\xB4\x8D", + "\x94\x4D" => "\xEB\xB4\x8E", + "\x94\x4E" => "\xEB\xB4\x8F", + "\x94\x4F" => "\xEB\xB4\x91", + "\x94\x50" => "\xEB\xB4\x92", + "\x94\x51" => "\xEB\xB4\x93", + "\x94\x52" => "\xEB\xB4\x95", + "\x94\x53" => "\xEB\xB4\x96", + "\x94\x54" => "\xEB\xB4\x97", + "\x94\x55" => "\xEB\xB4\x98", + "\x94\x56" => "\xEB\xB4\x99", + "\x94\x57" => "\xEB\xB4\x9A", + "\x94\x58" => "\xEB\xB4\x9B", + "\x94\x59" => "\xEB\xB4\x9C", + "\x94\x5A" => "\xEB\xB4\x9D", + "\x94\x61" => "\xEB\xB4\x9E", + "\x94\x62" => "\xEB\xB4\x9F", + "\x94\x63" => "\xEB\xB4\xA0", + "\x94\x64" => "\xEB\xB4\xA1", + "\x94\x65" => "\xEB\xB4\xA2", + "\x94\x66" => "\xEB\xB4\xA3", + "\x94\x67" => "\xEB\xB4\xA5", + "\x94\x68" => "\xEB\xB4\xA6", + "\x94\x69" => "\xEB\xB4\xA7", + "\x94\x6A" => "\xEB\xB4\xA8", + "\x94\x6B" => "\xEB\xB4\xA9", + "\x94\x6C" => "\xEB\xB4\xAA", + "\x94\x6D" => "\xEB\xB4\xAB", + "\x94\x6E" => "\xEB\xB4\xAD", + "\x94\x6F" => "\xEB\xB4\xAE", + "\x94\x70" => "\xEB\xB4\xAF", + "\x94\x71" => "\xEB\xB4\xB0", + "\x94\x72" => "\xEB\xB4\xB1", + "\x94\x73" => "\xEB\xB4\xB2", + "\x94\x74" => "\xEB\xB4\xB3", + "\x94\x75" => "\xEB\xB4\xB4", + "\x94\x76" => "\xEB\xB4\xB5", + "\x94\x77" => "\xEB\xB4\xB6", + "\x94\x78" => "\xEB\xB4\xB7", + "\x94\x79" => "\xEB\xB4\xB8", + "\x94\x7A" => "\xEB\xB4\xB9", + "\x94\x81" => "\xEB\xB4\xBA", + "\x94\x82" => "\xEB\xB4\xBB", + "\x94\x83" => "\xEB\xB4\xBC", + "\x94\x84" => "\xEB\xB4\xBD", + "\x94\x85" => "\xEB\xB4\xBE", + "\x94\x86" => "\xEB\xB4\xBF", + "\x94\x87" => "\xEB\xB5\x81", + "\x94\x88" => "\xEB\xB5\x82", + "\x94\x89" => "\xEB\xB5\x83", + "\x94\x8A" => "\xEB\xB5\x84", + "\x94\x8B" => "\xEB\xB5\x85", + "\x94\x8C" => "\xEB\xB5\x86", + "\x94\x8D" => "\xEB\xB5\x87", + "\x94\x8E" => "\xEB\xB5\x8A", + "\x94\x8F" => "\xEB\xB5\x8B", + "\x94\x90" => "\xEB\xB5\x8D", + "\x94\x91" => "\xEB\xB5\x8E", + "\x94\x92" => "\xEB\xB5\x8F", + "\x94\x93" => "\xEB\xB5\x91", + "\x94\x94" => "\xEB\xB5\x92", + "\x94\x95" => "\xEB\xB5\x93", + "\x94\x96" => "\xEB\xB5\x94", + "\x94\x97" => "\xEB\xB5\x95", + "\x94\x98" => "\xEB\xB5\x96", + "\x94\x99" => "\xEB\xB5\x97", + "\x94\x9A" => "\xEB\xB5\x9A", + "\x94\x9B" => "\xEB\xB5\x9B", + "\x94\x9C" => "\xEB\xB5\x9C", + "\x94\x9D" => "\xEB\xB5\x9D", + "\x94\x9E" => "\xEB\xB5\x9E", + "\x94\x9F" => "\xEB\xB5\x9F", + "\x94\xA0" => "\xEB\xB5\xA0", + "\x94\xA1" => "\xEB\xB5\xA1", + "\x94\xA2" => "\xEB\xB5\xA2", + "\x94\xA3" => "\xEB\xB5\xA3", + "\x94\xA4" => "\xEB\xB5\xA5", + "\x94\xA5" => "\xEB\xB5\xA6", + "\x94\xA6" => "\xEB\xB5\xA7", + "\x94\xA7" => "\xEB\xB5\xA9", + "\x94\xA8" => "\xEB\xB5\xAA", + "\x94\xA9" => "\xEB\xB5\xAB", + "\x94\xAA" => "\xEB\xB5\xAC", + "\x94\xAB" => "\xEB\xB5\xAD", + "\x94\xAC" => "\xEB\xB5\xAE", + "\x94\xAD" => "\xEB\xB5\xAF", + "\x94\xAE" => "\xEB\xB5\xB0", + "\x94\xAF" => "\xEB\xB5\xB1", + "\x94\xB0" => "\xEB\xB5\xB2", + "\x94\xB1" => "\xEB\xB5\xB3", + "\x94\xB2" => "\xEB\xB5\xB4", + "\x94\xB3" => "\xEB\xB5\xB5", + "\x94\xB4" => "\xEB\xB5\xB6", + "\x94\xB5" => "\xEB\xB5\xB7", + "\x94\xB6" => "\xEB\xB5\xB8", + "\x94\xB7" => "\xEB\xB5\xB9", + "\x94\xB8" => "\xEB\xB5\xBA", + "\x94\xB9" => "\xEB\xB5\xBB", + "\x94\xBA" => "\xEB\xB5\xBC", + "\x94\xBB" => "\xEB\xB5\xBD", + "\x94\xBC" => "\xEB\xB5\xBE", + "\x94\xBD" => "\xEB\xB5\xBF", + "\x94\xBE" => "\xEB\xB6\x82", + "\x94\xBF" => "\xEB\xB6\x83", + "\x94\xC0" => "\xEB\xB6\x85", + "\x94\xC1" => "\xEB\xB6\x86", + "\x94\xC2" => "\xEB\xB6\x8B", + "\x94\xC3" => "\xEB\xB6\x8C", + "\x94\xC4" => "\xEB\xB6\x8D", + "\x94\xC5" => "\xEB\xB6\x8E", + "\x94\xC6" => "\xEB\xB6\x8F", + "\x94\xC7" => "\xEB\xB6\x92", + "\x94\xC8" => "\xEB\xB6\x94", + "\x94\xC9" => "\xEB\xB6\x96", + "\x94\xCA" => "\xEB\xB6\x97", + "\x94\xCB" => "\xEB\xB6\x98", + "\x94\xCC" => "\xEB\xB6\x9B", + "\x94\xCD" => "\xEB\xB6\x9D", + "\x94\xCE" => "\xEB\xB6\x9E", + "\x94\xCF" => "\xEB\xB6\x9F", + "\x94\xD0" => "\xEB\xB6\xA0", + "\x94\xD1" => "\xEB\xB6\xA1", + "\x94\xD2" => "\xEB\xB6\xA2", + "\x94\xD3" => "\xEB\xB6\xA3", + "\x94\xD4" => "\xEB\xB6\xA5", + "\x94\xD5" => "\xEB\xB6\xA6", + "\x94\xD6" => "\xEB\xB6\xA7", + "\x94\xD7" => "\xEB\xB6\xA8", + "\x94\xD8" => "\xEB\xB6\xA9", + "\x94\xD9" => "\xEB\xB6\xAA", + "\x94\xDA" => "\xEB\xB6\xAB", + "\x94\xDB" => "\xEB\xB6\xAC", + "\x94\xDC" => "\xEB\xB6\xAD", + "\x94\xDD" => "\xEB\xB6\xAE", + "\x94\xDE" => "\xEB\xB6\xAF", + "\x94\xDF" => "\xEB\xB6\xB1", + "\x94\xE0" => "\xEB\xB6\xB2", + "\x94\xE1" => "\xEB\xB6\xB3", + "\x94\xE2" => "\xEB\xB6\xB4", + "\x94\xE3" => "\xEB\xB6\xB5", + "\x94\xE4" => "\xEB\xB6\xB6", + "\x94\xE5" => "\xEB\xB6\xB7", + "\x94\xE6" => "\xEB\xB6\xB9", + "\x94\xE7" => "\xEB\xB6\xBA", + "\x94\xE8" => "\xEB\xB6\xBB", + "\x94\xE9" => "\xEB\xB6\xBC", + "\x94\xEA" => "\xEB\xB6\xBD", + "\x94\xEB" => "\xEB\xB6\xBE", + "\x94\xEC" => "\xEB\xB6\xBF", + "\x94\xED" => "\xEB\xB7\x80", + "\x94\xEE" => "\xEB\xB7\x81", + "\x94\xEF" => "\xEB\xB7\x82", + "\x94\xF0" => "\xEB\xB7\x83", + "\x94\xF1" => "\xEB\xB7\x84", + "\x94\xF2" => "\xEB\xB7\x85", + "\x94\xF3" => "\xEB\xB7\x86", + "\x94\xF4" => "\xEB\xB7\x87", + "\x94\xF5" => "\xEB\xB7\x88", + "\x94\xF6" => "\xEB\xB7\x89", + "\x94\xF7" => "\xEB\xB7\x8A", + "\x94\xF8" => "\xEB\xB7\x8B", + "\x94\xF9" => "\xEB\xB7\x8C", + "\x94\xFA" => "\xEB\xB7\x8D", + "\x94\xFB" => "\xEB\xB7\x8E", + "\x94\xFC" => "\xEB\xB7\x8F", + "\x94\xFD" => "\xEB\xB7\x90", + "\x94\xFE" => "\xEB\xB7\x91", + "\x95\x41" => "\xEB\xB7\x92", + "\x95\x42" => "\xEB\xB7\x93", + "\x95\x43" => "\xEB\xB7\x96", + "\x95\x44" => "\xEB\xB7\x97", + "\x95\x45" => "\xEB\xB7\x99", + "\x95\x46" => "\xEB\xB7\x9A", + "\x95\x47" => "\xEB\xB7\x9B", + "\x95\x48" => "\xEB\xB7\x9D", + "\x95\x49" => "\xEB\xB7\x9E", + "\x95\x4A" => "\xEB\xB7\x9F", + "\x95\x4B" => "\xEB\xB7\xA0", + "\x95\x4C" => "\xEB\xB7\xA1", + "\x95\x4D" => "\xEB\xB7\xA2", + "\x95\x4E" => "\xEB\xB7\xA3", + "\x95\x4F" => "\xEB\xB7\xA4", + "\x95\x50" => "\xEB\xB7\xA5", + "\x95\x51" => "\xEB\xB7\xA6", + "\x95\x52" => "\xEB\xB7\xA7", + "\x95\x53" => "\xEB\xB7\xA8", + "\x95\x54" => "\xEB\xB7\xAA", + "\x95\x55" => "\xEB\xB7\xAB", + "\x95\x56" => "\xEB\xB7\xAC", + "\x95\x57" => "\xEB\xB7\xAD", + "\x95\x58" => "\xEB\xB7\xAE", + "\x95\x59" => "\xEB\xB7\xAF", + "\x95\x5A" => "\xEB\xB7\xB1", + "\x95\x61" => "\xEB\xB7\xB2", + "\x95\x62" => "\xEB\xB7\xB3", + "\x95\x63" => "\xEB\xB7\xB5", + "\x95\x64" => "\xEB\xB7\xB6", + "\x95\x65" => "\xEB\xB7\xB7", + "\x95\x66" => "\xEB\xB7\xB9", + "\x95\x67" => "\xEB\xB7\xBA", + "\x95\x68" => "\xEB\xB7\xBB", + "\x95\x69" => "\xEB\xB7\xBC", + "\x95\x6A" => "\xEB\xB7\xBD", + "\x95\x6B" => "\xEB\xB7\xBE", + "\x95\x6C" => "\xEB\xB7\xBF", + "\x95\x6D" => "\xEB\xB8\x81", + "\x95\x6E" => "\xEB\xB8\x82", + "\x95\x6F" => "\xEB\xB8\x84", + "\x95\x70" => "\xEB\xB8\x86", + "\x95\x71" => "\xEB\xB8\x87", + "\x95\x72" => "\xEB\xB8\x88", + "\x95\x73" => "\xEB\xB8\x89", + "\x95\x74" => "\xEB\xB8\x8A", + "\x95\x75" => "\xEB\xB8\x8B", + "\x95\x76" => "\xEB\xB8\x8E", + "\x95\x77" => "\xEB\xB8\x8F", + "\x95\x78" => "\xEB\xB8\x91", + "\x95\x79" => "\xEB\xB8\x92", + "\x95\x7A" => "\xEB\xB8\x93", + "\x95\x81" => "\xEB\xB8\x95", + "\x95\x82" => "\xEB\xB8\x96", + "\x95\x83" => "\xEB\xB8\x97", + "\x95\x84" => "\xEB\xB8\x98", + "\x95\x85" => "\xEB\xB8\x99", + "\x95\x86" => "\xEB\xB8\x9A", + "\x95\x87" => "\xEB\xB8\x9B", + "\x95\x88" => "\xEB\xB8\x9E", + "\x95\x89" => "\xEB\xB8\xA0", + "\x95\x8A" => "\xEB\xB8\xA1", + "\x95\x8B" => "\xEB\xB8\xA2", + "\x95\x8C" => "\xEB\xB8\xA3", + "\x95\x8D" => "\xEB\xB8\xA4", + "\x95\x8E" => "\xEB\xB8\xA5", + "\x95\x8F" => "\xEB\xB8\xA6", + "\x95\x90" => "\xEB\xB8\xA7", + "\x95\x91" => "\xEB\xB8\xA8", + "\x95\x92" => "\xEB\xB8\xA9", + "\x95\x93" => "\xEB\xB8\xAA", + "\x95\x94" => "\xEB\xB8\xAB", + "\x95\x95" => "\xEB\xB8\xAC", + "\x95\x96" => "\xEB\xB8\xAD", + "\x95\x97" => "\xEB\xB8\xAE", + "\x95\x98" => "\xEB\xB8\xAF", + "\x95\x99" => "\xEB\xB8\xB0", + "\x95\x9A" => "\xEB\xB8\xB1", + "\x95\x9B" => "\xEB\xB8\xB2", + "\x95\x9C" => "\xEB\xB8\xB3", + "\x95\x9D" => "\xEB\xB8\xB4", + "\x95\x9E" => "\xEB\xB8\xB5", + "\x95\x9F" => "\xEB\xB8\xB6", + "\x95\xA0" => "\xEB\xB8\xB7", + "\x95\xA1" => "\xEB\xB8\xB8", + "\x95\xA2" => "\xEB\xB8\xB9", + "\x95\xA3" => "\xEB\xB8\xBA", + "\x95\xA4" => "\xEB\xB8\xBB", + "\x95\xA5" => "\xEB\xB8\xBC", + "\x95\xA6" => "\xEB\xB8\xBD", + "\x95\xA7" => "\xEB\xB8\xBE", + "\x95\xA8" => "\xEB\xB8\xBF", + "\x95\xA9" => "\xEB\xB9\x80", + "\x95\xAA" => "\xEB\xB9\x81", + "\x95\xAB" => "\xEB\xB9\x82", + "\x95\xAC" => "\xEB\xB9\x83", + "\x95\xAD" => "\xEB\xB9\x86", + "\x95\xAE" => "\xEB\xB9\x87", + "\x95\xAF" => "\xEB\xB9\x89", + "\x95\xB0" => "\xEB\xB9\x8A", + "\x95\xB1" => "\xEB\xB9\x8B", + "\x95\xB2" => "\xEB\xB9\x8D", + "\x95\xB3" => "\xEB\xB9\x8F", + "\x95\xB4" => "\xEB\xB9\x90", + "\x95\xB5" => "\xEB\xB9\x91", + "\x95\xB6" => "\xEB\xB9\x92", + "\x95\xB7" => "\xEB\xB9\x93", + "\x95\xB8" => "\xEB\xB9\x96", + "\x95\xB9" => "\xEB\xB9\x98", + "\x95\xBA" => "\xEB\xB9\x9C", + "\x95\xBB" => "\xEB\xB9\x9D", + "\x95\xBC" => "\xEB\xB9\x9E", + "\x95\xBD" => "\xEB\xB9\x9F", + "\x95\xBE" => "\xEB\xB9\xA2", + "\x95\xBF" => "\xEB\xB9\xA3", + "\x95\xC0" => "\xEB\xB9\xA5", + "\x95\xC1" => "\xEB\xB9\xA6", + "\x95\xC2" => "\xEB\xB9\xA7", + "\x95\xC3" => "\xEB\xB9\xA9", + "\x95\xC4" => "\xEB\xB9\xAB", + "\x95\xC5" => "\xEB\xB9\xAC", + "\x95\xC6" => "\xEB\xB9\xAD", + "\x95\xC7" => "\xEB\xB9\xAE", + "\x95\xC8" => "\xEB\xB9\xAF", + "\x95\xC9" => "\xEB\xB9\xB2", + "\x95\xCA" => "\xEB\xB9\xB6", + "\x95\xCB" => "\xEB\xB9\xB7", + "\x95\xCC" => "\xEB\xB9\xB8", + "\x95\xCD" => "\xEB\xB9\xB9", + "\x95\xCE" => "\xEB\xB9\xBA", + "\x95\xCF" => "\xEB\xB9\xBE", + "\x95\xD0" => "\xEB\xB9\xBF", + "\x95\xD1" => "\xEB\xBA\x81", + "\x95\xD2" => "\xEB\xBA\x82", + "\x95\xD3" => "\xEB\xBA\x83", + "\x95\xD4" => "\xEB\xBA\x85", + "\x95\xD5" => "\xEB\xBA\x86", + "\x95\xD6" => "\xEB\xBA\x87", + "\x95\xD7" => "\xEB\xBA\x88", + "\x95\xD8" => "\xEB\xBA\x89", + "\x95\xD9" => "\xEB\xBA\x8A", + "\x95\xDA" => "\xEB\xBA\x8B", + "\x95\xDB" => "\xEB\xBA\x8E", + "\x95\xDC" => "\xEB\xBA\x92", + "\x95\xDD" => "\xEB\xBA\x93", + "\x95\xDE" => "\xEB\xBA\x94", + "\x95\xDF" => "\xEB\xBA\x95", + "\x95\xE0" => "\xEB\xBA\x96", + "\x95\xE1" => "\xEB\xBA\x97", + "\x95\xE2" => "\xEB\xBA\x9A", + "\x95\xE3" => "\xEB\xBA\x9B", + "\x95\xE4" => "\xEB\xBA\x9C", + "\x95\xE5" => "\xEB\xBA\x9D", + "\x95\xE6" => "\xEB\xBA\x9E", + "\x95\xE7" => "\xEB\xBA\x9F", + "\x95\xE8" => "\xEB\xBA\xA0", + "\x95\xE9" => "\xEB\xBA\xA1", + "\x95\xEA" => "\xEB\xBA\xA2", + "\x95\xEB" => "\xEB\xBA\xA3", + "\x95\xEC" => "\xEB\xBA\xA4", + "\x95\xED" => "\xEB\xBA\xA5", + "\x95\xEE" => "\xEB\xBA\xA6", + "\x95\xEF" => "\xEB\xBA\xA7", + "\x95\xF0" => "\xEB\xBA\xA9", + "\x95\xF1" => "\xEB\xBA\xAA", + "\x95\xF2" => "\xEB\xBA\xAB", + "\x95\xF3" => "\xEB\xBA\xAC", + "\x95\xF4" => "\xEB\xBA\xAD", + "\x95\xF5" => "\xEB\xBA\xAE", + "\x95\xF6" => "\xEB\xBA\xAF", + "\x95\xF7" => "\xEB\xBA\xB0", + "\x95\xF8" => "\xEB\xBA\xB1", + "\x95\xF9" => "\xEB\xBA\xB2", + "\x95\xFA" => "\xEB\xBA\xB3", + "\x95\xFB" => "\xEB\xBA\xB4", + "\x95\xFC" => "\xEB\xBA\xB5", + "\x95\xFD" => "\xEB\xBA\xB6", + "\x95\xFE" => "\xEB\xBA\xB7", + "\x96\x41" => "\xEB\xBA\xB8", + "\x96\x42" => "\xEB\xBA\xB9", + "\x96\x43" => "\xEB\xBA\xBA", + "\x96\x44" => "\xEB\xBA\xBB", + "\x96\x45" => "\xEB\xBA\xBC", + "\x96\x46" => "\xEB\xBA\xBD", + "\x96\x47" => "\xEB\xBA\xBE", + "\x96\x48" => "\xEB\xBA\xBF", + "\x96\x49" => "\xEB\xBB\x80", + "\x96\x4A" => "\xEB\xBB\x81", + "\x96\x4B" => "\xEB\xBB\x82", + "\x96\x4C" => "\xEB\xBB\x83", + "\x96\x4D" => "\xEB\xBB\x84", + "\x96\x4E" => "\xEB\xBB\x85", + "\x96\x4F" => "\xEB\xBB\x86", + "\x96\x50" => "\xEB\xBB\x87", + "\x96\x51" => "\xEB\xBB\x88", + "\x96\x52" => "\xEB\xBB\x89", + "\x96\x53" => "\xEB\xBB\x8A", + "\x96\x54" => "\xEB\xBB\x8B", + "\x96\x55" => "\xEB\xBB\x8C", + "\x96\x56" => "\xEB\xBB\x8D", + "\x96\x57" => "\xEB\xBB\x8E", + "\x96\x58" => "\xEB\xBB\x8F", + "\x96\x59" => "\xEB\xBB\x92", + "\x96\x5A" => "\xEB\xBB\x93", + "\x96\x61" => "\xEB\xBB\x95", + "\x96\x62" => "\xEB\xBB\x96", + "\x96\x63" => "\xEB\xBB\x99", + "\x96\x64" => "\xEB\xBB\x9A", + "\x96\x65" => "\xEB\xBB\x9B", + "\x96\x66" => "\xEB\xBB\x9C", + "\x96\x67" => "\xEB\xBB\x9D", + "\x96\x68" => "\xEB\xBB\x9E", + "\x96\x69" => "\xEB\xBB\x9F", + "\x96\x6A" => "\xEB\xBB\xA1", + "\x96\x6B" => "\xEB\xBB\xA2", + "\x96\x6C" => "\xEB\xBB\xA6", + "\x96\x6D" => "\xEB\xBB\xA7", + "\x96\x6E" => "\xEB\xBB\xA8", + "\x96\x6F" => "\xEB\xBB\xA9", + "\x96\x70" => "\xEB\xBB\xAA", + "\x96\x71" => "\xEB\xBB\xAB", + "\x96\x72" => "\xEB\xBB\xAD", + "\x96\x73" => "\xEB\xBB\xAE", + "\x96\x74" => "\xEB\xBB\xAF", + "\x96\x75" => "\xEB\xBB\xB0", + "\x96\x76" => "\xEB\xBB\xB1", + "\x96\x77" => "\xEB\xBB\xB2", + "\x96\x78" => "\xEB\xBB\xB3", + "\x96\x79" => "\xEB\xBB\xB4", + "\x96\x7A" => "\xEB\xBB\xB5", + "\x96\x81" => "\xEB\xBB\xB6", + "\x96\x82" => "\xEB\xBB\xB7", + "\x96\x83" => "\xEB\xBB\xB8", + "\x96\x84" => "\xEB\xBB\xB9", + "\x96\x85" => "\xEB\xBB\xBA", + "\x96\x86" => "\xEB\xBB\xBB", + "\x96\x87" => "\xEB\xBB\xBC", + "\x96\x88" => "\xEB\xBB\xBD", + "\x96\x89" => "\xEB\xBB\xBE", + "\x96\x8A" => "\xEB\xBB\xBF", + "\x96\x8B" => "\xEB\xBC\x80", + "\x96\x8C" => "\xEB\xBC\x82", + "\x96\x8D" => "\xEB\xBC\x83", + "\x96\x8E" => "\xEB\xBC\x84", + "\x96\x8F" => "\xEB\xBC\x85", + "\x96\x90" => "\xEB\xBC\x86", + "\x96\x91" => "\xEB\xBC\x87", + "\x96\x92" => "\xEB\xBC\x8A", + "\x96\x93" => "\xEB\xBC\x8B", + "\x96\x94" => "\xEB\xBC\x8C", + "\x96\x95" => "\xEB\xBC\x8D", + "\x96\x96" => "\xEB\xBC\x8E", + "\x96\x97" => "\xEB\xBC\x8F", + "\x96\x98" => "\xEB\xBC\x90", + "\x96\x99" => "\xEB\xBC\x91", + "\x96\x9A" => "\xEB\xBC\x92", + "\x96\x9B" => "\xEB\xBC\x93", + "\x96\x9C" => "\xEB\xBC\x94", + "\x96\x9D" => "\xEB\xBC\x95", + "\x96\x9E" => "\xEB\xBC\x96", + "\x96\x9F" => "\xEB\xBC\x97", + "\x96\xA0" => "\xEB\xBC\x9A", + "\x96\xA1" => "\xEB\xBC\x9E", + "\x96\xA2" => "\xEB\xBC\x9F", + "\x96\xA3" => "\xEB\xBC\xA0", + "\x96\xA4" => "\xEB\xBC\xA1", + "\x96\xA5" => "\xEB\xBC\xA2", + "\x96\xA6" => "\xEB\xBC\xA3", + "\x96\xA7" => "\xEB\xBC\xA4", + "\x96\xA8" => "\xEB\xBC\xA5", + "\x96\xA9" => "\xEB\xBC\xA6", + "\x96\xAA" => "\xEB\xBC\xA7", + "\x96\xAB" => "\xEB\xBC\xA8", + "\x96\xAC" => "\xEB\xBC\xA9", + "\x96\xAD" => "\xEB\xBC\xAA", + "\x96\xAE" => "\xEB\xBC\xAB", + "\x96\xAF" => "\xEB\xBC\xAC", + "\x96\xB0" => "\xEB\xBC\xAD", + "\x96\xB1" => "\xEB\xBC\xAE", + "\x96\xB2" => "\xEB\xBC\xAF", + "\x96\xB3" => "\xEB\xBC\xB0", + "\x96\xB4" => "\xEB\xBC\xB1", + "\x96\xB5" => "\xEB\xBC\xB2", + "\x96\xB6" => "\xEB\xBC\xB3", + "\x96\xB7" => "\xEB\xBC\xB4", + "\x96\xB8" => "\xEB\xBC\xB5", + "\x96\xB9" => "\xEB\xBC\xB6", + "\x96\xBA" => "\xEB\xBC\xB7", + "\x96\xBB" => "\xEB\xBC\xB8", + "\x96\xBC" => "\xEB\xBC\xB9", + "\x96\xBD" => "\xEB\xBC\xBA", + "\x96\xBE" => "\xEB\xBC\xBB", + "\x96\xBF" => "\xEB\xBC\xBC", + "\x96\xC0" => "\xEB\xBC\xBD", + "\x96\xC1" => "\xEB\xBC\xBE", + "\x96\xC2" => "\xEB\xBC\xBF", + "\x96\xC3" => "\xEB\xBD\x82", + "\x96\xC4" => "\xEB\xBD\x83", + "\x96\xC5" => "\xEB\xBD\x85", + "\x96\xC6" => "\xEB\xBD\x86", + "\x96\xC7" => "\xEB\xBD\x87", + "\x96\xC8" => "\xEB\xBD\x89", + "\x96\xC9" => "\xEB\xBD\x8A", + "\x96\xCA" => "\xEB\xBD\x8B", + "\x96\xCB" => "\xEB\xBD\x8C", + "\x96\xCC" => "\xEB\xBD\x8D", + "\x96\xCD" => "\xEB\xBD\x8E", + "\x96\xCE" => "\xEB\xBD\x8F", + "\x96\xCF" => "\xEB\xBD\x92", + "\x96\xD0" => "\xEB\xBD\x93", + "\x96\xD1" => "\xEB\xBD\x94", + "\x96\xD2" => "\xEB\xBD\x96", + "\x96\xD3" => "\xEB\xBD\x97", + "\x96\xD4" => "\xEB\xBD\x98", + "\x96\xD5" => "\xEB\xBD\x99", + "\x96\xD6" => "\xEB\xBD\x9A", + "\x96\xD7" => "\xEB\xBD\x9B", + "\x96\xD8" => "\xEB\xBD\x9C", + "\x96\xD9" => "\xEB\xBD\x9D", + "\x96\xDA" => "\xEB\xBD\x9E", + "\x96\xDB" => "\xEB\xBD\x9F", + "\x96\xDC" => "\xEB\xBD\xA0", + "\x96\xDD" => "\xEB\xBD\xA1", + "\x96\xDE" => "\xEB\xBD\xA2", + "\x96\xDF" => "\xEB\xBD\xA3", + "\x96\xE0" => "\xEB\xBD\xA4", + "\x96\xE1" => "\xEB\xBD\xA5", + "\x96\xE2" => "\xEB\xBD\xA6", + "\x96\xE3" => "\xEB\xBD\xA7", + "\x96\xE4" => "\xEB\xBD\xA8", + "\x96\xE5" => "\xEB\xBD\xA9", + "\x96\xE6" => "\xEB\xBD\xAA", + "\x96\xE7" => "\xEB\xBD\xAB", + "\x96\xE8" => "\xEB\xBD\xAC", + "\x96\xE9" => "\xEB\xBD\xAD", + "\x96\xEA" => "\xEB\xBD\xAE", + "\x96\xEB" => "\xEB\xBD\xAF", + "\x96\xEC" => "\xEB\xBD\xB0", + "\x96\xED" => "\xEB\xBD\xB1", + "\x96\xEE" => "\xEB\xBD\xB2", + "\x96\xEF" => "\xEB\xBD\xB3", + "\x96\xF0" => "\xEB\xBD\xB4", + "\x96\xF1" => "\xEB\xBD\xB5", + "\x96\xF2" => "\xEB\xBD\xB6", + "\x96\xF3" => "\xEB\xBD\xB7", + "\x96\xF4" => "\xEB\xBD\xB8", + "\x96\xF5" => "\xEB\xBD\xB9", + "\x96\xF6" => "\xEB\xBD\xBA", + "\x96\xF7" => "\xEB\xBD\xBB", + "\x96\xF8" => "\xEB\xBD\xBC", + "\x96\xF9" => "\xEB\xBD\xBD", + "\x96\xFA" => "\xEB\xBD\xBE", + "\x96\xFB" => "\xEB\xBD\xBF", + "\x96\xFC" => "\xEB\xBE\x80", + "\x96\xFD" => "\xEB\xBE\x81", + "\x96\xFE" => "\xEB\xBE\x82", + "\x97\x41" => "\xEB\xBE\x83", + "\x97\x42" => "\xEB\xBE\x84", + "\x97\x43" => "\xEB\xBE\x85", + "\x97\x44" => "\xEB\xBE\x86", + "\x97\x45" => "\xEB\xBE\x87", + "\x97\x46" => "\xEB\xBE\x88", + "\x97\x47" => "\xEB\xBE\x89", + "\x97\x48" => "\xEB\xBE\x8A", + "\x97\x49" => "\xEB\xBE\x8B", + "\x97\x4A" => "\xEB\xBE\x8C", + "\x97\x4B" => "\xEB\xBE\x8D", + "\x97\x4C" => "\xEB\xBE\x8E", + "\x97\x4D" => "\xEB\xBE\x8F", + "\x97\x4E" => "\xEB\xBE\x90", + "\x97\x4F" => "\xEB\xBE\x91", + "\x97\x50" => "\xEB\xBE\x92", + "\x97\x51" => "\xEB\xBE\x93", + "\x97\x52" => "\xEB\xBE\x95", + "\x97\x53" => "\xEB\xBE\x96", + "\x97\x54" => "\xEB\xBE\x97", + "\x97\x55" => "\xEB\xBE\x98", + "\x97\x56" => "\xEB\xBE\x99", + "\x97\x57" => "\xEB\xBE\x9A", + "\x97\x58" => "\xEB\xBE\x9B", + "\x97\x59" => "\xEB\xBE\x9C", + "\x97\x5A" => "\xEB\xBE\x9D", + "\x97\x61" => "\xEB\xBE\x9E", + "\x97\x62" => "\xEB\xBE\x9F", + "\x97\x63" => "\xEB\xBE\xA0", + "\x97\x64" => "\xEB\xBE\xA1", + "\x97\x65" => "\xEB\xBE\xA2", + "\x97\x66" => "\xEB\xBE\xA3", + "\x97\x67" => "\xEB\xBE\xA4", + "\x97\x68" => "\xEB\xBE\xA5", + "\x97\x69" => "\xEB\xBE\xA6", + "\x97\x6A" => "\xEB\xBE\xA7", + "\x97\x6B" => "\xEB\xBE\xA8", + "\x97\x6C" => "\xEB\xBE\xA9", + "\x97\x6D" => "\xEB\xBE\xAA", + "\x97\x6E" => "\xEB\xBE\xAB", + "\x97\x6F" => "\xEB\xBE\xAC", + "\x97\x70" => "\xEB\xBE\xAD", + "\x97\x71" => "\xEB\xBE\xAE", + "\x97\x72" => "\xEB\xBE\xAF", + "\x97\x73" => "\xEB\xBE\xB1", + "\x97\x74" => "\xEB\xBE\xB2", + "\x97\x75" => "\xEB\xBE\xB3", + "\x97\x76" => "\xEB\xBE\xB4", + "\x97\x77" => "\xEB\xBE\xB5", + "\x97\x78" => "\xEB\xBE\xB6", + "\x97\x79" => "\xEB\xBE\xB7", + "\x97\x7A" => "\xEB\xBE\xB8", + "\x97\x81" => "\xEB\xBE\xB9", + "\x97\x82" => "\xEB\xBE\xBA", + "\x97\x83" => "\xEB\xBE\xBB", + "\x97\x84" => "\xEB\xBE\xBC", + "\x97\x85" => "\xEB\xBE\xBD", + "\x97\x86" => "\xEB\xBE\xBE", + "\x97\x87" => "\xEB\xBE\xBF", + "\x97\x88" => "\xEB\xBF\x80", + "\x97\x89" => "\xEB\xBF\x81", + "\x97\x8A" => "\xEB\xBF\x82", + "\x97\x8B" => "\xEB\xBF\x83", + "\x97\x8C" => "\xEB\xBF\x84", + "\x97\x8D" => "\xEB\xBF\x86", + "\x97\x8E" => "\xEB\xBF\x87", + "\x97\x8F" => "\xEB\xBF\x88", + "\x97\x90" => "\xEB\xBF\x89", + "\x97\x91" => "\xEB\xBF\x8A", + "\x97\x92" => "\xEB\xBF\x8B", + "\x97\x93" => "\xEB\xBF\x8E", + "\x97\x94" => "\xEB\xBF\x8F", + "\x97\x95" => "\xEB\xBF\x91", + "\x97\x96" => "\xEB\xBF\x92", + "\x97\x97" => "\xEB\xBF\x93", + "\x97\x98" => "\xEB\xBF\x95", + "\x97\x99" => "\xEB\xBF\x96", + "\x97\x9A" => "\xEB\xBF\x97", + "\x97\x9B" => "\xEB\xBF\x98", + "\x97\x9C" => "\xEB\xBF\x99", + "\x97\x9D" => "\xEB\xBF\x9A", + "\x97\x9E" => "\xEB\xBF\x9B", + "\x97\x9F" => "\xEB\xBF\x9D", + "\x97\xA0" => "\xEB\xBF\x9E", + "\x97\xA1" => "\xEB\xBF\xA0", + "\x97\xA2" => "\xEB\xBF\xA2", + "\x97\xA3" => "\xEB\xBF\xA3", + "\x97\xA4" => "\xEB\xBF\xA4", + "\x97\xA5" => "\xEB\xBF\xA5", + "\x97\xA6" => "\xEB\xBF\xA6", + "\x97\xA7" => "\xEB\xBF\xA7", + "\x97\xA8" => "\xEB\xBF\xA8", + "\x97\xA9" => "\xEB\xBF\xA9", + "\x97\xAA" => "\xEB\xBF\xAA", + "\x97\xAB" => "\xEB\xBF\xAB", + "\x97\xAC" => "\xEB\xBF\xAC", + "\x97\xAD" => "\xEB\xBF\xAD", + "\x97\xAE" => "\xEB\xBF\xAE", + "\x97\xAF" => "\xEB\xBF\xAF", + "\x97\xB0" => "\xEB\xBF\xB0", + "\x97\xB1" => "\xEB\xBF\xB1", + "\x97\xB2" => "\xEB\xBF\xB2", + "\x97\xB3" => "\xEB\xBF\xB3", + "\x97\xB4" => "\xEB\xBF\xB4", + "\x97\xB5" => "\xEB\xBF\xB5", + "\x97\xB6" => "\xEB\xBF\xB6", + "\x97\xB7" => "\xEB\xBF\xB7", + "\x97\xB8" => "\xEB\xBF\xB8", + "\x97\xB9" => "\xEB\xBF\xB9", + "\x97\xBA" => "\xEB\xBF\xBA", + "\x97\xBB" => "\xEB\xBF\xBB", + "\x97\xBC" => "\xEB\xBF\xBC", + "\x97\xBD" => "\xEB\xBF\xBD", + "\x97\xBE" => "\xEB\xBF\xBE", + "\x97\xBF" => "\xEB\xBF\xBF", + "\x97\xC0" => "\xEC\x80\x80", + "\x97\xC1" => "\xEC\x80\x81", + "\x97\xC2" => "\xEC\x80\x82", + "\x97\xC3" => "\xEC\x80\x83", + "\x97\xC4" => "\xEC\x80\x84", + "\x97\xC5" => "\xEC\x80\x85", + "\x97\xC6" => "\xEC\x80\x86", + "\x97\xC7" => "\xEC\x80\x87", + "\x97\xC8" => "\xEC\x80\x88", + "\x97\xC9" => "\xEC\x80\x89", + "\x97\xCA" => "\xEC\x80\x8A", + "\x97\xCB" => "\xEC\x80\x8B", + "\x97\xCC" => "\xEC\x80\x8C", + "\x97\xCD" => "\xEC\x80\x8D", + "\x97\xCE" => "\xEC\x80\x8E", + "\x97\xCF" => "\xEC\x80\x8F", + "\x97\xD0" => "\xEC\x80\x90", + "\x97\xD1" => "\xEC\x80\x91", + "\x97\xD2" => "\xEC\x80\x92", + "\x97\xD3" => "\xEC\x80\x93", + "\x97\xD4" => "\xEC\x80\x94", + "\x97\xD5" => "\xEC\x80\x95", + "\x97\xD6" => "\xEC\x80\x96", + "\x97\xD7" => "\xEC\x80\x97", + "\x97\xD8" => "\xEC\x80\x98", + "\x97\xD9" => "\xEC\x80\x99", + "\x97\xDA" => "\xEC\x80\x9A", + "\x97\xDB" => "\xEC\x80\x9B", + "\x97\xDC" => "\xEC\x80\x9C", + "\x97\xDD" => "\xEC\x80\x9D", + "\x97\xDE" => "\xEC\x80\x9E", + "\x97\xDF" => "\xEC\x80\x9F", + "\x97\xE0" => "\xEC\x80\xA0", + "\x97\xE1" => "\xEC\x80\xA1", + "\x97\xE2" => "\xEC\x80\xA2", + "\x97\xE3" => "\xEC\x80\xA3", + "\x97\xE4" => "\xEC\x80\xA4", + "\x97\xE5" => "\xEC\x80\xA5", + "\x97\xE6" => "\xEC\x80\xA6", + "\x97\xE7" => "\xEC\x80\xA7", + "\x97\xE8" => "\xEC\x80\xA8", + "\x97\xE9" => "\xEC\x80\xA9", + "\x97\xEA" => "\xEC\x80\xAA", + "\x97\xEB" => "\xEC\x80\xAB", + "\x97\xEC" => "\xEC\x80\xAC", + "\x97\xED" => "\xEC\x80\xAD", + "\x97\xEE" => "\xEC\x80\xAE", + "\x97\xEF" => "\xEC\x80\xAF", + "\x97\xF0" => "\xEC\x80\xB0", + "\x97\xF1" => "\xEC\x80\xB1", + "\x97\xF2" => "\xEC\x80\xB2", + "\x97\xF3" => "\xEC\x80\xB3", + "\x97\xF4" => "\xEC\x80\xB4", + "\x97\xF5" => "\xEC\x80\xB5", + "\x97\xF6" => "\xEC\x80\xB6", + "\x97\xF7" => "\xEC\x80\xB7", + "\x97\xF8" => "\xEC\x80\xB8", + "\x97\xF9" => "\xEC\x80\xB9", + "\x97\xFA" => "\xEC\x80\xBA", + "\x97\xFB" => "\xEC\x80\xBB", + "\x97\xFC" => "\xEC\x80\xBD", + "\x97\xFD" => "\xEC\x80\xBE", + "\x97\xFE" => "\xEC\x80\xBF", + "\x98\x41" => "\xEC\x81\x80", + "\x98\x42" => "\xEC\x81\x81", + "\x98\x43" => "\xEC\x81\x82", + "\x98\x44" => "\xEC\x81\x83", + "\x98\x45" => "\xEC\x81\x84", + "\x98\x46" => "\xEC\x81\x85", + "\x98\x47" => "\xEC\x81\x86", + "\x98\x48" => "\xEC\x81\x87", + "\x98\x49" => "\xEC\x81\x88", + "\x98\x4A" => "\xEC\x81\x89", + "\x98\x4B" => "\xEC\x81\x8A", + "\x98\x4C" => "\xEC\x81\x8B", + "\x98\x4D" => "\xEC\x81\x8C", + "\x98\x4E" => "\xEC\x81\x8D", + "\x98\x4F" => "\xEC\x81\x8E", + "\x98\x50" => "\xEC\x81\x8F", + "\x98\x51" => "\xEC\x81\x90", + "\x98\x52" => "\xEC\x81\x92", + "\x98\x53" => "\xEC\x81\x93", + "\x98\x54" => "\xEC\x81\x94", + "\x98\x55" => "\xEC\x81\x95", + "\x98\x56" => "\xEC\x81\x96", + "\x98\x57" => "\xEC\x81\x97", + "\x98\x58" => "\xEC\x81\x99", + "\x98\x59" => "\xEC\x81\x9A", + "\x98\x5A" => "\xEC\x81\x9B", + "\x98\x61" => "\xEC\x81\x9D", + "\x98\x62" => "\xEC\x81\x9E", + "\x98\x63" => "\xEC\x81\x9F", + "\x98\x64" => "\xEC\x81\xA1", + "\x98\x65" => "\xEC\x81\xA2", + "\x98\x66" => "\xEC\x81\xA3", + "\x98\x67" => "\xEC\x81\xA4", + "\x98\x68" => "\xEC\x81\xA5", + "\x98\x69" => "\xEC\x81\xA6", + "\x98\x6A" => "\xEC\x81\xA7", + "\x98\x6B" => "\xEC\x81\xAA", + "\x98\x6C" => "\xEC\x81\xAB", + "\x98\x6D" => "\xEC\x81\xAC", + "\x98\x6E" => "\xEC\x81\xAD", + "\x98\x6F" => "\xEC\x81\xAE", + "\x98\x70" => "\xEC\x81\xAF", + "\x98\x71" => "\xEC\x81\xB0", + "\x98\x72" => "\xEC\x81\xB1", + "\x98\x73" => "\xEC\x81\xB2", + "\x98\x74" => "\xEC\x81\xB3", + "\x98\x75" => "\xEC\x81\xB4", + "\x98\x76" => "\xEC\x81\xB5", + "\x98\x77" => "\xEC\x81\xB6", + "\x98\x78" => "\xEC\x81\xB7", + "\x98\x79" => "\xEC\x81\xB8", + "\x98\x7A" => "\xEC\x81\xB9", + "\x98\x81" => "\xEC\x81\xBA", + "\x98\x82" => "\xEC\x81\xBB", + "\x98\x83" => "\xEC\x81\xBC", + "\x98\x84" => "\xEC\x81\xBD", + "\x98\x85" => "\xEC\x81\xBE", + "\x98\x86" => "\xEC\x81\xBF", + "\x98\x87" => "\xEC\x82\x80", + "\x98\x88" => "\xEC\x82\x81", + "\x98\x89" => "\xEC\x82\x82", + "\x98\x8A" => "\xEC\x82\x83", + "\x98\x8B" => "\xEC\x82\x84", + "\x98\x8C" => "\xEC\x82\x85", + "\x98\x8D" => "\xEC\x82\x86", + "\x98\x8E" => "\xEC\x82\x87", + "\x98\x8F" => "\xEC\x82\x88", + "\x98\x90" => "\xEC\x82\x89", + "\x98\x91" => "\xEC\x82\x8A", + "\x98\x92" => "\xEC\x82\x8B", + "\x98\x93" => "\xEC\x82\x8C", + "\x98\x94" => "\xEC\x82\x8D", + "\x98\x95" => "\xEC\x82\x8E", + "\x98\x96" => "\xEC\x82\x8F", + "\x98\x97" => "\xEC\x82\x92", + "\x98\x98" => "\xEC\x82\x93", + "\x98\x99" => "\xEC\x82\x95", + "\x98\x9A" => "\xEC\x82\x96", + "\x98\x9B" => "\xEC\x82\x97", + "\x98\x9C" => "\xEC\x82\x99", + "\x98\x9D" => "\xEC\x82\x9A", + "\x98\x9E" => "\xEC\x82\x9B", + "\x98\x9F" => "\xEC\x82\x9C", + "\x98\xA0" => "\xEC\x82\x9D", + "\x98\xA1" => "\xEC\x82\x9E", + "\x98\xA2" => "\xEC\x82\x9F", + "\x98\xA3" => "\xEC\x82\xA2", + "\x98\xA4" => "\xEC\x82\xA4", + "\x98\xA5" => "\xEC\x82\xA6", + "\x98\xA6" => "\xEC\x82\xA7", + "\x98\xA7" => "\xEC\x82\xA8", + "\x98\xA8" => "\xEC\x82\xA9", + "\x98\xA9" => "\xEC\x82\xAA", + "\x98\xAA" => "\xEC\x82\xAB", + "\x98\xAB" => "\xEC\x82\xAE", + "\x98\xAC" => "\xEC\x82\xB1", + "\x98\xAD" => "\xEC\x82\xB2", + "\x98\xAE" => "\xEC\x82\xB7", + "\x98\xAF" => "\xEC\x82\xB8", + "\x98\xB0" => "\xEC\x82\xB9", + "\x98\xB1" => "\xEC\x82\xBA", + "\x98\xB2" => "\xEC\x82\xBB", + "\x98\xB3" => "\xEC\x82\xBE", + "\x98\xB4" => "\xEC\x83\x82", + "\x98\xB5" => "\xEC\x83\x83", + "\x98\xB6" => "\xEC\x83\x84", + "\x98\xB7" => "\xEC\x83\x86", + "\x98\xB8" => "\xEC\x83\x87", + "\x98\xB9" => "\xEC\x83\x8A", + "\x98\xBA" => "\xEC\x83\x8B", + "\x98\xBB" => "\xEC\x83\x8D", + "\x98\xBC" => "\xEC\x83\x8E", + "\x98\xBD" => "\xEC\x83\x8F", + "\x98\xBE" => "\xEC\x83\x91", + "\x98\xBF" => "\xEC\x83\x92", + "\x98\xC0" => "\xEC\x83\x93", + "\x98\xC1" => "\xEC\x83\x94", + "\x98\xC2" => "\xEC\x83\x95", + "\x98\xC3" => "\xEC\x83\x96", + "\x98\xC4" => "\xEC\x83\x97", + "\x98\xC5" => "\xEC\x83\x9A", + "\x98\xC6" => "\xEC\x83\x9E", + "\x98\xC7" => "\xEC\x83\x9F", + "\x98\xC8" => "\xEC\x83\xA0", + "\x98\xC9" => "\xEC\x83\xA1", + "\x98\xCA" => "\xEC\x83\xA2", + "\x98\xCB" => "\xEC\x83\xA3", + "\x98\xCC" => "\xEC\x83\xA6", + "\x98\xCD" => "\xEC\x83\xA7", + "\x98\xCE" => "\xEC\x83\xA9", + "\x98\xCF" => "\xEC\x83\xAA", + "\x98\xD0" => "\xEC\x83\xAB", + "\x98\xD1" => "\xEC\x83\xAD", + "\x98\xD2" => "\xEC\x83\xAE", + "\x98\xD3" => "\xEC\x83\xAF", + "\x98\xD4" => "\xEC\x83\xB0", + "\x98\xD5" => "\xEC\x83\xB1", + "\x98\xD6" => "\xEC\x83\xB2", + "\x98\xD7" => "\xEC\x83\xB3", + "\x98\xD8" => "\xEC\x83\xB6", + "\x98\xD9" => "\xEC\x83\xB8", + "\x98\xDA" => "\xEC\x83\xBA", + "\x98\xDB" => "\xEC\x83\xBB", + "\x98\xDC" => "\xEC\x83\xBC", + "\x98\xDD" => "\xEC\x83\xBD", + "\x98\xDE" => "\xEC\x83\xBE", + "\x98\xDF" => "\xEC\x83\xBF", + "\x98\xE0" => "\xEC\x84\x81", + "\x98\xE1" => "\xEC\x84\x82", + "\x98\xE2" => "\xEC\x84\x83", + "\x98\xE3" => "\xEC\x84\x85", + "\x98\xE4" => "\xEC\x84\x86", + "\x98\xE5" => "\xEC\x84\x87", + "\x98\xE6" => "\xEC\x84\x89", + "\x98\xE7" => "\xEC\x84\x8A", + "\x98\xE8" => "\xEC\x84\x8B", + "\x98\xE9" => "\xEC\x84\x8C", + "\x98\xEA" => "\xEC\x84\x8D", + "\x98\xEB" => "\xEC\x84\x8E", + "\x98\xEC" => "\xEC\x84\x8F", + "\x98\xED" => "\xEC\x84\x91", + "\x98\xEE" => "\xEC\x84\x92", + "\x98\xEF" => "\xEC\x84\x93", + "\x98\xF0" => "\xEC\x84\x94", + "\x98\xF1" => "\xEC\x84\x96", + "\x98\xF2" => "\xEC\x84\x97", + "\x98\xF3" => "\xEC\x84\x98", + "\x98\xF4" => "\xEC\x84\x99", + "\x98\xF5" => "\xEC\x84\x9A", + "\x98\xF6" => "\xEC\x84\x9B", + "\x98\xF7" => "\xEC\x84\xA1", + "\x98\xF8" => "\xEC\x84\xA2", + "\x98\xF9" => "\xEC\x84\xA5", + "\x98\xFA" => "\xEC\x84\xA8", + "\x98\xFB" => "\xEC\x84\xA9", + "\x98\xFC" => "\xEC\x84\xAA", + "\x98\xFD" => "\xEC\x84\xAB", + "\x98\xFE" => "\xEC\x84\xAE", + "\x99\x41" => "\xEC\x84\xB2", + "\x99\x42" => "\xEC\x84\xB3", + "\x99\x43" => "\xEC\x84\xB4", + "\x99\x44" => "\xEC\x84\xB5", + "\x99\x45" => "\xEC\x84\xB7", + "\x99\x46" => "\xEC\x84\xBA", + "\x99\x47" => "\xEC\x84\xBB", + "\x99\x48" => "\xEC\x84\xBD", + "\x99\x49" => "\xEC\x84\xBE", + "\x99\x4A" => "\xEC\x84\xBF", + "\x99\x4B" => "\xEC\x85\x81", + "\x99\x4C" => "\xEC\x85\x82", + "\x99\x4D" => "\xEC\x85\x83", + "\x99\x4E" => "\xEC\x85\x84", + "\x99\x4F" => "\xEC\x85\x85", + "\x99\x50" => "\xEC\x85\x86", + "\x99\x51" => "\xEC\x85\x87", + "\x99\x52" => "\xEC\x85\x8A", + "\x99\x53" => "\xEC\x85\x8E", + "\x99\x54" => "\xEC\x85\x8F", + "\x99\x55" => "\xEC\x85\x90", + "\x99\x56" => "\xEC\x85\x91", + "\x99\x57" => "\xEC\x85\x92", + "\x99\x58" => "\xEC\x85\x93", + "\x99\x59" => "\xEC\x85\x96", + "\x99\x5A" => "\xEC\x85\x97", + "\x99\x61" => "\xEC\x85\x99", + "\x99\x62" => "\xEC\x85\x9A", + "\x99\x63" => "\xEC\x85\x9B", + "\x99\x64" => "\xEC\x85\x9D", + "\x99\x65" => "\xEC\x85\x9E", + "\x99\x66" => "\xEC\x85\x9F", + "\x99\x67" => "\xEC\x85\xA0", + "\x99\x68" => "\xEC\x85\xA1", + "\x99\x69" => "\xEC\x85\xA2", + "\x99\x6A" => "\xEC\x85\xA3", + "\x99\x6B" => "\xEC\x85\xA6", + "\x99\x6C" => "\xEC\x85\xAA", + "\x99\x6D" => "\xEC\x85\xAB", + "\x99\x6E" => "\xEC\x85\xAC", + "\x99\x6F" => "\xEC\x85\xAD", + "\x99\x70" => "\xEC\x85\xAE", + "\x99\x71" => "\xEC\x85\xAF", + "\x99\x72" => "\xEC\x85\xB1", + "\x99\x73" => "\xEC\x85\xB2", + "\x99\x74" => "\xEC\x85\xB3", + "\x99\x75" => "\xEC\x85\xB5", + "\x99\x76" => "\xEC\x85\xB6", + "\x99\x77" => "\xEC\x85\xB7", + "\x99\x78" => "\xEC\x85\xB9", + "\x99\x79" => "\xEC\x85\xBA", + "\x99\x7A" => "\xEC\x85\xBB", + "\x99\x81" => "\xEC\x85\xBC", + "\x99\x82" => "\xEC\x85\xBD", + "\x99\x83" => "\xEC\x85\xBE", + "\x99\x84" => "\xEC\x85\xBF", + "\x99\x85" => "\xEC\x86\x80", + "\x99\x86" => "\xEC\x86\x81", + "\x99\x87" => "\xEC\x86\x82", + "\x99\x88" => "\xEC\x86\x83", + "\x99\x89" => "\xEC\x86\x84", + "\x99\x8A" => "\xEC\x86\x86", + "\x99\x8B" => "\xEC\x86\x87", + "\x99\x8C" => "\xEC\x86\x88", + "\x99\x8D" => "\xEC\x86\x89", + "\x99\x8E" => "\xEC\x86\x8A", + "\x99\x8F" => "\xEC\x86\x8B", + "\x99\x90" => "\xEC\x86\x8F", + "\x99\x91" => "\xEC\x86\x91", + "\x99\x92" => "\xEC\x86\x92", + "\x99\x93" => "\xEC\x86\x93", + "\x99\x94" => "\xEC\x86\x95", + "\x99\x95" => "\xEC\x86\x97", + "\x99\x96" => "\xEC\x86\x98", + "\x99\x97" => "\xEC\x86\x99", + "\x99\x98" => "\xEC\x86\x9A", + "\x99\x99" => "\xEC\x86\x9B", + "\x99\x9A" => "\xEC\x86\x9E", + "\x99\x9B" => "\xEC\x86\xA0", + "\x99\x9C" => "\xEC\x86\xA2", + "\x99\x9D" => "\xEC\x86\xA3", + "\x99\x9E" => "\xEC\x86\xA4", + "\x99\x9F" => "\xEC\x86\xA6", + "\x99\xA0" => "\xEC\x86\xA7", + "\x99\xA1" => "\xEC\x86\xAA", + "\x99\xA2" => "\xEC\x86\xAB", + "\x99\xA3" => "\xEC\x86\xAD", + "\x99\xA4" => "\xEC\x86\xAE", + "\x99\xA5" => "\xEC\x86\xAF", + "\x99\xA6" => "\xEC\x86\xB1", + "\x99\xA7" => "\xEC\x86\xB2", + "\x99\xA8" => "\xEC\x86\xB3", + "\x99\xA9" => "\xEC\x86\xB4", + "\x99\xAA" => "\xEC\x86\xB5", + "\x99\xAB" => "\xEC\x86\xB6", + "\x99\xAC" => "\xEC\x86\xB7", + "\x99\xAD" => "\xEC\x86\xB8", + "\x99\xAE" => "\xEC\x86\xB9", + "\x99\xAF" => "\xEC\x86\xBA", + "\x99\xB0" => "\xEC\x86\xBB", + "\x99\xB1" => "\xEC\x86\xBC", + "\x99\xB2" => "\xEC\x86\xBE", + "\x99\xB3" => "\xEC\x86\xBF", + "\x99\xB4" => "\xEC\x87\x80", + "\x99\xB5" => "\xEC\x87\x81", + "\x99\xB6" => "\xEC\x87\x82", + "\x99\xB7" => "\xEC\x87\x83", + "\x99\xB8" => "\xEC\x87\x85", + "\x99\xB9" => "\xEC\x87\x86", + "\x99\xBA" => "\xEC\x87\x87", + "\x99\xBB" => "\xEC\x87\x89", + "\x99\xBC" => "\xEC\x87\x8A", + "\x99\xBD" => "\xEC\x87\x8B", + "\x99\xBE" => "\xEC\x87\x8D", + "\x99\xBF" => "\xEC\x87\x8E", + "\x99\xC0" => "\xEC\x87\x8F", + "\x99\xC1" => "\xEC\x87\x90", + "\x99\xC2" => "\xEC\x87\x91", + "\x99\xC3" => "\xEC\x87\x92", + "\x99\xC4" => "\xEC\x87\x93", + "\x99\xC5" => "\xEC\x87\x95", + "\x99\xC6" => "\xEC\x87\x96", + "\x99\xC7" => "\xEC\x87\x99", + "\x99\xC8" => "\xEC\x87\x9A", + "\x99\xC9" => "\xEC\x87\x9B", + "\x99\xCA" => "\xEC\x87\x9C", + "\x99\xCB" => "\xEC\x87\x9D", + "\x99\xCC" => "\xEC\x87\x9E", + "\x99\xCD" => "\xEC\x87\x9F", + "\x99\xCE" => "\xEC\x87\xA1", + "\x99\xCF" => "\xEC\x87\xA2", + "\x99\xD0" => "\xEC\x87\xA3", + "\x99\xD1" => "\xEC\x87\xA5", + "\x99\xD2" => "\xEC\x87\xA6", + "\x99\xD3" => "\xEC\x87\xA7", + "\x99\xD4" => "\xEC\x87\xA9", + "\x99\xD5" => "\xEC\x87\xAA", + "\x99\xD6" => "\xEC\x87\xAB", + "\x99\xD7" => "\xEC\x87\xAC", + "\x99\xD8" => "\xEC\x87\xAD", + "\x99\xD9" => "\xEC\x87\xAE", + "\x99\xDA" => "\xEC\x87\xAF", + "\x99\xDB" => "\xEC\x87\xB2", + "\x99\xDC" => "\xEC\x87\xB4", + "\x99\xDD" => "\xEC\x87\xB5", + "\x99\xDE" => "\xEC\x87\xB6", + "\x99\xDF" => "\xEC\x87\xB7", + "\x99\xE0" => "\xEC\x87\xB8", + "\x99\xE1" => "\xEC\x87\xB9", + "\x99\xE2" => "\xEC\x87\xBA", + "\x99\xE3" => "\xEC\x87\xBB", + "\x99\xE4" => "\xEC\x87\xBE", + "\x99\xE5" => "\xEC\x87\xBF", + "\x99\xE6" => "\xEC\x88\x81", + "\x99\xE7" => "\xEC\x88\x82", + "\x99\xE8" => "\xEC\x88\x83", + "\x99\xE9" => "\xEC\x88\x85", + "\x99\xEA" => "\xEC\x88\x86", + "\x99\xEB" => "\xEC\x88\x87", + "\x99\xEC" => "\xEC\x88\x88", + "\x99\xED" => "\xEC\x88\x89", + "\x99\xEE" => "\xEC\x88\x8A", + "\x99\xEF" => "\xEC\x88\x8B", + "\x99\xF0" => "\xEC\x88\x8E", + "\x99\xF1" => "\xEC\x88\x90", + "\x99\xF2" => "\xEC\x88\x92", + "\x99\xF3" => "\xEC\x88\x93", + "\x99\xF4" => "\xEC\x88\x94", + "\x99\xF5" => "\xEC\x88\x95", + "\x99\xF6" => "\xEC\x88\x96", + "\x99\xF7" => "\xEC\x88\x97", + "\x99\xF8" => "\xEC\x88\x9A", + "\x99\xF9" => "\xEC\x88\x9B", + "\x99\xFA" => "\xEC\x88\x9D", + "\x99\xFB" => "\xEC\x88\x9E", + "\x99\xFC" => "\xEC\x88\xA1", + "\x99\xFD" => "\xEC\x88\xA2", + "\x99\xFE" => "\xEC\x88\xA3", + "\x9A\x41" => "\xEC\x88\xA4", + "\x9A\x42" => "\xEC\x88\xA5", + "\x9A\x43" => "\xEC\x88\xA6", + "\x9A\x44" => "\xEC\x88\xA7", + "\x9A\x45" => "\xEC\x88\xAA", + "\x9A\x46" => "\xEC\x88\xAC", + "\x9A\x47" => "\xEC\x88\xAE", + "\x9A\x48" => "\xEC\x88\xB0", + "\x9A\x49" => "\xEC\x88\xB3", + "\x9A\x4A" => "\xEC\x88\xB5", + "\x9A\x4B" => "\xEC\x88\xB6", + "\x9A\x4C" => "\xEC\x88\xB7", + "\x9A\x4D" => "\xEC\x88\xB8", + "\x9A\x4E" => "\xEC\x88\xB9", + "\x9A\x4F" => "\xEC\x88\xBA", + "\x9A\x50" => "\xEC\x88\xBB", + "\x9A\x51" => "\xEC\x88\xBC", + "\x9A\x52" => "\xEC\x88\xBD", + "\x9A\x53" => "\xEC\x88\xBE", + "\x9A\x54" => "\xEC\x88\xBF", + "\x9A\x55" => "\xEC\x89\x80", + "\x9A\x56" => "\xEC\x89\x81", + "\x9A\x57" => "\xEC\x89\x82", + "\x9A\x58" => "\xEC\x89\x83", + "\x9A\x59" => "\xEC\x89\x84", + "\x9A\x5A" => "\xEC\x89\x85", + "\x9A\x61" => "\xEC\x89\x86", + "\x9A\x62" => "\xEC\x89\x87", + "\x9A\x63" => "\xEC\x89\x89", + "\x9A\x64" => "\xEC\x89\x8A", + "\x9A\x65" => "\xEC\x89\x8B", + "\x9A\x66" => "\xEC\x89\x8C", + "\x9A\x67" => "\xEC\x89\x8D", + "\x9A\x68" => "\xEC\x89\x8E", + "\x9A\x69" => "\xEC\x89\x8F", + "\x9A\x6A" => "\xEC\x89\x92", + "\x9A\x6B" => "\xEC\x89\x93", + "\x9A\x6C" => "\xEC\x89\x95", + "\x9A\x6D" => "\xEC\x89\x96", + "\x9A\x6E" => "\xEC\x89\x97", + "\x9A\x6F" => "\xEC\x89\x99", + "\x9A\x70" => "\xEC\x89\x9A", + "\x9A\x71" => "\xEC\x89\x9B", + "\x9A\x72" => "\xEC\x89\x9C", + "\x9A\x73" => "\xEC\x89\x9D", + "\x9A\x74" => "\xEC\x89\x9E", + "\x9A\x75" => "\xEC\x89\x9F", + "\x9A\x76" => "\xEC\x89\xA1", + "\x9A\x77" => "\xEC\x89\xA2", + "\x9A\x78" => "\xEC\x89\xA3", + "\x9A\x79" => "\xEC\x89\xA4", + "\x9A\x7A" => "\xEC\x89\xA6", + "\x9A\x81" => "\xEC\x89\xA7", + "\x9A\x82" => "\xEC\x89\xA8", + "\x9A\x83" => "\xEC\x89\xA9", + "\x9A\x84" => "\xEC\x89\xAA", + "\x9A\x85" => "\xEC\x89\xAB", + "\x9A\x86" => "\xEC\x89\xAE", + "\x9A\x87" => "\xEC\x89\xAF", + "\x9A\x88" => "\xEC\x89\xB1", + "\x9A\x89" => "\xEC\x89\xB2", + "\x9A\x8A" => "\xEC\x89\xB3", + "\x9A\x8B" => "\xEC\x89\xB5", + "\x9A\x8C" => "\xEC\x89\xB6", + "\x9A\x8D" => "\xEC\x89\xB7", + "\x9A\x8E" => "\xEC\x89\xB8", + "\x9A\x8F" => "\xEC\x89\xB9", + "\x9A\x90" => "\xEC\x89\xBA", + "\x9A\x91" => "\xEC\x89\xBB", + "\x9A\x92" => "\xEC\x89\xBE", + "\x9A\x93" => "\xEC\x8A\x80", + "\x9A\x94" => "\xEC\x8A\x82", + "\x9A\x95" => "\xEC\x8A\x83", + "\x9A\x96" => "\xEC\x8A\x84", + "\x9A\x97" => "\xEC\x8A\x85", + "\x9A\x98" => "\xEC\x8A\x86", + "\x9A\x99" => "\xEC\x8A\x87", + "\x9A\x9A" => "\xEC\x8A\x8A", + "\x9A\x9B" => "\xEC\x8A\x8B", + "\x9A\x9C" => "\xEC\x8A\x8C", + "\x9A\x9D" => "\xEC\x8A\x8D", + "\x9A\x9E" => "\xEC\x8A\x8E", + "\x9A\x9F" => "\xEC\x8A\x8F", + "\x9A\xA0" => "\xEC\x8A\x91", + "\x9A\xA1" => "\xEC\x8A\x92", + "\x9A\xA2" => "\xEC\x8A\x93", + "\x9A\xA3" => "\xEC\x8A\x94", + "\x9A\xA4" => "\xEC\x8A\x95", + "\x9A\xA5" => "\xEC\x8A\x96", + "\x9A\xA6" => "\xEC\x8A\x97", + "\x9A\xA7" => "\xEC\x8A\x99", + "\x9A\xA8" => "\xEC\x8A\x9A", + "\x9A\xA9" => "\xEC\x8A\x9C", + "\x9A\xAA" => "\xEC\x8A\x9E", + "\x9A\xAB" => "\xEC\x8A\x9F", + "\x9A\xAC" => "\xEC\x8A\xA0", + "\x9A\xAD" => "\xEC\x8A\xA1", + "\x9A\xAE" => "\xEC\x8A\xA2", + "\x9A\xAF" => "\xEC\x8A\xA3", + "\x9A\xB0" => "\xEC\x8A\xA6", + "\x9A\xB1" => "\xEC\x8A\xA7", + "\x9A\xB2" => "\xEC\x8A\xA9", + "\x9A\xB3" => "\xEC\x8A\xAA", + "\x9A\xB4" => "\xEC\x8A\xAB", + "\x9A\xB5" => "\xEC\x8A\xAE", + "\x9A\xB6" => "\xEC\x8A\xAF", + "\x9A\xB7" => "\xEC\x8A\xB0", + "\x9A\xB8" => "\xEC\x8A\xB1", + "\x9A\xB9" => "\xEC\x8A\xB2", + "\x9A\xBA" => "\xEC\x8A\xB3", + "\x9A\xBB" => "\xEC\x8A\xB6", + "\x9A\xBC" => "\xEC\x8A\xB8", + "\x9A\xBD" => "\xEC\x8A\xBA", + "\x9A\xBE" => "\xEC\x8A\xBB", + "\x9A\xBF" => "\xEC\x8A\xBC", + "\x9A\xC0" => "\xEC\x8A\xBD", + "\x9A\xC1" => "\xEC\x8A\xBE", + "\x9A\xC2" => "\xEC\x8A\xBF", + "\x9A\xC3" => "\xEC\x8B\x80", + "\x9A\xC4" => "\xEC\x8B\x81", + "\x9A\xC5" => "\xEC\x8B\x82", + "\x9A\xC6" => "\xEC\x8B\x83", + "\x9A\xC7" => "\xEC\x8B\x84", + "\x9A\xC8" => "\xEC\x8B\x85", + "\x9A\xC9" => "\xEC\x8B\x86", + "\x9A\xCA" => "\xEC\x8B\x87", + "\x9A\xCB" => "\xEC\x8B\x88", + "\x9A\xCC" => "\xEC\x8B\x89", + "\x9A\xCD" => "\xEC\x8B\x8A", + "\x9A\xCE" => "\xEC\x8B\x8B", + "\x9A\xCF" => "\xEC\x8B\x8C", + "\x9A\xD0" => "\xEC\x8B\x8D", + "\x9A\xD1" => "\xEC\x8B\x8E", + "\x9A\xD2" => "\xEC\x8B\x8F", + "\x9A\xD3" => "\xEC\x8B\x90", + "\x9A\xD4" => "\xEC\x8B\x91", + "\x9A\xD5" => "\xEC\x8B\x92", + "\x9A\xD6" => "\xEC\x8B\x93", + "\x9A\xD7" => "\xEC\x8B\x94", + "\x9A\xD8" => "\xEC\x8B\x95", + "\x9A\xD9" => "\xEC\x8B\x96", + "\x9A\xDA" => "\xEC\x8B\x97", + "\x9A\xDB" => "\xEC\x8B\x98", + "\x9A\xDC" => "\xEC\x8B\x99", + "\x9A\xDD" => "\xEC\x8B\x9A", + "\x9A\xDE" => "\xEC\x8B\x9B", + "\x9A\xDF" => "\xEC\x8B\x9E", + "\x9A\xE0" => "\xEC\x8B\x9F", + "\x9A\xE1" => "\xEC\x8B\xA1", + "\x9A\xE2" => "\xEC\x8B\xA2", + "\x9A\xE3" => "\xEC\x8B\xA5", + "\x9A\xE4" => "\xEC\x8B\xA6", + "\x9A\xE5" => "\xEC\x8B\xA7", + "\x9A\xE6" => "\xEC\x8B\xA8", + "\x9A\xE7" => "\xEC\x8B\xA9", + "\x9A\xE8" => "\xEC\x8B\xAA", + "\x9A\xE9" => "\xEC\x8B\xAE", + "\x9A\xEA" => "\xEC\x8B\xB0", + "\x9A\xEB" => "\xEC\x8B\xB2", + "\x9A\xEC" => "\xEC\x8B\xB3", + "\x9A\xED" => "\xEC\x8B\xB4", + "\x9A\xEE" => "\xEC\x8B\xB5", + "\x9A\xEF" => "\xEC\x8B\xB7", + "\x9A\xF0" => "\xEC\x8B\xBA", + "\x9A\xF1" => "\xEC\x8B\xBD", + "\x9A\xF2" => "\xEC\x8B\xBE", + "\x9A\xF3" => "\xEC\x8B\xBF", + "\x9A\xF4" => "\xEC\x8C\x81", + "\x9A\xF5" => "\xEC\x8C\x82", + "\x9A\xF6" => "\xEC\x8C\x83", + "\x9A\xF7" => "\xEC\x8C\x84", + "\x9A\xF8" => "\xEC\x8C\x85", + "\x9A\xF9" => "\xEC\x8C\x86", + "\x9A\xFA" => "\xEC\x8C\x87", + "\x9A\xFB" => "\xEC\x8C\x8A", + "\x9A\xFC" => "\xEC\x8C\x8B", + "\x9A\xFD" => "\xEC\x8C\x8E", + "\x9A\xFE" => "\xEC\x8C\x8F", + "\x9B\x41" => "\xEC\x8C\x90", + "\x9B\x42" => "\xEC\x8C\x91", + "\x9B\x43" => "\xEC\x8C\x92", + "\x9B\x44" => "\xEC\x8C\x96", + "\x9B\x45" => "\xEC\x8C\x97", + "\x9B\x46" => "\xEC\x8C\x99", + "\x9B\x47" => "\xEC\x8C\x9A", + "\x9B\x48" => "\xEC\x8C\x9B", + "\x9B\x49" => "\xEC\x8C\x9D", + "\x9B\x4A" => "\xEC\x8C\x9E", + "\x9B\x4B" => "\xEC\x8C\x9F", + "\x9B\x4C" => "\xEC\x8C\xA0", + "\x9B\x4D" => "\xEC\x8C\xA1", + "\x9B\x4E" => "\xEC\x8C\xA2", + "\x9B\x4F" => "\xEC\x8C\xA3", + "\x9B\x50" => "\xEC\x8C\xA6", + "\x9B\x51" => "\xEC\x8C\xA7", + "\x9B\x52" => "\xEC\x8C\xAA", + "\x9B\x53" => "\xEC\x8C\xAB", + "\x9B\x54" => "\xEC\x8C\xAC", + "\x9B\x55" => "\xEC\x8C\xAD", + "\x9B\x56" => "\xEC\x8C\xAE", + "\x9B\x57" => "\xEC\x8C\xAF", + "\x9B\x58" => "\xEC\x8C\xB0", + "\x9B\x59" => "\xEC\x8C\xB1", + "\x9B\x5A" => "\xEC\x8C\xB2", + "\x9B\x61" => "\xEC\x8C\xB3", + "\x9B\x62" => "\xEC\x8C\xB4", + "\x9B\x63" => "\xEC\x8C\xB5", + "\x9B\x64" => "\xEC\x8C\xB6", + "\x9B\x65" => "\xEC\x8C\xB7", + "\x9B\x66" => "\xEC\x8C\xB8", + "\x9B\x67" => "\xEC\x8C\xB9", + "\x9B\x68" => "\xEC\x8C\xBA", + "\x9B\x69" => "\xEC\x8C\xBB", + "\x9B\x6A" => "\xEC\x8C\xBC", + "\x9B\x6B" => "\xEC\x8C\xBD", + "\x9B\x6C" => "\xEC\x8C\xBE", + "\x9B\x6D" => "\xEC\x8C\xBF", + "\x9B\x6E" => "\xEC\x8D\x80", + "\x9B\x6F" => "\xEC\x8D\x81", + "\x9B\x70" => "\xEC\x8D\x82", + "\x9B\x71" => "\xEC\x8D\x83", + "\x9B\x72" => "\xEC\x8D\x84", + "\x9B\x73" => "\xEC\x8D\x86", + "\x9B\x74" => "\xEC\x8D\x87", + "\x9B\x75" => "\xEC\x8D\x88", + "\x9B\x76" => "\xEC\x8D\x89", + "\x9B\x77" => "\xEC\x8D\x8A", + "\x9B\x78" => "\xEC\x8D\x8B", + "\x9B\x79" => "\xEC\x8D\x8C", + "\x9B\x7A" => "\xEC\x8D\x8D", + "\x9B\x81" => "\xEC\x8D\x8E", + "\x9B\x82" => "\xEC\x8D\x8F", + "\x9B\x83" => "\xEC\x8D\x90", + "\x9B\x84" => "\xEC\x8D\x91", + "\x9B\x85" => "\xEC\x8D\x92", + "\x9B\x86" => "\xEC\x8D\x93", + "\x9B\x87" => "\xEC\x8D\x94", + "\x9B\x88" => "\xEC\x8D\x95", + "\x9B\x89" => "\xEC\x8D\x96", + "\x9B\x8A" => "\xEC\x8D\x97", + "\x9B\x8B" => "\xEC\x8D\x98", + "\x9B\x8C" => "\xEC\x8D\x99", + "\x9B\x8D" => "\xEC\x8D\x9A", + "\x9B\x8E" => "\xEC\x8D\x9B", + "\x9B\x8F" => "\xEC\x8D\x9C", + "\x9B\x90" => "\xEC\x8D\x9D", + "\x9B\x91" => "\xEC\x8D\x9E", + "\x9B\x92" => "\xEC\x8D\x9F", + "\x9B\x93" => "\xEC\x8D\xA0", + "\x9B\x94" => "\xEC\x8D\xA1", + "\x9B\x95" => "\xEC\x8D\xA2", + "\x9B\x96" => "\xEC\x8D\xA3", + "\x9B\x97" => "\xEC\x8D\xA4", + "\x9B\x98" => "\xEC\x8D\xA5", + "\x9B\x99" => "\xEC\x8D\xA6", + "\x9B\x9A" => "\xEC\x8D\xA7", + "\x9B\x9B" => "\xEC\x8D\xAA", + "\x9B\x9C" => "\xEC\x8D\xAB", + "\x9B\x9D" => "\xEC\x8D\xAD", + "\x9B\x9E" => "\xEC\x8D\xAE", + "\x9B\x9F" => "\xEC\x8D\xAF", + "\x9B\xA0" => "\xEC\x8D\xB1", + "\x9B\xA1" => "\xEC\x8D\xB3", + "\x9B\xA2" => "\xEC\x8D\xB4", + "\x9B\xA3" => "\xEC\x8D\xB5", + "\x9B\xA4" => "\xEC\x8D\xB6", + "\x9B\xA5" => "\xEC\x8D\xB7", + "\x9B\xA6" => "\xEC\x8D\xBA", + "\x9B\xA7" => "\xEC\x8D\xBB", + "\x9B\xA8" => "\xEC\x8D\xBE", + "\x9B\xA9" => "\xEC\x8D\xBF", + "\x9B\xAA" => "\xEC\x8E\x80", + "\x9B\xAB" => "\xEC\x8E\x81", + "\x9B\xAC" => "\xEC\x8E\x82", + "\x9B\xAD" => "\xEC\x8E\x83", + "\x9B\xAE" => "\xEC\x8E\x85", + "\x9B\xAF" => "\xEC\x8E\x86", + "\x9B\xB0" => "\xEC\x8E\x87", + "\x9B\xB1" => "\xEC\x8E\x89", + "\x9B\xB2" => "\xEC\x8E\x8A", + "\x9B\xB3" => "\xEC\x8E\x8B", + "\x9B\xB4" => "\xEC\x8E\x8D", + "\x9B\xB5" => "\xEC\x8E\x8E", + "\x9B\xB6" => "\xEC\x8E\x8F", + "\x9B\xB7" => "\xEC\x8E\x90", + "\x9B\xB8" => "\xEC\x8E\x91", + "\x9B\xB9" => "\xEC\x8E\x92", + "\x9B\xBA" => "\xEC\x8E\x93", + "\x9B\xBB" => "\xEC\x8E\x94", + "\x9B\xBC" => "\xEC\x8E\x95", + "\x9B\xBD" => "\xEC\x8E\x96", + "\x9B\xBE" => "\xEC\x8E\x97", + "\x9B\xBF" => "\xEC\x8E\x98", + "\x9B\xC0" => "\xEC\x8E\x99", + "\x9B\xC1" => "\xEC\x8E\x9A", + "\x9B\xC2" => "\xEC\x8E\x9B", + "\x9B\xC3" => "\xEC\x8E\x9C", + "\x9B\xC4" => "\xEC\x8E\x9D", + "\x9B\xC5" => "\xEC\x8E\x9E", + "\x9B\xC6" => "\xEC\x8E\x9F", + "\x9B\xC7" => "\xEC\x8E\xA0", + "\x9B\xC8" => "\xEC\x8E\xA1", + "\x9B\xC9" => "\xEC\x8E\xA2", + "\x9B\xCA" => "\xEC\x8E\xA3", + "\x9B\xCB" => "\xEC\x8E\xA4", + "\x9B\xCC" => "\xEC\x8E\xA5", + "\x9B\xCD" => "\xEC\x8E\xA6", + "\x9B\xCE" => "\xEC\x8E\xA7", + "\x9B\xCF" => "\xEC\x8E\xA8", + "\x9B\xD0" => "\xEC\x8E\xA9", + "\x9B\xD1" => "\xEC\x8E\xAA", + "\x9B\xD2" => "\xEC\x8E\xAB", + "\x9B\xD3" => "\xEC\x8E\xAC", + "\x9B\xD4" => "\xEC\x8E\xAD", + "\x9B\xD5" => "\xEC\x8E\xAE", + "\x9B\xD6" => "\xEC\x8E\xAF", + "\x9B\xD7" => "\xEC\x8E\xB0", + "\x9B\xD8" => "\xEC\x8E\xB1", + "\x9B\xD9" => "\xEC\x8E\xB2", + "\x9B\xDA" => "\xEC\x8E\xB3", + "\x9B\xDB" => "\xEC\x8E\xB4", + "\x9B\xDC" => "\xEC\x8E\xB5", + "\x9B\xDD" => "\xEC\x8E\xB6", + "\x9B\xDE" => "\xEC\x8E\xB7", + "\x9B\xDF" => "\xEC\x8E\xB8", + "\x9B\xE0" => "\xEC\x8E\xB9", + "\x9B\xE1" => "\xEC\x8E\xBA", + "\x9B\xE2" => "\xEC\x8E\xBB", + "\x9B\xE3" => "\xEC\x8E\xBC", + "\x9B\xE4" => "\xEC\x8E\xBD", + "\x9B\xE5" => "\xEC\x8E\xBE", + "\x9B\xE6" => "\xEC\x8E\xBF", + "\x9B\xE7" => "\xEC\x8F\x81", + "\x9B\xE8" => "\xEC\x8F\x82", + "\x9B\xE9" => "\xEC\x8F\x83", + "\x9B\xEA" => "\xEC\x8F\x84", + "\x9B\xEB" => "\xEC\x8F\x85", + "\x9B\xEC" => "\xEC\x8F\x86", + "\x9B\xED" => "\xEC\x8F\x87", + "\x9B\xEE" => "\xEC\x8F\x88", + "\x9B\xEF" => "\xEC\x8F\x89", + "\x9B\xF0" => "\xEC\x8F\x8A", + "\x9B\xF1" => "\xEC\x8F\x8B", + "\x9B\xF2" => "\xEC\x8F\x8C", + "\x9B\xF3" => "\xEC\x8F\x8D", + "\x9B\xF4" => "\xEC\x8F\x8E", + "\x9B\xF5" => "\xEC\x8F\x8F", + "\x9B\xF6" => "\xEC\x8F\x90", + "\x9B\xF7" => "\xEC\x8F\x91", + "\x9B\xF8" => "\xEC\x8F\x92", + "\x9B\xF9" => "\xEC\x8F\x93", + "\x9B\xFA" => "\xEC\x8F\x94", + "\x9B\xFB" => "\xEC\x8F\x95", + "\x9B\xFC" => "\xEC\x8F\x96", + "\x9B\xFD" => "\xEC\x8F\x97", + "\x9B\xFE" => "\xEC\x8F\x9A", + "\x9C\x41" => "\xEC\x8F\x9B", + "\x9C\x42" => "\xEC\x8F\x9D", + "\x9C\x43" => "\xEC\x8F\x9E", + "\x9C\x44" => "\xEC\x8F\xA1", + "\x9C\x45" => "\xEC\x8F\xA3", + "\x9C\x46" => "\xEC\x8F\xA4", + "\x9C\x47" => "\xEC\x8F\xA5", + "\x9C\x48" => "\xEC\x8F\xA6", + "\x9C\x49" => "\xEC\x8F\xA7", + "\x9C\x4A" => "\xEC\x8F\xAA", + "\x9C\x4B" => "\xEC\x8F\xAB", + "\x9C\x4C" => "\xEC\x8F\xAC", + "\x9C\x4D" => "\xEC\x8F\xAE", + "\x9C\x4E" => "\xEC\x8F\xAF", + "\x9C\x4F" => "\xEC\x8F\xB0", + "\x9C\x50" => "\xEC\x8F\xB1", + "\x9C\x51" => "\xEC\x8F\xB2", + "\x9C\x52" => "\xEC\x8F\xB3", + "\x9C\x53" => "\xEC\x8F\xB6", + "\x9C\x54" => "\xEC\x8F\xB7", + "\x9C\x55" => "\xEC\x8F\xB9", + "\x9C\x56" => "\xEC\x8F\xBA", + "\x9C\x57" => "\xEC\x8F\xBB", + "\x9C\x58" => "\xEC\x8F\xBC", + "\x9C\x59" => "\xEC\x8F\xBD", + "\x9C\x5A" => "\xEC\x8F\xBE", + "\x9C\x61" => "\xEC\x8F\xBF", + "\x9C\x62" => "\xEC\x90\x80", + "\x9C\x63" => "\xEC\x90\x81", + "\x9C\x64" => "\xEC\x90\x82", + "\x9C\x65" => "\xEC\x90\x83", + "\x9C\x66" => "\xEC\x90\x84", + "\x9C\x67" => "\xEC\x90\x85", + "\x9C\x68" => "\xEC\x90\x86", + "\x9C\x69" => "\xEC\x90\x87", + "\x9C\x6A" => "\xEC\x90\x89", + "\x9C\x6B" => "\xEC\x90\x8A", + "\x9C\x6C" => "\xEC\x90\x8B", + "\x9C\x6D" => "\xEC\x90\x8C", + "\x9C\x6E" => "\xEC\x90\x8D", + "\x9C\x6F" => "\xEC\x90\x8E", + "\x9C\x70" => "\xEC\x90\x8F", + "\x9C\x71" => "\xEC\x90\x91", + "\x9C\x72" => "\xEC\x90\x92", + "\x9C\x73" => "\xEC\x90\x93", + "\x9C\x74" => "\xEC\x90\x94", + "\x9C\x75" => "\xEC\x90\x95", + "\x9C\x76" => "\xEC\x90\x96", + "\x9C\x77" => "\xEC\x90\x97", + "\x9C\x78" => "\xEC\x90\x98", + "\x9C\x79" => "\xEC\x90\x99", + "\x9C\x7A" => "\xEC\x90\x9A", + "\x9C\x81" => "\xEC\x90\x9B", + "\x9C\x82" => "\xEC\x90\x9C", + "\x9C\x83" => "\xEC\x90\x9D", + "\x9C\x84" => "\xEC\x90\x9E", + "\x9C\x85" => "\xEC\x90\x9F", + "\x9C\x86" => "\xEC\x90\xA0", + "\x9C\x87" => "\xEC\x90\xA1", + "\x9C\x88" => "\xEC\x90\xA2", + "\x9C\x89" => "\xEC\x90\xA3", + "\x9C\x8A" => "\xEC\x90\xA5", + "\x9C\x8B" => "\xEC\x90\xA6", + "\x9C\x8C" => "\xEC\x90\xA7", + "\x9C\x8D" => "\xEC\x90\xA8", + "\x9C\x8E" => "\xEC\x90\xA9", + "\x9C\x8F" => "\xEC\x90\xAA", + "\x9C\x90" => "\xEC\x90\xAB", + "\x9C\x91" => "\xEC\x90\xAD", + "\x9C\x92" => "\xEC\x90\xAE", + "\x9C\x93" => "\xEC\x90\xAF", + "\x9C\x94" => "\xEC\x90\xB1", + "\x9C\x95" => "\xEC\x90\xB2", + "\x9C\x96" => "\xEC\x90\xB3", + "\x9C\x97" => "\xEC\x90\xB5", + "\x9C\x98" => "\xEC\x90\xB6", + "\x9C\x99" => "\xEC\x90\xB7", + "\x9C\x9A" => "\xEC\x90\xB8", + "\x9C\x9B" => "\xEC\x90\xB9", + "\x9C\x9C" => "\xEC\x90\xBA", + "\x9C\x9D" => "\xEC\x90\xBB", + "\x9C\x9E" => "\xEC\x90\xBE", + "\x9C\x9F" => "\xEC\x90\xBF", + "\x9C\xA0" => "\xEC\x91\x80", + "\x9C\xA1" => "\xEC\x91\x81", + "\x9C\xA2" => "\xEC\x91\x82", + "\x9C\xA3" => "\xEC\x91\x83", + "\x9C\xA4" => "\xEC\x91\x84", + "\x9C\xA5" => "\xEC\x91\x85", + "\x9C\xA6" => "\xEC\x91\x86", + "\x9C\xA7" => "\xEC\x91\x87", + "\x9C\xA8" => "\xEC\x91\x89", + "\x9C\xA9" => "\xEC\x91\x8A", + "\x9C\xAA" => "\xEC\x91\x8B", + "\x9C\xAB" => "\xEC\x91\x8C", + "\x9C\xAC" => "\xEC\x91\x8D", + "\x9C\xAD" => "\xEC\x91\x8E", + "\x9C\xAE" => "\xEC\x91\x8F", + "\x9C\xAF" => "\xEC\x91\x90", + "\x9C\xB0" => "\xEC\x91\x91", + "\x9C\xB1" => "\xEC\x91\x92", + "\x9C\xB2" => "\xEC\x91\x93", + "\x9C\xB3" => "\xEC\x91\x94", + "\x9C\xB4" => "\xEC\x91\x95", + "\x9C\xB5" => "\xEC\x91\x96", + "\x9C\xB6" => "\xEC\x91\x97", + "\x9C\xB7" => "\xEC\x91\x98", + "\x9C\xB8" => "\xEC\x91\x99", + "\x9C\xB9" => "\xEC\x91\x9A", + "\x9C\xBA" => "\xEC\x91\x9B", + "\x9C\xBB" => "\xEC\x91\x9C", + "\x9C\xBC" => "\xEC\x91\x9D", + "\x9C\xBD" => "\xEC\x91\x9E", + "\x9C\xBE" => "\xEC\x91\x9F", + "\x9C\xBF" => "\xEC\x91\xA0", + "\x9C\xC0" => "\xEC\x91\xA1", + "\x9C\xC1" => "\xEC\x91\xA2", + "\x9C\xC2" => "\xEC\x91\xA3", + "\x9C\xC3" => "\xEC\x91\xA6", + "\x9C\xC4" => "\xEC\x91\xA7", + "\x9C\xC5" => "\xEC\x91\xA9", + "\x9C\xC6" => "\xEC\x91\xAA", + "\x9C\xC7" => "\xEC\x91\xAB", + "\x9C\xC8" => "\xEC\x91\xAD", + "\x9C\xC9" => "\xEC\x91\xAE", + "\x9C\xCA" => "\xEC\x91\xAF", + "\x9C\xCB" => "\xEC\x91\xB0", + "\x9C\xCC" => "\xEC\x91\xB1", + "\x9C\xCD" => "\xEC\x91\xB2", + "\x9C\xCE" => "\xEC\x91\xB3", + "\x9C\xCF" => "\xEC\x91\xB6", + "\x9C\xD0" => "\xEC\x91\xB7", + "\x9C\xD1" => "\xEC\x91\xB8", + "\x9C\xD2" => "\xEC\x91\xBA", + "\x9C\xD3" => "\xEC\x91\xBB", + "\x9C\xD4" => "\xEC\x91\xBC", + "\x9C\xD5" => "\xEC\x91\xBD", + "\x9C\xD6" => "\xEC\x91\xBE", + "\x9C\xD7" => "\xEC\x91\xBF", + "\x9C\xD8" => "\xEC\x92\x81", + "\x9C\xD9" => "\xEC\x92\x82", + "\x9C\xDA" => "\xEC\x92\x83", + "\x9C\xDB" => "\xEC\x92\x84", + "\x9C\xDC" => "\xEC\x92\x85", + "\x9C\xDD" => "\xEC\x92\x86", + "\x9C\xDE" => "\xEC\x92\x87", + "\x9C\xDF" => "\xEC\x92\x88", + "\x9C\xE0" => "\xEC\x92\x89", + "\x9C\xE1" => "\xEC\x92\x8A", + "\x9C\xE2" => "\xEC\x92\x8B", + "\x9C\xE3" => "\xEC\x92\x8C", + "\x9C\xE4" => "\xEC\x92\x8D", + "\x9C\xE5" => "\xEC\x92\x8E", + "\x9C\xE6" => "\xEC\x92\x8F", + "\x9C\xE7" => "\xEC\x92\x90", + "\x9C\xE8" => "\xEC\x92\x91", + "\x9C\xE9" => "\xEC\x92\x92", + "\x9C\xEA" => "\xEC\x92\x93", + "\x9C\xEB" => "\xEC\x92\x95", + "\x9C\xEC" => "\xEC\x92\x96", + "\x9C\xED" => "\xEC\x92\x97", + "\x9C\xEE" => "\xEC\x92\x98", + "\x9C\xEF" => "\xEC\x92\x99", + "\x9C\xF0" => "\xEC\x92\x9A", + "\x9C\xF1" => "\xEC\x92\x9B", + "\x9C\xF2" => "\xEC\x92\x9D", + "\x9C\xF3" => "\xEC\x92\x9E", + "\x9C\xF4" => "\xEC\x92\x9F", + "\x9C\xF5" => "\xEC\x92\xA0", + "\x9C\xF6" => "\xEC\x92\xA1", + "\x9C\xF7" => "\xEC\x92\xA2", + "\x9C\xF8" => "\xEC\x92\xA3", + "\x9C\xF9" => "\xEC\x92\xA4", + "\x9C\xFA" => "\xEC\x92\xA5", + "\x9C\xFB" => "\xEC\x92\xA6", + "\x9C\xFC" => "\xEC\x92\xA7", + "\x9C\xFD" => "\xEC\x92\xA8", + "\x9C\xFE" => "\xEC\x92\xA9", + "\x9D\x41" => "\xEC\x92\xAA", + "\x9D\x42" => "\xEC\x92\xAB", + "\x9D\x43" => "\xEC\x92\xAC", + "\x9D\x44" => "\xEC\x92\xAD", + "\x9D\x45" => "\xEC\x92\xAE", + "\x9D\x46" => "\xEC\x92\xAF", + "\x9D\x47" => "\xEC\x92\xB0", + "\x9D\x48" => "\xEC\x92\xB1", + "\x9D\x49" => "\xEC\x92\xB2", + "\x9D\x4A" => "\xEC\x92\xB3", + "\x9D\x4B" => "\xEC\x92\xB4", + "\x9D\x4C" => "\xEC\x92\xB5", + "\x9D\x4D" => "\xEC\x92\xB6", + "\x9D\x4E" => "\xEC\x92\xB7", + "\x9D\x4F" => "\xEC\x92\xB9", + "\x9D\x50" => "\xEC\x92\xBA", + "\x9D\x51" => "\xEC\x92\xBB", + "\x9D\x52" => "\xEC\x92\xBD", + "\x9D\x53" => "\xEC\x92\xBE", + "\x9D\x54" => "\xEC\x92\xBF", + "\x9D\x55" => "\xEC\x93\x80", + "\x9D\x56" => "\xEC\x93\x81", + "\x9D\x57" => "\xEC\x93\x82", + "\x9D\x58" => "\xEC\x93\x83", + "\x9D\x59" => "\xEC\x93\x84", + "\x9D\x5A" => "\xEC\x93\x85", + "\x9D\x61" => "\xEC\x93\x86", + "\x9D\x62" => "\xEC\x93\x87", + "\x9D\x63" => "\xEC\x93\x88", + "\x9D\x64" => "\xEC\x93\x89", + "\x9D\x65" => "\xEC\x93\x8A", + "\x9D\x66" => "\xEC\x93\x8B", + "\x9D\x67" => "\xEC\x93\x8C", + "\x9D\x68" => "\xEC\x93\x8D", + "\x9D\x69" => "\xEC\x93\x8E", + "\x9D\x6A" => "\xEC\x93\x8F", + "\x9D\x6B" => "\xEC\x93\x90", + "\x9D\x6C" => "\xEC\x93\x91", + "\x9D\x6D" => "\xEC\x93\x92", + "\x9D\x6E" => "\xEC\x93\x93", + "\x9D\x6F" => "\xEC\x93\x94", + "\x9D\x70" => "\xEC\x93\x95", + "\x9D\x71" => "\xEC\x93\x96", + "\x9D\x72" => "\xEC\x93\x97", + "\x9D\x73" => "\xEC\x93\x98", + "\x9D\x74" => "\xEC\x93\x99", + "\x9D\x75" => "\xEC\x93\x9A", + "\x9D\x76" => "\xEC\x93\x9B", + "\x9D\x77" => "\xEC\x93\x9C", + "\x9D\x78" => "\xEC\x93\x9D", + "\x9D\x79" => "\xEC\x93\x9E", + "\x9D\x7A" => "\xEC\x93\x9F", + "\x9D\x81" => "\xEC\x93\xA0", + "\x9D\x82" => "\xEC\x93\xA1", + "\x9D\x83" => "\xEC\x93\xA2", + "\x9D\x84" => "\xEC\x93\xA3", + "\x9D\x85" => "\xEC\x93\xA4", + "\x9D\x86" => "\xEC\x93\xA5", + "\x9D\x87" => "\xEC\x93\xA6", + "\x9D\x88" => "\xEC\x93\xA7", + "\x9D\x89" => "\xEC\x93\xA8", + "\x9D\x8A" => "\xEC\x93\xAA", + "\x9D\x8B" => "\xEC\x93\xAB", + "\x9D\x8C" => "\xEC\x93\xAC", + "\x9D\x8D" => "\xEC\x93\xAD", + "\x9D\x8E" => "\xEC\x93\xAE", + "\x9D\x8F" => "\xEC\x93\xAF", + "\x9D\x90" => "\xEC\x93\xB2", + "\x9D\x91" => "\xEC\x93\xB3", + "\x9D\x92" => "\xEC\x93\xB5", + "\x9D\x93" => "\xEC\x93\xB6", + "\x9D\x94" => "\xEC\x93\xB7", + "\x9D\x95" => "\xEC\x93\xB9", + "\x9D\x96" => "\xEC\x93\xBB", + "\x9D\x97" => "\xEC\x93\xBC", + "\x9D\x98" => "\xEC\x93\xBD", + "\x9D\x99" => "\xEC\x93\xBE", + "\x9D\x9A" => "\xEC\x94\x82", + "\x9D\x9B" => "\xEC\x94\x83", + "\x9D\x9C" => "\xEC\x94\x84", + "\x9D\x9D" => "\xEC\x94\x85", + "\x9D\x9E" => "\xEC\x94\x86", + "\x9D\x9F" => "\xEC\x94\x87", + "\x9D\xA0" => "\xEC\x94\x88", + "\x9D\xA1" => "\xEC\x94\x89", + "\x9D\xA2" => "\xEC\x94\x8A", + "\x9D\xA3" => "\xEC\x94\x8B", + "\x9D\xA4" => "\xEC\x94\x8D", + "\x9D\xA5" => "\xEC\x94\x8E", + "\x9D\xA6" => "\xEC\x94\x8F", + "\x9D\xA7" => "\xEC\x94\x91", + "\x9D\xA8" => "\xEC\x94\x92", + "\x9D\xA9" => "\xEC\x94\x93", + "\x9D\xAA" => "\xEC\x94\x95", + "\x9D\xAB" => "\xEC\x94\x96", + "\x9D\xAC" => "\xEC\x94\x97", + "\x9D\xAD" => "\xEC\x94\x98", + "\x9D\xAE" => "\xEC\x94\x99", + "\x9D\xAF" => "\xEC\x94\x9A", + "\x9D\xB0" => "\xEC\x94\x9B", + "\x9D\xB1" => "\xEC\x94\x9D", + "\x9D\xB2" => "\xEC\x94\x9E", + "\x9D\xB3" => "\xEC\x94\x9F", + "\x9D\xB4" => "\xEC\x94\xA0", + "\x9D\xB5" => "\xEC\x94\xA1", + "\x9D\xB6" => "\xEC\x94\xA2", + "\x9D\xB7" => "\xEC\x94\xA3", + "\x9D\xB8" => "\xEC\x94\xA4", + "\x9D\xB9" => "\xEC\x94\xA5", + "\x9D\xBA" => "\xEC\x94\xA6", + "\x9D\xBB" => "\xEC\x94\xA7", + "\x9D\xBC" => "\xEC\x94\xAA", + "\x9D\xBD" => "\xEC\x94\xAB", + "\x9D\xBE" => "\xEC\x94\xAD", + "\x9D\xBF" => "\xEC\x94\xAE", + "\x9D\xC0" => "\xEC\x94\xAF", + "\x9D\xC1" => "\xEC\x94\xB1", + "\x9D\xC2" => "\xEC\x94\xB2", + "\x9D\xC3" => "\xEC\x94\xB3", + "\x9D\xC4" => "\xEC\x94\xB4", + "\x9D\xC5" => "\xEC\x94\xB5", + "\x9D\xC6" => "\xEC\x94\xB6", + "\x9D\xC7" => "\xEC\x94\xB7", + "\x9D\xC8" => "\xEC\x94\xBA", + "\x9D\xC9" => "\xEC\x94\xBC", + "\x9D\xCA" => "\xEC\x94\xBE", + "\x9D\xCB" => "\xEC\x94\xBF", + "\x9D\xCC" => "\xEC\x95\x80", + "\x9D\xCD" => "\xEC\x95\x81", + "\x9D\xCE" => "\xEC\x95\x82", + "\x9D\xCF" => "\xEC\x95\x83", + "\x9D\xD0" => "\xEC\x95\x86", + "\x9D\xD1" => "\xEC\x95\x87", + "\x9D\xD2" => "\xEC\x95\x8B", + "\x9D\xD3" => "\xEC\x95\x8F", + "\x9D\xD4" => "\xEC\x95\x90", + "\x9D\xD5" => "\xEC\x95\x91", + "\x9D\xD6" => "\xEC\x95\x92", + "\x9D\xD7" => "\xEC\x95\x96", + "\x9D\xD8" => "\xEC\x95\x9A", + "\x9D\xD9" => "\xEC\x95\x9B", + "\x9D\xDA" => "\xEC\x95\x9C", + "\x9D\xDB" => "\xEC\x95\x9F", + "\x9D\xDC" => "\xEC\x95\xA2", + "\x9D\xDD" => "\xEC\x95\xA3", + "\x9D\xDE" => "\xEC\x95\xA5", + "\x9D\xDF" => "\xEC\x95\xA6", + "\x9D\xE0" => "\xEC\x95\xA7", + "\x9D\xE1" => "\xEC\x95\xA9", + "\x9D\xE2" => "\xEC\x95\xAA", + "\x9D\xE3" => "\xEC\x95\xAB", + "\x9D\xE4" => "\xEC\x95\xAC", + "\x9D\xE5" => "\xEC\x95\xAD", + "\x9D\xE6" => "\xEC\x95\xAE", + "\x9D\xE7" => "\xEC\x95\xAF", + "\x9D\xE8" => "\xEC\x95\xB2", + "\x9D\xE9" => "\xEC\x95\xB6", + "\x9D\xEA" => "\xEC\x95\xB7", + "\x9D\xEB" => "\xEC\x95\xB8", + "\x9D\xEC" => "\xEC\x95\xB9", + "\x9D\xED" => "\xEC\x95\xBA", + "\x9D\xEE" => "\xEC\x95\xBB", + "\x9D\xEF" => "\xEC\x95\xBE", + "\x9D\xF0" => "\xEC\x95\xBF", + "\x9D\xF1" => "\xEC\x96\x81", + "\x9D\xF2" => "\xEC\x96\x82", + "\x9D\xF3" => "\xEC\x96\x83", + "\x9D\xF4" => "\xEC\x96\x85", + "\x9D\xF5" => "\xEC\x96\x86", + "\x9D\xF6" => "\xEC\x96\x88", + "\x9D\xF7" => "\xEC\x96\x89", + "\x9D\xF8" => "\xEC\x96\x8A", + "\x9D\xF9" => "\xEC\x96\x8B", + "\x9D\xFA" => "\xEC\x96\x8E", + "\x9D\xFB" => "\xEC\x96\x90", + "\x9D\xFC" => "\xEC\x96\x92", + "\x9D\xFD" => "\xEC\x96\x93", + "\x9D\xFE" => "\xEC\x96\x94", + "\x9E\x41" => "\xEC\x96\x96", + "\x9E\x42" => "\xEC\x96\x99", + "\x9E\x43" => "\xEC\x96\x9A", + "\x9E\x44" => "\xEC\x96\x9B", + "\x9E\x45" => "\xEC\x96\x9D", + "\x9E\x46" => "\xEC\x96\x9E", + "\x9E\x47" => "\xEC\x96\x9F", + "\x9E\x48" => "\xEC\x96\xA1", + "\x9E\x49" => "\xEC\x96\xA2", + "\x9E\x4A" => "\xEC\x96\xA3", + "\x9E\x4B" => "\xEC\x96\xA4", + "\x9E\x4C" => "\xEC\x96\xA5", + "\x9E\x4D" => "\xEC\x96\xA6", + "\x9E\x4E" => "\xEC\x96\xA7", + "\x9E\x4F" => "\xEC\x96\xA8", + "\x9E\x50" => "\xEC\x96\xAA", + "\x9E\x51" => "\xEC\x96\xAB", + "\x9E\x52" => "\xEC\x96\xAC", + "\x9E\x53" => "\xEC\x96\xAD", + "\x9E\x54" => "\xEC\x96\xAE", + "\x9E\x55" => "\xEC\x96\xAF", + "\x9E\x56" => "\xEC\x96\xB0", + "\x9E\x57" => "\xEC\x96\xB1", + "\x9E\x58" => "\xEC\x96\xB2", + "\x9E\x59" => "\xEC\x96\xB3", + "\x9E\x5A" => "\xEC\x96\xB6", + "\x9E\x61" => "\xEC\x96\xB7", + "\x9E\x62" => "\xEC\x96\xBA", + "\x9E\x63" => "\xEC\x96\xBF", + "\x9E\x64" => "\xEC\x97\x80", + "\x9E\x65" => "\xEC\x97\x81", + "\x9E\x66" => "\xEC\x97\x82", + "\x9E\x67" => "\xEC\x97\x83", + "\x9E\x68" => "\xEC\x97\x8B", + "\x9E\x69" => "\xEC\x97\x8D", + "\x9E\x6A" => "\xEC\x97\x8F", + "\x9E\x6B" => "\xEC\x97\x92", + "\x9E\x6C" => "\xEC\x97\x93", + "\x9E\x6D" => "\xEC\x97\x95", + "\x9E\x6E" => "\xEC\x97\x96", + "\x9E\x6F" => "\xEC\x97\x97", + "\x9E\x70" => "\xEC\x97\x99", + "\x9E\x71" => "\xEC\x97\x9A", + "\x9E\x72" => "\xEC\x97\x9B", + "\x9E\x73" => "\xEC\x97\x9C", + "\x9E\x74" => "\xEC\x97\x9D", + "\x9E\x75" => "\xEC\x97\x9E", + "\x9E\x76" => "\xEC\x97\x9F", + "\x9E\x77" => "\xEC\x97\xA2", + "\x9E\x78" => "\xEC\x97\xA4", + "\x9E\x79" => "\xEC\x97\xA6", + "\x9E\x7A" => "\xEC\x97\xA7", + "\x9E\x81" => "\xEC\x97\xA8", + "\x9E\x82" => "\xEC\x97\xA9", + "\x9E\x83" => "\xEC\x97\xAA", + "\x9E\x84" => "\xEC\x97\xAB", + "\x9E\x85" => "\xEC\x97\xAF", + "\x9E\x86" => "\xEC\x97\xB1", + "\x9E\x87" => "\xEC\x97\xB2", + "\x9E\x88" => "\xEC\x97\xB3", + "\x9E\x89" => "\xEC\x97\xB5", + "\x9E\x8A" => "\xEC\x97\xB8", + "\x9E\x8B" => "\xEC\x97\xB9", + "\x9E\x8C" => "\xEC\x97\xBA", + "\x9E\x8D" => "\xEC\x97\xBB", + "\x9E\x8E" => "\xEC\x98\x82", + "\x9E\x8F" => "\xEC\x98\x83", + "\x9E\x90" => "\xEC\x98\x84", + "\x9E\x91" => "\xEC\x98\x89", + "\x9E\x92" => "\xEC\x98\x8A", + "\x9E\x93" => "\xEC\x98\x8B", + "\x9E\x94" => "\xEC\x98\x8D", + "\x9E\x95" => "\xEC\x98\x8E", + "\x9E\x96" => "\xEC\x98\x8F", + "\x9E\x97" => "\xEC\x98\x91", + "\x9E\x98" => "\xEC\x98\x92", + "\x9E\x99" => "\xEC\x98\x93", + "\x9E\x9A" => "\xEC\x98\x94", + "\x9E\x9B" => "\xEC\x98\x95", + "\x9E\x9C" => "\xEC\x98\x96", + "\x9E\x9D" => "\xEC\x98\x97", + "\x9E\x9E" => "\xEC\x98\x9A", + "\x9E\x9F" => "\xEC\x98\x9D", + "\x9E\xA0" => "\xEC\x98\x9E", + "\x9E\xA1" => "\xEC\x98\x9F", + "\x9E\xA2" => "\xEC\x98\xA0", + "\x9E\xA3" => "\xEC\x98\xA1", + "\x9E\xA4" => "\xEC\x98\xA2", + "\x9E\xA5" => "\xEC\x98\xA3", + "\x9E\xA6" => "\xEC\x98\xA6", + "\x9E\xA7" => "\xEC\x98\xA7", + "\x9E\xA8" => "\xEC\x98\xA9", + "\x9E\xA9" => "\xEC\x98\xAA", + "\x9E\xAA" => "\xEC\x98\xAB", + "\x9E\xAB" => "\xEC\x98\xAF", + "\x9E\xAC" => "\xEC\x98\xB1", + "\x9E\xAD" => "\xEC\x98\xB2", + "\x9E\xAE" => "\xEC\x98\xB6", + "\x9E\xAF" => "\xEC\x98\xB8", + "\x9E\xB0" => "\xEC\x98\xBA", + "\x9E\xB1" => "\xEC\x98\xBC", + "\x9E\xB2" => "\xEC\x98\xBD", + "\x9E\xB3" => "\xEC\x98\xBE", + "\x9E\xB4" => "\xEC\x98\xBF", + "\x9E\xB5" => "\xEC\x99\x82", + "\x9E\xB6" => "\xEC\x99\x83", + "\x9E\xB7" => "\xEC\x99\x85", + "\x9E\xB8" => "\xEC\x99\x86", + "\x9E\xB9" => "\xEC\x99\x87", + "\x9E\xBA" => "\xEC\x99\x89", + "\x9E\xBB" => "\xEC\x99\x8A", + "\x9E\xBC" => "\xEC\x99\x8B", + "\x9E\xBD" => "\xEC\x99\x8C", + "\x9E\xBE" => "\xEC\x99\x8D", + "\x9E\xBF" => "\xEC\x99\x8E", + "\x9E\xC0" => "\xEC\x99\x8F", + "\x9E\xC1" => "\xEC\x99\x92", + "\x9E\xC2" => "\xEC\x99\x96", + "\x9E\xC3" => "\xEC\x99\x97", + "\x9E\xC4" => "\xEC\x99\x98", + "\x9E\xC5" => "\xEC\x99\x99", + "\x9E\xC6" => "\xEC\x99\x9A", + "\x9E\xC7" => "\xEC\x99\x9B", + "\x9E\xC8" => "\xEC\x99\x9E", + "\x9E\xC9" => "\xEC\x99\x9F", + "\x9E\xCA" => "\xEC\x99\xA1", + "\x9E\xCB" => "\xEC\x99\xA2", + "\x9E\xCC" => "\xEC\x99\xA3", + "\x9E\xCD" => "\xEC\x99\xA4", + "\x9E\xCE" => "\xEC\x99\xA5", + "\x9E\xCF" => "\xEC\x99\xA6", + "\x9E\xD0" => "\xEC\x99\xA7", + "\x9E\xD1" => "\xEC\x99\xA8", + "\x9E\xD2" => "\xEC\x99\xA9", + "\x9E\xD3" => "\xEC\x99\xAA", + "\x9E\xD4" => "\xEC\x99\xAB", + "\x9E\xD5" => "\xEC\x99\xAD", + "\x9E\xD6" => "\xEC\x99\xAE", + "\x9E\xD7" => "\xEC\x99\xB0", + "\x9E\xD8" => "\xEC\x99\xB2", + "\x9E\xD9" => "\xEC\x99\xB3", + "\x9E\xDA" => "\xEC\x99\xB4", + "\x9E\xDB" => "\xEC\x99\xB5", + "\x9E\xDC" => "\xEC\x99\xB6", + "\x9E\xDD" => "\xEC\x99\xB7", + "\x9E\xDE" => "\xEC\x99\xBA", + "\x9E\xDF" => "\xEC\x99\xBB", + "\x9E\xE0" => "\xEC\x99\xBD", + "\x9E\xE1" => "\xEC\x99\xBE", + "\x9E\xE2" => "\xEC\x99\xBF", + "\x9E\xE3" => "\xEC\x9A\x81", + "\x9E\xE4" => "\xEC\x9A\x82", + "\x9E\xE5" => "\xEC\x9A\x83", + "\x9E\xE6" => "\xEC\x9A\x84", + "\x9E\xE7" => "\xEC\x9A\x85", + "\x9E\xE8" => "\xEC\x9A\x86", + "\x9E\xE9" => "\xEC\x9A\x87", + "\x9E\xEA" => "\xEC\x9A\x8A", + "\x9E\xEB" => "\xEC\x9A\x8C", + "\x9E\xEC" => "\xEC\x9A\x8E", + "\x9E\xED" => "\xEC\x9A\x8F", + "\x9E\xEE" => "\xEC\x9A\x90", + "\x9E\xEF" => "\xEC\x9A\x91", + "\x9E\xF0" => "\xEC\x9A\x92", + "\x9E\xF1" => "\xEC\x9A\x93", + "\x9E\xF2" => "\xEC\x9A\x96", + "\x9E\xF3" => "\xEC\x9A\x97", + "\x9E\xF4" => "\xEC\x9A\x99", + "\x9E\xF5" => "\xEC\x9A\x9A", + "\x9E\xF6" => "\xEC\x9A\x9B", + "\x9E\xF7" => "\xEC\x9A\x9D", + "\x9E\xF8" => "\xEC\x9A\x9E", + "\x9E\xF9" => "\xEC\x9A\x9F", + "\x9E\xFA" => "\xEC\x9A\xA0", + "\x9E\xFB" => "\xEC\x9A\xA1", + "\x9E\xFC" => "\xEC\x9A\xA2", + "\x9E\xFD" => "\xEC\x9A\xA3", + "\x9E\xFE" => "\xEC\x9A\xA6", + "\x9F\x41" => "\xEC\x9A\xA8", + "\x9F\x42" => "\xEC\x9A\xAA", + "\x9F\x43" => "\xEC\x9A\xAB", + "\x9F\x44" => "\xEC\x9A\xAC", + "\x9F\x45" => "\xEC\x9A\xAD", + "\x9F\x46" => "\xEC\x9A\xAE", + "\x9F\x47" => "\xEC\x9A\xAF", + "\x9F\x48" => "\xEC\x9A\xB2", + "\x9F\x49" => "\xEC\x9A\xB3", + "\x9F\x4A" => "\xEC\x9A\xB5", + "\x9F\x4B" => "\xEC\x9A\xB6", + "\x9F\x4C" => "\xEC\x9A\xB7", + "\x9F\x4D" => "\xEC\x9A\xBB", + "\x9F\x4E" => "\xEC\x9A\xBC", + "\x9F\x4F" => "\xEC\x9A\xBD", + "\x9F\x50" => "\xEC\x9A\xBE", + "\x9F\x51" => "\xEC\x9A\xBF", + "\x9F\x52" => "\xEC\x9B\x82", + "\x9F\x53" => "\xEC\x9B\x84", + "\x9F\x54" => "\xEC\x9B\x86", + "\x9F\x55" => "\xEC\x9B\x87", + "\x9F\x56" => "\xEC\x9B\x88", + "\x9F\x57" => "\xEC\x9B\x89", + "\x9F\x58" => "\xEC\x9B\x8A", + "\x9F\x59" => "\xEC\x9B\x8B", + "\x9F\x5A" => "\xEC\x9B\x8E", + "\x9F\x61" => "\xEC\x9B\x8F", + "\x9F\x62" => "\xEC\x9B\x91", + "\x9F\x63" => "\xEC\x9B\x92", + "\x9F\x64" => "\xEC\x9B\x93", + "\x9F\x65" => "\xEC\x9B\x95", + "\x9F\x66" => "\xEC\x9B\x96", + "\x9F\x67" => "\xEC\x9B\x97", + "\x9F\x68" => "\xEC\x9B\x98", + "\x9F\x69" => "\xEC\x9B\x99", + "\x9F\x6A" => "\xEC\x9B\x9A", + "\x9F\x6B" => "\xEC\x9B\x9B", + "\x9F\x6C" => "\xEC\x9B\x9E", + "\x9F\x6D" => "\xEC\x9B\x9F", + "\x9F\x6E" => "\xEC\x9B\xA2", + "\x9F\x6F" => "\xEC\x9B\xA3", + "\x9F\x70" => "\xEC\x9B\xA4", + "\x9F\x71" => "\xEC\x9B\xA5", + "\x9F\x72" => "\xEC\x9B\xA6", + "\x9F\x73" => "\xEC\x9B\xA7", + "\x9F\x74" => "\xEC\x9B\xAA", + "\x9F\x75" => "\xEC\x9B\xAB", + "\x9F\x76" => "\xEC\x9B\xAD", + "\x9F\x77" => "\xEC\x9B\xAE", + "\x9F\x78" => "\xEC\x9B\xAF", + "\x9F\x79" => "\xEC\x9B\xB1", + "\x9F\x7A" => "\xEC\x9B\xB2", + "\x9F\x81" => "\xEC\x9B\xB3", + "\x9F\x82" => "\xEC\x9B\xB4", + "\x9F\x83" => "\xEC\x9B\xB5", + "\x9F\x84" => "\xEC\x9B\xB6", + "\x9F\x85" => "\xEC\x9B\xB7", + "\x9F\x86" => "\xEC\x9B\xBA", + "\x9F\x87" => "\xEC\x9B\xBB", + "\x9F\x88" => "\xEC\x9B\xBC", + "\x9F\x89" => "\xEC\x9B\xBE", + "\x9F\x8A" => "\xEC\x9B\xBF", + "\x9F\x8B" => "\xEC\x9C\x80", + "\x9F\x8C" => "\xEC\x9C\x81", + "\x9F\x8D" => "\xEC\x9C\x82", + "\x9F\x8E" => "\xEC\x9C\x83", + "\x9F\x8F" => "\xEC\x9C\x86", + "\x9F\x90" => "\xEC\x9C\x87", + "\x9F\x91" => "\xEC\x9C\x89", + "\x9F\x92" => "\xEC\x9C\x8A", + "\x9F\x93" => "\xEC\x9C\x8B", + "\x9F\x94" => "\xEC\x9C\x8D", + "\x9F\x95" => "\xEC\x9C\x8E", + "\x9F\x96" => "\xEC\x9C\x8F", + "\x9F\x97" => "\xEC\x9C\x90", + "\x9F\x98" => "\xEC\x9C\x91", + "\x9F\x99" => "\xEC\x9C\x92", + "\x9F\x9A" => "\xEC\x9C\x93", + "\x9F\x9B" => "\xEC\x9C\x96", + "\x9F\x9C" => "\xEC\x9C\x98", + "\x9F\x9D" => "\xEC\x9C\x9A", + "\x9F\x9E" => "\xEC\x9C\x9B", + "\x9F\x9F" => "\xEC\x9C\x9C", + "\x9F\xA0" => "\xEC\x9C\x9D", + "\x9F\xA1" => "\xEC\x9C\x9E", + "\x9F\xA2" => "\xEC\x9C\x9F", + "\x9F\xA3" => "\xEC\x9C\xA2", + "\x9F\xA4" => "\xEC\x9C\xA3", + "\x9F\xA5" => "\xEC\x9C\xA5", + "\x9F\xA6" => "\xEC\x9C\xA6", + "\x9F\xA7" => "\xEC\x9C\xA7", + "\x9F\xA8" => "\xEC\x9C\xA9", + "\x9F\xA9" => "\xEC\x9C\xAA", + "\x9F\xAA" => "\xEC\x9C\xAB", + "\x9F\xAB" => "\xEC\x9C\xAC", + "\x9F\xAC" => "\xEC\x9C\xAD", + "\x9F\xAD" => "\xEC\x9C\xAE", + "\x9F\xAE" => "\xEC\x9C\xAF", + "\x9F\xAF" => "\xEC\x9C\xB2", + "\x9F\xB0" => "\xEC\x9C\xB4", + "\x9F\xB1" => "\xEC\x9C\xB6", + "\x9F\xB2" => "\xEC\x9C\xB8", + "\x9F\xB3" => "\xEC\x9C\xB9", + "\x9F\xB4" => "\xEC\x9C\xBA", + "\x9F\xB5" => "\xEC\x9C\xBB", + "\x9F\xB6" => "\xEC\x9C\xBE", + "\x9F\xB7" => "\xEC\x9C\xBF", + "\x9F\xB8" => "\xEC\x9D\x81", + "\x9F\xB9" => "\xEC\x9D\x82", + "\x9F\xBA" => "\xEC\x9D\x83", + "\x9F\xBB" => "\xEC\x9D\x85", + "\x9F\xBC" => "\xEC\x9D\x86", + "\x9F\xBD" => "\xEC\x9D\x87", + "\x9F\xBE" => "\xEC\x9D\x88", + "\x9F\xBF" => "\xEC\x9D\x89", + "\x9F\xC0" => "\xEC\x9D\x8B", + "\x9F\xC1" => "\xEC\x9D\x8E", + "\x9F\xC2" => "\xEC\x9D\x90", + "\x9F\xC3" => "\xEC\x9D\x99", + "\x9F\xC4" => "\xEC\x9D\x9A", + "\x9F\xC5" => "\xEC\x9D\x9B", + "\x9F\xC6" => "\xEC\x9D\x9D", + "\x9F\xC7" => "\xEC\x9D\x9E", + "\x9F\xC8" => "\xEC\x9D\x9F", + "\x9F\xC9" => "\xEC\x9D\xA1", + "\x9F\xCA" => "\xEC\x9D\xA2", + "\x9F\xCB" => "\xEC\x9D\xA3", + "\x9F\xCC" => "\xEC\x9D\xA4", + "\x9F\xCD" => "\xEC\x9D\xA5", + "\x9F\xCE" => "\xEC\x9D\xA6", + "\x9F\xCF" => "\xEC\x9D\xA7", + "\x9F\xD0" => "\xEC\x9D\xA9", + "\x9F\xD1" => "\xEC\x9D\xAA", + "\x9F\xD2" => "\xEC\x9D\xAC", + "\x9F\xD3" => "\xEC\x9D\xAD", + "\x9F\xD4" => "\xEC\x9D\xAE", + "\x9F\xD5" => "\xEC\x9D\xAF", + "\x9F\xD6" => "\xEC\x9D\xB0", + "\x9F\xD7" => "\xEC\x9D\xB1", + "\x9F\xD8" => "\xEC\x9D\xB2", + "\x9F\xD9" => "\xEC\x9D\xB3", + "\x9F\xDA" => "\xEC\x9D\xB6", + "\x9F\xDB" => "\xEC\x9D\xB7", + "\x9F\xDC" => "\xEC\x9D\xB9", + "\x9F\xDD" => "\xEC\x9D\xBA", + "\x9F\xDE" => "\xEC\x9D\xBB", + "\x9F\xDF" => "\xEC\x9D\xBF", + "\x9F\xE0" => "\xEC\x9E\x80", + "\x9F\xE1" => "\xEC\x9E\x81", + "\x9F\xE2" => "\xEC\x9E\x82", + "\x9F\xE3" => "\xEC\x9E\x86", + "\x9F\xE4" => "\xEC\x9E\x8B", + "\x9F\xE5" => "\xEC\x9E\x8C", + "\x9F\xE6" => "\xEC\x9E\x8D", + "\x9F\xE7" => "\xEC\x9E\x8F", + "\x9F\xE8" => "\xEC\x9E\x92", + "\x9F\xE9" => "\xEC\x9E\x93", + "\x9F\xEA" => "\xEC\x9E\x95", + "\x9F\xEB" => "\xEC\x9E\x99", + "\x9F\xEC" => "\xEC\x9E\x9B", + "\x9F\xED" => "\xEC\x9E\x9C", + "\x9F\xEE" => "\xEC\x9E\x9D", + "\x9F\xEF" => "\xEC\x9E\x9E", + "\x9F\xF0" => "\xEC\x9E\x9F", + "\x9F\xF1" => "\xEC\x9E\xA2", + "\x9F\xF2" => "\xEC\x9E\xA7", + "\x9F\xF3" => "\xEC\x9E\xA8", + "\x9F\xF4" => "\xEC\x9E\xA9", + "\x9F\xF5" => "\xEC\x9E\xAA", + "\x9F\xF6" => "\xEC\x9E\xAB", + "\x9F\xF7" => "\xEC\x9E\xAE", + "\x9F\xF8" => "\xEC\x9E\xAF", + "\x9F\xF9" => "\xEC\x9E\xB1", + "\x9F\xFA" => "\xEC\x9E\xB2", + "\x9F\xFB" => "\xEC\x9E\xB3", + "\x9F\xFC" => "\xEC\x9E\xB5", + "\x9F\xFD" => "\xEC\x9E\xB6", + "\x9F\xFE" => "\xEC\x9E\xB7", + "\xA0\x41" => "\xEC\x9E\xB8", + "\xA0\x42" => "\xEC\x9E\xB9", + "\xA0\x43" => "\xEC\x9E\xBA", + "\xA0\x44" => "\xEC\x9E\xBB", + "\xA0\x45" => "\xEC\x9E\xBE", + "\xA0\x46" => "\xEC\x9F\x82", + "\xA0\x47" => "\xEC\x9F\x83", + "\xA0\x48" => "\xEC\x9F\x84", + "\xA0\x49" => "\xEC\x9F\x85", + "\xA0\x4A" => "\xEC\x9F\x86", + "\xA0\x4B" => "\xEC\x9F\x87", + "\xA0\x4C" => "\xEC\x9F\x8A", + "\xA0\x4D" => "\xEC\x9F\x8B", + "\xA0\x4E" => "\xEC\x9F\x8D", + "\xA0\x4F" => "\xEC\x9F\x8F", + "\xA0\x50" => "\xEC\x9F\x91", + "\xA0\x51" => "\xEC\x9F\x92", + "\xA0\x52" => "\xEC\x9F\x93", + "\xA0\x53" => "\xEC\x9F\x94", + "\xA0\x54" => "\xEC\x9F\x95", + "\xA0\x55" => "\xEC\x9F\x96", + "\xA0\x56" => "\xEC\x9F\x97", + "\xA0\x57" => "\xEC\x9F\x99", + "\xA0\x58" => "\xEC\x9F\x9A", + "\xA0\x59" => "\xEC\x9F\x9B", + "\xA0\x5A" => "\xEC\x9F\x9C", + "\xA0\x61" => "\xEC\x9F\x9E", + "\xA0\x62" => "\xEC\x9F\x9F", + "\xA0\x63" => "\xEC\x9F\xA0", + "\xA0\x64" => "\xEC\x9F\xA1", + "\xA0\x65" => "\xEC\x9F\xA2", + "\xA0\x66" => "\xEC\x9F\xA3", + "\xA0\x67" => "\xEC\x9F\xA5", + "\xA0\x68" => "\xEC\x9F\xA6", + "\xA0\x69" => "\xEC\x9F\xA7", + "\xA0\x6A" => "\xEC\x9F\xA9", + "\xA0\x6B" => "\xEC\x9F\xAA", + "\xA0\x6C" => "\xEC\x9F\xAB", + "\xA0\x6D" => "\xEC\x9F\xAD", + "\xA0\x6E" => "\xEC\x9F\xAE", + "\xA0\x6F" => "\xEC\x9F\xAF", + "\xA0\x70" => "\xEC\x9F\xB0", + "\xA0\x71" => "\xEC\x9F\xB1", + "\xA0\x72" => "\xEC\x9F\xB2", + "\xA0\x73" => "\xEC\x9F\xB3", + "\xA0\x74" => "\xEC\x9F\xB4", + "\xA0\x75" => "\xEC\x9F\xB5", + "\xA0\x76" => "\xEC\x9F\xB6", + "\xA0\x77" => "\xEC\x9F\xB7", + "\xA0\x78" => "\xEC\x9F\xB8", + "\xA0\x79" => "\xEC\x9F\xB9", + "\xA0\x7A" => "\xEC\x9F\xBA", + "\xA0\x81" => "\xEC\x9F\xBB", + "\xA0\x82" => "\xEC\x9F\xBC", + "\xA0\x83" => "\xEC\x9F\xBD", + "\xA0\x84" => "\xEC\x9F\xBE", + "\xA0\x85" => "\xEC\x9F\xBF", + "\xA0\x86" => "\xEC\xA0\x82", + "\xA0\x87" => "\xEC\xA0\x83", + "\xA0\x88" => "\xEC\xA0\x85", + "\xA0\x89" => "\xEC\xA0\x86", + "\xA0\x8A" => "\xEC\xA0\x87", + "\xA0\x8B" => "\xEC\xA0\x89", + "\xA0\x8C" => "\xEC\xA0\x8B", + "\xA0\x8D" => "\xEC\xA0\x8C", + "\xA0\x8E" => "\xEC\xA0\x8D", + "\xA0\x8F" => "\xEC\xA0\x8E", + "\xA0\x90" => "\xEC\xA0\x8F", + "\xA0\x91" => "\xEC\xA0\x92", + "\xA0\x92" => "\xEC\xA0\x94", + "\xA0\x93" => "\xEC\xA0\x97", + "\xA0\x94" => "\xEC\xA0\x98", + "\xA0\x95" => "\xEC\xA0\x99", + "\xA0\x96" => "\xEC\xA0\x9A", + "\xA0\x97" => "\xEC\xA0\x9B", + "\xA0\x98" => "\xEC\xA0\x9E", + "\xA0\x99" => "\xEC\xA0\x9F", + "\xA0\x9A" => "\xEC\xA0\xA1", + "\xA0\x9B" => "\xEC\xA0\xA2", + "\xA0\x9C" => "\xEC\xA0\xA3", + "\xA0\x9D" => "\xEC\xA0\xA5", + "\xA0\x9E" => "\xEC\xA0\xA6", + "\xA0\x9F" => "\xEC\xA0\xA7", + "\xA0\xA0" => "\xEC\xA0\xA8", + "\xA0\xA1" => "\xEC\xA0\xA9", + "\xA0\xA2" => "\xEC\xA0\xAA", + "\xA0\xA3" => "\xEC\xA0\xAB", + "\xA0\xA4" => "\xEC\xA0\xAE", + "\xA0\xA5" => "\xEC\xA0\xB0", + "\xA0\xA6" => "\xEC\xA0\xB2", + "\xA0\xA7" => "\xEC\xA0\xB3", + "\xA0\xA8" => "\xEC\xA0\xB4", + "\xA0\xA9" => "\xEC\xA0\xB5", + "\xA0\xAA" => "\xEC\xA0\xB6", + "\xA0\xAB" => "\xEC\xA0\xB7", + "\xA0\xAC" => "\xEC\xA0\xB9", + "\xA0\xAD" => "\xEC\xA0\xBA", + "\xA0\xAE" => "\xEC\xA0\xBB", + "\xA0\xAF" => "\xEC\xA0\xBD", + "\xA0\xB0" => "\xEC\xA0\xBE", + "\xA0\xB1" => "\xEC\xA0\xBF", + "\xA0\xB2" => "\xEC\xA1\x81", + "\xA0\xB3" => "\xEC\xA1\x82", + "\xA0\xB4" => "\xEC\xA1\x83", + "\xA0\xB5" => "\xEC\xA1\x84", + "\xA0\xB6" => "\xEC\xA1\x85", + "\xA0\xB7" => "\xEC\xA1\x86", + "\xA0\xB8" => "\xEC\xA1\x87", + "\xA0\xB9" => "\xEC\xA1\x8A", + "\xA0\xBA" => "\xEC\xA1\x8B", + "\xA0\xBB" => "\xEC\xA1\x8E", + "\xA0\xBC" => "\xEC\xA1\x8F", + "\xA0\xBD" => "\xEC\xA1\x90", + "\xA0\xBE" => "\xEC\xA1\x91", + "\xA0\xBF" => "\xEC\xA1\x92", + "\xA0\xC0" => "\xEC\xA1\x93", + "\xA0\xC1" => "\xEC\xA1\x95", + "\xA0\xC2" => "\xEC\xA1\x96", + "\xA0\xC3" => "\xEC\xA1\x97", + "\xA0\xC4" => "\xEC\xA1\x98", + "\xA0\xC5" => "\xEC\xA1\x99", + "\xA0\xC6" => "\xEC\xA1\x9A", + "\xA0\xC7" => "\xEC\xA1\x9B", + "\xA0\xC8" => "\xEC\xA1\x9C", + "\xA0\xC9" => "\xEC\xA1\x9D", + "\xA0\xCA" => "\xEC\xA1\x9E", + "\xA0\xCB" => "\xEC\xA1\x9F", + "\xA0\xCC" => "\xEC\xA1\xA0", + "\xA0\xCD" => "\xEC\xA1\xA1", + "\xA0\xCE" => "\xEC\xA1\xA2", + "\xA0\xCF" => "\xEC\xA1\xA3", + "\xA0\xD0" => "\xEC\xA1\xA4", + "\xA0\xD1" => "\xEC\xA1\xA5", + "\xA0\xD2" => "\xEC\xA1\xA6", + "\xA0\xD3" => "\xEC\xA1\xA7", + "\xA0\xD4" => "\xEC\xA1\xA8", + "\xA0\xD5" => "\xEC\xA1\xA9", + "\xA0\xD6" => "\xEC\xA1\xAA", + "\xA0\xD7" => "\xEC\xA1\xAB", + "\xA0\xD8" => "\xEC\xA1\xAC", + "\xA0\xD9" => "\xEC\xA1\xAD", + "\xA0\xDA" => "\xEC\xA1\xAE", + "\xA0\xDB" => "\xEC\xA1\xAF", + "\xA0\xDC" => "\xEC\xA1\xB2", + "\xA0\xDD" => "\xEC\xA1\xB3", + "\xA0\xDE" => "\xEC\xA1\xB5", + "\xA0\xDF" => "\xEC\xA1\xB6", + "\xA0\xE0" => "\xEC\xA1\xB7", + "\xA0\xE1" => "\xEC\xA1\xB9", + "\xA0\xE2" => "\xEC\xA1\xBB", + "\xA0\xE3" => "\xEC\xA1\xBC", + "\xA0\xE4" => "\xEC\xA1\xBD", + "\xA0\xE5" => "\xEC\xA1\xBE", + "\xA0\xE6" => "\xEC\xA1\xBF", + "\xA0\xE7" => "\xEC\xA2\x82", + "\xA0\xE8" => "\xEC\xA2\x84", + "\xA0\xE9" => "\xEC\xA2\x88", + "\xA0\xEA" => "\xEC\xA2\x89", + "\xA0\xEB" => "\xEC\xA2\x8A", + "\xA0\xEC" => "\xEC\xA2\x8E", + "\xA0\xED" => "\xEC\xA2\x8F", + "\xA0\xEE" => "\xEC\xA2\x90", + "\xA0\xEF" => "\xEC\xA2\x91", + "\xA0\xF0" => "\xEC\xA2\x92", + "\xA0\xF1" => "\xEC\xA2\x93", + "\xA0\xF2" => "\xEC\xA2\x95", + "\xA0\xF3" => "\xEC\xA2\x96", + "\xA0\xF4" => "\xEC\xA2\x97", + "\xA0\xF5" => "\xEC\xA2\x98", + "\xA0\xF6" => "\xEC\xA2\x99", + "\xA0\xF7" => "\xEC\xA2\x9A", + "\xA0\xF8" => "\xEC\xA2\x9B", + "\xA0\xF9" => "\xEC\xA2\x9C", + "\xA0\xFA" => "\xEC\xA2\x9E", + "\xA0\xFB" => "\xEC\xA2\xA0", + "\xA0\xFC" => "\xEC\xA2\xA2", + "\xA0\xFD" => "\xEC\xA2\xA3", + "\xA0\xFE" => "\xEC\xA2\xA4", + "\xA1\x41" => "\xEC\xA2\xA5", + "\xA1\x42" => "\xEC\xA2\xA6", + "\xA1\x43" => "\xEC\xA2\xA7", + "\xA1\x44" => "\xEC\xA2\xA9", + "\xA1\x45" => "\xEC\xA2\xAA", + "\xA1\x46" => "\xEC\xA2\xAB", + "\xA1\x47" => "\xEC\xA2\xAC", + "\xA1\x48" => "\xEC\xA2\xAD", + "\xA1\x49" => "\xEC\xA2\xAE", + "\xA1\x4A" => "\xEC\xA2\xAF", + "\xA1\x4B" => "\xEC\xA2\xB0", + "\xA1\x4C" => "\xEC\xA2\xB1", + "\xA1\x4D" => "\xEC\xA2\xB2", + "\xA1\x4E" => "\xEC\xA2\xB3", + "\xA1\x4F" => "\xEC\xA2\xB4", + "\xA1\x50" => "\xEC\xA2\xB5", + "\xA1\x51" => "\xEC\xA2\xB6", + "\xA1\x52" => "\xEC\xA2\xB7", + "\xA1\x53" => "\xEC\xA2\xB8", + "\xA1\x54" => "\xEC\xA2\xB9", + "\xA1\x55" => "\xEC\xA2\xBA", + "\xA1\x56" => "\xEC\xA2\xBB", + "\xA1\x57" => "\xEC\xA2\xBE", + "\xA1\x58" => "\xEC\xA2\xBF", + "\xA1\x59" => "\xEC\xA3\x80", + "\xA1\x5A" => "\xEC\xA3\x81", + "\xA1\x61" => "\xEC\xA3\x82", + "\xA1\x62" => "\xEC\xA3\x83", + "\xA1\x63" => "\xEC\xA3\x85", + "\xA1\x64" => "\xEC\xA3\x86", + "\xA1\x65" => "\xEC\xA3\x87", + "\xA1\x66" => "\xEC\xA3\x89", + "\xA1\x67" => "\xEC\xA3\x8A", + "\xA1\x68" => "\xEC\xA3\x8B", + "\xA1\x69" => "\xEC\xA3\x8D", + "\xA1\x6A" => "\xEC\xA3\x8E", + "\xA1\x6B" => "\xEC\xA3\x8F", + "\xA1\x6C" => "\xEC\xA3\x90", + "\xA1\x6D" => "\xEC\xA3\x91", + "\xA1\x6E" => "\xEC\xA3\x92", + "\xA1\x6F" => "\xEC\xA3\x93", + "\xA1\x70" => "\xEC\xA3\x96", + "\xA1\x71" => "\xEC\xA3\x98", + "\xA1\x72" => "\xEC\xA3\x9A", + "\xA1\x73" => "\xEC\xA3\x9B", + "\xA1\x74" => "\xEC\xA3\x9C", + "\xA1\x75" => "\xEC\xA3\x9D", + "\xA1\x76" => "\xEC\xA3\x9E", + "\xA1\x77" => "\xEC\xA3\x9F", + "\xA1\x78" => "\xEC\xA3\xA2", + "\xA1\x79" => "\xEC\xA3\xA3", + "\xA1\x7A" => "\xEC\xA3\xA5", + "\xA1\x81" => "\xEC\xA3\xA6", + "\xA1\x82" => "\xEC\xA3\xA7", + "\xA1\x83" => "\xEC\xA3\xA8", + "\xA1\x84" => "\xEC\xA3\xA9", + "\xA1\x85" => "\xEC\xA3\xAA", + "\xA1\x86" => "\xEC\xA3\xAB", + "\xA1\x87" => "\xEC\xA3\xAC", + "\xA1\x88" => "\xEC\xA3\xAD", + "\xA1\x89" => "\xEC\xA3\xAE", + "\xA1\x8A" => "\xEC\xA3\xAF", + "\xA1\x8B" => "\xEC\xA3\xB0", + "\xA1\x8C" => "\xEC\xA3\xB1", + "\xA1\x8D" => "\xEC\xA3\xB2", + "\xA1\x8E" => "\xEC\xA3\xB3", + "\xA1\x8F" => "\xEC\xA3\xB4", + "\xA1\x90" => "\xEC\xA3\xB6", + "\xA1\x91" => "\xEC\xA3\xB7", + "\xA1\x92" => "\xEC\xA3\xB8", + "\xA1\x93" => "\xEC\xA3\xB9", + "\xA1\x94" => "\xEC\xA3\xBA", + "\xA1\x95" => "\xEC\xA3\xBB", + "\xA1\x96" => "\xEC\xA3\xBE", + "\xA1\x97" => "\xEC\xA3\xBF", + "\xA1\x98" => "\xEC\xA4\x81", + "\xA1\x99" => "\xEC\xA4\x82", + "\xA1\x9A" => "\xEC\xA4\x83", + "\xA1\x9B" => "\xEC\xA4\x87", + "\xA1\x9C" => "\xEC\xA4\x88", + "\xA1\x9D" => "\xEC\xA4\x89", + "\xA1\x9E" => "\xEC\xA4\x8A", + "\xA1\x9F" => "\xEC\xA4\x8B", + "\xA1\xA0" => "\xEC\xA4\x8E", + "\xA1\xA1" => "\xE3\x80\x80", + "\xA1\xA2" => "\xE3\x80\x81", + "\xA1\xA3" => "\xE3\x80\x82", + "\xA1\xA4" => "\xC2\xB7", + "\xA1\xA5" => "\xE2\x80\xA5", + "\xA1\xA6" => "\xE2\x80\xA6", + "\xA1\xA7" => "\xC2\xA8", + "\xA1\xA8" => "\xE3\x80\x83", + "\xA1\xA9" => "\xC2\xAD", + "\xA1\xAA" => "\xE2\x80\x95", + "\xA1\xAB" => "\xE2\x88\xA5", + "\xA1\xAC" => "\xEF\xBC\xBC", + "\xA1\xAD" => "\xE2\x88\xBC", + "\xA1\xAE" => "\xE2\x80\x98", + "\xA1\xAF" => "\xE2\x80\x99", + "\xA1\xB0" => "\xE2\x80\x9C", + "\xA1\xB1" => "\xE2\x80\x9D", + "\xA1\xB2" => "\xE3\x80\x94", + "\xA1\xB3" => "\xE3\x80\x95", + "\xA1\xB4" => "\xE3\x80\x88", + "\xA1\xB5" => "\xE3\x80\x89", + "\xA1\xB6" => "\xE3\x80\x8A", + "\xA1\xB7" => "\xE3\x80\x8B", + "\xA1\xB8" => "\xE3\x80\x8C", + "\xA1\xB9" => "\xE3\x80\x8D", + "\xA1\xBA" => "\xE3\x80\x8E", + "\xA1\xBB" => "\xE3\x80\x8F", + "\xA1\xBC" => "\xE3\x80\x90", + "\xA1\xBD" => "\xE3\x80\x91", + "\xA1\xBE" => "\xC2\xB1", + "\xA1\xBF" => "\xC3\x97", + "\xA1\xC0" => "\xC3\xB7", + "\xA1\xC1" => "\xE2\x89\xA0", + "\xA1\xC2" => "\xE2\x89\xA4", + "\xA1\xC3" => "\xE2\x89\xA5", + "\xA1\xC4" => "\xE2\x88\x9E", + "\xA1\xC5" => "\xE2\x88\xB4", + "\xA1\xC6" => "\xC2\xB0", + "\xA1\xC7" => "\xE2\x80\xB2", + "\xA1\xC8" => "\xE2\x80\xB3", + "\xA1\xC9" => "\xE2\x84\x83", + "\xA1\xCA" => "\xE2\x84\xAB", + "\xA1\xCB" => "\xEF\xBF\xA0", + "\xA1\xCC" => "\xEF\xBF\xA1", + "\xA1\xCD" => "\xEF\xBF\xA5", + "\xA1\xCE" => "\xE2\x99\x82", + "\xA1\xCF" => "\xE2\x99\x80", + "\xA1\xD0" => "\xE2\x88\xA0", + "\xA1\xD1" => "\xE2\x8A\xA5", + "\xA1\xD2" => "\xE2\x8C\x92", + "\xA1\xD3" => "\xE2\x88\x82", + "\xA1\xD4" => "\xE2\x88\x87", + "\xA1\xD5" => "\xE2\x89\xA1", + "\xA1\xD6" => "\xE2\x89\x92", + "\xA1\xD7" => "\xC2\xA7", + "\xA1\xD8" => "\xE2\x80\xBB", + "\xA1\xD9" => "\xE2\x98\x86", + "\xA1\xDA" => "\xE2\x98\x85", + "\xA1\xDB" => "\xE2\x97\x8B", + "\xA1\xDC" => "\xE2\x97\x8F", + "\xA1\xDD" => "\xE2\x97\x8E", + "\xA1\xDE" => "\xE2\x97\x87", + "\xA1\xDF" => "\xE2\x97\x86", + "\xA1\xE0" => "\xE2\x96\xA1", + "\xA1\xE1" => "\xE2\x96\xA0", + "\xA1\xE2" => "\xE2\x96\xB3", + "\xA1\xE3" => "\xE2\x96\xB2", + "\xA1\xE4" => "\xE2\x96\xBD", + "\xA1\xE5" => "\xE2\x96\xBC", + "\xA1\xE6" => "\xE2\x86\x92", + "\xA1\xE7" => "\xE2\x86\x90", + "\xA1\xE8" => "\xE2\x86\x91", + "\xA1\xE9" => "\xE2\x86\x93", + "\xA1\xEA" => "\xE2\x86\x94", + "\xA1\xEB" => "\xE3\x80\x93", + "\xA1\xEC" => "\xE2\x89\xAA", + "\xA1\xED" => "\xE2\x89\xAB", + "\xA1\xEE" => "\xE2\x88\x9A", + "\xA1\xEF" => "\xE2\x88\xBD", + "\xA1\xF0" => "\xE2\x88\x9D", + "\xA1\xF1" => "\xE2\x88\xB5", + "\xA1\xF2" => "\xE2\x88\xAB", + "\xA1\xF3" => "\xE2\x88\xAC", + "\xA1\xF4" => "\xE2\x88\x88", + "\xA1\xF5" => "\xE2\x88\x8B", + "\xA1\xF6" => "\xE2\x8A\x86", + "\xA1\xF7" => "\xE2\x8A\x87", + "\xA1\xF8" => "\xE2\x8A\x82", + "\xA1\xF9" => "\xE2\x8A\x83", + "\xA1\xFA" => "\xE2\x88\xAA", + "\xA1\xFB" => "\xE2\x88\xA9", + "\xA1\xFC" => "\xE2\x88\xA7", + "\xA1\xFD" => "\xE2\x88\xA8", + "\xA1\xFE" => "\xEF\xBF\xA2", + "\xA2\x41" => "\xEC\xA4\x90", + "\xA2\x42" => "\xEC\xA4\x92", + "\xA2\x43" => "\xEC\xA4\x93", + "\xA2\x44" => "\xEC\xA4\x94", + "\xA2\x45" => "\xEC\xA4\x95", + "\xA2\x46" => "\xEC\xA4\x96", + "\xA2\x47" => "\xEC\xA4\x97", + "\xA2\x48" => "\xEC\xA4\x99", + "\xA2\x49" => "\xEC\xA4\x9A", + "\xA2\x4A" => "\xEC\xA4\x9B", + "\xA2\x4B" => "\xEC\xA4\x9C", + "\xA2\x4C" => "\xEC\xA4\x9D", + "\xA2\x4D" => "\xEC\xA4\x9E", + "\xA2\x4E" => "\xEC\xA4\x9F", + "\xA2\x4F" => "\xEC\xA4\xA0", + "\xA2\x50" => "\xEC\xA4\xA1", + "\xA2\x51" => "\xEC\xA4\xA2", + "\xA2\x52" => "\xEC\xA4\xA3", + "\xA2\x53" => "\xEC\xA4\xA4", + "\xA2\x54" => "\xEC\xA4\xA5", + "\xA2\x55" => "\xEC\xA4\xA6", + "\xA2\x56" => "\xEC\xA4\xA7", + "\xA2\x57" => "\xEC\xA4\xA8", + "\xA2\x58" => "\xEC\xA4\xA9", + "\xA2\x59" => "\xEC\xA4\xAA", + "\xA2\x5A" => "\xEC\xA4\xAB", + "\xA2\x61" => "\xEC\xA4\xAD", + "\xA2\x62" => "\xEC\xA4\xAE", + "\xA2\x63" => "\xEC\xA4\xAF", + "\xA2\x64" => "\xEC\xA4\xB0", + "\xA2\x65" => "\xEC\xA4\xB1", + "\xA2\x66" => "\xEC\xA4\xB2", + "\xA2\x67" => "\xEC\xA4\xB3", + "\xA2\x68" => "\xEC\xA4\xB5", + "\xA2\x69" => "\xEC\xA4\xB6", + "\xA2\x6A" => "\xEC\xA4\xB7", + "\xA2\x6B" => "\xEC\xA4\xB8", + "\xA2\x6C" => "\xEC\xA4\xB9", + "\xA2\x6D" => "\xEC\xA4\xBA", + "\xA2\x6E" => "\xEC\xA4\xBB", + "\xA2\x6F" => "\xEC\xA4\xBC", + "\xA2\x70" => "\xEC\xA4\xBD", + "\xA2\x71" => "\xEC\xA4\xBE", + "\xA2\x72" => "\xEC\xA4\xBF", + "\xA2\x73" => "\xEC\xA5\x80", + "\xA2\x74" => "\xEC\xA5\x81", + "\xA2\x75" => "\xEC\xA5\x82", + "\xA2\x76" => "\xEC\xA5\x83", + "\xA2\x77" => "\xEC\xA5\x84", + "\xA2\x78" => "\xEC\xA5\x85", + "\xA2\x79" => "\xEC\xA5\x86", + "\xA2\x7A" => "\xEC\xA5\x87", + "\xA2\x81" => "\xEC\xA5\x88", + "\xA2\x82" => "\xEC\xA5\x89", + "\xA2\x83" => "\xEC\xA5\x8A", + "\xA2\x84" => "\xEC\xA5\x8B", + "\xA2\x85" => "\xEC\xA5\x8C", + "\xA2\x86" => "\xEC\xA5\x8D", + "\xA2\x87" => "\xEC\xA5\x8E", + "\xA2\x88" => "\xEC\xA5\x8F", + "\xA2\x89" => "\xEC\xA5\x92", + "\xA2\x8A" => "\xEC\xA5\x93", + "\xA2\x8B" => "\xEC\xA5\x95", + "\xA2\x8C" => "\xEC\xA5\x96", + "\xA2\x8D" => "\xEC\xA5\x97", + "\xA2\x8E" => "\xEC\xA5\x99", + "\xA2\x8F" => "\xEC\xA5\x9A", + "\xA2\x90" => "\xEC\xA5\x9B", + "\xA2\x91" => "\xEC\xA5\x9C", + "\xA2\x92" => "\xEC\xA5\x9D", + "\xA2\x93" => "\xEC\xA5\x9E", + "\xA2\x94" => "\xEC\xA5\x9F", + "\xA2\x95" => "\xEC\xA5\xA2", + "\xA2\x96" => "\xEC\xA5\xA4", + "\xA2\x97" => "\xEC\xA5\xA5", + "\xA2\x98" => "\xEC\xA5\xA6", + "\xA2\x99" => "\xEC\xA5\xA7", + "\xA2\x9A" => "\xEC\xA5\xA8", + "\xA2\x9B" => "\xEC\xA5\xA9", + "\xA2\x9C" => "\xEC\xA5\xAA", + "\xA2\x9D" => "\xEC\xA5\xAB", + "\xA2\x9E" => "\xEC\xA5\xAD", + "\xA2\x9F" => "\xEC\xA5\xAE", + "\xA2\xA0" => "\xEC\xA5\xAF", + "\xA2\xA1" => "\xE2\x87\x92", + "\xA2\xA2" => "\xE2\x87\x94", + "\xA2\xA3" => "\xE2\x88\x80", + "\xA2\xA4" => "\xE2\x88\x83", + "\xA2\xA5" => "\xC2\xB4", + "\xA2\xA6" => "\xEF\xBD\x9E", + "\xA2\xA7" => "\xCB\x87", + "\xA2\xA8" => "\xCB\x98", + "\xA2\xA9" => "\xCB\x9D", + "\xA2\xAA" => "\xCB\x9A", + "\xA2\xAB" => "\xCB\x99", + "\xA2\xAC" => "\xC2\xB8", + "\xA2\xAD" => "\xCB\x9B", + "\xA2\xAE" => "\xC2\xA1", + "\xA2\xAF" => "\xC2\xBF", + "\xA2\xB0" => "\xCB\x90", + "\xA2\xB1" => "\xE2\x88\xAE", + "\xA2\xB2" => "\xE2\x88\x91", + "\xA2\xB3" => "\xE2\x88\x8F", + "\xA2\xB4" => "\xC2\xA4", + "\xA2\xB5" => "\xE2\x84\x89", + "\xA2\xB6" => "\xE2\x80\xB0", + "\xA2\xB7" => "\xE2\x97\x81", + "\xA2\xB8" => "\xE2\x97\x80", + "\xA2\xB9" => "\xE2\x96\xB7", + "\xA2\xBA" => "\xE2\x96\xB6", + "\xA2\xBB" => "\xE2\x99\xA4", + "\xA2\xBC" => "\xE2\x99\xA0", + "\xA2\xBD" => "\xE2\x99\xA1", + "\xA2\xBE" => "\xE2\x99\xA5", + "\xA2\xBF" => "\xE2\x99\xA7", + "\xA2\xC0" => "\xE2\x99\xA3", + "\xA2\xC1" => "\xE2\x8A\x99", + "\xA2\xC2" => "\xE2\x97\x88", + "\xA2\xC3" => "\xE2\x96\xA3", + "\xA2\xC4" => "\xE2\x97\x90", + "\xA2\xC5" => "\xE2\x97\x91", + "\xA2\xC6" => "\xE2\x96\x92", + "\xA2\xC7" => "\xE2\x96\xA4", + "\xA2\xC8" => "\xE2\x96\xA5", + "\xA2\xC9" => "\xE2\x96\xA8", + "\xA2\xCA" => "\xE2\x96\xA7", + "\xA2\xCB" => "\xE2\x96\xA6", + "\xA2\xCC" => "\xE2\x96\xA9", + "\xA2\xCD" => "\xE2\x99\xA8", + "\xA2\xCE" => "\xE2\x98\x8F", + "\xA2\xCF" => "\xE2\x98\x8E", + "\xA2\xD0" => "\xE2\x98\x9C", + "\xA2\xD1" => "\xE2\x98\x9E", + "\xA2\xD2" => "\xC2\xB6", + "\xA2\xD3" => "\xE2\x80\xA0", + "\xA2\xD4" => "\xE2\x80\xA1", + "\xA2\xD5" => "\xE2\x86\x95", + "\xA2\xD6" => "\xE2\x86\x97", + "\xA2\xD7" => "\xE2\x86\x99", + "\xA2\xD8" => "\xE2\x86\x96", + "\xA2\xD9" => "\xE2\x86\x98", + "\xA2\xDA" => "\xE2\x99\xAD", + "\xA2\xDB" => "\xE2\x99\xA9", + "\xA2\xDC" => "\xE2\x99\xAA", + "\xA2\xDD" => "\xE2\x99\xAC", + "\xA2\xDE" => "\xE3\x89\xBF", + "\xA2\xDF" => "\xE3\x88\x9C", + "\xA2\xE0" => "\xE2\x84\x96", + "\xA2\xE1" => "\xE3\x8F\x87", + "\xA2\xE2" => "\xE2\x84\xA2", + "\xA2\xE3" => "\xE3\x8F\x82", + "\xA2\xE4" => "\xE3\x8F\x98", + "\xA2\xE5" => "\xE2\x84\xA1", + "\xA3\x41" => "\xEC\xA5\xB1", + "\xA3\x42" => "\xEC\xA5\xB2", + "\xA3\x43" => "\xEC\xA5\xB3", + "\xA3\x44" => "\xEC\xA5\xB5", + "\xA3\x45" => "\xEC\xA5\xB6", + "\xA3\x46" => "\xEC\xA5\xB7", + "\xA3\x47" => "\xEC\xA5\xB8", + "\xA3\x48" => "\xEC\xA5\xB9", + "\xA3\x49" => "\xEC\xA5\xBA", + "\xA3\x4A" => "\xEC\xA5\xBB", + "\xA3\x4B" => "\xEC\xA5\xBD", + "\xA3\x4C" => "\xEC\xA5\xBE", + "\xA3\x4D" => "\xEC\xA5\xBF", + "\xA3\x4E" => "\xEC\xA6\x80", + "\xA3\x4F" => "\xEC\xA6\x81", + "\xA3\x50" => "\xEC\xA6\x82", + "\xA3\x51" => "\xEC\xA6\x83", + "\xA3\x52" => "\xEC\xA6\x84", + "\xA3\x53" => "\xEC\xA6\x85", + "\xA3\x54" => "\xEC\xA6\x86", + "\xA3\x55" => "\xEC\xA6\x87", + "\xA3\x56" => "\xEC\xA6\x8A", + "\xA3\x57" => "\xEC\xA6\x8B", + "\xA3\x58" => "\xEC\xA6\x8D", + "\xA3\x59" => "\xEC\xA6\x8E", + "\xA3\x5A" => "\xEC\xA6\x8F", + "\xA3\x61" => "\xEC\xA6\x91", + "\xA3\x62" => "\xEC\xA6\x92", + "\xA3\x63" => "\xEC\xA6\x93", + "\xA3\x64" => "\xEC\xA6\x94", + "\xA3\x65" => "\xEC\xA6\x95", + "\xA3\x66" => "\xEC\xA6\x96", + "\xA3\x67" => "\xEC\xA6\x97", + "\xA3\x68" => "\xEC\xA6\x9A", + "\xA3\x69" => "\xEC\xA6\x9C", + "\xA3\x6A" => "\xEC\xA6\x9E", + "\xA3\x6B" => "\xEC\xA6\x9F", + "\xA3\x6C" => "\xEC\xA6\xA0", + "\xA3\x6D" => "\xEC\xA6\xA1", + "\xA3\x6E" => "\xEC\xA6\xA2", + "\xA3\x6F" => "\xEC\xA6\xA3", + "\xA3\x70" => "\xEC\xA6\xA4", + "\xA3\x71" => "\xEC\xA6\xA5", + "\xA3\x72" => "\xEC\xA6\xA6", + "\xA3\x73" => "\xEC\xA6\xA7", + "\xA3\x74" => "\xEC\xA6\xA8", + "\xA3\x75" => "\xEC\xA6\xA9", + "\xA3\x76" => "\xEC\xA6\xAA", + "\xA3\x77" => "\xEC\xA6\xAB", + "\xA3\x78" => "\xEC\xA6\xAC", + "\xA3\x79" => "\xEC\xA6\xAD", + "\xA3\x7A" => "\xEC\xA6\xAE", + "\xA3\x81" => "\xEC\xA6\xAF", + "\xA3\x82" => "\xEC\xA6\xB0", + "\xA3\x83" => "\xEC\xA6\xB1", + "\xA3\x84" => "\xEC\xA6\xB2", + "\xA3\x85" => "\xEC\xA6\xB3", + "\xA3\x86" => "\xEC\xA6\xB4", + "\xA3\x87" => "\xEC\xA6\xB5", + "\xA3\x88" => "\xEC\xA6\xB6", + "\xA3\x89" => "\xEC\xA6\xB7", + "\xA3\x8A" => "\xEC\xA6\xB8", + "\xA3\x8B" => "\xEC\xA6\xB9", + "\xA3\x8C" => "\xEC\xA6\xBA", + "\xA3\x8D" => "\xEC\xA6\xBB", + "\xA3\x8E" => "\xEC\xA6\xBC", + "\xA3\x8F" => "\xEC\xA6\xBD", + "\xA3\x90" => "\xEC\xA6\xBE", + "\xA3\x91" => "\xEC\xA6\xBF", + "\xA3\x92" => "\xEC\xA7\x82", + "\xA3\x93" => "\xEC\xA7\x83", + "\xA3\x94" => "\xEC\xA7\x85", + "\xA3\x95" => "\xEC\xA7\x86", + "\xA3\x96" => "\xEC\xA7\x89", + "\xA3\x97" => "\xEC\xA7\x8B", + "\xA3\x98" => "\xEC\xA7\x8C", + "\xA3\x99" => "\xEC\xA7\x8D", + "\xA3\x9A" => "\xEC\xA7\x8E", + "\xA3\x9B" => "\xEC\xA7\x8F", + "\xA3\x9C" => "\xEC\xA7\x92", + "\xA3\x9D" => "\xEC\xA7\x94", + "\xA3\x9E" => "\xEC\xA7\x97", + "\xA3\x9F" => "\xEC\xA7\x98", + "\xA3\xA0" => "\xEC\xA7\x9B", + "\xA3\xA1" => "\xEF\xBC\x81", + "\xA3\xA2" => "\xEF\xBC\x82", + "\xA3\xA3" => "\xEF\xBC\x83", + "\xA3\xA4" => "\xEF\xBC\x84", + "\xA3\xA5" => "\xEF\xBC\x85", + "\xA3\xA6" => "\xEF\xBC\x86", + "\xA3\xA7" => "\xEF\xBC\x87", + "\xA3\xA8" => "\xEF\xBC\x88", + "\xA3\xA9" => "\xEF\xBC\x89", + "\xA3\xAA" => "\xEF\xBC\x8A", + "\xA3\xAB" => "\xEF\xBC\x8B", + "\xA3\xAC" => "\xEF\xBC\x8C", + "\xA3\xAD" => "\xEF\xBC\x8D", + "\xA3\xAE" => "\xEF\xBC\x8E", + "\xA3\xAF" => "\xEF\xBC\x8F", + "\xA3\xB0" => "\xEF\xBC\x90", + "\xA3\xB1" => "\xEF\xBC\x91", + "\xA3\xB2" => "\xEF\xBC\x92", + "\xA3\xB3" => "\xEF\xBC\x93", + "\xA3\xB4" => "\xEF\xBC\x94", + "\xA3\xB5" => "\xEF\xBC\x95", + "\xA3\xB6" => "\xEF\xBC\x96", + "\xA3\xB7" => "\xEF\xBC\x97", + "\xA3\xB8" => "\xEF\xBC\x98", + "\xA3\xB9" => "\xEF\xBC\x99", + "\xA3\xBA" => "\xEF\xBC\x9A", + "\xA3\xBB" => "\xEF\xBC\x9B", + "\xA3\xBC" => "\xEF\xBC\x9C", + "\xA3\xBD" => "\xEF\xBC\x9D", + "\xA3\xBE" => "\xEF\xBC\x9E", + "\xA3\xBF" => "\xEF\xBC\x9F", + "\xA3\xC0" => "\xEF\xBC\xA0", + "\xA3\xC1" => "\xEF\xBC\xA1", + "\xA3\xC2" => "\xEF\xBC\xA2", + "\xA3\xC3" => "\xEF\xBC\xA3", + "\xA3\xC4" => "\xEF\xBC\xA4", + "\xA3\xC5" => "\xEF\xBC\xA5", + "\xA3\xC6" => "\xEF\xBC\xA6", + "\xA3\xC7" => "\xEF\xBC\xA7", + "\xA3\xC8" => "\xEF\xBC\xA8", + "\xA3\xC9" => "\xEF\xBC\xA9", + "\xA3\xCA" => "\xEF\xBC\xAA", + "\xA3\xCB" => "\xEF\xBC\xAB", + "\xA3\xCC" => "\xEF\xBC\xAC", + "\xA3\xCD" => "\xEF\xBC\xAD", + "\xA3\xCE" => "\xEF\xBC\xAE", + "\xA3\xCF" => "\xEF\xBC\xAF", + "\xA3\xD0" => "\xEF\xBC\xB0", + "\xA3\xD1" => "\xEF\xBC\xB1", + "\xA3\xD2" => "\xEF\xBC\xB2", + "\xA3\xD3" => "\xEF\xBC\xB3", + "\xA3\xD4" => "\xEF\xBC\xB4", + "\xA3\xD5" => "\xEF\xBC\xB5", + "\xA3\xD6" => "\xEF\xBC\xB6", + "\xA3\xD7" => "\xEF\xBC\xB7", + "\xA3\xD8" => "\xEF\xBC\xB8", + "\xA3\xD9" => "\xEF\xBC\xB9", + "\xA3\xDA" => "\xEF\xBC\xBA", + "\xA3\xDB" => "\xEF\xBC\xBB", + "\xA3\xDC" => "\xEF\xBF\xA6", + "\xA3\xDD" => "\xEF\xBC\xBD", + "\xA3\xDE" => "\xEF\xBC\xBE", + "\xA3\xDF" => "\xEF\xBC\xBF", + "\xA3\xE0" => "\xEF\xBD\x80", + "\xA3\xE1" => "\xEF\xBD\x81", + "\xA3\xE2" => "\xEF\xBD\x82", + "\xA3\xE3" => "\xEF\xBD\x83", + "\xA3\xE4" => "\xEF\xBD\x84", + "\xA3\xE5" => "\xEF\xBD\x85", + "\xA3\xE6" => "\xEF\xBD\x86", + "\xA3\xE7" => "\xEF\xBD\x87", + "\xA3\xE8" => "\xEF\xBD\x88", + "\xA3\xE9" => "\xEF\xBD\x89", + "\xA3\xEA" => "\xEF\xBD\x8A", + "\xA3\xEB" => "\xEF\xBD\x8B", + "\xA3\xEC" => "\xEF\xBD\x8C", + "\xA3\xED" => "\xEF\xBD\x8D", + "\xA3\xEE" => "\xEF\xBD\x8E", + "\xA3\xEF" => "\xEF\xBD\x8F", + "\xA3\xF0" => "\xEF\xBD\x90", + "\xA3\xF1" => "\xEF\xBD\x91", + "\xA3\xF2" => "\xEF\xBD\x92", + "\xA3\xF3" => "\xEF\xBD\x93", + "\xA3\xF4" => "\xEF\xBD\x94", + "\xA3\xF5" => "\xEF\xBD\x95", + "\xA3\xF6" => "\xEF\xBD\x96", + "\xA3\xF7" => "\xEF\xBD\x97", + "\xA3\xF8" => "\xEF\xBD\x98", + "\xA3\xF9" => "\xEF\xBD\x99", + "\xA3\xFA" => "\xEF\xBD\x9A", + "\xA3\xFB" => "\xEF\xBD\x9B", + "\xA3\xFC" => "\xEF\xBD\x9C", + "\xA3\xFD" => "\xEF\xBD\x9D", + "\xA3\xFE" => "\xEF\xBF\xA3", + "\xA4\x41" => "\xEC\xA7\x9E", + "\xA4\x42" => "\xEC\xA7\x9F", + "\xA4\x43" => "\xEC\xA7\xA1", + "\xA4\x44" => "\xEC\xA7\xA3", + "\xA4\x45" => "\xEC\xA7\xA5", + "\xA4\x46" => "\xEC\xA7\xA6", + "\xA4\x47" => "\xEC\xA7\xA8", + "\xA4\x48" => "\xEC\xA7\xA9", + "\xA4\x49" => "\xEC\xA7\xAA", + "\xA4\x4A" => "\xEC\xA7\xAB", + "\xA4\x4B" => "\xEC\xA7\xAE", + "\xA4\x4C" => "\xEC\xA7\xB2", + "\xA4\x4D" => "\xEC\xA7\xB3", + "\xA4\x4E" => "\xEC\xA7\xB4", + "\xA4\x4F" => "\xEC\xA7\xB5", + "\xA4\x50" => "\xEC\xA7\xB6", + "\xA4\x51" => "\xEC\xA7\xB7", + "\xA4\x52" => "\xEC\xA7\xBA", + "\xA4\x53" => "\xEC\xA7\xBB", + "\xA4\x54" => "\xEC\xA7\xBD", + "\xA4\x55" => "\xEC\xA7\xBE", + "\xA4\x56" => "\xEC\xA7\xBF", + "\xA4\x57" => "\xEC\xA8\x81", + "\xA4\x58" => "\xEC\xA8\x82", + "\xA4\x59" => "\xEC\xA8\x83", + "\xA4\x5A" => "\xEC\xA8\x84", + "\xA4\x61" => "\xEC\xA8\x85", + "\xA4\x62" => "\xEC\xA8\x86", + "\xA4\x63" => "\xEC\xA8\x87", + "\xA4\x64" => "\xEC\xA8\x8A", + "\xA4\x65" => "\xEC\xA8\x8E", + "\xA4\x66" => "\xEC\xA8\x8F", + "\xA4\x67" => "\xEC\xA8\x90", + "\xA4\x68" => "\xEC\xA8\x91", + "\xA4\x69" => "\xEC\xA8\x92", + "\xA4\x6A" => "\xEC\xA8\x93", + "\xA4\x6B" => "\xEC\xA8\x95", + "\xA4\x6C" => "\xEC\xA8\x96", + "\xA4\x6D" => "\xEC\xA8\x97", + "\xA4\x6E" => "\xEC\xA8\x99", + "\xA4\x6F" => "\xEC\xA8\x9A", + "\xA4\x70" => "\xEC\xA8\x9B", + "\xA4\x71" => "\xEC\xA8\x9C", + "\xA4\x72" => "\xEC\xA8\x9D", + "\xA4\x73" => "\xEC\xA8\x9E", + "\xA4\x74" => "\xEC\xA8\x9F", + "\xA4\x75" => "\xEC\xA8\xA0", + "\xA4\x76" => "\xEC\xA8\xA1", + "\xA4\x77" => "\xEC\xA8\xA2", + "\xA4\x78" => "\xEC\xA8\xA3", + "\xA4\x79" => "\xEC\xA8\xA4", + "\xA4\x7A" => "\xEC\xA8\xA5", + "\xA4\x81" => "\xEC\xA8\xA6", + "\xA4\x82" => "\xEC\xA8\xA7", + "\xA4\x83" => "\xEC\xA8\xA8", + "\xA4\x84" => "\xEC\xA8\xAA", + "\xA4\x85" => "\xEC\xA8\xAB", + "\xA4\x86" => "\xEC\xA8\xAC", + "\xA4\x87" => "\xEC\xA8\xAD", + "\xA4\x88" => "\xEC\xA8\xAE", + "\xA4\x89" => "\xEC\xA8\xAF", + "\xA4\x8A" => "\xEC\xA8\xB0", + "\xA4\x8B" => "\xEC\xA8\xB1", + "\xA4\x8C" => "\xEC\xA8\xB2", + "\xA4\x8D" => "\xEC\xA8\xB3", + "\xA4\x8E" => "\xEC\xA8\xB4", + "\xA4\x8F" => "\xEC\xA8\xB5", + "\xA4\x90" => "\xEC\xA8\xB6", + "\xA4\x91" => "\xEC\xA8\xB7", + "\xA4\x92" => "\xEC\xA8\xB8", + "\xA4\x93" => "\xEC\xA8\xB9", + "\xA4\x94" => "\xEC\xA8\xBA", + "\xA4\x95" => "\xEC\xA8\xBB", + "\xA4\x96" => "\xEC\xA8\xBC", + "\xA4\x97" => "\xEC\xA8\xBD", + "\xA4\x98" => "\xEC\xA8\xBE", + "\xA4\x99" => "\xEC\xA8\xBF", + "\xA4\x9A" => "\xEC\xA9\x80", + "\xA4\x9B" => "\xEC\xA9\x81", + "\xA4\x9C" => "\xEC\xA9\x82", + "\xA4\x9D" => "\xEC\xA9\x83", + "\xA4\x9E" => "\xEC\xA9\x84", + "\xA4\x9F" => "\xEC\xA9\x85", + "\xA4\xA0" => "\xEC\xA9\x86", + "\xA4\xA1" => "\xE3\x84\xB1", + "\xA4\xA2" => "\xE3\x84\xB2", + "\xA4\xA3" => "\xE3\x84\xB3", + "\xA4\xA4" => "\xE3\x84\xB4", + "\xA4\xA5" => "\xE3\x84\xB5", + "\xA4\xA6" => "\xE3\x84\xB6", + "\xA4\xA7" => "\xE3\x84\xB7", + "\xA4\xA8" => "\xE3\x84\xB8", + "\xA4\xA9" => "\xE3\x84\xB9", + "\xA4\xAA" => "\xE3\x84\xBA", + "\xA4\xAB" => "\xE3\x84\xBB", + "\xA4\xAC" => "\xE3\x84\xBC", + "\xA4\xAD" => "\xE3\x84\xBD", + "\xA4\xAE" => "\xE3\x84\xBE", + "\xA4\xAF" => "\xE3\x84\xBF", + "\xA4\xB0" => "\xE3\x85\x80", + "\xA4\xB1" => "\xE3\x85\x81", + "\xA4\xB2" => "\xE3\x85\x82", + "\xA4\xB3" => "\xE3\x85\x83", + "\xA4\xB4" => "\xE3\x85\x84", + "\xA4\xB5" => "\xE3\x85\x85", + "\xA4\xB6" => "\xE3\x85\x86", + "\xA4\xB7" => "\xE3\x85\x87", + "\xA4\xB8" => "\xE3\x85\x88", + "\xA4\xB9" => "\xE3\x85\x89", + "\xA4\xBA" => "\xE3\x85\x8A", + "\xA4\xBB" => "\xE3\x85\x8B", + "\xA4\xBC" => "\xE3\x85\x8C", + "\xA4\xBD" => "\xE3\x85\x8D", + "\xA4\xBE" => "\xE3\x85\x8E", + "\xA4\xBF" => "\xE3\x85\x8F", + "\xA4\xC0" => "\xE3\x85\x90", + "\xA4\xC1" => "\xE3\x85\x91", + "\xA4\xC2" => "\xE3\x85\x92", + "\xA4\xC3" => "\xE3\x85\x93", + "\xA4\xC4" => "\xE3\x85\x94", + "\xA4\xC5" => "\xE3\x85\x95", + "\xA4\xC6" => "\xE3\x85\x96", + "\xA4\xC7" => "\xE3\x85\x97", + "\xA4\xC8" => "\xE3\x85\x98", + "\xA4\xC9" => "\xE3\x85\x99", + "\xA4\xCA" => "\xE3\x85\x9A", + "\xA4\xCB" => "\xE3\x85\x9B", + "\xA4\xCC" => "\xE3\x85\x9C", + "\xA4\xCD" => "\xE3\x85\x9D", + "\xA4\xCE" => "\xE3\x85\x9E", + "\xA4\xCF" => "\xE3\x85\x9F", + "\xA4\xD0" => "\xE3\x85\xA0", + "\xA4\xD1" => "\xE3\x85\xA1", + "\xA4\xD2" => "\xE3\x85\xA2", + "\xA4\xD3" => "\xE3\x85\xA3", + "\xA4\xD4" => "\xE3\x85\xA4", + "\xA4\xD5" => "\xE3\x85\xA5", + "\xA4\xD6" => "\xE3\x85\xA6", + "\xA4\xD7" => "\xE3\x85\xA7", + "\xA4\xD8" => "\xE3\x85\xA8", + "\xA4\xD9" => "\xE3\x85\xA9", + "\xA4\xDA" => "\xE3\x85\xAA", + "\xA4\xDB" => "\xE3\x85\xAB", + "\xA4\xDC" => "\xE3\x85\xAC", + "\xA4\xDD" => "\xE3\x85\xAD", + "\xA4\xDE" => "\xE3\x85\xAE", + "\xA4\xDF" => "\xE3\x85\xAF", + "\xA4\xE0" => "\xE3\x85\xB0", + "\xA4\xE1" => "\xE3\x85\xB1", + "\xA4\xE2" => "\xE3\x85\xB2", + "\xA4\xE3" => "\xE3\x85\xB3", + "\xA4\xE4" => "\xE3\x85\xB4", + "\xA4\xE5" => "\xE3\x85\xB5", + "\xA4\xE6" => "\xE3\x85\xB6", + "\xA4\xE7" => "\xE3\x85\xB7", + "\xA4\xE8" => "\xE3\x85\xB8", + "\xA4\xE9" => "\xE3\x85\xB9", + "\xA4\xEA" => "\xE3\x85\xBA", + "\xA4\xEB" => "\xE3\x85\xBB", + "\xA4\xEC" => "\xE3\x85\xBC", + "\xA4\xED" => "\xE3\x85\xBD", + "\xA4\xEE" => "\xE3\x85\xBE", + "\xA4\xEF" => "\xE3\x85\xBF", + "\xA4\xF0" => "\xE3\x86\x80", + "\xA4\xF1" => "\xE3\x86\x81", + "\xA4\xF2" => "\xE3\x86\x82", + "\xA4\xF3" => "\xE3\x86\x83", + "\xA4\xF4" => "\xE3\x86\x84", + "\xA4\xF5" => "\xE3\x86\x85", + "\xA4\xF6" => "\xE3\x86\x86", + "\xA4\xF7" => "\xE3\x86\x87", + "\xA4\xF8" => "\xE3\x86\x88", + "\xA4\xF9" => "\xE3\x86\x89", + "\xA4\xFA" => "\xE3\x86\x8A", + "\xA4\xFB" => "\xE3\x86\x8B", + "\xA4\xFC" => "\xE3\x86\x8C", + "\xA4\xFD" => "\xE3\x86\x8D", + "\xA4\xFE" => "\xE3\x86\x8E", + "\xA5\x41" => "\xEC\xA9\x87", + "\xA5\x42" => "\xEC\xA9\x88", + "\xA5\x43" => "\xEC\xA9\x89", + "\xA5\x44" => "\xEC\xA9\x8A", + "\xA5\x45" => "\xEC\xA9\x8B", + "\xA5\x46" => "\xEC\xA9\x8E", + "\xA5\x47" => "\xEC\xA9\x8F", + "\xA5\x48" => "\xEC\xA9\x91", + "\xA5\x49" => "\xEC\xA9\x92", + "\xA5\x4A" => "\xEC\xA9\x93", + "\xA5\x4B" => "\xEC\xA9\x95", + "\xA5\x4C" => "\xEC\xA9\x96", + "\xA5\x4D" => "\xEC\xA9\x97", + "\xA5\x4E" => "\xEC\xA9\x98", + "\xA5\x4F" => "\xEC\xA9\x99", + "\xA5\x50" => "\xEC\xA9\x9A", + "\xA5\x51" => "\xEC\xA9\x9B", + "\xA5\x52" => "\xEC\xA9\x9E", + "\xA5\x53" => "\xEC\xA9\xA2", + "\xA5\x54" => "\xEC\xA9\xA3", + "\xA5\x55" => "\xEC\xA9\xA4", + "\xA5\x56" => "\xEC\xA9\xA5", + "\xA5\x57" => "\xEC\xA9\xA6", + "\xA5\x58" => "\xEC\xA9\xA7", + "\xA5\x59" => "\xEC\xA9\xA9", + "\xA5\x5A" => "\xEC\xA9\xAA", + "\xA5\x61" => "\xEC\xA9\xAB", + "\xA5\x62" => "\xEC\xA9\xAC", + "\xA5\x63" => "\xEC\xA9\xAD", + "\xA5\x64" => "\xEC\xA9\xAE", + "\xA5\x65" => "\xEC\xA9\xAF", + "\xA5\x66" => "\xEC\xA9\xB0", + "\xA5\x67" => "\xEC\xA9\xB1", + "\xA5\x68" => "\xEC\xA9\xB2", + "\xA5\x69" => "\xEC\xA9\xB3", + "\xA5\x6A" => "\xEC\xA9\xB4", + "\xA5\x6B" => "\xEC\xA9\xB5", + "\xA5\x6C" => "\xEC\xA9\xB6", + "\xA5\x6D" => "\xEC\xA9\xB7", + "\xA5\x6E" => "\xEC\xA9\xB8", + "\xA5\x6F" => "\xEC\xA9\xB9", + "\xA5\x70" => "\xEC\xA9\xBA", + "\xA5\x71" => "\xEC\xA9\xBB", + "\xA5\x72" => "\xEC\xA9\xBC", + "\xA5\x73" => "\xEC\xA9\xBE", + "\xA5\x74" => "\xEC\xA9\xBF", + "\xA5\x75" => "\xEC\xAA\x80", + "\xA5\x76" => "\xEC\xAA\x81", + "\xA5\x77" => "\xEC\xAA\x82", + "\xA5\x78" => "\xEC\xAA\x83", + "\xA5\x79" => "\xEC\xAA\x85", + "\xA5\x7A" => "\xEC\xAA\x86", + "\xA5\x81" => "\xEC\xAA\x87", + "\xA5\x82" => "\xEC\xAA\x88", + "\xA5\x83" => "\xEC\xAA\x89", + "\xA5\x84" => "\xEC\xAA\x8A", + "\xA5\x85" => "\xEC\xAA\x8B", + "\xA5\x86" => "\xEC\xAA\x8C", + "\xA5\x87" => "\xEC\xAA\x8D", + "\xA5\x88" => "\xEC\xAA\x8E", + "\xA5\x89" => "\xEC\xAA\x8F", + "\xA5\x8A" => "\xEC\xAA\x90", + "\xA5\x8B" => "\xEC\xAA\x91", + "\xA5\x8C" => "\xEC\xAA\x92", + "\xA5\x8D" => "\xEC\xAA\x93", + "\xA5\x8E" => "\xEC\xAA\x94", + "\xA5\x8F" => "\xEC\xAA\x95", + "\xA5\x90" => "\xEC\xAA\x96", + "\xA5\x91" => "\xEC\xAA\x97", + "\xA5\x92" => "\xEC\xAA\x99", + "\xA5\x93" => "\xEC\xAA\x9A", + "\xA5\x94" => "\xEC\xAA\x9B", + "\xA5\x95" => "\xEC\xAA\x9C", + "\xA5\x96" => "\xEC\xAA\x9D", + "\xA5\x97" => "\xEC\xAA\x9E", + "\xA5\x98" => "\xEC\xAA\x9F", + "\xA5\x99" => "\xEC\xAA\xA0", + "\xA5\x9A" => "\xEC\xAA\xA1", + "\xA5\x9B" => "\xEC\xAA\xA2", + "\xA5\x9C" => "\xEC\xAA\xA3", + "\xA5\x9D" => "\xEC\xAA\xA4", + "\xA5\x9E" => "\xEC\xAA\xA5", + "\xA5\x9F" => "\xEC\xAA\xA6", + "\xA5\xA0" => "\xEC\xAA\xA7", + "\xA5\xA1" => "\xE2\x85\xB0", + "\xA5\xA2" => "\xE2\x85\xB1", + "\xA5\xA3" => "\xE2\x85\xB2", + "\xA5\xA4" => "\xE2\x85\xB3", + "\xA5\xA5" => "\xE2\x85\xB4", + "\xA5\xA6" => "\xE2\x85\xB5", + "\xA5\xA7" => "\xE2\x85\xB6", + "\xA5\xA8" => "\xE2\x85\xB7", + "\xA5\xA9" => "\xE2\x85\xB8", + "\xA5\xAA" => "\xE2\x85\xB9", + "\xA5\xB0" => "\xE2\x85\xA0", + "\xA5\xB1" => "\xE2\x85\xA1", + "\xA5\xB2" => "\xE2\x85\xA2", + "\xA5\xB3" => "\xE2\x85\xA3", + "\xA5\xB4" => "\xE2\x85\xA4", + "\xA5\xB5" => "\xE2\x85\xA5", + "\xA5\xB6" => "\xE2\x85\xA6", + "\xA5\xB7" => "\xE2\x85\xA7", + "\xA5\xB8" => "\xE2\x85\xA8", + "\xA5\xB9" => "\xE2\x85\xA9", + "\xA5\xC1" => "\xCE\x91", + "\xA5\xC2" => "\xCE\x92", + "\xA5\xC3" => "\xCE\x93", + "\xA5\xC4" => "\xCE\x94", + "\xA5\xC5" => "\xCE\x95", + "\xA5\xC6" => "\xCE\x96", + "\xA5\xC7" => "\xCE\x97", + "\xA5\xC8" => "\xCE\x98", + "\xA5\xC9" => "\xCE\x99", + "\xA5\xCA" => "\xCE\x9A", + "\xA5\xCB" => "\xCE\x9B", + "\xA5\xCC" => "\xCE\x9C", + "\xA5\xCD" => "\xCE\x9D", + "\xA5\xCE" => "\xCE\x9E", + "\xA5\xCF" => "\xCE\x9F", + "\xA5\xD0" => "\xCE\xA0", + "\xA5\xD1" => "\xCE\xA1", + "\xA5\xD2" => "\xCE\xA3", + "\xA5\xD3" => "\xCE\xA4", + "\xA5\xD4" => "\xCE\xA5", + "\xA5\xD5" => "\xCE\xA6", + "\xA5\xD6" => "\xCE\xA7", + "\xA5\xD7" => "\xCE\xA8", + "\xA5\xD8" => "\xCE\xA9", + "\xA5\xE1" => "\xCE\xB1", + "\xA5\xE2" => "\xCE\xB2", + "\xA5\xE3" => "\xCE\xB3", + "\xA5\xE4" => "\xCE\xB4", + "\xA5\xE5" => "\xCE\xB5", + "\xA5\xE6" => "\xCE\xB6", + "\xA5\xE7" => "\xCE\xB7", + "\xA5\xE8" => "\xCE\xB8", + "\xA5\xE9" => "\xCE\xB9", + "\xA5\xEA" => "\xCE\xBA", + "\xA5\xEB" => "\xCE\xBB", + "\xA5\xEC" => "\xCE\xBC", + "\xA5\xED" => "\xCE\xBD", + "\xA5\xEE" => "\xCE\xBE", + "\xA5\xEF" => "\xCE\xBF", + "\xA5\xF0" => "\xCF\x80", + "\xA5\xF1" => "\xCF\x81", + "\xA5\xF2" => "\xCF\x83", + "\xA5\xF3" => "\xCF\x84", + "\xA5\xF4" => "\xCF\x85", + "\xA5\xF5" => "\xCF\x86", + "\xA5\xF6" => "\xCF\x87", + "\xA5\xF7" => "\xCF\x88", + "\xA5\xF8" => "\xCF\x89", + "\xA6\x41" => "\xEC\xAA\xA8", + "\xA6\x42" => "\xEC\xAA\xA9", + "\xA6\x43" => "\xEC\xAA\xAA", + "\xA6\x44" => "\xEC\xAA\xAB", + "\xA6\x45" => "\xEC\xAA\xAC", + "\xA6\x46" => "\xEC\xAA\xAD", + "\xA6\x47" => "\xEC\xAA\xAE", + "\xA6\x48" => "\xEC\xAA\xAF", + "\xA6\x49" => "\xEC\xAA\xB0", + "\xA6\x4A" => "\xEC\xAA\xB1", + "\xA6\x4B" => "\xEC\xAA\xB2", + "\xA6\x4C" => "\xEC\xAA\xB3", + "\xA6\x4D" => "\xEC\xAA\xB4", + "\xA6\x4E" => "\xEC\xAA\xB5", + "\xA6\x4F" => "\xEC\xAA\xB6", + "\xA6\x50" => "\xEC\xAA\xB7", + "\xA6\x51" => "\xEC\xAA\xB8", + "\xA6\x52" => "\xEC\xAA\xB9", + "\xA6\x53" => "\xEC\xAA\xBA", + "\xA6\x54" => "\xEC\xAA\xBB", + "\xA6\x55" => "\xEC\xAA\xBE", + "\xA6\x56" => "\xEC\xAA\xBF", + "\xA6\x57" => "\xEC\xAB\x81", + "\xA6\x58" => "\xEC\xAB\x82", + "\xA6\x59" => "\xEC\xAB\x83", + "\xA6\x5A" => "\xEC\xAB\x85", + "\xA6\x61" => "\xEC\xAB\x86", + "\xA6\x62" => "\xEC\xAB\x87", + "\xA6\x63" => "\xEC\xAB\x88", + "\xA6\x64" => "\xEC\xAB\x89", + "\xA6\x65" => "\xEC\xAB\x8A", + "\xA6\x66" => "\xEC\xAB\x8B", + "\xA6\x67" => "\xEC\xAB\x8E", + "\xA6\x68" => "\xEC\xAB\x90", + "\xA6\x69" => "\xEC\xAB\x92", + "\xA6\x6A" => "\xEC\xAB\x94", + "\xA6\x6B" => "\xEC\xAB\x95", + "\xA6\x6C" => "\xEC\xAB\x96", + "\xA6\x6D" => "\xEC\xAB\x97", + "\xA6\x6E" => "\xEC\xAB\x9A", + "\xA6\x6F" => "\xEC\xAB\x9B", + "\xA6\x70" => "\xEC\xAB\x9C", + "\xA6\x71" => "\xEC\xAB\x9D", + "\xA6\x72" => "\xEC\xAB\x9E", + "\xA6\x73" => "\xEC\xAB\x9F", + "\xA6\x74" => "\xEC\xAB\xA1", + "\xA6\x75" => "\xEC\xAB\xA2", + "\xA6\x76" => "\xEC\xAB\xA3", + "\xA6\x77" => "\xEC\xAB\xA4", + "\xA6\x78" => "\xEC\xAB\xA5", + "\xA6\x79" => "\xEC\xAB\xA6", + "\xA6\x7A" => "\xEC\xAB\xA7", + "\xA6\x81" => "\xEC\xAB\xA8", + "\xA6\x82" => "\xEC\xAB\xA9", + "\xA6\x83" => "\xEC\xAB\xAA", + "\xA6\x84" => "\xEC\xAB\xAB", + "\xA6\x85" => "\xEC\xAB\xAD", + "\xA6\x86" => "\xEC\xAB\xAE", + "\xA6\x87" => "\xEC\xAB\xAF", + "\xA6\x88" => "\xEC\xAB\xB0", + "\xA6\x89" => "\xEC\xAB\xB1", + "\xA6\x8A" => "\xEC\xAB\xB2", + "\xA6\x8B" => "\xEC\xAB\xB3", + "\xA6\x8C" => "\xEC\xAB\xB5", + "\xA6\x8D" => "\xEC\xAB\xB6", + "\xA6\x8E" => "\xEC\xAB\xB7", + "\xA6\x8F" => "\xEC\xAB\xB8", + "\xA6\x90" => "\xEC\xAB\xB9", + "\xA6\x91" => "\xEC\xAB\xBA", + "\xA6\x92" => "\xEC\xAB\xBB", + "\xA6\x93" => "\xEC\xAB\xBC", + "\xA6\x94" => "\xEC\xAB\xBD", + "\xA6\x95" => "\xEC\xAB\xBE", + "\xA6\x96" => "\xEC\xAB\xBF", + "\xA6\x97" => "\xEC\xAC\x80", + "\xA6\x98" => "\xEC\xAC\x81", + "\xA6\x99" => "\xEC\xAC\x82", + "\xA6\x9A" => "\xEC\xAC\x83", + "\xA6\x9B" => "\xEC\xAC\x84", + "\xA6\x9C" => "\xEC\xAC\x85", + "\xA6\x9D" => "\xEC\xAC\x86", + "\xA6\x9E" => "\xEC\xAC\x87", + "\xA6\x9F" => "\xEC\xAC\x89", + "\xA6\xA0" => "\xEC\xAC\x8A", + "\xA6\xA1" => "\xE2\x94\x80", + "\xA6\xA2" => "\xE2\x94\x82", + "\xA6\xA3" => "\xE2\x94\x8C", + "\xA6\xA4" => "\xE2\x94\x90", + "\xA6\xA5" => "\xE2\x94\x98", + "\xA6\xA6" => "\xE2\x94\x94", + "\xA6\xA7" => "\xE2\x94\x9C", + "\xA6\xA8" => "\xE2\x94\xAC", + "\xA6\xA9" => "\xE2\x94\xA4", + "\xA6\xAA" => "\xE2\x94\xB4", + "\xA6\xAB" => "\xE2\x94\xBC", + "\xA6\xAC" => "\xE2\x94\x81", + "\xA6\xAD" => "\xE2\x94\x83", + "\xA6\xAE" => "\xE2\x94\x8F", + "\xA6\xAF" => "\xE2\x94\x93", + "\xA6\xB0" => "\xE2\x94\x9B", + "\xA6\xB1" => "\xE2\x94\x97", + "\xA6\xB2" => "\xE2\x94\xA3", + "\xA6\xB3" => "\xE2\x94\xB3", + "\xA6\xB4" => "\xE2\x94\xAB", + "\xA6\xB5" => "\xE2\x94\xBB", + "\xA6\xB6" => "\xE2\x95\x8B", + "\xA6\xB7" => "\xE2\x94\xA0", + "\xA6\xB8" => "\xE2\x94\xAF", + "\xA6\xB9" => "\xE2\x94\xA8", + "\xA6\xBA" => "\xE2\x94\xB7", + "\xA6\xBB" => "\xE2\x94\xBF", + "\xA6\xBC" => "\xE2\x94\x9D", + "\xA6\xBD" => "\xE2\x94\xB0", + "\xA6\xBE" => "\xE2\x94\xA5", + "\xA6\xBF" => "\xE2\x94\xB8", + "\xA6\xC0" => "\xE2\x95\x82", + "\xA6\xC1" => "\xE2\x94\x92", + "\xA6\xC2" => "\xE2\x94\x91", + "\xA6\xC3" => "\xE2\x94\x9A", + "\xA6\xC4" => "\xE2\x94\x99", + "\xA6\xC5" => "\xE2\x94\x96", + "\xA6\xC6" => "\xE2\x94\x95", + "\xA6\xC7" => "\xE2\x94\x8E", + "\xA6\xC8" => "\xE2\x94\x8D", + "\xA6\xC9" => "\xE2\x94\x9E", + "\xA6\xCA" => "\xE2\x94\x9F", + "\xA6\xCB" => "\xE2\x94\xA1", + "\xA6\xCC" => "\xE2\x94\xA2", + "\xA6\xCD" => "\xE2\x94\xA6", + "\xA6\xCE" => "\xE2\x94\xA7", + "\xA6\xCF" => "\xE2\x94\xA9", + "\xA6\xD0" => "\xE2\x94\xAA", + "\xA6\xD1" => "\xE2\x94\xAD", + "\xA6\xD2" => "\xE2\x94\xAE", + "\xA6\xD3" => "\xE2\x94\xB1", + "\xA6\xD4" => "\xE2\x94\xB2", + "\xA6\xD5" => "\xE2\x94\xB5", + "\xA6\xD6" => "\xE2\x94\xB6", + "\xA6\xD7" => "\xE2\x94\xB9", + "\xA6\xD8" => "\xE2\x94\xBA", + "\xA6\xD9" => "\xE2\x94\xBD", + "\xA6\xDA" => "\xE2\x94\xBE", + "\xA6\xDB" => "\xE2\x95\x80", + "\xA6\xDC" => "\xE2\x95\x81", + "\xA6\xDD" => "\xE2\x95\x83", + "\xA6\xDE" => "\xE2\x95\x84", + "\xA6\xDF" => "\xE2\x95\x85", + "\xA6\xE0" => "\xE2\x95\x86", + "\xA6\xE1" => "\xE2\x95\x87", + "\xA6\xE2" => "\xE2\x95\x88", + "\xA6\xE3" => "\xE2\x95\x89", + "\xA6\xE4" => "\xE2\x95\x8A", + "\xA7\x41" => "\xEC\xAC\x8B", + "\xA7\x42" => "\xEC\xAC\x8C", + "\xA7\x43" => "\xEC\xAC\x8D", + "\xA7\x44" => "\xEC\xAC\x8E", + "\xA7\x45" => "\xEC\xAC\x8F", + "\xA7\x46" => "\xEC\xAC\x91", + "\xA7\x47" => "\xEC\xAC\x92", + "\xA7\x48" => "\xEC\xAC\x93", + "\xA7\x49" => "\xEC\xAC\x95", + "\xA7\x4A" => "\xEC\xAC\x96", + "\xA7\x4B" => "\xEC\xAC\x97", + "\xA7\x4C" => "\xEC\xAC\x99", + "\xA7\x4D" => "\xEC\xAC\x9A", + "\xA7\x4E" => "\xEC\xAC\x9B", + "\xA7\x4F" => "\xEC\xAC\x9C", + "\xA7\x50" => "\xEC\xAC\x9D", + "\xA7\x51" => "\xEC\xAC\x9E", + "\xA7\x52" => "\xEC\xAC\x9F", + "\xA7\x53" => "\xEC\xAC\xA2", + "\xA7\x54" => "\xEC\xAC\xA3", + "\xA7\x55" => "\xEC\xAC\xA4", + "\xA7\x56" => "\xEC\xAC\xA5", + "\xA7\x57" => "\xEC\xAC\xA6", + "\xA7\x58" => "\xEC\xAC\xA7", + "\xA7\x59" => "\xEC\xAC\xA8", + "\xA7\x5A" => "\xEC\xAC\xA9", + "\xA7\x61" => "\xEC\xAC\xAA", + "\xA7\x62" => "\xEC\xAC\xAB", + "\xA7\x63" => "\xEC\xAC\xAC", + "\xA7\x64" => "\xEC\xAC\xAD", + "\xA7\x65" => "\xEC\xAC\xAE", + "\xA7\x66" => "\xEC\xAC\xAF", + "\xA7\x67" => "\xEC\xAC\xB0", + "\xA7\x68" => "\xEC\xAC\xB1", + "\xA7\x69" => "\xEC\xAC\xB2", + "\xA7\x6A" => "\xEC\xAC\xB3", + "\xA7\x6B" => "\xEC\xAC\xB4", + "\xA7\x6C" => "\xEC\xAC\xB5", + "\xA7\x6D" => "\xEC\xAC\xB6", + "\xA7\x6E" => "\xEC\xAC\xB7", + "\xA7\x6F" => "\xEC\xAC\xB8", + "\xA7\x70" => "\xEC\xAC\xB9", + "\xA7\x71" => "\xEC\xAC\xBA", + "\xA7\x72" => "\xEC\xAC\xBB", + "\xA7\x73" => "\xEC\xAC\xBC", + "\xA7\x74" => "\xEC\xAC\xBD", + "\xA7\x75" => "\xEC\xAC\xBE", + "\xA7\x76" => "\xEC\xAC\xBF", + "\xA7\x77" => "\xEC\xAD\x80", + "\xA7\x78" => "\xEC\xAD\x82", + "\xA7\x79" => "\xEC\xAD\x83", + "\xA7\x7A" => "\xEC\xAD\x84", + "\xA7\x81" => "\xEC\xAD\x85", + "\xA7\x82" => "\xEC\xAD\x86", + "\xA7\x83" => "\xEC\xAD\x87", + "\xA7\x84" => "\xEC\xAD\x8A", + "\xA7\x85" => "\xEC\xAD\x8B", + "\xA7\x86" => "\xEC\xAD\x8D", + "\xA7\x87" => "\xEC\xAD\x8E", + "\xA7\x88" => "\xEC\xAD\x8F", + "\xA7\x89" => "\xEC\xAD\x91", + "\xA7\x8A" => "\xEC\xAD\x92", + "\xA7\x8B" => "\xEC\xAD\x93", + "\xA7\x8C" => "\xEC\xAD\x94", + "\xA7\x8D" => "\xEC\xAD\x95", + "\xA7\x8E" => "\xEC\xAD\x96", + "\xA7\x8F" => "\xEC\xAD\x97", + "\xA7\x90" => "\xEC\xAD\x9A", + "\xA7\x91" => "\xEC\xAD\x9B", + "\xA7\x92" => "\xEC\xAD\x9C", + "\xA7\x93" => "\xEC\xAD\x9E", + "\xA7\x94" => "\xEC\xAD\x9F", + "\xA7\x95" => "\xEC\xAD\xA0", + "\xA7\x96" => "\xEC\xAD\xA1", + "\xA7\x97" => "\xEC\xAD\xA2", + "\xA7\x98" => "\xEC\xAD\xA3", + "\xA7\x99" => "\xEC\xAD\xA5", + "\xA7\x9A" => "\xEC\xAD\xA6", + "\xA7\x9B" => "\xEC\xAD\xA7", + "\xA7\x9C" => "\xEC\xAD\xA8", + "\xA7\x9D" => "\xEC\xAD\xA9", + "\xA7\x9E" => "\xEC\xAD\xAA", + "\xA7\x9F" => "\xEC\xAD\xAB", + "\xA7\xA0" => "\xEC\xAD\xAC", + "\xA7\xA1" => "\xE3\x8E\x95", + "\xA7\xA2" => "\xE3\x8E\x96", + "\xA7\xA3" => "\xE3\x8E\x97", + "\xA7\xA4" => "\xE2\x84\x93", + "\xA7\xA5" => "\xE3\x8E\x98", + "\xA7\xA6" => "\xE3\x8F\x84", + "\xA7\xA7" => "\xE3\x8E\xA3", + "\xA7\xA8" => "\xE3\x8E\xA4", + "\xA7\xA9" => "\xE3\x8E\xA5", + "\xA7\xAA" => "\xE3\x8E\xA6", + "\xA7\xAB" => "\xE3\x8E\x99", + "\xA7\xAC" => "\xE3\x8E\x9A", + "\xA7\xAD" => "\xE3\x8E\x9B", + "\xA7\xAE" => "\xE3\x8E\x9C", + "\xA7\xAF" => "\xE3\x8E\x9D", + "\xA7\xB0" => "\xE3\x8E\x9E", + "\xA7\xB1" => "\xE3\x8E\x9F", + "\xA7\xB2" => "\xE3\x8E\xA0", + "\xA7\xB3" => "\xE3\x8E\xA1", + "\xA7\xB4" => "\xE3\x8E\xA2", + "\xA7\xB5" => "\xE3\x8F\x8A", + "\xA7\xB6" => "\xE3\x8E\x8D", + "\xA7\xB7" => "\xE3\x8E\x8E", + "\xA7\xB8" => "\xE3\x8E\x8F", + "\xA7\xB9" => "\xE3\x8F\x8F", + "\xA7\xBA" => "\xE3\x8E\x88", + "\xA7\xBB" => "\xE3\x8E\x89", + "\xA7\xBC" => "\xE3\x8F\x88", + "\xA7\xBD" => "\xE3\x8E\xA7", + "\xA7\xBE" => "\xE3\x8E\xA8", + "\xA7\xBF" => "\xE3\x8E\xB0", + "\xA7\xC0" => "\xE3\x8E\xB1", + "\xA7\xC1" => "\xE3\x8E\xB2", + "\xA7\xC2" => "\xE3\x8E\xB3", + "\xA7\xC3" => "\xE3\x8E\xB4", + "\xA7\xC4" => "\xE3\x8E\xB5", + "\xA7\xC5" => "\xE3\x8E\xB6", + "\xA7\xC6" => "\xE3\x8E\xB7", + "\xA7\xC7" => "\xE3\x8E\xB8", + "\xA7\xC8" => "\xE3\x8E\xB9", + "\xA7\xC9" => "\xE3\x8E\x80", + "\xA7\xCA" => "\xE3\x8E\x81", + "\xA7\xCB" => "\xE3\x8E\x82", + "\xA7\xCC" => "\xE3\x8E\x83", + "\xA7\xCD" => "\xE3\x8E\x84", + "\xA7\xCE" => "\xE3\x8E\xBA", + "\xA7\xCF" => "\xE3\x8E\xBB", + "\xA7\xD0" => "\xE3\x8E\xBC", + "\xA7\xD1" => "\xE3\x8E\xBD", + "\xA7\xD2" => "\xE3\x8E\xBE", + "\xA7\xD3" => "\xE3\x8E\xBF", + "\xA7\xD4" => "\xE3\x8E\x90", + "\xA7\xD5" => "\xE3\x8E\x91", + "\xA7\xD6" => "\xE3\x8E\x92", + "\xA7\xD7" => "\xE3\x8E\x93", + "\xA7\xD8" => "\xE3\x8E\x94", + "\xA7\xD9" => "\xE2\x84\xA6", + "\xA7\xDA" => "\xE3\x8F\x80", + "\xA7\xDB" => "\xE3\x8F\x81", + "\xA7\xDC" => "\xE3\x8E\x8A", + "\xA7\xDD" => "\xE3\x8E\x8B", + "\xA7\xDE" => "\xE3\x8E\x8C", + "\xA7\xDF" => "\xE3\x8F\x96", + "\xA7\xE0" => "\xE3\x8F\x85", + "\xA7\xE1" => "\xE3\x8E\xAD", + "\xA7\xE2" => "\xE3\x8E\xAE", + "\xA7\xE3" => "\xE3\x8E\xAF", + "\xA7\xE4" => "\xE3\x8F\x9B", + "\xA7\xE5" => "\xE3\x8E\xA9", + "\xA7\xE6" => "\xE3\x8E\xAA", + "\xA7\xE7" => "\xE3\x8E\xAB", + "\xA7\xE8" => "\xE3\x8E\xAC", + "\xA7\xE9" => "\xE3\x8F\x9D", + "\xA7\xEA" => "\xE3\x8F\x90", + "\xA7\xEB" => "\xE3\x8F\x93", + "\xA7\xEC" => "\xE3\x8F\x83", + "\xA7\xED" => "\xE3\x8F\x89", + "\xA7\xEE" => "\xE3\x8F\x9C", + "\xA7\xEF" => "\xE3\x8F\x86", + "\xA8\x41" => "\xEC\xAD\xAD", + "\xA8\x42" => "\xEC\xAD\xAE", + "\xA8\x43" => "\xEC\xAD\xAF", + "\xA8\x44" => "\xEC\xAD\xB0", + "\xA8\x45" => "\xEC\xAD\xB1", + "\xA8\x46" => "\xEC\xAD\xB2", + "\xA8\x47" => "\xEC\xAD\xB3", + "\xA8\x48" => "\xEC\xAD\xB4", + "\xA8\x49" => "\xEC\xAD\xB5", + "\xA8\x4A" => "\xEC\xAD\xB6", + "\xA8\x4B" => "\xEC\xAD\xB7", + "\xA8\x4C" => "\xEC\xAD\xBA", + "\xA8\x4D" => "\xEC\xAD\xBB", + "\xA8\x4E" => "\xEC\xAD\xBC", + "\xA8\x4F" => "\xEC\xAD\xBD", + "\xA8\x50" => "\xEC\xAD\xBE", + "\xA8\x51" => "\xEC\xAD\xBF", + "\xA8\x52" => "\xEC\xAE\x80", + "\xA8\x53" => "\xEC\xAE\x81", + "\xA8\x54" => "\xEC\xAE\x82", + "\xA8\x55" => "\xEC\xAE\x83", + "\xA8\x56" => "\xEC\xAE\x84", + "\xA8\x57" => "\xEC\xAE\x85", + "\xA8\x58" => "\xEC\xAE\x86", + "\xA8\x59" => "\xEC\xAE\x87", + "\xA8\x5A" => "\xEC\xAE\x88", + "\xA8\x61" => "\xEC\xAE\x89", + "\xA8\x62" => "\xEC\xAE\x8A", + "\xA8\x63" => "\xEC\xAE\x8B", + "\xA8\x64" => "\xEC\xAE\x8C", + "\xA8\x65" => "\xEC\xAE\x8D", + "\xA8\x66" => "\xEC\xAE\x8E", + "\xA8\x67" => "\xEC\xAE\x8F", + "\xA8\x68" => "\xEC\xAE\x90", + "\xA8\x69" => "\xEC\xAE\x91", + "\xA8\x6A" => "\xEC\xAE\x92", + "\xA8\x6B" => "\xEC\xAE\x93", + "\xA8\x6C" => "\xEC\xAE\x94", + "\xA8\x6D" => "\xEC\xAE\x95", + "\xA8\x6E" => "\xEC\xAE\x96", + "\xA8\x6F" => "\xEC\xAE\x97", + "\xA8\x70" => "\xEC\xAE\x98", + "\xA8\x71" => "\xEC\xAE\x99", + "\xA8\x72" => "\xEC\xAE\x9A", + "\xA8\x73" => "\xEC\xAE\x9B", + "\xA8\x74" => "\xEC\xAE\x9D", + "\xA8\x75" => "\xEC\xAE\x9E", + "\xA8\x76" => "\xEC\xAE\x9F", + "\xA8\x77" => "\xEC\xAE\xA0", + "\xA8\x78" => "\xEC\xAE\xA1", + "\xA8\x79" => "\xEC\xAE\xA2", + "\xA8\x7A" => "\xEC\xAE\xA3", + "\xA8\x81" => "\xEC\xAE\xA4", + "\xA8\x82" => "\xEC\xAE\xA5", + "\xA8\x83" => "\xEC\xAE\xA6", + "\xA8\x84" => "\xEC\xAE\xA7", + "\xA8\x85" => "\xEC\xAE\xA8", + "\xA8\x86" => "\xEC\xAE\xA9", + "\xA8\x87" => "\xEC\xAE\xAA", + "\xA8\x88" => "\xEC\xAE\xAB", + "\xA8\x89" => "\xEC\xAE\xAC", + "\xA8\x8A" => "\xEC\xAE\xAD", + "\xA8\x8B" => "\xEC\xAE\xAE", + "\xA8\x8C" => "\xEC\xAE\xAF", + "\xA8\x8D" => "\xEC\xAE\xB0", + "\xA8\x8E" => "\xEC\xAE\xB1", + "\xA8\x8F" => "\xEC\xAE\xB2", + "\xA8\x90" => "\xEC\xAE\xB3", + "\xA8\x91" => "\xEC\xAE\xB4", + "\xA8\x92" => "\xEC\xAE\xB5", + "\xA8\x93" => "\xEC\xAE\xB6", + "\xA8\x94" => "\xEC\xAE\xB7", + "\xA8\x95" => "\xEC\xAE\xB9", + "\xA8\x96" => "\xEC\xAE\xBA", + "\xA8\x97" => "\xEC\xAE\xBB", + "\xA8\x98" => "\xEC\xAE\xBC", + "\xA8\x99" => "\xEC\xAE\xBD", + "\xA8\x9A" => "\xEC\xAE\xBE", + "\xA8\x9B" => "\xEC\xAE\xBF", + "\xA8\x9C" => "\xEC\xAF\x80", + "\xA8\x9D" => "\xEC\xAF\x81", + "\xA8\x9E" => "\xEC\xAF\x82", + "\xA8\x9F" => "\xEC\xAF\x83", + "\xA8\xA0" => "\xEC\xAF\x84", + "\xA8\xA1" => "\xC3\x86", + "\xA8\xA2" => "\xC3\x90", + "\xA8\xA3" => "\xC2\xAA", + "\xA8\xA4" => "\xC4\xA6", + "\xA8\xA6" => "\xC4\xB2", + "\xA8\xA8" => "\xC4\xBF", + "\xA8\xA9" => "\xC5\x81", + "\xA8\xAA" => "\xC3\x98", + "\xA8\xAB" => "\xC5\x92", + "\xA8\xAC" => "\xC2\xBA", + "\xA8\xAD" => "\xC3\x9E", + "\xA8\xAE" => "\xC5\xA6", + "\xA8\xAF" => "\xC5\x8A", + "\xA8\xB1" => "\xE3\x89\xA0", + "\xA8\xB2" => "\xE3\x89\xA1", + "\xA8\xB3" => "\xE3\x89\xA2", + "\xA8\xB4" => "\xE3\x89\xA3", + "\xA8\xB5" => "\xE3\x89\xA4", + "\xA8\xB6" => "\xE3\x89\xA5", + "\xA8\xB7" => "\xE3\x89\xA6", + "\xA8\xB8" => "\xE3\x89\xA7", + "\xA8\xB9" => "\xE3\x89\xA8", + "\xA8\xBA" => "\xE3\x89\xA9", + "\xA8\xBB" => "\xE3\x89\xAA", + "\xA8\xBC" => "\xE3\x89\xAB", + "\xA8\xBD" => "\xE3\x89\xAC", + "\xA8\xBE" => "\xE3\x89\xAD", + "\xA8\xBF" => "\xE3\x89\xAE", + "\xA8\xC0" => "\xE3\x89\xAF", + "\xA8\xC1" => "\xE3\x89\xB0", + "\xA8\xC2" => "\xE3\x89\xB1", + "\xA8\xC3" => "\xE3\x89\xB2", + "\xA8\xC4" => "\xE3\x89\xB3", + "\xA8\xC5" => "\xE3\x89\xB4", + "\xA8\xC6" => "\xE3\x89\xB5", + "\xA8\xC7" => "\xE3\x89\xB6", + "\xA8\xC8" => "\xE3\x89\xB7", + "\xA8\xC9" => "\xE3\x89\xB8", + "\xA8\xCA" => "\xE3\x89\xB9", + "\xA8\xCB" => "\xE3\x89\xBA", + "\xA8\xCC" => "\xE3\x89\xBB", + "\xA8\xCD" => "\xE2\x93\x90", + "\xA8\xCE" => "\xE2\x93\x91", + "\xA8\xCF" => "\xE2\x93\x92", + "\xA8\xD0" => "\xE2\x93\x93", + "\xA8\xD1" => "\xE2\x93\x94", + "\xA8\xD2" => "\xE2\x93\x95", + "\xA8\xD3" => "\xE2\x93\x96", + "\xA8\xD4" => "\xE2\x93\x97", + "\xA8\xD5" => "\xE2\x93\x98", + "\xA8\xD6" => "\xE2\x93\x99", + "\xA8\xD7" => "\xE2\x93\x9A", + "\xA8\xD8" => "\xE2\x93\x9B", + "\xA8\xD9" => "\xE2\x93\x9C", + "\xA8\xDA" => "\xE2\x93\x9D", + "\xA8\xDB" => "\xE2\x93\x9E", + "\xA8\xDC" => "\xE2\x93\x9F", + "\xA8\xDD" => "\xE2\x93\xA0", + "\xA8\xDE" => "\xE2\x93\xA1", + "\xA8\xDF" => "\xE2\x93\xA2", + "\xA8\xE0" => "\xE2\x93\xA3", + "\xA8\xE1" => "\xE2\x93\xA4", + "\xA8\xE2" => "\xE2\x93\xA5", + "\xA8\xE3" => "\xE2\x93\xA6", + "\xA8\xE4" => "\xE2\x93\xA7", + "\xA8\xE5" => "\xE2\x93\xA8", + "\xA8\xE6" => "\xE2\x93\xA9", + "\xA8\xE7" => "\xE2\x91\xA0", + "\xA8\xE8" => "\xE2\x91\xA1", + "\xA8\xE9" => "\xE2\x91\xA2", + "\xA8\xEA" => "\xE2\x91\xA3", + "\xA8\xEB" => "\xE2\x91\xA4", + "\xA8\xEC" => "\xE2\x91\xA5", + "\xA8\xED" => "\xE2\x91\xA6", + "\xA8\xEE" => "\xE2\x91\xA7", + "\xA8\xEF" => "\xE2\x91\xA8", + "\xA8\xF0" => "\xE2\x91\xA9", + "\xA8\xF1" => "\xE2\x91\xAA", + "\xA8\xF2" => "\xE2\x91\xAB", + "\xA8\xF3" => "\xE2\x91\xAC", + "\xA8\xF4" => "\xE2\x91\xAD", + "\xA8\xF5" => "\xE2\x91\xAE", + "\xA8\xF6" => "\xC2\xBD", + "\xA8\xF7" => "\xE2\x85\x93", + "\xA8\xF8" => "\xE2\x85\x94", + "\xA8\xF9" => "\xC2\xBC", + "\xA8\xFA" => "\xC2\xBE", + "\xA8\xFB" => "\xE2\x85\x9B", + "\xA8\xFC" => "\xE2\x85\x9C", + "\xA8\xFD" => "\xE2\x85\x9D", + "\xA8\xFE" => "\xE2\x85\x9E", + "\xA9\x41" => "\xEC\xAF\x85", + "\xA9\x42" => "\xEC\xAF\x86", + "\xA9\x43" => "\xEC\xAF\x87", + "\xA9\x44" => "\xEC\xAF\x88", + "\xA9\x45" => "\xEC\xAF\x89", + "\xA9\x46" => "\xEC\xAF\x8A", + "\xA9\x47" => "\xEC\xAF\x8B", + "\xA9\x48" => "\xEC\xAF\x8C", + "\xA9\x49" => "\xEC\xAF\x8D", + "\xA9\x4A" => "\xEC\xAF\x8E", + "\xA9\x4B" => "\xEC\xAF\x8F", + "\xA9\x4C" => "\xEC\xAF\x90", + "\xA9\x4D" => "\xEC\xAF\x91", + "\xA9\x4E" => "\xEC\xAF\x92", + "\xA9\x4F" => "\xEC\xAF\x93", + "\xA9\x50" => "\xEC\xAF\x95", + "\xA9\x51" => "\xEC\xAF\x96", + "\xA9\x52" => "\xEC\xAF\x97", + "\xA9\x53" => "\xEC\xAF\x98", + "\xA9\x54" => "\xEC\xAF\x99", + "\xA9\x55" => "\xEC\xAF\x9A", + "\xA9\x56" => "\xEC\xAF\x9B", + "\xA9\x57" => "\xEC\xAF\x9C", + "\xA9\x58" => "\xEC\xAF\x9D", + "\xA9\x59" => "\xEC\xAF\x9E", + "\xA9\x5A" => "\xEC\xAF\x9F", + "\xA9\x61" => "\xEC\xAF\xA0", + "\xA9\x62" => "\xEC\xAF\xA1", + "\xA9\x63" => "\xEC\xAF\xA2", + "\xA9\x64" => "\xEC\xAF\xA3", + "\xA9\x65" => "\xEC\xAF\xA5", + "\xA9\x66" => "\xEC\xAF\xA6", + "\xA9\x67" => "\xEC\xAF\xA8", + "\xA9\x68" => "\xEC\xAF\xAA", + "\xA9\x69" => "\xEC\xAF\xAB", + "\xA9\x6A" => "\xEC\xAF\xAC", + "\xA9\x6B" => "\xEC\xAF\xAD", + "\xA9\x6C" => "\xEC\xAF\xAE", + "\xA9\x6D" => "\xEC\xAF\xAF", + "\xA9\x6E" => "\xEC\xAF\xB0", + "\xA9\x6F" => "\xEC\xAF\xB1", + "\xA9\x70" => "\xEC\xAF\xB2", + "\xA9\x71" => "\xEC\xAF\xB3", + "\xA9\x72" => "\xEC\xAF\xB4", + "\xA9\x73" => "\xEC\xAF\xB5", + "\xA9\x74" => "\xEC\xAF\xB6", + "\xA9\x75" => "\xEC\xAF\xB7", + "\xA9\x76" => "\xEC\xAF\xB8", + "\xA9\x77" => "\xEC\xAF\xB9", + "\xA9\x78" => "\xEC\xAF\xBA", + "\xA9\x79" => "\xEC\xAF\xBB", + "\xA9\x7A" => "\xEC\xAF\xBC", + "\xA9\x81" => "\xEC\xAF\xBD", + "\xA9\x82" => "\xEC\xAF\xBE", + "\xA9\x83" => "\xEC\xAF\xBF", + "\xA9\x84" => "\xEC\xB0\x80", + "\xA9\x85" => "\xEC\xB0\x81", + "\xA9\x86" => "\xEC\xB0\x82", + "\xA9\x87" => "\xEC\xB0\x83", + "\xA9\x88" => "\xEC\xB0\x84", + "\xA9\x89" => "\xEC\xB0\x85", + "\xA9\x8A" => "\xEC\xB0\x86", + "\xA9\x8B" => "\xEC\xB0\x87", + "\xA9\x8C" => "\xEC\xB0\x88", + "\xA9\x8D" => "\xEC\xB0\x89", + "\xA9\x8E" => "\xEC\xB0\x8A", + "\xA9\x8F" => "\xEC\xB0\x8B", + "\xA9\x90" => "\xEC\xB0\x8E", + "\xA9\x91" => "\xEC\xB0\x8F", + "\xA9\x92" => "\xEC\xB0\x91", + "\xA9\x93" => "\xEC\xB0\x92", + "\xA9\x94" => "\xEC\xB0\x93", + "\xA9\x95" => "\xEC\xB0\x95", + "\xA9\x96" => "\xEC\xB0\x96", + "\xA9\x97" => "\xEC\xB0\x97", + "\xA9\x98" => "\xEC\xB0\x98", + "\xA9\x99" => "\xEC\xB0\x99", + "\xA9\x9A" => "\xEC\xB0\x9A", + "\xA9\x9B" => "\xEC\xB0\x9B", + "\xA9\x9C" => "\xEC\xB0\x9E", + "\xA9\x9D" => "\xEC\xB0\x9F", + "\xA9\x9E" => "\xEC\xB0\xA0", + "\xA9\x9F" => "\xEC\xB0\xA3", + "\xA9\xA0" => "\xEC\xB0\xA4", + "\xA9\xA1" => "\xC3\xA6", + "\xA9\xA2" => "\xC4\x91", + "\xA9\xA3" => "\xC3\xB0", + "\xA9\xA4" => "\xC4\xA7", + "\xA9\xA5" => "\xC4\xB1", + "\xA9\xA6" => "\xC4\xB3", + "\xA9\xA7" => "\xC4\xB8", + "\xA9\xA8" => "\xC5\x80", + "\xA9\xA9" => "\xC5\x82", + "\xA9\xAA" => "\xC3\xB8", + "\xA9\xAB" => "\xC5\x93", + "\xA9\xAC" => "\xC3\x9F", + "\xA9\xAD" => "\xC3\xBE", + "\xA9\xAE" => "\xC5\xA7", + "\xA9\xAF" => "\xC5\x8B", + "\xA9\xB0" => "\xC5\x89", + "\xA9\xB1" => "\xE3\x88\x80", + "\xA9\xB2" => "\xE3\x88\x81", + "\xA9\xB3" => "\xE3\x88\x82", + "\xA9\xB4" => "\xE3\x88\x83", + "\xA9\xB5" => "\xE3\x88\x84", + "\xA9\xB6" => "\xE3\x88\x85", + "\xA9\xB7" => "\xE3\x88\x86", + "\xA9\xB8" => "\xE3\x88\x87", + "\xA9\xB9" => "\xE3\x88\x88", + "\xA9\xBA" => "\xE3\x88\x89", + "\xA9\xBB" => "\xE3\x88\x8A", + "\xA9\xBC" => "\xE3\x88\x8B", + "\xA9\xBD" => "\xE3\x88\x8C", + "\xA9\xBE" => "\xE3\x88\x8D", + "\xA9\xBF" => "\xE3\x88\x8E", + "\xA9\xC0" => "\xE3\x88\x8F", + "\xA9\xC1" => "\xE3\x88\x90", + "\xA9\xC2" => "\xE3\x88\x91", + "\xA9\xC3" => "\xE3\x88\x92", + "\xA9\xC4" => "\xE3\x88\x93", + "\xA9\xC5" => "\xE3\x88\x94", + "\xA9\xC6" => "\xE3\x88\x95", + "\xA9\xC7" => "\xE3\x88\x96", + "\xA9\xC8" => "\xE3\x88\x97", + "\xA9\xC9" => "\xE3\x88\x98", + "\xA9\xCA" => "\xE3\x88\x99", + "\xA9\xCB" => "\xE3\x88\x9A", + "\xA9\xCC" => "\xE3\x88\x9B", + "\xA9\xCD" => "\xE2\x92\x9C", + "\xA9\xCE" => "\xE2\x92\x9D", + "\xA9\xCF" => "\xE2\x92\x9E", + "\xA9\xD0" => "\xE2\x92\x9F", + "\xA9\xD1" => "\xE2\x92\xA0", + "\xA9\xD2" => "\xE2\x92\xA1", + "\xA9\xD3" => "\xE2\x92\xA2", + "\xA9\xD4" => "\xE2\x92\xA3", + "\xA9\xD5" => "\xE2\x92\xA4", + "\xA9\xD6" => "\xE2\x92\xA5", + "\xA9\xD7" => "\xE2\x92\xA6", + "\xA9\xD8" => "\xE2\x92\xA7", + "\xA9\xD9" => "\xE2\x92\xA8", + "\xA9\xDA" => "\xE2\x92\xA9", + "\xA9\xDB" => "\xE2\x92\xAA", + "\xA9\xDC" => "\xE2\x92\xAB", + "\xA9\xDD" => "\xE2\x92\xAC", + "\xA9\xDE" => "\xE2\x92\xAD", + "\xA9\xDF" => "\xE2\x92\xAE", + "\xA9\xE0" => "\xE2\x92\xAF", + "\xA9\xE1" => "\xE2\x92\xB0", + "\xA9\xE2" => "\xE2\x92\xB1", + "\xA9\xE3" => "\xE2\x92\xB2", + "\xA9\xE4" => "\xE2\x92\xB3", + "\xA9\xE5" => "\xE2\x92\xB4", + "\xA9\xE6" => "\xE2\x92\xB5", + "\xA9\xE7" => "\xE2\x91\xB4", + "\xA9\xE8" => "\xE2\x91\xB5", + "\xA9\xE9" => "\xE2\x91\xB6", + "\xA9\xEA" => "\xE2\x91\xB7", + "\xA9\xEB" => "\xE2\x91\xB8", + "\xA9\xEC" => "\xE2\x91\xB9", + "\xA9\xED" => "\xE2\x91\xBA", + "\xA9\xEE" => "\xE2\x91\xBB", + "\xA9\xEF" => "\xE2\x91\xBC", + "\xA9\xF0" => "\xE2\x91\xBD", + "\xA9\xF1" => "\xE2\x91\xBE", + "\xA9\xF2" => "\xE2\x91\xBF", + "\xA9\xF3" => "\xE2\x92\x80", + "\xA9\xF4" => "\xE2\x92\x81", + "\xA9\xF5" => "\xE2\x92\x82", + "\xA9\xF6" => "\xC2\xB9", + "\xA9\xF7" => "\xC2\xB2", + "\xA9\xF8" => "\xC2\xB3", + "\xA9\xF9" => "\xE2\x81\xB4", + "\xA9\xFA" => "\xE2\x81\xBF", + "\xA9\xFB" => "\xE2\x82\x81", + "\xA9\xFC" => "\xE2\x82\x82", + "\xA9\xFD" => "\xE2\x82\x83", + "\xA9\xFE" => "\xE2\x82\x84", + "\xAA\x41" => "\xEC\xB0\xA5", + "\xAA\x42" => "\xEC\xB0\xA6", + "\xAA\x43" => "\xEC\xB0\xAA", + "\xAA\x44" => "\xEC\xB0\xAB", + "\xAA\x45" => "\xEC\xB0\xAD", + "\xAA\x46" => "\xEC\xB0\xAF", + "\xAA\x47" => "\xEC\xB0\xB1", + "\xAA\x48" => "\xEC\xB0\xB2", + "\xAA\x49" => "\xEC\xB0\xB3", + "\xAA\x4A" => "\xEC\xB0\xB4", + "\xAA\x4B" => "\xEC\xB0\xB5", + "\xAA\x4C" => "\xEC\xB0\xB6", + "\xAA\x4D" => "\xEC\xB0\xB7", + "\xAA\x4E" => "\xEC\xB0\xBA", + "\xAA\x4F" => "\xEC\xB0\xBF", + "\xAA\x50" => "\xEC\xB1\x80", + "\xAA\x51" => "\xEC\xB1\x81", + "\xAA\x52" => "\xEC\xB1\x82", + "\xAA\x53" => "\xEC\xB1\x83", + "\xAA\x54" => "\xEC\xB1\x86", + "\xAA\x55" => "\xEC\xB1\x87", + "\xAA\x56" => "\xEC\xB1\x89", + "\xAA\x57" => "\xEC\xB1\x8A", + "\xAA\x58" => "\xEC\xB1\x8B", + "\xAA\x59" => "\xEC\xB1\x8D", + "\xAA\x5A" => "\xEC\xB1\x8E", + "\xAA\x61" => "\xEC\xB1\x8F", + "\xAA\x62" => "\xEC\xB1\x90", + "\xAA\x63" => "\xEC\xB1\x91", + "\xAA\x64" => "\xEC\xB1\x92", + "\xAA\x65" => "\xEC\xB1\x93", + "\xAA\x66" => "\xEC\xB1\x96", + "\xAA\x67" => "\xEC\xB1\x9A", + "\xAA\x68" => "\xEC\xB1\x9B", + "\xAA\x69" => "\xEC\xB1\x9C", + "\xAA\x6A" => "\xEC\xB1\x9D", + "\xAA\x6B" => "\xEC\xB1\x9E", + "\xAA\x6C" => "\xEC\xB1\x9F", + "\xAA\x6D" => "\xEC\xB1\xA1", + "\xAA\x6E" => "\xEC\xB1\xA2", + "\xAA\x6F" => "\xEC\xB1\xA3", + "\xAA\x70" => "\xEC\xB1\xA5", + "\xAA\x71" => "\xEC\xB1\xA7", + "\xAA\x72" => "\xEC\xB1\xA9", + "\xAA\x73" => "\xEC\xB1\xAA", + "\xAA\x74" => "\xEC\xB1\xAB", + "\xAA\x75" => "\xEC\xB1\xAC", + "\xAA\x76" => "\xEC\xB1\xAD", + "\xAA\x77" => "\xEC\xB1\xAE", + "\xAA\x78" => "\xEC\xB1\xAF", + "\xAA\x79" => "\xEC\xB1\xB1", + "\xAA\x7A" => "\xEC\xB1\xB2", + "\xAA\x81" => "\xEC\xB1\xB3", + "\xAA\x82" => "\xEC\xB1\xB4", + "\xAA\x83" => "\xEC\xB1\xB6", + "\xAA\x84" => "\xEC\xB1\xB7", + "\xAA\x85" => "\xEC\xB1\xB8", + "\xAA\x86" => "\xEC\xB1\xB9", + "\xAA\x87" => "\xEC\xB1\xBA", + "\xAA\x88" => "\xEC\xB1\xBB", + "\xAA\x89" => "\xEC\xB1\xBC", + "\xAA\x8A" => "\xEC\xB1\xBD", + "\xAA\x8B" => "\xEC\xB1\xBE", + "\xAA\x8C" => "\xEC\xB1\xBF", + "\xAA\x8D" => "\xEC\xB2\x80", + "\xAA\x8E" => "\xEC\xB2\x81", + "\xAA\x8F" => "\xEC\xB2\x82", + "\xAA\x90" => "\xEC\xB2\x83", + "\xAA\x91" => "\xEC\xB2\x84", + "\xAA\x92" => "\xEC\xB2\x85", + "\xAA\x93" => "\xEC\xB2\x86", + "\xAA\x94" => "\xEC\xB2\x87", + "\xAA\x95" => "\xEC\xB2\x88", + "\xAA\x96" => "\xEC\xB2\x89", + "\xAA\x97" => "\xEC\xB2\x8A", + "\xAA\x98" => "\xEC\xB2\x8B", + "\xAA\x99" => "\xEC\xB2\x8C", + "\xAA\x9A" => "\xEC\xB2\x8D", + "\xAA\x9B" => "\xEC\xB2\x8E", + "\xAA\x9C" => "\xEC\xB2\x8F", + "\xAA\x9D" => "\xEC\xB2\x90", + "\xAA\x9E" => "\xEC\xB2\x91", + "\xAA\x9F" => "\xEC\xB2\x92", + "\xAA\xA0" => "\xEC\xB2\x93", + "\xAA\xA1" => "\xE3\x81\x81", + "\xAA\xA2" => "\xE3\x81\x82", + "\xAA\xA3" => "\xE3\x81\x83", + "\xAA\xA4" => "\xE3\x81\x84", + "\xAA\xA5" => "\xE3\x81\x85", + "\xAA\xA6" => "\xE3\x81\x86", + "\xAA\xA7" => "\xE3\x81\x87", + "\xAA\xA8" => "\xE3\x81\x88", + "\xAA\xA9" => "\xE3\x81\x89", + "\xAA\xAA" => "\xE3\x81\x8A", + "\xAA\xAB" => "\xE3\x81\x8B", + "\xAA\xAC" => "\xE3\x81\x8C", + "\xAA\xAD" => "\xE3\x81\x8D", + "\xAA\xAE" => "\xE3\x81\x8E", + "\xAA\xAF" => "\xE3\x81\x8F", + "\xAA\xB0" => "\xE3\x81\x90", + "\xAA\xB1" => "\xE3\x81\x91", + "\xAA\xB2" => "\xE3\x81\x92", + "\xAA\xB3" => "\xE3\x81\x93", + "\xAA\xB4" => "\xE3\x81\x94", + "\xAA\xB5" => "\xE3\x81\x95", + "\xAA\xB6" => "\xE3\x81\x96", + "\xAA\xB7" => "\xE3\x81\x97", + "\xAA\xB8" => "\xE3\x81\x98", + "\xAA\xB9" => "\xE3\x81\x99", + "\xAA\xBA" => "\xE3\x81\x9A", + "\xAA\xBB" => "\xE3\x81\x9B", + "\xAA\xBC" => "\xE3\x81\x9C", + "\xAA\xBD" => "\xE3\x81\x9D", + "\xAA\xBE" => "\xE3\x81\x9E", + "\xAA\xBF" => "\xE3\x81\x9F", + "\xAA\xC0" => "\xE3\x81\xA0", + "\xAA\xC1" => "\xE3\x81\xA1", + "\xAA\xC2" => "\xE3\x81\xA2", + "\xAA\xC3" => "\xE3\x81\xA3", + "\xAA\xC4" => "\xE3\x81\xA4", + "\xAA\xC5" => "\xE3\x81\xA5", + "\xAA\xC6" => "\xE3\x81\xA6", + "\xAA\xC7" => "\xE3\x81\xA7", + "\xAA\xC8" => "\xE3\x81\xA8", + "\xAA\xC9" => "\xE3\x81\xA9", + "\xAA\xCA" => "\xE3\x81\xAA", + "\xAA\xCB" => "\xE3\x81\xAB", + "\xAA\xCC" => "\xE3\x81\xAC", + "\xAA\xCD" => "\xE3\x81\xAD", + "\xAA\xCE" => "\xE3\x81\xAE", + "\xAA\xCF" => "\xE3\x81\xAF", + "\xAA\xD0" => "\xE3\x81\xB0", + "\xAA\xD1" => "\xE3\x81\xB1", + "\xAA\xD2" => "\xE3\x81\xB2", + "\xAA\xD3" => "\xE3\x81\xB3", + "\xAA\xD4" => "\xE3\x81\xB4", + "\xAA\xD5" => "\xE3\x81\xB5", + "\xAA\xD6" => "\xE3\x81\xB6", + "\xAA\xD7" => "\xE3\x81\xB7", + "\xAA\xD8" => "\xE3\x81\xB8", + "\xAA\xD9" => "\xE3\x81\xB9", + "\xAA\xDA" => "\xE3\x81\xBA", + "\xAA\xDB" => "\xE3\x81\xBB", + "\xAA\xDC" => "\xE3\x81\xBC", + "\xAA\xDD" => "\xE3\x81\xBD", + "\xAA\xDE" => "\xE3\x81\xBE", + "\xAA\xDF" => "\xE3\x81\xBF", + "\xAA\xE0" => "\xE3\x82\x80", + "\xAA\xE1" => "\xE3\x82\x81", + "\xAA\xE2" => "\xE3\x82\x82", + "\xAA\xE3" => "\xE3\x82\x83", + "\xAA\xE4" => "\xE3\x82\x84", + "\xAA\xE5" => "\xE3\x82\x85", + "\xAA\xE6" => "\xE3\x82\x86", + "\xAA\xE7" => "\xE3\x82\x87", + "\xAA\xE8" => "\xE3\x82\x88", + "\xAA\xE9" => "\xE3\x82\x89", + "\xAA\xEA" => "\xE3\x82\x8A", + "\xAA\xEB" => "\xE3\x82\x8B", + "\xAA\xEC" => "\xE3\x82\x8C", + "\xAA\xED" => "\xE3\x82\x8D", + "\xAA\xEE" => "\xE3\x82\x8E", + "\xAA\xEF" => "\xE3\x82\x8F", + "\xAA\xF0" => "\xE3\x82\x90", + "\xAA\xF1" => "\xE3\x82\x91", + "\xAA\xF2" => "\xE3\x82\x92", + "\xAA\xF3" => "\xE3\x82\x93", + "\xAB\x41" => "\xEC\xB2\x94", + "\xAB\x42" => "\xEC\xB2\x95", + "\xAB\x43" => "\xEC\xB2\x96", + "\xAB\x44" => "\xEC\xB2\x97", + "\xAB\x45" => "\xEC\xB2\x9A", + "\xAB\x46" => "\xEC\xB2\x9B", + "\xAB\x47" => "\xEC\xB2\x9D", + "\xAB\x48" => "\xEC\xB2\x9E", + "\xAB\x49" => "\xEC\xB2\x9F", + "\xAB\x4A" => "\xEC\xB2\xA1", + "\xAB\x4B" => "\xEC\xB2\xA2", + "\xAB\x4C" => "\xEC\xB2\xA3", + "\xAB\x4D" => "\xEC\xB2\xA4", + "\xAB\x4E" => "\xEC\xB2\xA5", + "\xAB\x4F" => "\xEC\xB2\xA6", + "\xAB\x50" => "\xEC\xB2\xA7", + "\xAB\x51" => "\xEC\xB2\xAA", + "\xAB\x52" => "\xEC\xB2\xAE", + "\xAB\x53" => "\xEC\xB2\xAF", + "\xAB\x54" => "\xEC\xB2\xB0", + "\xAB\x55" => "\xEC\xB2\xB1", + "\xAB\x56" => "\xEC\xB2\xB2", + "\xAB\x57" => "\xEC\xB2\xB3", + "\xAB\x58" => "\xEC\xB2\xB6", + "\xAB\x59" => "\xEC\xB2\xB7", + "\xAB\x5A" => "\xEC\xB2\xB9", + "\xAB\x61" => "\xEC\xB2\xBA", + "\xAB\x62" => "\xEC\xB2\xBB", + "\xAB\x63" => "\xEC\xB2\xBD", + "\xAB\x64" => "\xEC\xB2\xBE", + "\xAB\x65" => "\xEC\xB2\xBF", + "\xAB\x66" => "\xEC\xB3\x80", + "\xAB\x67" => "\xEC\xB3\x81", + "\xAB\x68" => "\xEC\xB3\x82", + "\xAB\x69" => "\xEC\xB3\x83", + "\xAB\x6A" => "\xEC\xB3\x86", + "\xAB\x6B" => "\xEC\xB3\x88", + "\xAB\x6C" => "\xEC\xB3\x8A", + "\xAB\x6D" => "\xEC\xB3\x8B", + "\xAB\x6E" => "\xEC\xB3\x8C", + "\xAB\x6F" => "\xEC\xB3\x8D", + "\xAB\x70" => "\xEC\xB3\x8E", + "\xAB\x71" => "\xEC\xB3\x8F", + "\xAB\x72" => "\xEC\xB3\x91", + "\xAB\x73" => "\xEC\xB3\x92", + "\xAB\x74" => "\xEC\xB3\x93", + "\xAB\x75" => "\xEC\xB3\x95", + "\xAB\x76" => "\xEC\xB3\x96", + "\xAB\x77" => "\xEC\xB3\x97", + "\xAB\x78" => "\xEC\xB3\x98", + "\xAB\x79" => "\xEC\xB3\x99", + "\xAB\x7A" => "\xEC\xB3\x9A", + "\xAB\x81" => "\xEC\xB3\x9B", + "\xAB\x82" => "\xEC\xB3\x9C", + "\xAB\x83" => "\xEC\xB3\x9D", + "\xAB\x84" => "\xEC\xB3\x9E", + "\xAB\x85" => "\xEC\xB3\x9F", + "\xAB\x86" => "\xEC\xB3\xA0", + "\xAB\x87" => "\xEC\xB3\xA1", + "\xAB\x88" => "\xEC\xB3\xA2", + "\xAB\x89" => "\xEC\xB3\xA3", + "\xAB\x8A" => "\xEC\xB3\xA5", + "\xAB\x8B" => "\xEC\xB3\xA6", + "\xAB\x8C" => "\xEC\xB3\xA7", + "\xAB\x8D" => "\xEC\xB3\xA8", + "\xAB\x8E" => "\xEC\xB3\xA9", + "\xAB\x8F" => "\xEC\xB3\xAA", + "\xAB\x90" => "\xEC\xB3\xAB", + "\xAB\x91" => "\xEC\xB3\xAD", + "\xAB\x92" => "\xEC\xB3\xAE", + "\xAB\x93" => "\xEC\xB3\xAF", + "\xAB\x94" => "\xEC\xB3\xB1", + "\xAB\x95" => "\xEC\xB3\xB2", + "\xAB\x96" => "\xEC\xB3\xB3", + "\xAB\x97" => "\xEC\xB3\xB4", + "\xAB\x98" => "\xEC\xB3\xB5", + "\xAB\x99" => "\xEC\xB3\xB6", + "\xAB\x9A" => "\xEC\xB3\xB7", + "\xAB\x9B" => "\xEC\xB3\xB8", + "\xAB\x9C" => "\xEC\xB3\xB9", + "\xAB\x9D" => "\xEC\xB3\xBA", + "\xAB\x9E" => "\xEC\xB3\xBB", + "\xAB\x9F" => "\xEC\xB3\xBC", + "\xAB\xA0" => "\xEC\xB3\xBD", + "\xAB\xA1" => "\xE3\x82\xA1", + "\xAB\xA2" => "\xE3\x82\xA2", + "\xAB\xA3" => "\xE3\x82\xA3", + "\xAB\xA4" => "\xE3\x82\xA4", + "\xAB\xA5" => "\xE3\x82\xA5", + "\xAB\xA6" => "\xE3\x82\xA6", + "\xAB\xA7" => "\xE3\x82\xA7", + "\xAB\xA8" => "\xE3\x82\xA8", + "\xAB\xA9" => "\xE3\x82\xA9", + "\xAB\xAA" => "\xE3\x82\xAA", + "\xAB\xAB" => "\xE3\x82\xAB", + "\xAB\xAC" => "\xE3\x82\xAC", + "\xAB\xAD" => "\xE3\x82\xAD", + "\xAB\xAE" => "\xE3\x82\xAE", + "\xAB\xAF" => "\xE3\x82\xAF", + "\xAB\xB0" => "\xE3\x82\xB0", + "\xAB\xB1" => "\xE3\x82\xB1", + "\xAB\xB2" => "\xE3\x82\xB2", + "\xAB\xB3" => "\xE3\x82\xB3", + "\xAB\xB4" => "\xE3\x82\xB4", + "\xAB\xB5" => "\xE3\x82\xB5", + "\xAB\xB6" => "\xE3\x82\xB6", + "\xAB\xB7" => "\xE3\x82\xB7", + "\xAB\xB8" => "\xE3\x82\xB8", + "\xAB\xB9" => "\xE3\x82\xB9", + "\xAB\xBA" => "\xE3\x82\xBA", + "\xAB\xBB" => "\xE3\x82\xBB", + "\xAB\xBC" => "\xE3\x82\xBC", + "\xAB\xBD" => "\xE3\x82\xBD", + "\xAB\xBE" => "\xE3\x82\xBE", + "\xAB\xBF" => "\xE3\x82\xBF", + "\xAB\xC0" => "\xE3\x83\x80", + "\xAB\xC1" => "\xE3\x83\x81", + "\xAB\xC2" => "\xE3\x83\x82", + "\xAB\xC3" => "\xE3\x83\x83", + "\xAB\xC4" => "\xE3\x83\x84", + "\xAB\xC5" => "\xE3\x83\x85", + "\xAB\xC6" => "\xE3\x83\x86", + "\xAB\xC7" => "\xE3\x83\x87", + "\xAB\xC8" => "\xE3\x83\x88", + "\xAB\xC9" => "\xE3\x83\x89", + "\xAB\xCA" => "\xE3\x83\x8A", + "\xAB\xCB" => "\xE3\x83\x8B", + "\xAB\xCC" => "\xE3\x83\x8C", + "\xAB\xCD" => "\xE3\x83\x8D", + "\xAB\xCE" => "\xE3\x83\x8E", + "\xAB\xCF" => "\xE3\x83\x8F", + "\xAB\xD0" => "\xE3\x83\x90", + "\xAB\xD1" => "\xE3\x83\x91", + "\xAB\xD2" => "\xE3\x83\x92", + "\xAB\xD3" => "\xE3\x83\x93", + "\xAB\xD4" => "\xE3\x83\x94", + "\xAB\xD5" => "\xE3\x83\x95", + "\xAB\xD6" => "\xE3\x83\x96", + "\xAB\xD7" => "\xE3\x83\x97", + "\xAB\xD8" => "\xE3\x83\x98", + "\xAB\xD9" => "\xE3\x83\x99", + "\xAB\xDA" => "\xE3\x83\x9A", + "\xAB\xDB" => "\xE3\x83\x9B", + "\xAB\xDC" => "\xE3\x83\x9C", + "\xAB\xDD" => "\xE3\x83\x9D", + "\xAB\xDE" => "\xE3\x83\x9E", + "\xAB\xDF" => "\xE3\x83\x9F", + "\xAB\xE0" => "\xE3\x83\xA0", + "\xAB\xE1" => "\xE3\x83\xA1", + "\xAB\xE2" => "\xE3\x83\xA2", + "\xAB\xE3" => "\xE3\x83\xA3", + "\xAB\xE4" => "\xE3\x83\xA4", + "\xAB\xE5" => "\xE3\x83\xA5", + "\xAB\xE6" => "\xE3\x83\xA6", + "\xAB\xE7" => "\xE3\x83\xA7", + "\xAB\xE8" => "\xE3\x83\xA8", + "\xAB\xE9" => "\xE3\x83\xA9", + "\xAB\xEA" => "\xE3\x83\xAA", + "\xAB\xEB" => "\xE3\x83\xAB", + "\xAB\xEC" => "\xE3\x83\xAC", + "\xAB\xED" => "\xE3\x83\xAD", + "\xAB\xEE" => "\xE3\x83\xAE", + "\xAB\xEF" => "\xE3\x83\xAF", + "\xAB\xF0" => "\xE3\x83\xB0", + "\xAB\xF1" => "\xE3\x83\xB1", + "\xAB\xF2" => "\xE3\x83\xB2", + "\xAB\xF3" => "\xE3\x83\xB3", + "\xAB\xF4" => "\xE3\x83\xB4", + "\xAB\xF5" => "\xE3\x83\xB5", + "\xAB\xF6" => "\xE3\x83\xB6", + "\xAC\x41" => "\xEC\xB3\xBE", + "\xAC\x42" => "\xEC\xB3\xBF", + "\xAC\x43" => "\xEC\xB4\x80", + "\xAC\x44" => "\xEC\xB4\x82", + "\xAC\x45" => "\xEC\xB4\x83", + "\xAC\x46" => "\xEC\xB4\x84", + "\xAC\x47" => "\xEC\xB4\x85", + "\xAC\x48" => "\xEC\xB4\x86", + "\xAC\x49" => "\xEC\xB4\x87", + "\xAC\x4A" => "\xEC\xB4\x8A", + "\xAC\x4B" => "\xEC\xB4\x8B", + "\xAC\x4C" => "\xEC\xB4\x8D", + "\xAC\x4D" => "\xEC\xB4\x8E", + "\xAC\x4E" => "\xEC\xB4\x8F", + "\xAC\x4F" => "\xEC\xB4\x91", + "\xAC\x50" => "\xEC\xB4\x92", + "\xAC\x51" => "\xEC\xB4\x93", + "\xAC\x52" => "\xEC\xB4\x94", + "\xAC\x53" => "\xEC\xB4\x95", + "\xAC\x54" => "\xEC\xB4\x96", + "\xAC\x55" => "\xEC\xB4\x97", + "\xAC\x56" => "\xEC\xB4\x9A", + "\xAC\x57" => "\xEC\xB4\x9C", + "\xAC\x58" => "\xEC\xB4\x9E", + "\xAC\x59" => "\xEC\xB4\x9F", + "\xAC\x5A" => "\xEC\xB4\xA0", + "\xAC\x61" => "\xEC\xB4\xA1", + "\xAC\x62" => "\xEC\xB4\xA2", + "\xAC\x63" => "\xEC\xB4\xA3", + "\xAC\x64" => "\xEC\xB4\xA5", + "\xAC\x65" => "\xEC\xB4\xA6", + "\xAC\x66" => "\xEC\xB4\xA7", + "\xAC\x67" => "\xEC\xB4\xA9", + "\xAC\x68" => "\xEC\xB4\xAA", + "\xAC\x69" => "\xEC\xB4\xAB", + "\xAC\x6A" => "\xEC\xB4\xAD", + "\xAC\x6B" => "\xEC\xB4\xAE", + "\xAC\x6C" => "\xEC\xB4\xAF", + "\xAC\x6D" => "\xEC\xB4\xB0", + "\xAC\x6E" => "\xEC\xB4\xB1", + "\xAC\x6F" => "\xEC\xB4\xB2", + "\xAC\x70" => "\xEC\xB4\xB3", + "\xAC\x71" => "\xEC\xB4\xB4", + "\xAC\x72" => "\xEC\xB4\xB5", + "\xAC\x73" => "\xEC\xB4\xB6", + "\xAC\x74" => "\xEC\xB4\xB7", + "\xAC\x75" => "\xEC\xB4\xB8", + "\xAC\x76" => "\xEC\xB4\xBA", + "\xAC\x77" => "\xEC\xB4\xBB", + "\xAC\x78" => "\xEC\xB4\xBC", + "\xAC\x79" => "\xEC\xB4\xBD", + "\xAC\x7A" => "\xEC\xB4\xBE", + "\xAC\x81" => "\xEC\xB4\xBF", + "\xAC\x82" => "\xEC\xB5\x80", + "\xAC\x83" => "\xEC\xB5\x81", + "\xAC\x84" => "\xEC\xB5\x82", + "\xAC\x85" => "\xEC\xB5\x83", + "\xAC\x86" => "\xEC\xB5\x84", + "\xAC\x87" => "\xEC\xB5\x85", + "\xAC\x88" => "\xEC\xB5\x86", + "\xAC\x89" => "\xEC\xB5\x87", + "\xAC\x8A" => "\xEC\xB5\x88", + "\xAC\x8B" => "\xEC\xB5\x89", + "\xAC\x8C" => "\xEC\xB5\x8A", + "\xAC\x8D" => "\xEC\xB5\x8B", + "\xAC\x8E" => "\xEC\xB5\x8C", + "\xAC\x8F" => "\xEC\xB5\x8D", + "\xAC\x90" => "\xEC\xB5\x8E", + "\xAC\x91" => "\xEC\xB5\x8F", + "\xAC\x92" => "\xEC\xB5\x90", + "\xAC\x93" => "\xEC\xB5\x91", + "\xAC\x94" => "\xEC\xB5\x92", + "\xAC\x95" => "\xEC\xB5\x93", + "\xAC\x96" => "\xEC\xB5\x94", + "\xAC\x97" => "\xEC\xB5\x95", + "\xAC\x98" => "\xEC\xB5\x96", + "\xAC\x99" => "\xEC\xB5\x97", + "\xAC\x9A" => "\xEC\xB5\x98", + "\xAC\x9B" => "\xEC\xB5\x99", + "\xAC\x9C" => "\xEC\xB5\x9A", + "\xAC\x9D" => "\xEC\xB5\x9B", + "\xAC\x9E" => "\xEC\xB5\x9D", + "\xAC\x9F" => "\xEC\xB5\x9E", + "\xAC\xA0" => "\xEC\xB5\x9F", + "\xAC\xA1" => "\xD0\x90", + "\xAC\xA2" => "\xD0\x91", + "\xAC\xA3" => "\xD0\x92", + "\xAC\xA4" => "\xD0\x93", + "\xAC\xA5" => "\xD0\x94", + "\xAC\xA6" => "\xD0\x95", + "\xAC\xA7" => "\xD0\x81", + "\xAC\xA8" => "\xD0\x96", + "\xAC\xA9" => "\xD0\x97", + "\xAC\xAA" => "\xD0\x98", + "\xAC\xAB" => "\xD0\x99", + "\xAC\xAC" => "\xD0\x9A", + "\xAC\xAD" => "\xD0\x9B", + "\xAC\xAE" => "\xD0\x9C", + "\xAC\xAF" => "\xD0\x9D", + "\xAC\xB0" => "\xD0\x9E", + "\xAC\xB1" => "\xD0\x9F", + "\xAC\xB2" => "\xD0\xA0", + "\xAC\xB3" => "\xD0\xA1", + "\xAC\xB4" => "\xD0\xA2", + "\xAC\xB5" => "\xD0\xA3", + "\xAC\xB6" => "\xD0\xA4", + "\xAC\xB7" => "\xD0\xA5", + "\xAC\xB8" => "\xD0\xA6", + "\xAC\xB9" => "\xD0\xA7", + "\xAC\xBA" => "\xD0\xA8", + "\xAC\xBB" => "\xD0\xA9", + "\xAC\xBC" => "\xD0\xAA", + "\xAC\xBD" => "\xD0\xAB", + "\xAC\xBE" => "\xD0\xAC", + "\xAC\xBF" => "\xD0\xAD", + "\xAC\xC0" => "\xD0\xAE", + "\xAC\xC1" => "\xD0\xAF", + "\xAC\xD1" => "\xD0\xB0", + "\xAC\xD2" => "\xD0\xB1", + "\xAC\xD3" => "\xD0\xB2", + "\xAC\xD4" => "\xD0\xB3", + "\xAC\xD5" => "\xD0\xB4", + "\xAC\xD6" => "\xD0\xB5", + "\xAC\xD7" => "\xD1\x91", + "\xAC\xD8" => "\xD0\xB6", + "\xAC\xD9" => "\xD0\xB7", + "\xAC\xDA" => "\xD0\xB8", + "\xAC\xDB" => "\xD0\xB9", + "\xAC\xDC" => "\xD0\xBA", + "\xAC\xDD" => "\xD0\xBB", + "\xAC\xDE" => "\xD0\xBC", + "\xAC\xDF" => "\xD0\xBD", + "\xAC\xE0" => "\xD0\xBE", + "\xAC\xE1" => "\xD0\xBF", + "\xAC\xE2" => "\xD1\x80", + "\xAC\xE3" => "\xD1\x81", + "\xAC\xE4" => "\xD1\x82", + "\xAC\xE5" => "\xD1\x83", + "\xAC\xE6" => "\xD1\x84", + "\xAC\xE7" => "\xD1\x85", + "\xAC\xE8" => "\xD1\x86", + "\xAC\xE9" => "\xD1\x87", + "\xAC\xEA" => "\xD1\x88", + "\xAC\xEB" => "\xD1\x89", + "\xAC\xEC" => "\xD1\x8A", + "\xAC\xED" => "\xD1\x8B", + "\xAC\xEE" => "\xD1\x8C", + "\xAC\xEF" => "\xD1\x8D", + "\xAC\xF0" => "\xD1\x8E", + "\xAC\xF1" => "\xD1\x8F", + "\xAD\x41" => "\xEC\xB5\xA1", + "\xAD\x42" => "\xEC\xB5\xA2", + "\xAD\x43" => "\xEC\xB5\xA3", + "\xAD\x44" => "\xEC\xB5\xA5", + "\xAD\x45" => "\xEC\xB5\xA6", + "\xAD\x46" => "\xEC\xB5\xA7", + "\xAD\x47" => "\xEC\xB5\xA8", + "\xAD\x48" => "\xEC\xB5\xA9", + "\xAD\x49" => "\xEC\xB5\xAA", + "\xAD\x4A" => "\xEC\xB5\xAB", + "\xAD\x4B" => "\xEC\xB5\xAE", + "\xAD\x4C" => "\xEC\xB5\xB0", + "\xAD\x4D" => "\xEC\xB5\xB2", + "\xAD\x4E" => "\xEC\xB5\xB3", + "\xAD\x4F" => "\xEC\xB5\xB4", + "\xAD\x50" => "\xEC\xB5\xB5", + "\xAD\x51" => "\xEC\xB5\xB6", + "\xAD\x52" => "\xEC\xB5\xB7", + "\xAD\x53" => "\xEC\xB5\xB9", + "\xAD\x54" => "\xEC\xB5\xBA", + "\xAD\x55" => "\xEC\xB5\xBB", + "\xAD\x56" => "\xEC\xB5\xBC", + "\xAD\x57" => "\xEC\xB5\xBD", + "\xAD\x58" => "\xEC\xB5\xBE", + "\xAD\x59" => "\xEC\xB5\xBF", + "\xAD\x5A" => "\xEC\xB6\x80", + "\xAD\x61" => "\xEC\xB6\x81", + "\xAD\x62" => "\xEC\xB6\x82", + "\xAD\x63" => "\xEC\xB6\x83", + "\xAD\x64" => "\xEC\xB6\x84", + "\xAD\x65" => "\xEC\xB6\x85", + "\xAD\x66" => "\xEC\xB6\x86", + "\xAD\x67" => "\xEC\xB6\x87", + "\xAD\x68" => "\xEC\xB6\x89", + "\xAD\x69" => "\xEC\xB6\x8A", + "\xAD\x6A" => "\xEC\xB6\x8B", + "\xAD\x6B" => "\xEC\xB6\x8C", + "\xAD\x6C" => "\xEC\xB6\x8D", + "\xAD\x6D" => "\xEC\xB6\x8E", + "\xAD\x6E" => "\xEC\xB6\x8F", + "\xAD\x6F" => "\xEC\xB6\x90", + "\xAD\x70" => "\xEC\xB6\x91", + "\xAD\x71" => "\xEC\xB6\x92", + "\xAD\x72" => "\xEC\xB6\x93", + "\xAD\x73" => "\xEC\xB6\x96", + "\xAD\x74" => "\xEC\xB6\x97", + "\xAD\x75" => "\xEC\xB6\x99", + "\xAD\x76" => "\xEC\xB6\x9A", + "\xAD\x77" => "\xEC\xB6\x9B", + "\xAD\x78" => "\xEC\xB6\x9D", + "\xAD\x79" => "\xEC\xB6\x9E", + "\xAD\x7A" => "\xEC\xB6\x9F", + "\xAD\x81" => "\xEC\xB6\xA0", + "\xAD\x82" => "\xEC\xB6\xA1", + "\xAD\x83" => "\xEC\xB6\xA2", + "\xAD\x84" => "\xEC\xB6\xA3", + "\xAD\x85" => "\xEC\xB6\xA6", + "\xAD\x86" => "\xEC\xB6\xA8", + "\xAD\x87" => "\xEC\xB6\xAA", + "\xAD\x88" => "\xEC\xB6\xAB", + "\xAD\x89" => "\xEC\xB6\xAC", + "\xAD\x8A" => "\xEC\xB6\xAD", + "\xAD\x8B" => "\xEC\xB6\xAE", + "\xAD\x8C" => "\xEC\xB6\xAF", + "\xAD\x8D" => "\xEC\xB6\xB1", + "\xAD\x8E" => "\xEC\xB6\xB2", + "\xAD\x8F" => "\xEC\xB6\xB3", + "\xAD\x90" => "\xEC\xB6\xB4", + "\xAD\x91" => "\xEC\xB6\xB5", + "\xAD\x92" => "\xEC\xB6\xB6", + "\xAD\x93" => "\xEC\xB6\xB7", + "\xAD\x94" => "\xEC\xB6\xB8", + "\xAD\x95" => "\xEC\xB6\xB9", + "\xAD\x96" => "\xEC\xB6\xBA", + "\xAD\x97" => "\xEC\xB6\xBB", + "\xAD\x98" => "\xEC\xB6\xBC", + "\xAD\x99" => "\xEC\xB6\xBD", + "\xAD\x9A" => "\xEC\xB6\xBE", + "\xAD\x9B" => "\xEC\xB6\xBF", + "\xAD\x9C" => "\xEC\xB7\x80", + "\xAD\x9D" => "\xEC\xB7\x81", + "\xAD\x9E" => "\xEC\xB7\x82", + "\xAD\x9F" => "\xEC\xB7\x83", + "\xAD\xA0" => "\xEC\xB7\x85", + "\xAE\x41" => "\xEC\xB7\x86", + "\xAE\x42" => "\xEC\xB7\x87", + "\xAE\x43" => "\xEC\xB7\x88", + "\xAE\x44" => "\xEC\xB7\x89", + "\xAE\x45" => "\xEC\xB7\x8A", + "\xAE\x46" => "\xEC\xB7\x8B", + "\xAE\x47" => "\xEC\xB7\x8D", + "\xAE\x48" => "\xEC\xB7\x8E", + "\xAE\x49" => "\xEC\xB7\x8F", + "\xAE\x4A" => "\xEC\xB7\x91", + "\xAE\x4B" => "\xEC\xB7\x92", + "\xAE\x4C" => "\xEC\xB7\x93", + "\xAE\x4D" => "\xEC\xB7\x94", + "\xAE\x4E" => "\xEC\xB7\x95", + "\xAE\x4F" => "\xEC\xB7\x96", + "\xAE\x50" => "\xEC\xB7\x97", + "\xAE\x51" => "\xEC\xB7\x98", + "\xAE\x52" => "\xEC\xB7\x99", + "\xAE\x53" => "\xEC\xB7\x9A", + "\xAE\x54" => "\xEC\xB7\x9B", + "\xAE\x55" => "\xEC\xB7\x9C", + "\xAE\x56" => "\xEC\xB7\x9D", + "\xAE\x57" => "\xEC\xB7\x9E", + "\xAE\x58" => "\xEC\xB7\x9F", + "\xAE\x59" => "\xEC\xB7\xA0", + "\xAE\x5A" => "\xEC\xB7\xA1", + "\xAE\x61" => "\xEC\xB7\xA2", + "\xAE\x62" => "\xEC\xB7\xA3", + "\xAE\x63" => "\xEC\xB7\xA4", + "\xAE\x64" => "\xEC\xB7\xA5", + "\xAE\x65" => "\xEC\xB7\xA6", + "\xAE\x66" => "\xEC\xB7\xA7", + "\xAE\x67" => "\xEC\xB7\xA9", + "\xAE\x68" => "\xEC\xB7\xAA", + "\xAE\x69" => "\xEC\xB7\xAB", + "\xAE\x6A" => "\xEC\xB7\xAD", + "\xAE\x6B" => "\xEC\xB7\xAE", + "\xAE\x6C" => "\xEC\xB7\xAF", + "\xAE\x6D" => "\xEC\xB7\xB1", + "\xAE\x6E" => "\xEC\xB7\xB2", + "\xAE\x6F" => "\xEC\xB7\xB3", + "\xAE\x70" => "\xEC\xB7\xB4", + "\xAE\x71" => "\xEC\xB7\xB5", + "\xAE\x72" => "\xEC\xB7\xB6", + "\xAE\x73" => "\xEC\xB7\xB7", + "\xAE\x74" => "\xEC\xB7\xBA", + "\xAE\x75" => "\xEC\xB7\xBC", + "\xAE\x76" => "\xEC\xB7\xBE", + "\xAE\x77" => "\xEC\xB7\xBF", + "\xAE\x78" => "\xEC\xB8\x80", + "\xAE\x79" => "\xEC\xB8\x81", + "\xAE\x7A" => "\xEC\xB8\x82", + "\xAE\x81" => "\xEC\xB8\x83", + "\xAE\x82" => "\xEC\xB8\x85", + "\xAE\x83" => "\xEC\xB8\x86", + "\xAE\x84" => "\xEC\xB8\x87", + "\xAE\x85" => "\xEC\xB8\x89", + "\xAE\x86" => "\xEC\xB8\x8A", + "\xAE\x87" => "\xEC\xB8\x8B", + "\xAE\x88" => "\xEC\xB8\x8D", + "\xAE\x89" => "\xEC\xB8\x8E", + "\xAE\x8A" => "\xEC\xB8\x8F", + "\xAE\x8B" => "\xEC\xB8\x90", + "\xAE\x8C" => "\xEC\xB8\x91", + "\xAE\x8D" => "\xEC\xB8\x92", + "\xAE\x8E" => "\xEC\xB8\x93", + "\xAE\x8F" => "\xEC\xB8\x95", + "\xAE\x90" => "\xEC\xB8\x96", + "\xAE\x91" => "\xEC\xB8\x97", + "\xAE\x92" => "\xEC\xB8\x98", + "\xAE\x93" => "\xEC\xB8\x9A", + "\xAE\x94" => "\xEC\xB8\x9B", + "\xAE\x95" => "\xEC\xB8\x9C", + "\xAE\x96" => "\xEC\xB8\x9D", + "\xAE\x97" => "\xEC\xB8\x9E", + "\xAE\x98" => "\xEC\xB8\x9F", + "\xAE\x99" => "\xEC\xB8\xA2", + "\xAE\x9A" => "\xEC\xB8\xA3", + "\xAE\x9B" => "\xEC\xB8\xA5", + "\xAE\x9C" => "\xEC\xB8\xA6", + "\xAE\x9D" => "\xEC\xB8\xA7", + "\xAE\x9E" => "\xEC\xB8\xA9", + "\xAE\x9F" => "\xEC\xB8\xAA", + "\xAE\xA0" => "\xEC\xB8\xAB", + "\xAF\x41" => "\xEC\xB8\xAC", + "\xAF\x42" => "\xEC\xB8\xAD", + "\xAF\x43" => "\xEC\xB8\xAE", + "\xAF\x44" => "\xEC\xB8\xAF", + "\xAF\x45" => "\xEC\xB8\xB2", + "\xAF\x46" => "\xEC\xB8\xB4", + "\xAF\x47" => "\xEC\xB8\xB6", + "\xAF\x48" => "\xEC\xB8\xB7", + "\xAF\x49" => "\xEC\xB8\xB8", + "\xAF\x4A" => "\xEC\xB8\xB9", + "\xAF\x4B" => "\xEC\xB8\xBA", + "\xAF\x4C" => "\xEC\xB8\xBB", + "\xAF\x4D" => "\xEC\xB8\xBC", + "\xAF\x4E" => "\xEC\xB8\xBD", + "\xAF\x4F" => "\xEC\xB8\xBE", + "\xAF\x50" => "\xEC\xB8\xBF", + "\xAF\x51" => "\xEC\xB9\x80", + "\xAF\x52" => "\xEC\xB9\x81", + "\xAF\x53" => "\xEC\xB9\x82", + "\xAF\x54" => "\xEC\xB9\x83", + "\xAF\x55" => "\xEC\xB9\x84", + "\xAF\x56" => "\xEC\xB9\x85", + "\xAF\x57" => "\xEC\xB9\x86", + "\xAF\x58" => "\xEC\xB9\x87", + "\xAF\x59" => "\xEC\xB9\x88", + "\xAF\x5A" => "\xEC\xB9\x89", + "\xAF\x61" => "\xEC\xB9\x8A", + "\xAF\x62" => "\xEC\xB9\x8B", + "\xAF\x63" => "\xEC\xB9\x8C", + "\xAF\x64" => "\xEC\xB9\x8D", + "\xAF\x65" => "\xEC\xB9\x8E", + "\xAF\x66" => "\xEC\xB9\x8F", + "\xAF\x67" => "\xEC\xB9\x90", + "\xAF\x68" => "\xEC\xB9\x91", + "\xAF\x69" => "\xEC\xB9\x92", + "\xAF\x6A" => "\xEC\xB9\x93", + "\xAF\x6B" => "\xEC\xB9\x94", + "\xAF\x6C" => "\xEC\xB9\x95", + "\xAF\x6D" => "\xEC\xB9\x96", + "\xAF\x6E" => "\xEC\xB9\x97", + "\xAF\x6F" => "\xEC\xB9\x9A", + "\xAF\x70" => "\xEC\xB9\x9B", + "\xAF\x71" => "\xEC\xB9\x9D", + "\xAF\x72" => "\xEC\xB9\x9E", + "\xAF\x73" => "\xEC\xB9\xA2", + "\xAF\x74" => "\xEC\xB9\xA3", + "\xAF\x75" => "\xEC\xB9\xA4", + "\xAF\x76" => "\xEC\xB9\xA5", + "\xAF\x77" => "\xEC\xB9\xA6", + "\xAF\x78" => "\xEC\xB9\xA7", + "\xAF\x79" => "\xEC\xB9\xAA", + "\xAF\x7A" => "\xEC\xB9\xAC", + "\xAF\x81" => "\xEC\xB9\xAE", + "\xAF\x82" => "\xEC\xB9\xAF", + "\xAF\x83" => "\xEC\xB9\xB0", + "\xAF\x84" => "\xEC\xB9\xB1", + "\xAF\x85" => "\xEC\xB9\xB2", + "\xAF\x86" => "\xEC\xB9\xB3", + "\xAF\x87" => "\xEC\xB9\xB6", + "\xAF\x88" => "\xEC\xB9\xB7", + "\xAF\x89" => "\xEC\xB9\xB9", + "\xAF\x8A" => "\xEC\xB9\xBA", + "\xAF\x8B" => "\xEC\xB9\xBB", + "\xAF\x8C" => "\xEC\xB9\xBD", + "\xAF\x8D" => "\xEC\xB9\xBE", + "\xAF\x8E" => "\xEC\xB9\xBF", + "\xAF\x8F" => "\xEC\xBA\x80", + "\xAF\x90" => "\xEC\xBA\x81", + "\xAF\x91" => "\xEC\xBA\x82", + "\xAF\x92" => "\xEC\xBA\x83", + "\xAF\x93" => "\xEC\xBA\x86", + "\xAF\x94" => "\xEC\xBA\x88", + "\xAF\x95" => "\xEC\xBA\x8A", + "\xAF\x96" => "\xEC\xBA\x8B", + "\xAF\x97" => "\xEC\xBA\x8C", + "\xAF\x98" => "\xEC\xBA\x8D", + "\xAF\x99" => "\xEC\xBA\x8E", + "\xAF\x9A" => "\xEC\xBA\x8F", + "\xAF\x9B" => "\xEC\xBA\x92", + "\xAF\x9C" => "\xEC\xBA\x93", + "\xAF\x9D" => "\xEC\xBA\x95", + "\xAF\x9E" => "\xEC\xBA\x96", + "\xAF\x9F" => "\xEC\xBA\x97", + "\xAF\xA0" => "\xEC\xBA\x99", + "\xB0\x41" => "\xEC\xBA\x9A", + "\xB0\x42" => "\xEC\xBA\x9B", + "\xB0\x43" => "\xEC\xBA\x9C", + "\xB0\x44" => "\xEC\xBA\x9D", + "\xB0\x45" => "\xEC\xBA\x9E", + "\xB0\x46" => "\xEC\xBA\x9F", + "\xB0\x47" => "\xEC\xBA\xA2", + "\xB0\x48" => "\xEC\xBA\xA6", + "\xB0\x49" => "\xEC\xBA\xA7", + "\xB0\x4A" => "\xEC\xBA\xA8", + "\xB0\x4B" => "\xEC\xBA\xA9", + "\xB0\x4C" => "\xEC\xBA\xAA", + "\xB0\x4D" => "\xEC\xBA\xAB", + "\xB0\x4E" => "\xEC\xBA\xAE", + "\xB0\x4F" => "\xEC\xBA\xAF", + "\xB0\x50" => "\xEC\xBA\xB0", + "\xB0\x51" => "\xEC\xBA\xB1", + "\xB0\x52" => "\xEC\xBA\xB2", + "\xB0\x53" => "\xEC\xBA\xB3", + "\xB0\x54" => "\xEC\xBA\xB4", + "\xB0\x55" => "\xEC\xBA\xB5", + "\xB0\x56" => "\xEC\xBA\xB6", + "\xB0\x57" => "\xEC\xBA\xB7", + "\xB0\x58" => "\xEC\xBA\xB8", + "\xB0\x59" => "\xEC\xBA\xB9", + "\xB0\x5A" => "\xEC\xBA\xBA", + "\xB0\x61" => "\xEC\xBA\xBB", + "\xB0\x62" => "\xEC\xBA\xBC", + "\xB0\x63" => "\xEC\xBA\xBD", + "\xB0\x64" => "\xEC\xBA\xBE", + "\xB0\x65" => "\xEC\xBA\xBF", + "\xB0\x66" => "\xEC\xBB\x80", + "\xB0\x67" => "\xEC\xBB\x82", + "\xB0\x68" => "\xEC\xBB\x83", + "\xB0\x69" => "\xEC\xBB\x84", + "\xB0\x6A" => "\xEC\xBB\x85", + "\xB0\x6B" => "\xEC\xBB\x86", + "\xB0\x6C" => "\xEC\xBB\x87", + "\xB0\x6D" => "\xEC\xBB\x88", + "\xB0\x6E" => "\xEC\xBB\x89", + "\xB0\x6F" => "\xEC\xBB\x8A", + "\xB0\x70" => "\xEC\xBB\x8B", + "\xB0\x71" => "\xEC\xBB\x8C", + "\xB0\x72" => "\xEC\xBB\x8D", + "\xB0\x73" => "\xEC\xBB\x8E", + "\xB0\x74" => "\xEC\xBB\x8F", + "\xB0\x75" => "\xEC\xBB\x90", + "\xB0\x76" => "\xEC\xBB\x91", + "\xB0\x77" => "\xEC\xBB\x92", + "\xB0\x78" => "\xEC\xBB\x93", + "\xB0\x79" => "\xEC\xBB\x94", + "\xB0\x7A" => "\xEC\xBB\x95", + "\xB0\x81" => "\xEC\xBB\x96", + "\xB0\x82" => "\xEC\xBB\x97", + "\xB0\x83" => "\xEC\xBB\x98", + "\xB0\x84" => "\xEC\xBB\x99", + "\xB0\x85" => "\xEC\xBB\x9A", + "\xB0\x86" => "\xEC\xBB\x9B", + "\xB0\x87" => "\xEC\xBB\x9C", + "\xB0\x88" => "\xEC\xBB\x9D", + "\xB0\x89" => "\xEC\xBB\x9E", + "\xB0\x8A" => "\xEC\xBB\x9F", + "\xB0\x8B" => "\xEC\xBB\xA0", + "\xB0\x8C" => "\xEC\xBB\xA1", + "\xB0\x8D" => "\xEC\xBB\xA2", + "\xB0\x8E" => "\xEC\xBB\xA3", + "\xB0\x8F" => "\xEC\xBB\xA6", + "\xB0\x90" => "\xEC\xBB\xA7", + "\xB0\x91" => "\xEC\xBB\xA9", + "\xB0\x92" => "\xEC\xBB\xAA", + "\xB0\x93" => "\xEC\xBB\xAD", + "\xB0\x94" => "\xEC\xBB\xAE", + "\xB0\x95" => "\xEC\xBB\xAF", + "\xB0\x96" => "\xEC\xBB\xB0", + "\xB0\x97" => "\xEC\xBB\xB1", + "\xB0\x98" => "\xEC\xBB\xB2", + "\xB0\x99" => "\xEC\xBB\xB3", + "\xB0\x9A" => "\xEC\xBB\xB6", + "\xB0\x9B" => "\xEC\xBB\xBA", + "\xB0\x9C" => "\xEC\xBB\xBB", + "\xB0\x9D" => "\xEC\xBB\xBC", + "\xB0\x9E" => "\xEC\xBB\xBD", + "\xB0\x9F" => "\xEC\xBB\xBE", + "\xB0\xA0" => "\xEC\xBB\xBF", + "\xB0\xA1" => "\xEA\xB0\x80", + "\xB0\xA2" => "\xEA\xB0\x81", + "\xB0\xA3" => "\xEA\xB0\x84", + "\xB0\xA4" => "\xEA\xB0\x87", + "\xB0\xA5" => "\xEA\xB0\x88", + "\xB0\xA6" => "\xEA\xB0\x89", + "\xB0\xA7" => "\xEA\xB0\x8A", + "\xB0\xA8" => "\xEA\xB0\x90", + "\xB0\xA9" => "\xEA\xB0\x91", + "\xB0\xAA" => "\xEA\xB0\x92", + "\xB0\xAB" => "\xEA\xB0\x93", + "\xB0\xAC" => "\xEA\xB0\x94", + "\xB0\xAD" => "\xEA\xB0\x95", + "\xB0\xAE" => "\xEA\xB0\x96", + "\xB0\xAF" => "\xEA\xB0\x97", + "\xB0\xB0" => "\xEA\xB0\x99", + "\xB0\xB1" => "\xEA\xB0\x9A", + "\xB0\xB2" => "\xEA\xB0\x9B", + "\xB0\xB3" => "\xEA\xB0\x9C", + "\xB0\xB4" => "\xEA\xB0\x9D", + "\xB0\xB5" => "\xEA\xB0\xA0", + "\xB0\xB6" => "\xEA\xB0\xA4", + "\xB0\xB7" => "\xEA\xB0\xAC", + "\xB0\xB8" => "\xEA\xB0\xAD", + "\xB0\xB9" => "\xEA\xB0\xAF", + "\xB0\xBA" => "\xEA\xB0\xB0", + "\xB0\xBB" => "\xEA\xB0\xB1", + "\xB0\xBC" => "\xEA\xB0\xB8", + "\xB0\xBD" => "\xEA\xB0\xB9", + "\xB0\xBE" => "\xEA\xB0\xBC", + "\xB0\xBF" => "\xEA\xB1\x80", + "\xB0\xC0" => "\xEA\xB1\x8B", + "\xB0\xC1" => "\xEA\xB1\x8D", + "\xB0\xC2" => "\xEA\xB1\x94", + "\xB0\xC3" => "\xEA\xB1\x98", + "\xB0\xC4" => "\xEA\xB1\x9C", + "\xB0\xC5" => "\xEA\xB1\xB0", + "\xB0\xC6" => "\xEA\xB1\xB1", + "\xB0\xC7" => "\xEA\xB1\xB4", + "\xB0\xC8" => "\xEA\xB1\xB7", + "\xB0\xC9" => "\xEA\xB1\xB8", + "\xB0\xCA" => "\xEA\xB1\xBA", + "\xB0\xCB" => "\xEA\xB2\x80", + "\xB0\xCC" => "\xEA\xB2\x81", + "\xB0\xCD" => "\xEA\xB2\x83", + "\xB0\xCE" => "\xEA\xB2\x84", + "\xB0\xCF" => "\xEA\xB2\x85", + "\xB0\xD0" => "\xEA\xB2\x86", + "\xB0\xD1" => "\xEA\xB2\x89", + "\xB0\xD2" => "\xEA\xB2\x8A", + "\xB0\xD3" => "\xEA\xB2\x8B", + "\xB0\xD4" => "\xEA\xB2\x8C", + "\xB0\xD5" => "\xEA\xB2\x90", + "\xB0\xD6" => "\xEA\xB2\x94", + "\xB0\xD7" => "\xEA\xB2\x9C", + "\xB0\xD8" => "\xEA\xB2\x9D", + "\xB0\xD9" => "\xEA\xB2\x9F", + "\xB0\xDA" => "\xEA\xB2\xA0", + "\xB0\xDB" => "\xEA\xB2\xA1", + "\xB0\xDC" => "\xEA\xB2\xA8", + "\xB0\xDD" => "\xEA\xB2\xA9", + "\xB0\xDE" => "\xEA\xB2\xAA", + "\xB0\xDF" => "\xEA\xB2\xAC", + "\xB0\xE0" => "\xEA\xB2\xAF", + "\xB0\xE1" => "\xEA\xB2\xB0", + "\xB0\xE2" => "\xEA\xB2\xB8", + "\xB0\xE3" => "\xEA\xB2\xB9", + "\xB0\xE4" => "\xEA\xB2\xBB", + "\xB0\xE5" => "\xEA\xB2\xBC", + "\xB0\xE6" => "\xEA\xB2\xBD", + "\xB0\xE7" => "\xEA\xB3\x81", + "\xB0\xE8" => "\xEA\xB3\x84", + "\xB0\xE9" => "\xEA\xB3\x88", + "\xB0\xEA" => "\xEA\xB3\x8C", + "\xB0\xEB" => "\xEA\xB3\x95", + "\xB0\xEC" => "\xEA\xB3\x97", + "\xB0\xED" => "\xEA\xB3\xA0", + "\xB0\xEE" => "\xEA\xB3\xA1", + "\xB0\xEF" => "\xEA\xB3\xA4", + "\xB0\xF0" => "\xEA\xB3\xA7", + "\xB0\xF1" => "\xEA\xB3\xA8", + "\xB0\xF2" => "\xEA\xB3\xAA", + "\xB0\xF3" => "\xEA\xB3\xAC", + "\xB0\xF4" => "\xEA\xB3\xAF", + "\xB0\xF5" => "\xEA\xB3\xB0", + "\xB0\xF6" => "\xEA\xB3\xB1", + "\xB0\xF7" => "\xEA\xB3\xB3", + "\xB0\xF8" => "\xEA\xB3\xB5", + "\xB0\xF9" => "\xEA\xB3\xB6", + "\xB0\xFA" => "\xEA\xB3\xBC", + "\xB0\xFB" => "\xEA\xB3\xBD", + "\xB0\xFC" => "\xEA\xB4\x80", + "\xB0\xFD" => "\xEA\xB4\x84", + "\xB0\xFE" => "\xEA\xB4\x86", + "\xB1\x41" => "\xEC\xBC\x82", + "\xB1\x42" => "\xEC\xBC\x83", + "\xB1\x43" => "\xEC\xBC\x85", + "\xB1\x44" => "\xEC\xBC\x86", + "\xB1\x45" => "\xEC\xBC\x87", + "\xB1\x46" => "\xEC\xBC\x89", + "\xB1\x47" => "\xEC\xBC\x8A", + "\xB1\x48" => "\xEC\xBC\x8B", + "\xB1\x49" => "\xEC\xBC\x8C", + "\xB1\x4A" => "\xEC\xBC\x8D", + "\xB1\x4B" => "\xEC\xBC\x8E", + "\xB1\x4C" => "\xEC\xBC\x8F", + "\xB1\x4D" => "\xEC\xBC\x92", + "\xB1\x4E" => "\xEC\xBC\x94", + "\xB1\x4F" => "\xEC\xBC\x96", + "\xB1\x50" => "\xEC\xBC\x97", + "\xB1\x51" => "\xEC\xBC\x98", + "\xB1\x52" => "\xEC\xBC\x99", + "\xB1\x53" => "\xEC\xBC\x9A", + "\xB1\x54" => "\xEC\xBC\x9B", + "\xB1\x55" => "\xEC\xBC\x9D", + "\xB1\x56" => "\xEC\xBC\x9E", + "\xB1\x57" => "\xEC\xBC\x9F", + "\xB1\x58" => "\xEC\xBC\xA1", + "\xB1\x59" => "\xEC\xBC\xA2", + "\xB1\x5A" => "\xEC\xBC\xA3", + "\xB1\x61" => "\xEC\xBC\xA5", + "\xB1\x62" => "\xEC\xBC\xA6", + "\xB1\x63" => "\xEC\xBC\xA7", + "\xB1\x64" => "\xEC\xBC\xA8", + "\xB1\x65" => "\xEC\xBC\xA9", + "\xB1\x66" => "\xEC\xBC\xAA", + "\xB1\x67" => "\xEC\xBC\xAB", + "\xB1\x68" => "\xEC\xBC\xAE", + "\xB1\x69" => "\xEC\xBC\xB2", + "\xB1\x6A" => "\xEC\xBC\xB3", + "\xB1\x6B" => "\xEC\xBC\xB4", + "\xB1\x6C" => "\xEC\xBC\xB5", + "\xB1\x6D" => "\xEC\xBC\xB6", + "\xB1\x6E" => "\xEC\xBC\xB7", + "\xB1\x6F" => "\xEC\xBC\xB9", + "\xB1\x70" => "\xEC\xBC\xBA", + "\xB1\x71" => "\xEC\xBC\xBB", + "\xB1\x72" => "\xEC\xBC\xBC", + "\xB1\x73" => "\xEC\xBC\xBD", + "\xB1\x74" => "\xEC\xBC\xBE", + "\xB1\x75" => "\xEC\xBC\xBF", + "\xB1\x76" => "\xEC\xBD\x80", + "\xB1\x77" => "\xEC\xBD\x81", + "\xB1\x78" => "\xEC\xBD\x82", + "\xB1\x79" => "\xEC\xBD\x83", + "\xB1\x7A" => "\xEC\xBD\x84", + "\xB1\x81" => "\xEC\xBD\x85", + "\xB1\x82" => "\xEC\xBD\x86", + "\xB1\x83" => "\xEC\xBD\x87", + "\xB1\x84" => "\xEC\xBD\x88", + "\xB1\x85" => "\xEC\xBD\x89", + "\xB1\x86" => "\xEC\xBD\x8A", + "\xB1\x87" => "\xEC\xBD\x8B", + "\xB1\x88" => "\xEC\xBD\x8C", + "\xB1\x89" => "\xEC\xBD\x8D", + "\xB1\x8A" => "\xEC\xBD\x8E", + "\xB1\x8B" => "\xEC\xBD\x8F", + "\xB1\x8C" => "\xEC\xBD\x90", + "\xB1\x8D" => "\xEC\xBD\x91", + "\xB1\x8E" => "\xEC\xBD\x92", + "\xB1\x8F" => "\xEC\xBD\x93", + "\xB1\x90" => "\xEC\xBD\x96", + "\xB1\x91" => "\xEC\xBD\x97", + "\xB1\x92" => "\xEC\xBD\x99", + "\xB1\x93" => "\xEC\xBD\x9A", + "\xB1\x94" => "\xEC\xBD\x9B", + "\xB1\x95" => "\xEC\xBD\x9D", + "\xB1\x96" => "\xEC\xBD\x9E", + "\xB1\x97" => "\xEC\xBD\x9F", + "\xB1\x98" => "\xEC\xBD\xA0", + "\xB1\x99" => "\xEC\xBD\xA1", + "\xB1\x9A" => "\xEC\xBD\xA2", + "\xB1\x9B" => "\xEC\xBD\xA3", + "\xB1\x9C" => "\xEC\xBD\xA6", + "\xB1\x9D" => "\xEC\xBD\xA8", + "\xB1\x9E" => "\xEC\xBD\xAA", + "\xB1\x9F" => "\xEC\xBD\xAB", + "\xB1\xA0" => "\xEC\xBD\xAC", + "\xB1\xA1" => "\xEA\xB4\x8C", + "\xB1\xA2" => "\xEA\xB4\x8D", + "\xB1\xA3" => "\xEA\xB4\x8F", + "\xB1\xA4" => "\xEA\xB4\x91", + "\xB1\xA5" => "\xEA\xB4\x98", + "\xB1\xA6" => "\xEA\xB4\x9C", + "\xB1\xA7" => "\xEA\xB4\xA0", + "\xB1\xA8" => "\xEA\xB4\xA9", + "\xB1\xA9" => "\xEA\xB4\xAC", + "\xB1\xAA" => "\xEA\xB4\xAD", + "\xB1\xAB" => "\xEA\xB4\xB4", + "\xB1\xAC" => "\xEA\xB4\xB5", + "\xB1\xAD" => "\xEA\xB4\xB8", + "\xB1\xAE" => "\xEA\xB4\xBC", + "\xB1\xAF" => "\xEA\xB5\x84", + "\xB1\xB0" => "\xEA\xB5\x85", + "\xB1\xB1" => "\xEA\xB5\x87", + "\xB1\xB2" => "\xEA\xB5\x89", + "\xB1\xB3" => "\xEA\xB5\x90", + "\xB1\xB4" => "\xEA\xB5\x94", + "\xB1\xB5" => "\xEA\xB5\x98", + "\xB1\xB6" => "\xEA\xB5\xA1", + "\xB1\xB7" => "\xEA\xB5\xA3", + "\xB1\xB8" => "\xEA\xB5\xAC", + "\xB1\xB9" => "\xEA\xB5\xAD", + "\xB1\xBA" => "\xEA\xB5\xB0", + "\xB1\xBB" => "\xEA\xB5\xB3", + "\xB1\xBC" => "\xEA\xB5\xB4", + "\xB1\xBD" => "\xEA\xB5\xB5", + "\xB1\xBE" => "\xEA\xB5\xB6", + "\xB1\xBF" => "\xEA\xB5\xBB", + "\xB1\xC0" => "\xEA\xB5\xBC", + "\xB1\xC1" => "\xEA\xB5\xBD", + "\xB1\xC2" => "\xEA\xB5\xBF", + "\xB1\xC3" => "\xEA\xB6\x81", + "\xB1\xC4" => "\xEA\xB6\x82", + "\xB1\xC5" => "\xEA\xB6\x88", + "\xB1\xC6" => "\xEA\xB6\x89", + "\xB1\xC7" => "\xEA\xB6\x8C", + "\xB1\xC8" => "\xEA\xB6\x90", + "\xB1\xC9" => "\xEA\xB6\x9C", + "\xB1\xCA" => "\xEA\xB6\x9D", + "\xB1\xCB" => "\xEA\xB6\xA4", + "\xB1\xCC" => "\xEA\xB6\xB7", + "\xB1\xCD" => "\xEA\xB7\x80", + "\xB1\xCE" => "\xEA\xB7\x81", + "\xB1\xCF" => "\xEA\xB7\x84", + "\xB1\xD0" => "\xEA\xB7\x88", + "\xB1\xD1" => "\xEA\xB7\x90", + "\xB1\xD2" => "\xEA\xB7\x91", + "\xB1\xD3" => "\xEA\xB7\x93", + "\xB1\xD4" => "\xEA\xB7\x9C", + "\xB1\xD5" => "\xEA\xB7\xA0", + "\xB1\xD6" => "\xEA\xB7\xA4", + "\xB1\xD7" => "\xEA\xB7\xB8", + "\xB1\xD8" => "\xEA\xB7\xB9", + "\xB1\xD9" => "\xEA\xB7\xBC", + "\xB1\xDA" => "\xEA\xB7\xBF", + "\xB1\xDB" => "\xEA\xB8\x80", + "\xB1\xDC" => "\xEA\xB8\x81", + "\xB1\xDD" => "\xEA\xB8\x88", + "\xB1\xDE" => "\xEA\xB8\x89", + "\xB1\xDF" => "\xEA\xB8\x8B", + "\xB1\xE0" => "\xEA\xB8\x8D", + "\xB1\xE1" => "\xEA\xB8\x94", + "\xB1\xE2" => "\xEA\xB8\xB0", + "\xB1\xE3" => "\xEA\xB8\xB1", + "\xB1\xE4" => "\xEA\xB8\xB4", + "\xB1\xE5" => "\xEA\xB8\xB7", + "\xB1\xE6" => "\xEA\xB8\xB8", + "\xB1\xE7" => "\xEA\xB8\xBA", + "\xB1\xE8" => "\xEA\xB9\x80", + "\xB1\xE9" => "\xEA\xB9\x81", + "\xB1\xEA" => "\xEA\xB9\x83", + "\xB1\xEB" => "\xEA\xB9\x85", + "\xB1\xEC" => "\xEA\xB9\x86", + "\xB1\xED" => "\xEA\xB9\x8A", + "\xB1\xEE" => "\xEA\xB9\x8C", + "\xB1\xEF" => "\xEA\xB9\x8D", + "\xB1\xF0" => "\xEA\xB9\x8E", + "\xB1\xF1" => "\xEA\xB9\x90", + "\xB1\xF2" => "\xEA\xB9\x94", + "\xB1\xF3" => "\xEA\xB9\x96", + "\xB1\xF4" => "\xEA\xB9\x9C", + "\xB1\xF5" => "\xEA\xB9\x9D", + "\xB1\xF6" => "\xEA\xB9\x9F", + "\xB1\xF7" => "\xEA\xB9\xA0", + "\xB1\xF8" => "\xEA\xB9\xA1", + "\xB1\xF9" => "\xEA\xB9\xA5", + "\xB1\xFA" => "\xEA\xB9\xA8", + "\xB1\xFB" => "\xEA\xB9\xA9", + "\xB1\xFC" => "\xEA\xB9\xAC", + "\xB1\xFD" => "\xEA\xB9\xB0", + "\xB1\xFE" => "\xEA\xB9\xB8", + "\xB2\x41" => "\xEC\xBD\xAD", + "\xB2\x42" => "\xEC\xBD\xAE", + "\xB2\x43" => "\xEC\xBD\xAF", + "\xB2\x44" => "\xEC\xBD\xB2", + "\xB2\x45" => "\xEC\xBD\xB3", + "\xB2\x46" => "\xEC\xBD\xB5", + "\xB2\x47" => "\xEC\xBD\xB6", + "\xB2\x48" => "\xEC\xBD\xB7", + "\xB2\x49" => "\xEC\xBD\xB9", + "\xB2\x4A" => "\xEC\xBD\xBA", + "\xB2\x4B" => "\xEC\xBD\xBB", + "\xB2\x4C" => "\xEC\xBD\xBC", + "\xB2\x4D" => "\xEC\xBD\xBD", + "\xB2\x4E" => "\xEC\xBD\xBE", + "\xB2\x4F" => "\xEC\xBD\xBF", + "\xB2\x50" => "\xEC\xBE\x81", + "\xB2\x51" => "\xEC\xBE\x82", + "\xB2\x52" => "\xEC\xBE\x83", + "\xB2\x53" => "\xEC\xBE\x84", + "\xB2\x54" => "\xEC\xBE\x86", + "\xB2\x55" => "\xEC\xBE\x87", + "\xB2\x56" => "\xEC\xBE\x88", + "\xB2\x57" => "\xEC\xBE\x89", + "\xB2\x58" => "\xEC\xBE\x8A", + "\xB2\x59" => "\xEC\xBE\x8B", + "\xB2\x5A" => "\xEC\xBE\x8D", + "\xB2\x61" => "\xEC\xBE\x8E", + "\xB2\x62" => "\xEC\xBE\x8F", + "\xB2\x63" => "\xEC\xBE\x90", + "\xB2\x64" => "\xEC\xBE\x91", + "\xB2\x65" => "\xEC\xBE\x92", + "\xB2\x66" => "\xEC\xBE\x93", + "\xB2\x67" => "\xEC\xBE\x94", + "\xB2\x68" => "\xEC\xBE\x95", + "\xB2\x69" => "\xEC\xBE\x96", + "\xB2\x6A" => "\xEC\xBE\x97", + "\xB2\x6B" => "\xEC\xBE\x98", + "\xB2\x6C" => "\xEC\xBE\x99", + "\xB2\x6D" => "\xEC\xBE\x9A", + "\xB2\x6E" => "\xEC\xBE\x9B", + "\xB2\x6F" => "\xEC\xBE\x9C", + "\xB2\x70" => "\xEC\xBE\x9D", + "\xB2\x71" => "\xEC\xBE\x9E", + "\xB2\x72" => "\xEC\xBE\x9F", + "\xB2\x73" => "\xEC\xBE\xA0", + "\xB2\x74" => "\xEC\xBE\xA2", + "\xB2\x75" => "\xEC\xBE\xA3", + "\xB2\x76" => "\xEC\xBE\xA4", + "\xB2\x77" => "\xEC\xBE\xA5", + "\xB2\x78" => "\xEC\xBE\xA6", + "\xB2\x79" => "\xEC\xBE\xA7", + "\xB2\x7A" => "\xEC\xBE\xA9", + "\xB2\x81" => "\xEC\xBE\xAA", + "\xB2\x82" => "\xEC\xBE\xAB", + "\xB2\x83" => "\xEC\xBE\xAC", + "\xB2\x84" => "\xEC\xBE\xAD", + "\xB2\x85" => "\xEC\xBE\xAE", + "\xB2\x86" => "\xEC\xBE\xAF", + "\xB2\x87" => "\xEC\xBE\xB1", + "\xB2\x88" => "\xEC\xBE\xB2", + "\xB2\x89" => "\xEC\xBE\xB3", + "\xB2\x8A" => "\xEC\xBE\xB4", + "\xB2\x8B" => "\xEC\xBE\xB5", + "\xB2\x8C" => "\xEC\xBE\xB6", + "\xB2\x8D" => "\xEC\xBE\xB7", + "\xB2\x8E" => "\xEC\xBE\xB8", + "\xB2\x8F" => "\xEC\xBE\xB9", + "\xB2\x90" => "\xEC\xBE\xBA", + "\xB2\x91" => "\xEC\xBE\xBB", + "\xB2\x92" => "\xEC\xBE\xBC", + "\xB2\x93" => "\xEC\xBE\xBD", + "\xB2\x94" => "\xEC\xBE\xBE", + "\xB2\x95" => "\xEC\xBE\xBF", + "\xB2\x96" => "\xEC\xBF\x80", + "\xB2\x97" => "\xEC\xBF\x81", + "\xB2\x98" => "\xEC\xBF\x82", + "\xB2\x99" => "\xEC\xBF\x83", + "\xB2\x9A" => "\xEC\xBF\x85", + "\xB2\x9B" => "\xEC\xBF\x86", + "\xB2\x9C" => "\xEC\xBF\x87", + "\xB2\x9D" => "\xEC\xBF\x88", + "\xB2\x9E" => "\xEC\xBF\x89", + "\xB2\x9F" => "\xEC\xBF\x8A", + "\xB2\xA0" => "\xEC\xBF\x8B", + "\xB2\xA1" => "\xEA\xB9\xB9", + "\xB2\xA2" => "\xEA\xB9\xBB", + "\xB2\xA3" => "\xEA\xB9\xBC", + "\xB2\xA4" => "\xEA\xB9\xBD", + "\xB2\xA5" => "\xEA\xBA\x84", + "\xB2\xA6" => "\xEA\xBA\x85", + "\xB2\xA7" => "\xEA\xBA\x8C", + "\xB2\xA8" => "\xEA\xBA\xBC", + "\xB2\xA9" => "\xEA\xBA\xBD", + "\xB2\xAA" => "\xEA\xBA\xBE", + "\xB2\xAB" => "\xEA\xBB\x80", + "\xB2\xAC" => "\xEA\xBB\x84", + "\xB2\xAD" => "\xEA\xBB\x8C", + "\xB2\xAE" => "\xEA\xBB\x8D", + "\xB2\xAF" => "\xEA\xBB\x8F", + "\xB2\xB0" => "\xEA\xBB\x90", + "\xB2\xB1" => "\xEA\xBB\x91", + "\xB2\xB2" => "\xEA\xBB\x98", + "\xB2\xB3" => "\xEA\xBB\x99", + "\xB2\xB4" => "\xEA\xBB\x9C", + "\xB2\xB5" => "\xEA\xBB\xA8", + "\xB2\xB6" => "\xEA\xBB\xAB", + "\xB2\xB7" => "\xEA\xBB\xAD", + "\xB2\xB8" => "\xEA\xBB\xB4", + "\xB2\xB9" => "\xEA\xBB\xB8", + "\xB2\xBA" => "\xEA\xBB\xBC", + "\xB2\xBB" => "\xEA\xBC\x87", + "\xB2\xBC" => "\xEA\xBC\x88", + "\xB2\xBD" => "\xEA\xBC\x8D", + "\xB2\xBE" => "\xEA\xBC\x90", + "\xB2\xBF" => "\xEA\xBC\xAC", + "\xB2\xC0" => "\xEA\xBC\xAD", + "\xB2\xC1" => "\xEA\xBC\xB0", + "\xB2\xC2" => "\xEA\xBC\xB2", + "\xB2\xC3" => "\xEA\xBC\xB4", + "\xB2\xC4" => "\xEA\xBC\xBC", + "\xB2\xC5" => "\xEA\xBC\xBD", + "\xB2\xC6" => "\xEA\xBC\xBF", + "\xB2\xC7" => "\xEA\xBD\x81", + "\xB2\xC8" => "\xEA\xBD\x82", + "\xB2\xC9" => "\xEA\xBD\x83", + "\xB2\xCA" => "\xEA\xBD\x88", + "\xB2\xCB" => "\xEA\xBD\x89", + "\xB2\xCC" => "\xEA\xBD\x90", + "\xB2\xCD" => "\xEA\xBD\x9C", + "\xB2\xCE" => "\xEA\xBD\x9D", + "\xB2\xCF" => "\xEA\xBD\xA4", + "\xB2\xD0" => "\xEA\xBD\xA5", + "\xB2\xD1" => "\xEA\xBD\xB9", + "\xB2\xD2" => "\xEA\xBE\x80", + "\xB2\xD3" => "\xEA\xBE\x84", + "\xB2\xD4" => "\xEA\xBE\x88", + "\xB2\xD5" => "\xEA\xBE\x90", + "\xB2\xD6" => "\xEA\xBE\x91", + "\xB2\xD7" => "\xEA\xBE\x95", + "\xB2\xD8" => "\xEA\xBE\x9C", + "\xB2\xD9" => "\xEA\xBE\xB8", + "\xB2\xDA" => "\xEA\xBE\xB9", + "\xB2\xDB" => "\xEA\xBE\xBC", + "\xB2\xDC" => "\xEA\xBF\x80", + "\xB2\xDD" => "\xEA\xBF\x87", + "\xB2\xDE" => "\xEA\xBF\x88", + "\xB2\xDF" => "\xEA\xBF\x89", + "\xB2\xE0" => "\xEA\xBF\x8B", + "\xB2\xE1" => "\xEA\xBF\x8D", + "\xB2\xE2" => "\xEA\xBF\x8E", + "\xB2\xE3" => "\xEA\xBF\x94", + "\xB2\xE4" => "\xEA\xBF\x9C", + "\xB2\xE5" => "\xEA\xBF\xA8", + "\xB2\xE6" => "\xEA\xBF\xA9", + "\xB2\xE7" => "\xEA\xBF\xB0", + "\xB2\xE8" => "\xEA\xBF\xB1", + "\xB2\xE9" => "\xEA\xBF\xB4", + "\xB2\xEA" => "\xEA\xBF\xB8", + "\xB2\xEB" => "\xEB\x80\x80", + "\xB2\xEC" => "\xEB\x80\x81", + "\xB2\xED" => "\xEB\x80\x84", + "\xB2\xEE" => "\xEB\x80\x8C", + "\xB2\xEF" => "\xEB\x80\x90", + "\xB2\xF0" => "\xEB\x80\x94", + "\xB2\xF1" => "\xEB\x80\x9C", + "\xB2\xF2" => "\xEB\x80\x9D", + "\xB2\xF3" => "\xEB\x80\xA8", + "\xB2\xF4" => "\xEB\x81\x84", + "\xB2\xF5" => "\xEB\x81\x85", + "\xB2\xF6" => "\xEB\x81\x88", + "\xB2\xF7" => "\xEB\x81\x8A", + "\xB2\xF8" => "\xEB\x81\x8C", + "\xB2\xF9" => "\xEB\x81\x8E", + "\xB2\xFA" => "\xEB\x81\x93", + "\xB2\xFB" => "\xEB\x81\x94", + "\xB2\xFC" => "\xEB\x81\x95", + "\xB2\xFD" => "\xEB\x81\x97", + "\xB2\xFE" => "\xEB\x81\x99", + "\xB3\x41" => "\xEC\xBF\x8C", + "\xB3\x42" => "\xEC\xBF\x8D", + "\xB3\x43" => "\xEC\xBF\x8E", + "\xB3\x44" => "\xEC\xBF\x8F", + "\xB3\x45" => "\xEC\xBF\x90", + "\xB3\x46" => "\xEC\xBF\x91", + "\xB3\x47" => "\xEC\xBF\x92", + "\xB3\x48" => "\xEC\xBF\x93", + "\xB3\x49" => "\xEC\xBF\x94", + "\xB3\x4A" => "\xEC\xBF\x95", + "\xB3\x4B" => "\xEC\xBF\x96", + "\xB3\x4C" => "\xEC\xBF\x97", + "\xB3\x4D" => "\xEC\xBF\x98", + "\xB3\x4E" => "\xEC\xBF\x99", + "\xB3\x4F" => "\xEC\xBF\x9A", + "\xB3\x50" => "\xEC\xBF\x9B", + "\xB3\x51" => "\xEC\xBF\x9C", + "\xB3\x52" => "\xEC\xBF\x9D", + "\xB3\x53" => "\xEC\xBF\x9E", + "\xB3\x54" => "\xEC\xBF\x9F", + "\xB3\x55" => "\xEC\xBF\xA2", + "\xB3\x56" => "\xEC\xBF\xA3", + "\xB3\x57" => "\xEC\xBF\xA5", + "\xB3\x58" => "\xEC\xBF\xA6", + "\xB3\x59" => "\xEC\xBF\xA7", + "\xB3\x5A" => "\xEC\xBF\xA9", + "\xB3\x61" => "\xEC\xBF\xAA", + "\xB3\x62" => "\xEC\xBF\xAB", + "\xB3\x63" => "\xEC\xBF\xAC", + "\xB3\x64" => "\xEC\xBF\xAD", + "\xB3\x65" => "\xEC\xBF\xAE", + "\xB3\x66" => "\xEC\xBF\xAF", + "\xB3\x67" => "\xEC\xBF\xB2", + "\xB3\x68" => "\xEC\xBF\xB4", + "\xB3\x69" => "\xEC\xBF\xB6", + "\xB3\x6A" => "\xEC\xBF\xB7", + "\xB3\x6B" => "\xEC\xBF\xB8", + "\xB3\x6C" => "\xEC\xBF\xB9", + "\xB3\x6D" => "\xEC\xBF\xBA", + "\xB3\x6E" => "\xEC\xBF\xBB", + "\xB3\x6F" => "\xEC\xBF\xBD", + "\xB3\x70" => "\xEC\xBF\xBE", + "\xB3\x71" => "\xEC\xBF\xBF", + "\xB3\x72" => "\xED\x80\x81", + "\xB3\x73" => "\xED\x80\x82", + "\xB3\x74" => "\xED\x80\x83", + "\xB3\x75" => "\xED\x80\x85", + "\xB3\x76" => "\xED\x80\x86", + "\xB3\x77" => "\xED\x80\x87", + "\xB3\x78" => "\xED\x80\x88", + "\xB3\x79" => "\xED\x80\x89", + "\xB3\x7A" => "\xED\x80\x8A", + "\xB3\x81" => "\xED\x80\x8B", + "\xB3\x82" => "\xED\x80\x8C", + "\xB3\x83" => "\xED\x80\x8D", + "\xB3\x84" => "\xED\x80\x8E", + "\xB3\x85" => "\xED\x80\x8F", + "\xB3\x86" => "\xED\x80\x90", + "\xB3\x87" => "\xED\x80\x92", + "\xB3\x88" => "\xED\x80\x93", + "\xB3\x89" => "\xED\x80\x94", + "\xB3\x8A" => "\xED\x80\x95", + "\xB3\x8B" => "\xED\x80\x96", + "\xB3\x8C" => "\xED\x80\x97", + "\xB3\x8D" => "\xED\x80\x99", + "\xB3\x8E" => "\xED\x80\x9A", + "\xB3\x8F" => "\xED\x80\x9B", + "\xB3\x90" => "\xED\x80\x9C", + "\xB3\x91" => "\xED\x80\x9D", + "\xB3\x92" => "\xED\x80\x9E", + "\xB3\x93" => "\xED\x80\x9F", + "\xB3\x94" => "\xED\x80\xA0", + "\xB3\x95" => "\xED\x80\xA1", + "\xB3\x96" => "\xED\x80\xA2", + "\xB3\x97" => "\xED\x80\xA3", + "\xB3\x98" => "\xED\x80\xA4", + "\xB3\x99" => "\xED\x80\xA5", + "\xB3\x9A" => "\xED\x80\xA6", + "\xB3\x9B" => "\xED\x80\xA7", + "\xB3\x9C" => "\xED\x80\xA8", + "\xB3\x9D" => "\xED\x80\xA9", + "\xB3\x9E" => "\xED\x80\xAA", + "\xB3\x9F" => "\xED\x80\xAB", + "\xB3\xA0" => "\xED\x80\xAC", + "\xB3\xA1" => "\xEB\x81\x9D", + "\xB3\xA2" => "\xEB\x81\xBC", + "\xB3\xA3" => "\xEB\x81\xBD", + "\xB3\xA4" => "\xEB\x82\x80", + "\xB3\xA5" => "\xEB\x82\x84", + "\xB3\xA6" => "\xEB\x82\x8C", + "\xB3\xA7" => "\xEB\x82\x8D", + "\xB3\xA8" => "\xEB\x82\x8F", + "\xB3\xA9" => "\xEB\x82\x91", + "\xB3\xAA" => "\xEB\x82\x98", + "\xB3\xAB" => "\xEB\x82\x99", + "\xB3\xAC" => "\xEB\x82\x9A", + "\xB3\xAD" => "\xEB\x82\x9C", + "\xB3\xAE" => "\xEB\x82\x9F", + "\xB3\xAF" => "\xEB\x82\xA0", + "\xB3\xB0" => "\xEB\x82\xA1", + "\xB3\xB1" => "\xEB\x82\xA2", + "\xB3\xB2" => "\xEB\x82\xA8", + "\xB3\xB3" => "\xEB\x82\xA9", + "\xB3\xB4" => "\xEB\x82\xAB", + "\xB3\xB5" => "\xEB\x82\xAC", + "\xB3\xB6" => "\xEB\x82\xAD", + "\xB3\xB7" => "\xEB\x82\xAE", + "\xB3\xB8" => "\xEB\x82\xAF", + "\xB3\xB9" => "\xEB\x82\xB1", + "\xB3\xBA" => "\xEB\x82\xB3", + "\xB3\xBB" => "\xEB\x82\xB4", + "\xB3\xBC" => "\xEB\x82\xB5", + "\xB3\xBD" => "\xEB\x82\xB8", + "\xB3\xBE" => "\xEB\x82\xBC", + "\xB3\xBF" => "\xEB\x83\x84", + "\xB3\xC0" => "\xEB\x83\x85", + "\xB3\xC1" => "\xEB\x83\x87", + "\xB3\xC2" => "\xEB\x83\x88", + "\xB3\xC3" => "\xEB\x83\x89", + "\xB3\xC4" => "\xEB\x83\x90", + "\xB3\xC5" => "\xEB\x83\x91", + "\xB3\xC6" => "\xEB\x83\x94", + "\xB3\xC7" => "\xEB\x83\x98", + "\xB3\xC8" => "\xEB\x83\xA0", + "\xB3\xC9" => "\xEB\x83\xA5", + "\xB3\xCA" => "\xEB\x84\x88", + "\xB3\xCB" => "\xEB\x84\x89", + "\xB3\xCC" => "\xEB\x84\x8B", + "\xB3\xCD" => "\xEB\x84\x8C", + "\xB3\xCE" => "\xEB\x84\x90", + "\xB3\xCF" => "\xEB\x84\x92", + "\xB3\xD0" => "\xEB\x84\x93", + "\xB3\xD1" => "\xEB\x84\x98", + "\xB3\xD2" => "\xEB\x84\x99", + "\xB3\xD3" => "\xEB\x84\x9B", + "\xB3\xD4" => "\xEB\x84\x9C", + "\xB3\xD5" => "\xEB\x84\x9D", + "\xB3\xD6" => "\xEB\x84\xA3", + "\xB3\xD7" => "\xEB\x84\xA4", + "\xB3\xD8" => "\xEB\x84\xA5", + "\xB3\xD9" => "\xEB\x84\xA8", + "\xB3\xDA" => "\xEB\x84\xAC", + "\xB3\xDB" => "\xEB\x84\xB4", + "\xB3\xDC" => "\xEB\x84\xB5", + "\xB3\xDD" => "\xEB\x84\xB7", + "\xB3\xDE" => "\xEB\x84\xB8", + "\xB3\xDF" => "\xEB\x84\xB9", + "\xB3\xE0" => "\xEB\x85\x80", + "\xB3\xE1" => "\xEB\x85\x81", + "\xB3\xE2" => "\xEB\x85\x84", + "\xB3\xE3" => "\xEB\x85\x88", + "\xB3\xE4" => "\xEB\x85\x90", + "\xB3\xE5" => "\xEB\x85\x91", + "\xB3\xE6" => "\xEB\x85\x94", + "\xB3\xE7" => "\xEB\x85\x95", + "\xB3\xE8" => "\xEB\x85\x98", + "\xB3\xE9" => "\xEB\x85\x9C", + "\xB3\xEA" => "\xEB\x85\xA0", + "\xB3\xEB" => "\xEB\x85\xB8", + "\xB3\xEC" => "\xEB\x85\xB9", + "\xB3\xED" => "\xEB\x85\xBC", + "\xB3\xEE" => "\xEB\x86\x80", + "\xB3\xEF" => "\xEB\x86\x82", + "\xB3\xF0" => "\xEB\x86\x88", + "\xB3\xF1" => "\xEB\x86\x89", + "\xB3\xF2" => "\xEB\x86\x8B", + "\xB3\xF3" => "\xEB\x86\x8D", + "\xB3\xF4" => "\xEB\x86\x92", + "\xB3\xF5" => "\xEB\x86\x93", + "\xB3\xF6" => "\xEB\x86\x94", + "\xB3\xF7" => "\xEB\x86\x98", + "\xB3\xF8" => "\xEB\x86\x9C", + "\xB3\xF9" => "\xEB\x86\xA8", + "\xB3\xFA" => "\xEB\x87\x8C", + "\xB3\xFB" => "\xEB\x87\x90", + "\xB3\xFC" => "\xEB\x87\x94", + "\xB3\xFD" => "\xEB\x87\x9C", + "\xB3\xFE" => "\xEB\x87\x9D", + "\xB4\x41" => "\xED\x80\xAE", + "\xB4\x42" => "\xED\x80\xAF", + "\xB4\x43" => "\xED\x80\xB0", + "\xB4\x44" => "\xED\x80\xB1", + "\xB4\x45" => "\xED\x80\xB2", + "\xB4\x46" => "\xED\x80\xB3", + "\xB4\x47" => "\xED\x80\xB6", + "\xB4\x48" => "\xED\x80\xB7", + "\xB4\x49" => "\xED\x80\xB9", + "\xB4\x4A" => "\xED\x80\xBA", + "\xB4\x4B" => "\xED\x80\xBB", + "\xB4\x4C" => "\xED\x80\xBD", + "\xB4\x4D" => "\xED\x80\xBE", + "\xB4\x4E" => "\xED\x80\xBF", + "\xB4\x4F" => "\xED\x81\x80", + "\xB4\x50" => "\xED\x81\x81", + "\xB4\x51" => "\xED\x81\x82", + "\xB4\x52" => "\xED\x81\x83", + "\xB4\x53" => "\xED\x81\x86", + "\xB4\x54" => "\xED\x81\x88", + "\xB4\x55" => "\xED\x81\x8A", + "\xB4\x56" => "\xED\x81\x8B", + "\xB4\x57" => "\xED\x81\x8C", + "\xB4\x58" => "\xED\x81\x8D", + "\xB4\x59" => "\xED\x81\x8E", + "\xB4\x5A" => "\xED\x81\x8F", + "\xB4\x61" => "\xED\x81\x91", + "\xB4\x62" => "\xED\x81\x92", + "\xB4\x63" => "\xED\x81\x93", + "\xB4\x64" => "\xED\x81\x95", + "\xB4\x65" => "\xED\x81\x96", + "\xB4\x66" => "\xED\x81\x97", + "\xB4\x67" => "\xED\x81\x99", + "\xB4\x68" => "\xED\x81\x9A", + "\xB4\x69" => "\xED\x81\x9B", + "\xB4\x6A" => "\xED\x81\x9C", + "\xB4\x6B" => "\xED\x81\x9D", + "\xB4\x6C" => "\xED\x81\x9E", + "\xB4\x6D" => "\xED\x81\x9F", + "\xB4\x6E" => "\xED\x81\xA1", + "\xB4\x6F" => "\xED\x81\xA2", + "\xB4\x70" => "\xED\x81\xA3", + "\xB4\x71" => "\xED\x81\xA4", + "\xB4\x72" => "\xED\x81\xA5", + "\xB4\x73" => "\xED\x81\xA6", + "\xB4\x74" => "\xED\x81\xA7", + "\xB4\x75" => "\xED\x81\xA8", + "\xB4\x76" => "\xED\x81\xA9", + "\xB4\x77" => "\xED\x81\xAA", + "\xB4\x78" => "\xED\x81\xAB", + "\xB4\x79" => "\xED\x81\xAE", + "\xB4\x7A" => "\xED\x81\xAF", + "\xB4\x81" => "\xED\x81\xB1", + "\xB4\x82" => "\xED\x81\xB2", + "\xB4\x83" => "\xED\x81\xB3", + "\xB4\x84" => "\xED\x81\xB5", + "\xB4\x85" => "\xED\x81\xB6", + "\xB4\x86" => "\xED\x81\xB7", + "\xB4\x87" => "\xED\x81\xB8", + "\xB4\x88" => "\xED\x81\xB9", + "\xB4\x89" => "\xED\x81\xBA", + "\xB4\x8A" => "\xED\x81\xBB", + "\xB4\x8B" => "\xED\x81\xBE", + "\xB4\x8C" => "\xED\x81\xBF", + "\xB4\x8D" => "\xED\x82\x80", + "\xB4\x8E" => "\xED\x82\x82", + "\xB4\x8F" => "\xED\x82\x83", + "\xB4\x90" => "\xED\x82\x84", + "\xB4\x91" => "\xED\x82\x85", + "\xB4\x92" => "\xED\x82\x86", + "\xB4\x93" => "\xED\x82\x87", + "\xB4\x94" => "\xED\x82\x88", + "\xB4\x95" => "\xED\x82\x89", + "\xB4\x96" => "\xED\x82\x8A", + "\xB4\x97" => "\xED\x82\x8B", + "\xB4\x98" => "\xED\x82\x8C", + "\xB4\x99" => "\xED\x82\x8D", + "\xB4\x9A" => "\xED\x82\x8E", + "\xB4\x9B" => "\xED\x82\x8F", + "\xB4\x9C" => "\xED\x82\x90", + "\xB4\x9D" => "\xED\x82\x91", + "\xB4\x9E" => "\xED\x82\x92", + "\xB4\x9F" => "\xED\x82\x93", + "\xB4\xA0" => "\xED\x82\x94", + "\xB4\xA1" => "\xEB\x87\x9F", + "\xB4\xA2" => "\xEB\x87\xA8", + "\xB4\xA3" => "\xEB\x87\xA9", + "\xB4\xA4" => "\xEB\x87\xAC", + "\xB4\xA5" => "\xEB\x87\xB0", + "\xB4\xA6" => "\xEB\x87\xB9", + "\xB4\xA7" => "\xEB\x87\xBB", + "\xB4\xA8" => "\xEB\x87\xBD", + "\xB4\xA9" => "\xEB\x88\x84", + "\xB4\xAA" => "\xEB\x88\x85", + "\xB4\xAB" => "\xEB\x88\x88", + "\xB4\xAC" => "\xEB\x88\x8B", + "\xB4\xAD" => "\xEB\x88\x8C", + "\xB4\xAE" => "\xEB\x88\x94", + "\xB4\xAF" => "\xEB\x88\x95", + "\xB4\xB0" => "\xEB\x88\x97", + "\xB4\xB1" => "\xEB\x88\x99", + "\xB4\xB2" => "\xEB\x88\xA0", + "\xB4\xB3" => "\xEB\x88\xB4", + "\xB4\xB4" => "\xEB\x88\xBC", + "\xB4\xB5" => "\xEB\x89\x98", + "\xB4\xB6" => "\xEB\x89\x9C", + "\xB4\xB7" => "\xEB\x89\xA0", + "\xB4\xB8" => "\xEB\x89\xA8", + "\xB4\xB9" => "\xEB\x89\xA9", + "\xB4\xBA" => "\xEB\x89\xB4", + "\xB4\xBB" => "\xEB\x89\xB5", + "\xB4\xBC" => "\xEB\x89\xBC", + "\xB4\xBD" => "\xEB\x8A\x84", + "\xB4\xBE" => "\xEB\x8A\x85", + "\xB4\xBF" => "\xEB\x8A\x89", + "\xB4\xC0" => "\xEB\x8A\x90", + "\xB4\xC1" => "\xEB\x8A\x91", + "\xB4\xC2" => "\xEB\x8A\x94", + "\xB4\xC3" => "\xEB\x8A\x98", + "\xB4\xC4" => "\xEB\x8A\x99", + "\xB4\xC5" => "\xEB\x8A\x9A", + "\xB4\xC6" => "\xEB\x8A\xA0", + "\xB4\xC7" => "\xEB\x8A\xA1", + "\xB4\xC8" => "\xEB\x8A\xA3", + "\xB4\xC9" => "\xEB\x8A\xA5", + "\xB4\xCA" => "\xEB\x8A\xA6", + "\xB4\xCB" => "\xEB\x8A\xAA", + "\xB4\xCC" => "\xEB\x8A\xAC", + "\xB4\xCD" => "\xEB\x8A\xB0", + "\xB4\xCE" => "\xEB\x8A\xB4", + "\xB4\xCF" => "\xEB\x8B\x88", + "\xB4\xD0" => "\xEB\x8B\x89", + "\xB4\xD1" => "\xEB\x8B\x8C", + "\xB4\xD2" => "\xEB\x8B\x90", + "\xB4\xD3" => "\xEB\x8B\x92", + "\xB4\xD4" => "\xEB\x8B\x98", + "\xB4\xD5" => "\xEB\x8B\x99", + "\xB4\xD6" => "\xEB\x8B\x9B", + "\xB4\xD7" => "\xEB\x8B\x9D", + "\xB4\xD8" => "\xEB\x8B\xA2", + "\xB4\xD9" => "\xEB\x8B\xA4", + "\xB4\xDA" => "\xEB\x8B\xA5", + "\xB4\xDB" => "\xEB\x8B\xA6", + "\xB4\xDC" => "\xEB\x8B\xA8", + "\xB4\xDD" => "\xEB\x8B\xAB", + "\xB4\xDE" => "\xEB\x8B\xAC", + "\xB4\xDF" => "\xEB\x8B\xAD", + "\xB4\xE0" => "\xEB\x8B\xAE", + "\xB4\xE1" => "\xEB\x8B\xAF", + "\xB4\xE2" => "\xEB\x8B\xB3", + "\xB4\xE3" => "\xEB\x8B\xB4", + "\xB4\xE4" => "\xEB\x8B\xB5", + "\xB4\xE5" => "\xEB\x8B\xB7", + "\xB4\xE6" => "\xEB\x8B\xB8", + "\xB4\xE7" => "\xEB\x8B\xB9", + "\xB4\xE8" => "\xEB\x8B\xBA", + "\xB4\xE9" => "\xEB\x8B\xBB", + "\xB4\xEA" => "\xEB\x8B\xBF", + "\xB4\xEB" => "\xEB\x8C\x80", + "\xB4\xEC" => "\xEB\x8C\x81", + "\xB4\xED" => "\xEB\x8C\x84", + "\xB4\xEE" => "\xEB\x8C\x88", + "\xB4\xEF" => "\xEB\x8C\x90", + "\xB4\xF0" => "\xEB\x8C\x91", + "\xB4\xF1" => "\xEB\x8C\x93", + "\xB4\xF2" => "\xEB\x8C\x94", + "\xB4\xF3" => "\xEB\x8C\x95", + "\xB4\xF4" => "\xEB\x8C\x9C", + "\xB4\xF5" => "\xEB\x8D\x94", + "\xB4\xF6" => "\xEB\x8D\x95", + "\xB4\xF7" => "\xEB\x8D\x96", + "\xB4\xF8" => "\xEB\x8D\x98", + "\xB4\xF9" => "\xEB\x8D\x9B", + "\xB4\xFA" => "\xEB\x8D\x9C", + "\xB4\xFB" => "\xEB\x8D\x9E", + "\xB4\xFC" => "\xEB\x8D\x9F", + "\xB4\xFD" => "\xEB\x8D\xA4", + "\xB4\xFE" => "\xEB\x8D\xA5", + "\xB5\x41" => "\xED\x82\x95", + "\xB5\x42" => "\xED\x82\x96", + "\xB5\x43" => "\xED\x82\x97", + "\xB5\x44" => "\xED\x82\x98", + "\xB5\x45" => "\xED\x82\x99", + "\xB5\x46" => "\xED\x82\x9A", + "\xB5\x47" => "\xED\x82\x9B", + "\xB5\x48" => "\xED\x82\x9C", + "\xB5\x49" => "\xED\x82\x9D", + "\xB5\x4A" => "\xED\x82\x9E", + "\xB5\x4B" => "\xED\x82\x9F", + "\xB5\x4C" => "\xED\x82\xA0", + "\xB5\x4D" => "\xED\x82\xA1", + "\xB5\x4E" => "\xED\x82\xA2", + "\xB5\x4F" => "\xED\x82\xA3", + "\xB5\x50" => "\xED\x82\xA6", + "\xB5\x51" => "\xED\x82\xA7", + "\xB5\x52" => "\xED\x82\xA9", + "\xB5\x53" => "\xED\x82\xAA", + "\xB5\x54" => "\xED\x82\xAB", + "\xB5\x55" => "\xED\x82\xAD", + "\xB5\x56" => "\xED\x82\xAE", + "\xB5\x57" => "\xED\x82\xAF", + "\xB5\x58" => "\xED\x82\xB0", + "\xB5\x59" => "\xED\x82\xB1", + "\xB5\x5A" => "\xED\x82\xB2", + "\xB5\x61" => "\xED\x82\xB3", + "\xB5\x62" => "\xED\x82\xB6", + "\xB5\x63" => "\xED\x82\xB8", + "\xB5\x64" => "\xED\x82\xBA", + "\xB5\x65" => "\xED\x82\xBB", + "\xB5\x66" => "\xED\x82\xBC", + "\xB5\x67" => "\xED\x82\xBD", + "\xB5\x68" => "\xED\x82\xBE", + "\xB5\x69" => "\xED\x82\xBF", + "\xB5\x6A" => "\xED\x83\x82", + "\xB5\x6B" => "\xED\x83\x83", + "\xB5\x6C" => "\xED\x83\x85", + "\xB5\x6D" => "\xED\x83\x86", + "\xB5\x6E" => "\xED\x83\x87", + "\xB5\x6F" => "\xED\x83\x8A", + "\xB5\x70" => "\xED\x83\x8B", + "\xB5\x71" => "\xED\x83\x8C", + "\xB5\x72" => "\xED\x83\x8D", + "\xB5\x73" => "\xED\x83\x8E", + "\xB5\x74" => "\xED\x83\x8F", + "\xB5\x75" => "\xED\x83\x92", + "\xB5\x76" => "\xED\x83\x96", + "\xB5\x77" => "\xED\x83\x97", + "\xB5\x78" => "\xED\x83\x98", + "\xB5\x79" => "\xED\x83\x99", + "\xB5\x7A" => "\xED\x83\x9A", + "\xB5\x81" => "\xED\x83\x9B", + "\xB5\x82" => "\xED\x83\x9E", + "\xB5\x83" => "\xED\x83\x9F", + "\xB5\x84" => "\xED\x83\xA1", + "\xB5\x85" => "\xED\x83\xA2", + "\xB5\x86" => "\xED\x83\xA3", + "\xB5\x87" => "\xED\x83\xA5", + "\xB5\x88" => "\xED\x83\xA6", + "\xB5\x89" => "\xED\x83\xA7", + "\xB5\x8A" => "\xED\x83\xA8", + "\xB5\x8B" => "\xED\x83\xA9", + "\xB5\x8C" => "\xED\x83\xAA", + "\xB5\x8D" => "\xED\x83\xAB", + "\xB5\x8E" => "\xED\x83\xAE", + "\xB5\x8F" => "\xED\x83\xB2", + "\xB5\x90" => "\xED\x83\xB3", + "\xB5\x91" => "\xED\x83\xB4", + "\xB5\x92" => "\xED\x83\xB5", + "\xB5\x93" => "\xED\x83\xB6", + "\xB5\x94" => "\xED\x83\xB7", + "\xB5\x95" => "\xED\x83\xB9", + "\xB5\x96" => "\xED\x83\xBA", + "\xB5\x97" => "\xED\x83\xBB", + "\xB5\x98" => "\xED\x83\xBC", + "\xB5\x99" => "\xED\x83\xBD", + "\xB5\x9A" => "\xED\x83\xBE", + "\xB5\x9B" => "\xED\x83\xBF", + "\xB5\x9C" => "\xED\x84\x80", + "\xB5\x9D" => "\xED\x84\x81", + "\xB5\x9E" => "\xED\x84\x82", + "\xB5\x9F" => "\xED\x84\x83", + "\xB5\xA0" => "\xED\x84\x84", + "\xB5\xA1" => "\xEB\x8D\xA7", + "\xB5\xA2" => "\xEB\x8D\xA9", + "\xB5\xA3" => "\xEB\x8D\xAB", + "\xB5\xA4" => "\xEB\x8D\xAE", + "\xB5\xA5" => "\xEB\x8D\xB0", + "\xB5\xA6" => "\xEB\x8D\xB1", + "\xB5\xA7" => "\xEB\x8D\xB4", + "\xB5\xA8" => "\xEB\x8D\xB8", + "\xB5\xA9" => "\xEB\x8E\x80", + "\xB5\xAA" => "\xEB\x8E\x81", + "\xB5\xAB" => "\xEB\x8E\x83", + "\xB5\xAC" => "\xEB\x8E\x84", + "\xB5\xAD" => "\xEB\x8E\x85", + "\xB5\xAE" => "\xEB\x8E\x8C", + "\xB5\xAF" => "\xEB\x8E\x90", + "\xB5\xB0" => "\xEB\x8E\x94", + "\xB5\xB1" => "\xEB\x8E\xA0", + "\xB5\xB2" => "\xEB\x8E\xA1", + "\xB5\xB3" => "\xEB\x8E\xA8", + "\xB5\xB4" => "\xEB\x8E\xAC", + "\xB5\xB5" => "\xEB\x8F\x84", + "\xB5\xB6" => "\xEB\x8F\x85", + "\xB5\xB7" => "\xEB\x8F\x88", + "\xB5\xB8" => "\xEB\x8F\x8B", + "\xB5\xB9" => "\xEB\x8F\x8C", + "\xB5\xBA" => "\xEB\x8F\x8E", + "\xB5\xBB" => "\xEB\x8F\x90", + "\xB5\xBC" => "\xEB\x8F\x94", + "\xB5\xBD" => "\xEB\x8F\x95", + "\xB5\xBE" => "\xEB\x8F\x97", + "\xB5\xBF" => "\xEB\x8F\x99", + "\xB5\xC0" => "\xEB\x8F\x9B", + "\xB5\xC1" => "\xEB\x8F\x9D", + "\xB5\xC2" => "\xEB\x8F\xA0", + "\xB5\xC3" => "\xEB\x8F\xA4", + "\xB5\xC4" => "\xEB\x8F\xA8", + "\xB5\xC5" => "\xEB\x8F\xBC", + "\xB5\xC6" => "\xEB\x90\x90", + "\xB5\xC7" => "\xEB\x90\x98", + "\xB5\xC8" => "\xEB\x90\x9C", + "\xB5\xC9" => "\xEB\x90\xA0", + "\xB5\xCA" => "\xEB\x90\xA8", + "\xB5\xCB" => "\xEB\x90\xA9", + "\xB5\xCC" => "\xEB\x90\xAB", + "\xB5\xCD" => "\xEB\x90\xB4", + "\xB5\xCE" => "\xEB\x91\x90", + "\xB5\xCF" => "\xEB\x91\x91", + "\xB5\xD0" => "\xEB\x91\x94", + "\xB5\xD1" => "\xEB\x91\x98", + "\xB5\xD2" => "\xEB\x91\xA0", + "\xB5\xD3" => "\xEB\x91\xA1", + "\xB5\xD4" => "\xEB\x91\xA3", + "\xB5\xD5" => "\xEB\x91\xA5", + "\xB5\xD6" => "\xEB\x91\xAC", + "\xB5\xD7" => "\xEB\x92\x80", + "\xB5\xD8" => "\xEB\x92\x88", + "\xB5\xD9" => "\xEB\x92\x9D", + "\xB5\xDA" => "\xEB\x92\xA4", + "\xB5\xDB" => "\xEB\x92\xA8", + "\xB5\xDC" => "\xEB\x92\xAC", + "\xB5\xDD" => "\xEB\x92\xB5", + "\xB5\xDE" => "\xEB\x92\xB7", + "\xB5\xDF" => "\xEB\x92\xB9", + "\xB5\xE0" => "\xEB\x93\x80", + "\xB5\xE1" => "\xEB\x93\x84", + "\xB5\xE2" => "\xEB\x93\x88", + "\xB5\xE3" => "\xEB\x93\x90", + "\xB5\xE4" => "\xEB\x93\x95", + "\xB5\xE5" => "\xEB\x93\x9C", + "\xB5\xE6" => "\xEB\x93\x9D", + "\xB5\xE7" => "\xEB\x93\xA0", + "\xB5\xE8" => "\xEB\x93\xA3", + "\xB5\xE9" => "\xEB\x93\xA4", + "\xB5\xEA" => "\xEB\x93\xA6", + "\xB5\xEB" => "\xEB\x93\xAC", + "\xB5\xEC" => "\xEB\x93\xAD", + "\xB5\xED" => "\xEB\x93\xAF", + "\xB5\xEE" => "\xEB\x93\xB1", + "\xB5\xEF" => "\xEB\x93\xB8", + "\xB5\xF0" => "\xEB\x94\x94", + "\xB5\xF1" => "\xEB\x94\x95", + "\xB5\xF2" => "\xEB\x94\x98", + "\xB5\xF3" => "\xEB\x94\x9B", + "\xB5\xF4" => "\xEB\x94\x9C", + "\xB5\xF5" => "\xEB\x94\xA4", + "\xB5\xF6" => "\xEB\x94\xA5", + "\xB5\xF7" => "\xEB\x94\xA7", + "\xB5\xF8" => "\xEB\x94\xA8", + "\xB5\xF9" => "\xEB\x94\xA9", + "\xB5\xFA" => "\xEB\x94\xAA", + "\xB5\xFB" => "\xEB\x94\xB0", + "\xB5\xFC" => "\xEB\x94\xB1", + "\xB5\xFD" => "\xEB\x94\xB4", + "\xB5\xFE" => "\xEB\x94\xB8", + "\xB6\x41" => "\xED\x84\x85", + "\xB6\x42" => "\xED\x84\x86", + "\xB6\x43" => "\xED\x84\x87", + "\xB6\x44" => "\xED\x84\x88", + "\xB6\x45" => "\xED\x84\x89", + "\xB6\x46" => "\xED\x84\x8A", + "\xB6\x47" => "\xED\x84\x8B", + "\xB6\x48" => "\xED\x84\x8C", + "\xB6\x49" => "\xED\x84\x8E", + "\xB6\x4A" => "\xED\x84\x8F", + "\xB6\x4B" => "\xED\x84\x90", + "\xB6\x4C" => "\xED\x84\x91", + "\xB6\x4D" => "\xED\x84\x92", + "\xB6\x4E" => "\xED\x84\x93", + "\xB6\x4F" => "\xED\x84\x94", + "\xB6\x50" => "\xED\x84\x95", + "\xB6\x51" => "\xED\x84\x96", + "\xB6\x52" => "\xED\x84\x97", + "\xB6\x53" => "\xED\x84\x98", + "\xB6\x54" => "\xED\x84\x99", + "\xB6\x55" => "\xED\x84\x9A", + "\xB6\x56" => "\xED\x84\x9B", + "\xB6\x57" => "\xED\x84\x9C", + "\xB6\x58" => "\xED\x84\x9D", + "\xB6\x59" => "\xED\x84\x9E", + "\xB6\x5A" => "\xED\x84\x9F", + "\xB6\x61" => "\xED\x84\xA0", + "\xB6\x62" => "\xED\x84\xA1", + "\xB6\x63" => "\xED\x84\xA2", + "\xB6\x64" => "\xED\x84\xA3", + "\xB6\x65" => "\xED\x84\xA4", + "\xB6\x66" => "\xED\x84\xA5", + "\xB6\x67" => "\xED\x84\xA6", + "\xB6\x68" => "\xED\x84\xA7", + "\xB6\x69" => "\xED\x84\xA8", + "\xB6\x6A" => "\xED\x84\xA9", + "\xB6\x6B" => "\xED\x84\xAA", + "\xB6\x6C" => "\xED\x84\xAB", + "\xB6\x6D" => "\xED\x84\xAC", + "\xB6\x6E" => "\xED\x84\xAD", + "\xB6\x6F" => "\xED\x84\xAE", + "\xB6\x70" => "\xED\x84\xAF", + "\xB6\x71" => "\xED\x84\xB2", + "\xB6\x72" => "\xED\x84\xB3", + "\xB6\x73" => "\xED\x84\xB5", + "\xB6\x74" => "\xED\x84\xB6", + "\xB6\x75" => "\xED\x84\xB7", + "\xB6\x76" => "\xED\x84\xB9", + "\xB6\x77" => "\xED\x84\xBB", + "\xB6\x78" => "\xED\x84\xBC", + "\xB6\x79" => "\xED\x84\xBD", + "\xB6\x7A" => "\xED\x84\xBE", + "\xB6\x81" => "\xED\x84\xBF", + "\xB6\x82" => "\xED\x85\x82", + "\xB6\x83" => "\xED\x85\x86", + "\xB6\x84" => "\xED\x85\x87", + "\xB6\x85" => "\xED\x85\x88", + "\xB6\x86" => "\xED\x85\x89", + "\xB6\x87" => "\xED\x85\x8A", + "\xB6\x88" => "\xED\x85\x8B", + "\xB6\x89" => "\xED\x85\x8E", + "\xB6\x8A" => "\xED\x85\x8F", + "\xB6\x8B" => "\xED\x85\x91", + "\xB6\x8C" => "\xED\x85\x92", + "\xB6\x8D" => "\xED\x85\x93", + "\xB6\x8E" => "\xED\x85\x95", + "\xB6\x8F" => "\xED\x85\x96", + "\xB6\x90" => "\xED\x85\x97", + "\xB6\x91" => "\xED\x85\x98", + "\xB6\x92" => "\xED\x85\x99", + "\xB6\x93" => "\xED\x85\x9A", + "\xB6\x94" => "\xED\x85\x9B", + "\xB6\x95" => "\xED\x85\x9E", + "\xB6\x96" => "\xED\x85\xA0", + "\xB6\x97" => "\xED\x85\xA2", + "\xB6\x98" => "\xED\x85\xA3", + "\xB6\x99" => "\xED\x85\xA4", + "\xB6\x9A" => "\xED\x85\xA5", + "\xB6\x9B" => "\xED\x85\xA6", + "\xB6\x9C" => "\xED\x85\xA7", + "\xB6\x9D" => "\xED\x85\xA9", + "\xB6\x9E" => "\xED\x85\xAA", + "\xB6\x9F" => "\xED\x85\xAB", + "\xB6\xA0" => "\xED\x85\xAD", + "\xB6\xA1" => "\xEB\x95\x80", + "\xB6\xA2" => "\xEB\x95\x81", + "\xB6\xA3" => "\xEB\x95\x83", + "\xB6\xA4" => "\xEB\x95\x84", + "\xB6\xA5" => "\xEB\x95\x85", + "\xB6\xA6" => "\xEB\x95\x8B", + "\xB6\xA7" => "\xEB\x95\x8C", + "\xB6\xA8" => "\xEB\x95\x8D", + "\xB6\xA9" => "\xEB\x95\x90", + "\xB6\xAA" => "\xEB\x95\x94", + "\xB6\xAB" => "\xEB\x95\x9C", + "\xB6\xAC" => "\xEB\x95\x9D", + "\xB6\xAD" => "\xEB\x95\x9F", + "\xB6\xAE" => "\xEB\x95\xA0", + "\xB6\xAF" => "\xEB\x95\xA1", + "\xB6\xB0" => "\xEB\x96\xA0", + "\xB6\xB1" => "\xEB\x96\xA1", + "\xB6\xB2" => "\xEB\x96\xA4", + "\xB6\xB3" => "\xEB\x96\xA8", + "\xB6\xB4" => "\xEB\x96\xAA", + "\xB6\xB5" => "\xEB\x96\xAB", + "\xB6\xB6" => "\xEB\x96\xB0", + "\xB6\xB7" => "\xEB\x96\xB1", + "\xB6\xB8" => "\xEB\x96\xB3", + "\xB6\xB9" => "\xEB\x96\xB4", + "\xB6\xBA" => "\xEB\x96\xB5", + "\xB6\xBB" => "\xEB\x96\xBB", + "\xB6\xBC" => "\xEB\x96\xBC", + "\xB6\xBD" => "\xEB\x96\xBD", + "\xB6\xBE" => "\xEB\x97\x80", + "\xB6\xBF" => "\xEB\x97\x84", + "\xB6\xC0" => "\xEB\x97\x8C", + "\xB6\xC1" => "\xEB\x97\x8D", + "\xB6\xC2" => "\xEB\x97\x8F", + "\xB6\xC3" => "\xEB\x97\x90", + "\xB6\xC4" => "\xEB\x97\x91", + "\xB6\xC5" => "\xEB\x97\x98", + "\xB6\xC6" => "\xEB\x97\xAC", + "\xB6\xC7" => "\xEB\x98\x90", + "\xB6\xC8" => "\xEB\x98\x91", + "\xB6\xC9" => "\xEB\x98\x94", + "\xB6\xCA" => "\xEB\x98\x98", + "\xB6\xCB" => "\xEB\x98\xA5", + "\xB6\xCC" => "\xEB\x98\xAC", + "\xB6\xCD" => "\xEB\x98\xB4", + "\xB6\xCE" => "\xEB\x99\x88", + "\xB6\xCF" => "\xEB\x99\xA4", + "\xB6\xD0" => "\xEB\x99\xA8", + "\xB6\xD1" => "\xEB\x9A\x9C", + "\xB6\xD2" => "\xEB\x9A\x9D", + "\xB6\xD3" => "\xEB\x9A\xA0", + "\xB6\xD4" => "\xEB\x9A\xA4", + "\xB6\xD5" => "\xEB\x9A\xAB", + "\xB6\xD6" => "\xEB\x9A\xAC", + "\xB6\xD7" => "\xEB\x9A\xB1", + "\xB6\xD8" => "\xEB\x9B\x94", + "\xB6\xD9" => "\xEB\x9B\xB0", + "\xB6\xDA" => "\xEB\x9B\xB4", + "\xB6\xDB" => "\xEB\x9B\xB8", + "\xB6\xDC" => "\xEB\x9C\x80", + "\xB6\xDD" => "\xEB\x9C\x81", + "\xB6\xDE" => "\xEB\x9C\x85", + "\xB6\xDF" => "\xEB\x9C\xA8", + "\xB6\xE0" => "\xEB\x9C\xA9", + "\xB6\xE1" => "\xEB\x9C\xAC", + "\xB6\xE2" => "\xEB\x9C\xAF", + "\xB6\xE3" => "\xEB\x9C\xB0", + "\xB6\xE4" => "\xEB\x9C\xB8", + "\xB6\xE5" => "\xEB\x9C\xB9", + "\xB6\xE6" => "\xEB\x9C\xBB", + "\xB6\xE7" => "\xEB\x9D\x84", + "\xB6\xE8" => "\xEB\x9D\x88", + "\xB6\xE9" => "\xEB\x9D\x8C", + "\xB6\xEA" => "\xEB\x9D\x94", + "\xB6\xEB" => "\xEB\x9D\x95", + "\xB6\xEC" => "\xEB\x9D\xA0", + "\xB6\xED" => "\xEB\x9D\xA4", + "\xB6\xEE" => "\xEB\x9D\xA8", + "\xB6\xEF" => "\xEB\x9D\xB0", + "\xB6\xF0" => "\xEB\x9D\xB1", + "\xB6\xF1" => "\xEB\x9D\xB3", + "\xB6\xF2" => "\xEB\x9D\xB5", + "\xB6\xF3" => "\xEB\x9D\xBC", + "\xB6\xF4" => "\xEB\x9D\xBD", + "\xB6\xF5" => "\xEB\x9E\x80", + "\xB6\xF6" => "\xEB\x9E\x84", + "\xB6\xF7" => "\xEB\x9E\x8C", + "\xB6\xF8" => "\xEB\x9E\x8D", + "\xB6\xF9" => "\xEB\x9E\x8F", + "\xB6\xFA" => "\xEB\x9E\x90", + "\xB6\xFB" => "\xEB\x9E\x91", + "\xB6\xFC" => "\xEB\x9E\x92", + "\xB6\xFD" => "\xEB\x9E\x96", + "\xB6\xFE" => "\xEB\x9E\x97", + "\xB7\x41" => "\xED\x85\xAE", + "\xB7\x42" => "\xED\x85\xAF", + "\xB7\x43" => "\xED\x85\xB0", + "\xB7\x44" => "\xED\x85\xB1", + "\xB7\x45" => "\xED\x85\xB2", + "\xB7\x46" => "\xED\x85\xB3", + "\xB7\x47" => "\xED\x85\xB4", + "\xB7\x48" => "\xED\x85\xB5", + "\xB7\x49" => "\xED\x85\xB6", + "\xB7\x4A" => "\xED\x85\xB7", + "\xB7\x4B" => "\xED\x85\xB8", + "\xB7\x4C" => "\xED\x85\xB9", + "\xB7\x4D" => "\xED\x85\xBA", + "\xB7\x4E" => "\xED\x85\xBB", + "\xB7\x4F" => "\xED\x85\xBD", + "\xB7\x50" => "\xED\x85\xBE", + "\xB7\x51" => "\xED\x85\xBF", + "\xB7\x52" => "\xED\x86\x80", + "\xB7\x53" => "\xED\x86\x81", + "\xB7\x54" => "\xED\x86\x82", + "\xB7\x55" => "\xED\x86\x83", + "\xB7\x56" => "\xED\x86\x85", + "\xB7\x57" => "\xED\x86\x86", + "\xB7\x58" => "\xED\x86\x87", + "\xB7\x59" => "\xED\x86\x89", + "\xB7\x5A" => "\xED\x86\x8A", + "\xB7\x61" => "\xED\x86\x8B", + "\xB7\x62" => "\xED\x86\x8C", + "\xB7\x63" => "\xED\x86\x8D", + "\xB7\x64" => "\xED\x86\x8E", + "\xB7\x65" => "\xED\x86\x8F", + "\xB7\x66" => "\xED\x86\x90", + "\xB7\x67" => "\xED\x86\x91", + "\xB7\x68" => "\xED\x86\x92", + "\xB7\x69" => "\xED\x86\x93", + "\xB7\x6A" => "\xED\x86\x94", + "\xB7\x6B" => "\xED\x86\x95", + "\xB7\x6C" => "\xED\x86\x96", + "\xB7\x6D" => "\xED\x86\x97", + "\xB7\x6E" => "\xED\x86\x98", + "\xB7\x6F" => "\xED\x86\x99", + "\xB7\x70" => "\xED\x86\x9A", + "\xB7\x71" => "\xED\x86\x9B", + "\xB7\x72" => "\xED\x86\x9C", + "\xB7\x73" => "\xED\x86\x9D", + "\xB7\x74" => "\xED\x86\x9E", + "\xB7\x75" => "\xED\x86\x9F", + "\xB7\x76" => "\xED\x86\xA2", + "\xB7\x77" => "\xED\x86\xA3", + "\xB7\x78" => "\xED\x86\xA5", + "\xB7\x79" => "\xED\x86\xA6", + "\xB7\x7A" => "\xED\x86\xA7", + "\xB7\x81" => "\xED\x86\xA9", + "\xB7\x82" => "\xED\x86\xAA", + "\xB7\x83" => "\xED\x86\xAB", + "\xB7\x84" => "\xED\x86\xAC", + "\xB7\x85" => "\xED\x86\xAD", + "\xB7\x86" => "\xED\x86\xAE", + "\xB7\x87" => "\xED\x86\xAF", + "\xB7\x88" => "\xED\x86\xB2", + "\xB7\x89" => "\xED\x86\xB4", + "\xB7\x8A" => "\xED\x86\xB6", + "\xB7\x8B" => "\xED\x86\xB7", + "\xB7\x8C" => "\xED\x86\xB8", + "\xB7\x8D" => "\xED\x86\xB9", + "\xB7\x8E" => "\xED\x86\xBB", + "\xB7\x8F" => "\xED\x86\xBD", + "\xB7\x90" => "\xED\x86\xBE", + "\xB7\x91" => "\xED\x86\xBF", + "\xB7\x92" => "\xED\x87\x81", + "\xB7\x93" => "\xED\x87\x82", + "\xB7\x94" => "\xED\x87\x83", + "\xB7\x95" => "\xED\x87\x84", + "\xB7\x96" => "\xED\x87\x85", + "\xB7\x97" => "\xED\x87\x86", + "\xB7\x98" => "\xED\x87\x87", + "\xB7\x99" => "\xED\x87\x88", + "\xB7\x9A" => "\xED\x87\x89", + "\xB7\x9B" => "\xED\x87\x8A", + "\xB7\x9C" => "\xED\x87\x8B", + "\xB7\x9D" => "\xED\x87\x8C", + "\xB7\x9E" => "\xED\x87\x8D", + "\xB7\x9F" => "\xED\x87\x8E", + "\xB7\xA0" => "\xED\x87\x8F", + "\xB7\xA1" => "\xEB\x9E\x98", + "\xB7\xA2" => "\xEB\x9E\x99", + "\xB7\xA3" => "\xEB\x9E\x9C", + "\xB7\xA4" => "\xEB\x9E\xA0", + "\xB7\xA5" => "\xEB\x9E\xA8", + "\xB7\xA6" => "\xEB\x9E\xA9", + "\xB7\xA7" => "\xEB\x9E\xAB", + "\xB7\xA8" => "\xEB\x9E\xAC", + "\xB7\xA9" => "\xEB\x9E\xAD", + "\xB7\xAA" => "\xEB\x9E\xB4", + "\xB7\xAB" => "\xEB\x9E\xB5", + "\xB7\xAC" => "\xEB\x9E\xB8", + "\xB7\xAD" => "\xEB\x9F\x87", + "\xB7\xAE" => "\xEB\x9F\x89", + "\xB7\xAF" => "\xEB\x9F\xAC", + "\xB7\xB0" => "\xEB\x9F\xAD", + "\xB7\xB1" => "\xEB\x9F\xB0", + "\xB7\xB2" => "\xEB\x9F\xB4", + "\xB7\xB3" => "\xEB\x9F\xBC", + "\xB7\xB4" => "\xEB\x9F\xBD", + "\xB7\xB5" => "\xEB\x9F\xBF", + "\xB7\xB6" => "\xEB\xA0\x80", + "\xB7\xB7" => "\xEB\xA0\x81", + "\xB7\xB8" => "\xEB\xA0\x87", + "\xB7\xB9" => "\xEB\xA0\x88", + "\xB7\xBA" => "\xEB\xA0\x89", + "\xB7\xBB" => "\xEB\xA0\x8C", + "\xB7\xBC" => "\xEB\xA0\x90", + "\xB7\xBD" => "\xEB\xA0\x98", + "\xB7\xBE" => "\xEB\xA0\x99", + "\xB7\xBF" => "\xEB\xA0\x9B", + "\xB7\xC0" => "\xEB\xA0\x9D", + "\xB7\xC1" => "\xEB\xA0\xA4", + "\xB7\xC2" => "\xEB\xA0\xA5", + "\xB7\xC3" => "\xEB\xA0\xA8", + "\xB7\xC4" => "\xEB\xA0\xAC", + "\xB7\xC5" => "\xEB\xA0\xB4", + "\xB7\xC6" => "\xEB\xA0\xB5", + "\xB7\xC7" => "\xEB\xA0\xB7", + "\xB7\xC8" => "\xEB\xA0\xB8", + "\xB7\xC9" => "\xEB\xA0\xB9", + "\xB7\xCA" => "\xEB\xA1\x80", + "\xB7\xCB" => "\xEB\xA1\x84", + "\xB7\xCC" => "\xEB\xA1\x91", + "\xB7\xCD" => "\xEB\xA1\x93", + "\xB7\xCE" => "\xEB\xA1\x9C", + "\xB7\xCF" => "\xEB\xA1\x9D", + "\xB7\xD0" => "\xEB\xA1\xA0", + "\xB7\xD1" => "\xEB\xA1\xA4", + "\xB7\xD2" => "\xEB\xA1\xAC", + "\xB7\xD3" => "\xEB\xA1\xAD", + "\xB7\xD4" => "\xEB\xA1\xAF", + "\xB7\xD5" => "\xEB\xA1\xB1", + "\xB7\xD6" => "\xEB\xA1\xB8", + "\xB7\xD7" => "\xEB\xA1\xBC", + "\xB7\xD8" => "\xEB\xA2\x8D", + "\xB7\xD9" => "\xEB\xA2\xA8", + "\xB7\xDA" => "\xEB\xA2\xB0", + "\xB7\xDB" => "\xEB\xA2\xB4", + "\xB7\xDC" => "\xEB\xA2\xB8", + "\xB7\xDD" => "\xEB\xA3\x80", + "\xB7\xDE" => "\xEB\xA3\x81", + "\xB7\xDF" => "\xEB\xA3\x83", + "\xB7\xE0" => "\xEB\xA3\x85", + "\xB7\xE1" => "\xEB\xA3\x8C", + "\xB7\xE2" => "\xEB\xA3\x90", + "\xB7\xE3" => "\xEB\xA3\x94", + "\xB7\xE4" => "\xEB\xA3\x9D", + "\xB7\xE5" => "\xEB\xA3\x9F", + "\xB7\xE6" => "\xEB\xA3\xA1", + "\xB7\xE7" => "\xEB\xA3\xA8", + "\xB7\xE8" => "\xEB\xA3\xA9", + "\xB7\xE9" => "\xEB\xA3\xAC", + "\xB7\xEA" => "\xEB\xA3\xB0", + "\xB7\xEB" => "\xEB\xA3\xB8", + "\xB7\xEC" => "\xEB\xA3\xB9", + "\xB7\xED" => "\xEB\xA3\xBB", + "\xB7\xEE" => "\xEB\xA3\xBD", + "\xB7\xEF" => "\xEB\xA4\x84", + "\xB7\xF0" => "\xEB\xA4\x98", + "\xB7\xF1" => "\xEB\xA4\xA0", + "\xB7\xF2" => "\xEB\xA4\xBC", + "\xB7\xF3" => "\xEB\xA4\xBD", + "\xB7\xF4" => "\xEB\xA5\x80", + "\xB7\xF5" => "\xEB\xA5\x84", + "\xB7\xF6" => "\xEB\xA5\x8C", + "\xB7\xF7" => "\xEB\xA5\x8F", + "\xB7\xF8" => "\xEB\xA5\x91", + "\xB7\xF9" => "\xEB\xA5\x98", + "\xB7\xFA" => "\xEB\xA5\x99", + "\xB7\xFB" => "\xEB\xA5\x9C", + "\xB7\xFC" => "\xEB\xA5\xA0", + "\xB7\xFD" => "\xEB\xA5\xA8", + "\xB7\xFE" => "\xEB\xA5\xA9", + "\xB8\x41" => "\xED\x87\x90", + "\xB8\x42" => "\xED\x87\x91", + "\xB8\x43" => "\xED\x87\x92", + "\xB8\x44" => "\xED\x87\x93", + "\xB8\x45" => "\xED\x87\x94", + "\xB8\x46" => "\xED\x87\x95", + "\xB8\x47" => "\xED\x87\x96", + "\xB8\x48" => "\xED\x87\x97", + "\xB8\x49" => "\xED\x87\x99", + "\xB8\x4A" => "\xED\x87\x9A", + "\xB8\x4B" => "\xED\x87\x9B", + "\xB8\x4C" => "\xED\x87\x9C", + "\xB8\x4D" => "\xED\x87\x9D", + "\xB8\x4E" => "\xED\x87\x9E", + "\xB8\x4F" => "\xED\x87\x9F", + "\xB8\x50" => "\xED\x87\xA0", + "\xB8\x51" => "\xED\x87\xA1", + "\xB8\x52" => "\xED\x87\xA2", + "\xB8\x53" => "\xED\x87\xA3", + "\xB8\x54" => "\xED\x87\xA4", + "\xB8\x55" => "\xED\x87\xA5", + "\xB8\x56" => "\xED\x87\xA6", + "\xB8\x57" => "\xED\x87\xA7", + "\xB8\x58" => "\xED\x87\xA8", + "\xB8\x59" => "\xED\x87\xA9", + "\xB8\x5A" => "\xED\x87\xAA", + "\xB8\x61" => "\xED\x87\xAB", + "\xB8\x62" => "\xED\x87\xAC", + "\xB8\x63" => "\xED\x87\xAD", + "\xB8\x64" => "\xED\x87\xAE", + "\xB8\x65" => "\xED\x87\xAF", + "\xB8\x66" => "\xED\x87\xB0", + "\xB8\x67" => "\xED\x87\xB1", + "\xB8\x68" => "\xED\x87\xB2", + "\xB8\x69" => "\xED\x87\xB3", + "\xB8\x6A" => "\xED\x87\xB5", + "\xB8\x6B" => "\xED\x87\xB6", + "\xB8\x6C" => "\xED\x87\xB7", + "\xB8\x6D" => "\xED\x87\xB9", + "\xB8\x6E" => "\xED\x87\xBA", + "\xB8\x6F" => "\xED\x87\xBB", + "\xB8\x70" => "\xED\x87\xBC", + "\xB8\x71" => "\xED\x87\xBD", + "\xB8\x72" => "\xED\x87\xBE", + "\xB8\x73" => "\xED\x87\xBF", + "\xB8\x74" => "\xED\x88\x80", + "\xB8\x75" => "\xED\x88\x81", + "\xB8\x76" => "\xED\x88\x82", + "\xB8\x77" => "\xED\x88\x83", + "\xB8\x78" => "\xED\x88\x84", + "\xB8\x79" => "\xED\x88\x85", + "\xB8\x7A" => "\xED\x88\x86", + "\xB8\x81" => "\xED\x88\x88", + "\xB8\x82" => "\xED\x88\x8A", + "\xB8\x83" => "\xED\x88\x8B", + "\xB8\x84" => "\xED\x88\x8C", + "\xB8\x85" => "\xED\x88\x8D", + "\xB8\x86" => "\xED\x88\x8E", + "\xB8\x87" => "\xED\x88\x8F", + "\xB8\x88" => "\xED\x88\x91", + "\xB8\x89" => "\xED\x88\x92", + "\xB8\x8A" => "\xED\x88\x93", + "\xB8\x8B" => "\xED\x88\x94", + "\xB8\x8C" => "\xED\x88\x95", + "\xB8\x8D" => "\xED\x88\x96", + "\xB8\x8E" => "\xED\x88\x97", + "\xB8\x8F" => "\xED\x88\x98", + "\xB8\x90" => "\xED\x88\x99", + "\xB8\x91" => "\xED\x88\x9A", + "\xB8\x92" => "\xED\x88\x9B", + "\xB8\x93" => "\xED\x88\x9C", + "\xB8\x94" => "\xED\x88\x9D", + "\xB8\x95" => "\xED\x88\x9E", + "\xB8\x96" => "\xED\x88\x9F", + "\xB8\x97" => "\xED\x88\xA0", + "\xB8\x98" => "\xED\x88\xA1", + "\xB8\x99" => "\xED\x88\xA2", + "\xB8\x9A" => "\xED\x88\xA3", + "\xB8\x9B" => "\xED\x88\xA4", + "\xB8\x9C" => "\xED\x88\xA5", + "\xB8\x9D" => "\xED\x88\xA6", + "\xB8\x9E" => "\xED\x88\xA7", + "\xB8\x9F" => "\xED\x88\xA8", + "\xB8\xA0" => "\xED\x88\xA9", + "\xB8\xA1" => "\xEB\xA5\xAB", + "\xB8\xA2" => "\xEB\xA5\xAD", + "\xB8\xA3" => "\xEB\xA5\xB4", + "\xB8\xA4" => "\xEB\xA5\xB5", + "\xB8\xA5" => "\xEB\xA5\xB8", + "\xB8\xA6" => "\xEB\xA5\xBC", + "\xB8\xA7" => "\xEB\xA6\x84", + "\xB8\xA8" => "\xEB\xA6\x85", + "\xB8\xA9" => "\xEB\xA6\x87", + "\xB8\xAA" => "\xEB\xA6\x89", + "\xB8\xAB" => "\xEB\xA6\x8A", + "\xB8\xAC" => "\xEB\xA6\x8D", + "\xB8\xAD" => "\xEB\xA6\x8E", + "\xB8\xAE" => "\xEB\xA6\xAC", + "\xB8\xAF" => "\xEB\xA6\xAD", + "\xB8\xB0" => "\xEB\xA6\xB0", + "\xB8\xB1" => "\xEB\xA6\xB4", + "\xB8\xB2" => "\xEB\xA6\xBC", + "\xB8\xB3" => "\xEB\xA6\xBD", + "\xB8\xB4" => "\xEB\xA6\xBF", + "\xB8\xB5" => "\xEB\xA7\x81", + "\xB8\xB6" => "\xEB\xA7\x88", + "\xB8\xB7" => "\xEB\xA7\x89", + "\xB8\xB8" => "\xEB\xA7\x8C", + "\xB8\xB9" => "\xEB\xA7\x8E", + "\xB8\xBA" => "\xEB\xA7\x8F", + "\xB8\xBB" => "\xEB\xA7\x90", + "\xB8\xBC" => "\xEB\xA7\x91", + "\xB8\xBD" => "\xEB\xA7\x92", + "\xB8\xBE" => "\xEB\xA7\x98", + "\xB8\xBF" => "\xEB\xA7\x99", + "\xB8\xC0" => "\xEB\xA7\x9B", + "\xB8\xC1" => "\xEB\xA7\x9D", + "\xB8\xC2" => "\xEB\xA7\x9E", + "\xB8\xC3" => "\xEB\xA7\xA1", + "\xB8\xC4" => "\xEB\xA7\xA3", + "\xB8\xC5" => "\xEB\xA7\xA4", + "\xB8\xC6" => "\xEB\xA7\xA5", + "\xB8\xC7" => "\xEB\xA7\xA8", + "\xB8\xC8" => "\xEB\xA7\xAC", + "\xB8\xC9" => "\xEB\xA7\xB4", + "\xB8\xCA" => "\xEB\xA7\xB5", + "\xB8\xCB" => "\xEB\xA7\xB7", + "\xB8\xCC" => "\xEB\xA7\xB8", + "\xB8\xCD" => "\xEB\xA7\xB9", + "\xB8\xCE" => "\xEB\xA7\xBA", + "\xB8\xCF" => "\xEB\xA8\x80", + "\xB8\xD0" => "\xEB\xA8\x81", + "\xB8\xD1" => "\xEB\xA8\x88", + "\xB8\xD2" => "\xEB\xA8\x95", + "\xB8\xD3" => "\xEB\xA8\xB8", + "\xB8\xD4" => "\xEB\xA8\xB9", + "\xB8\xD5" => "\xEB\xA8\xBC", + "\xB8\xD6" => "\xEB\xA9\x80", + "\xB8\xD7" => "\xEB\xA9\x82", + "\xB8\xD8" => "\xEB\xA9\x88", + "\xB8\xD9" => "\xEB\xA9\x89", + "\xB8\xDA" => "\xEB\xA9\x8B", + "\xB8\xDB" => "\xEB\xA9\x8D", + "\xB8\xDC" => "\xEB\xA9\x8E", + "\xB8\xDD" => "\xEB\xA9\x93", + "\xB8\xDE" => "\xEB\xA9\x94", + "\xB8\xDF" => "\xEB\xA9\x95", + "\xB8\xE0" => "\xEB\xA9\x98", + "\xB8\xE1" => "\xEB\xA9\x9C", + "\xB8\xE2" => "\xEB\xA9\xA4", + "\xB8\xE3" => "\xEB\xA9\xA5", + "\xB8\xE4" => "\xEB\xA9\xA7", + "\xB8\xE5" => "\xEB\xA9\xA8", + "\xB8\xE6" => "\xEB\xA9\xA9", + "\xB8\xE7" => "\xEB\xA9\xB0", + "\xB8\xE8" => "\xEB\xA9\xB1", + "\xB8\xE9" => "\xEB\xA9\xB4", + "\xB8\xEA" => "\xEB\xA9\xB8", + "\xB8\xEB" => "\xEB\xAA\x83", + "\xB8\xEC" => "\xEB\xAA\x84", + "\xB8\xED" => "\xEB\xAA\x85", + "\xB8\xEE" => "\xEB\xAA\x87", + "\xB8\xEF" => "\xEB\xAA\x8C", + "\xB8\xF0" => "\xEB\xAA\xA8", + "\xB8\xF1" => "\xEB\xAA\xA9", + "\xB8\xF2" => "\xEB\xAA\xAB", + "\xB8\xF3" => "\xEB\xAA\xAC", + "\xB8\xF4" => "\xEB\xAA\xB0", + "\xB8\xF5" => "\xEB\xAA\xB2", + "\xB8\xF6" => "\xEB\xAA\xB8", + "\xB8\xF7" => "\xEB\xAA\xB9", + "\xB8\xF8" => "\xEB\xAA\xBB", + "\xB8\xF9" => "\xEB\xAA\xBD", + "\xB8\xFA" => "\xEB\xAB\x84", + "\xB8\xFB" => "\xEB\xAB\x88", + "\xB8\xFC" => "\xEB\xAB\x98", + "\xB8\xFD" => "\xEB\xAB\x99", + "\xB8\xFE" => "\xEB\xAB\xBC", + "\xB9\x41" => "\xED\x88\xAA", + "\xB9\x42" => "\xED\x88\xAB", + "\xB9\x43" => "\xED\x88\xAE", + "\xB9\x44" => "\xED\x88\xAF", + "\xB9\x45" => "\xED\x88\xB1", + "\xB9\x46" => "\xED\x88\xB2", + "\xB9\x47" => "\xED\x88\xB3", + "\xB9\x48" => "\xED\x88\xB5", + "\xB9\x49" => "\xED\x88\xB6", + "\xB9\x4A" => "\xED\x88\xB7", + "\xB9\x4B" => "\xED\x88\xB8", + "\xB9\x4C" => "\xED\x88\xB9", + "\xB9\x4D" => "\xED\x88\xBA", + "\xB9\x4E" => "\xED\x88\xBB", + "\xB9\x4F" => "\xED\x88\xBE", + "\xB9\x50" => "\xED\x89\x80", + "\xB9\x51" => "\xED\x89\x82", + "\xB9\x52" => "\xED\x89\x83", + "\xB9\x53" => "\xED\x89\x84", + "\xB9\x54" => "\xED\x89\x85", + "\xB9\x55" => "\xED\x89\x86", + "\xB9\x56" => "\xED\x89\x87", + "\xB9\x57" => "\xED\x89\x89", + "\xB9\x58" => "\xED\x89\x8A", + "\xB9\x59" => "\xED\x89\x8B", + "\xB9\x5A" => "\xED\x89\x8C", + "\xB9\x61" => "\xED\x89\x8D", + "\xB9\x62" => "\xED\x89\x8E", + "\xB9\x63" => "\xED\x89\x8F", + "\xB9\x64" => "\xED\x89\x90", + "\xB9\x65" => "\xED\x89\x91", + "\xB9\x66" => "\xED\x89\x92", + "\xB9\x67" => "\xED\x89\x93", + "\xB9\x68" => "\xED\x89\x94", + "\xB9\x69" => "\xED\x89\x95", + "\xB9\x6A" => "\xED\x89\x96", + "\xB9\x6B" => "\xED\x89\x97", + "\xB9\x6C" => "\xED\x89\x98", + "\xB9\x6D" => "\xED\x89\x99", + "\xB9\x6E" => "\xED\x89\x9A", + "\xB9\x6F" => "\xED\x89\x9B", + "\xB9\x70" => "\xED\x89\x9D", + "\xB9\x71" => "\xED\x89\x9E", + "\xB9\x72" => "\xED\x89\x9F", + "\xB9\x73" => "\xED\x89\xA0", + "\xB9\x74" => "\xED\x89\xA1", + "\xB9\x75" => "\xED\x89\xA2", + "\xB9\x76" => "\xED\x89\xA3", + "\xB9\x77" => "\xED\x89\xA5", + "\xB9\x78" => "\xED\x89\xA6", + "\xB9\x79" => "\xED\x89\xA7", + "\xB9\x7A" => "\xED\x89\xA8", + "\xB9\x81" => "\xED\x89\xA9", + "\xB9\x82" => "\xED\x89\xAA", + "\xB9\x83" => "\xED\x89\xAB", + "\xB9\x84" => "\xED\x89\xAC", + "\xB9\x85" => "\xED\x89\xAD", + "\xB9\x86" => "\xED\x89\xAE", + "\xB9\x87" => "\xED\x89\xAF", + "\xB9\x88" => "\xED\x89\xB0", + "\xB9\x89" => "\xED\x89\xB1", + "\xB9\x8A" => "\xED\x89\xB2", + "\xB9\x8B" => "\xED\x89\xB3", + "\xB9\x8C" => "\xED\x89\xB4", + "\xB9\x8D" => "\xED\x89\xB5", + "\xB9\x8E" => "\xED\x89\xB6", + "\xB9\x8F" => "\xED\x89\xB7", + "\xB9\x90" => "\xED\x89\xB8", + "\xB9\x91" => "\xED\x89\xB9", + "\xB9\x92" => "\xED\x89\xBA", + "\xB9\x93" => "\xED\x89\xBB", + "\xB9\x94" => "\xED\x89\xBC", + "\xB9\x95" => "\xED\x89\xBD", + "\xB9\x96" => "\xED\x89\xBE", + "\xB9\x97" => "\xED\x89\xBF", + "\xB9\x98" => "\xED\x8A\x82", + "\xB9\x99" => "\xED\x8A\x83", + "\xB9\x9A" => "\xED\x8A\x85", + "\xB9\x9B" => "\xED\x8A\x86", + "\xB9\x9C" => "\xED\x8A\x87", + "\xB9\x9D" => "\xED\x8A\x89", + "\xB9\x9E" => "\xED\x8A\x8A", + "\xB9\x9F" => "\xED\x8A\x8B", + "\xB9\xA0" => "\xED\x8A\x8C", + "\xB9\xA1" => "\xEB\xAC\x80", + "\xB9\xA2" => "\xEB\xAC\x84", + "\xB9\xA3" => "\xEB\xAC\x8D", + "\xB9\xA4" => "\xEB\xAC\x8F", + "\xB9\xA5" => "\xEB\xAC\x91", + "\xB9\xA6" => "\xEB\xAC\x98", + "\xB9\xA7" => "\xEB\xAC\x9C", + "\xB9\xA8" => "\xEB\xAC\xA0", + "\xB9\xA9" => "\xEB\xAC\xA9", + "\xB9\xAA" => "\xEB\xAC\xAB", + "\xB9\xAB" => "\xEB\xAC\xB4", + "\xB9\xAC" => "\xEB\xAC\xB5", + "\xB9\xAD" => "\xEB\xAC\xB6", + "\xB9\xAE" => "\xEB\xAC\xB8", + "\xB9\xAF" => "\xEB\xAC\xBB", + "\xB9\xB0" => "\xEB\xAC\xBC", + "\xB9\xB1" => "\xEB\xAC\xBD", + "\xB9\xB2" => "\xEB\xAC\xBE", + "\xB9\xB3" => "\xEB\xAD\x84", + "\xB9\xB4" => "\xEB\xAD\x85", + "\xB9\xB5" => "\xEB\xAD\x87", + "\xB9\xB6" => "\xEB\xAD\x89", + "\xB9\xB7" => "\xEB\xAD\x8D", + "\xB9\xB8" => "\xEB\xAD\x8F", + "\xB9\xB9" => "\xEB\xAD\x90", + "\xB9\xBA" => "\xEB\xAD\x94", + "\xB9\xBB" => "\xEB\xAD\x98", + "\xB9\xBC" => "\xEB\xAD\xA1", + "\xB9\xBD" => "\xEB\xAD\xA3", + "\xB9\xBE" => "\xEB\xAD\xAC", + "\xB9\xBF" => "\xEB\xAE\x88", + "\xB9\xC0" => "\xEB\xAE\x8C", + "\xB9\xC1" => "\xEB\xAE\x90", + "\xB9\xC2" => "\xEB\xAE\xA4", + "\xB9\xC3" => "\xEB\xAE\xA8", + "\xB9\xC4" => "\xEB\xAE\xAC", + "\xB9\xC5" => "\xEB\xAE\xB4", + "\xB9\xC6" => "\xEB\xAE\xB7", + "\xB9\xC7" => "\xEB\xAF\x80", + "\xB9\xC8" => "\xEB\xAF\x84", + "\xB9\xC9" => "\xEB\xAF\x88", + "\xB9\xCA" => "\xEB\xAF\x90", + "\xB9\xCB" => "\xEB\xAF\x93", + "\xB9\xCC" => "\xEB\xAF\xB8", + "\xB9\xCD" => "\xEB\xAF\xB9", + "\xB9\xCE" => "\xEB\xAF\xBC", + "\xB9\xCF" => "\xEB\xAF\xBF", + "\xB9\xD0" => "\xEB\xB0\x80", + "\xB9\xD1" => "\xEB\xB0\x82", + "\xB9\xD2" => "\xEB\xB0\x88", + "\xB9\xD3" => "\xEB\xB0\x89", + "\xB9\xD4" => "\xEB\xB0\x8B", + "\xB9\xD5" => "\xEB\xB0\x8C", + "\xB9\xD6" => "\xEB\xB0\x8D", + "\xB9\xD7" => "\xEB\xB0\x8F", + "\xB9\xD8" => "\xEB\xB0\x91", + "\xB9\xD9" => "\xEB\xB0\x94", + "\xB9\xDA" => "\xEB\xB0\x95", + "\xB9\xDB" => "\xEB\xB0\x96", + "\xB9\xDC" => "\xEB\xB0\x97", + "\xB9\xDD" => "\xEB\xB0\x98", + "\xB9\xDE" => "\xEB\xB0\x9B", + "\xB9\xDF" => "\xEB\xB0\x9C", + "\xB9\xE0" => "\xEB\xB0\x9D", + "\xB9\xE1" => "\xEB\xB0\x9E", + "\xB9\xE2" => "\xEB\xB0\x9F", + "\xB9\xE3" => "\xEB\xB0\xA4", + "\xB9\xE4" => "\xEB\xB0\xA5", + "\xB9\xE5" => "\xEB\xB0\xA7", + "\xB9\xE6" => "\xEB\xB0\xA9", + "\xB9\xE7" => "\xEB\xB0\xAD", + "\xB9\xE8" => "\xEB\xB0\xB0", + "\xB9\xE9" => "\xEB\xB0\xB1", + "\xB9\xEA" => "\xEB\xB0\xB4", + "\xB9\xEB" => "\xEB\xB0\xB8", + "\xB9\xEC" => "\xEB\xB1\x80", + "\xB9\xED" => "\xEB\xB1\x81", + "\xB9\xEE" => "\xEB\xB1\x83", + "\xB9\xEF" => "\xEB\xB1\x84", + "\xB9\xF0" => "\xEB\xB1\x85", + "\xB9\xF1" => "\xEB\xB1\x89", + "\xB9\xF2" => "\xEB\xB1\x8C", + "\xB9\xF3" => "\xEB\xB1\x8D", + "\xB9\xF4" => "\xEB\xB1\x90", + "\xB9\xF5" => "\xEB\xB1\x9D", + "\xB9\xF6" => "\xEB\xB2\x84", + "\xB9\xF7" => "\xEB\xB2\x85", + "\xB9\xF8" => "\xEB\xB2\x88", + "\xB9\xF9" => "\xEB\xB2\x8B", + "\xB9\xFA" => "\xEB\xB2\x8C", + "\xB9\xFB" => "\xEB\xB2\x8E", + "\xB9\xFC" => "\xEB\xB2\x94", + "\xB9\xFD" => "\xEB\xB2\x95", + "\xB9\xFE" => "\xEB\xB2\x97", + "\xBA\x41" => "\xED\x8A\x8D", + "\xBA\x42" => "\xED\x8A\x8E", + "\xBA\x43" => "\xED\x8A\x8F", + "\xBA\x44" => "\xED\x8A\x92", + "\xBA\x45" => "\xED\x8A\x93", + "\xBA\x46" => "\xED\x8A\x94", + "\xBA\x47" => "\xED\x8A\x96", + "\xBA\x48" => "\xED\x8A\x97", + "\xBA\x49" => "\xED\x8A\x98", + "\xBA\x4A" => "\xED\x8A\x99", + "\xBA\x4B" => "\xED\x8A\x9A", + "\xBA\x4C" => "\xED\x8A\x9B", + "\xBA\x4D" => "\xED\x8A\x9D", + "\xBA\x4E" => "\xED\x8A\x9E", + "\xBA\x4F" => "\xED\x8A\x9F", + "\xBA\x50" => "\xED\x8A\xA1", + "\xBA\x51" => "\xED\x8A\xA2", + "\xBA\x52" => "\xED\x8A\xA3", + "\xBA\x53" => "\xED\x8A\xA5", + "\xBA\x54" => "\xED\x8A\xA6", + "\xBA\x55" => "\xED\x8A\xA7", + "\xBA\x56" => "\xED\x8A\xA8", + "\xBA\x57" => "\xED\x8A\xA9", + "\xBA\x58" => "\xED\x8A\xAA", + "\xBA\x59" => "\xED\x8A\xAB", + "\xBA\x5A" => "\xED\x8A\xAD", + "\xBA\x61" => "\xED\x8A\xAE", + "\xBA\x62" => "\xED\x8A\xAF", + "\xBA\x63" => "\xED\x8A\xB0", + "\xBA\x64" => "\xED\x8A\xB2", + "\xBA\x65" => "\xED\x8A\xB3", + "\xBA\x66" => "\xED\x8A\xB4", + "\xBA\x67" => "\xED\x8A\xB5", + "\xBA\x68" => "\xED\x8A\xB6", + "\xBA\x69" => "\xED\x8A\xB7", + "\xBA\x6A" => "\xED\x8A\xBA", + "\xBA\x6B" => "\xED\x8A\xBB", + "\xBA\x6C" => "\xED\x8A\xBD", + "\xBA\x6D" => "\xED\x8A\xBE", + "\xBA\x6E" => "\xED\x8B\x81", + "\xBA\x6F" => "\xED\x8B\x83", + "\xBA\x70" => "\xED\x8B\x84", + "\xBA\x71" => "\xED\x8B\x85", + "\xBA\x72" => "\xED\x8B\x86", + "\xBA\x73" => "\xED\x8B\x87", + "\xBA\x74" => "\xED\x8B\x8A", + "\xBA\x75" => "\xED\x8B\x8C", + "\xBA\x76" => "\xED\x8B\x8D", + "\xBA\x77" => "\xED\x8B\x8E", + "\xBA\x78" => "\xED\x8B\x8F", + "\xBA\x79" => "\xED\x8B\x90", + "\xBA\x7A" => "\xED\x8B\x91", + "\xBA\x81" => "\xED\x8B\x92", + "\xBA\x82" => "\xED\x8B\x93", + "\xBA\x83" => "\xED\x8B\x95", + "\xBA\x84" => "\xED\x8B\x96", + "\xBA\x85" => "\xED\x8B\x97", + "\xBA\x86" => "\xED\x8B\x99", + "\xBA\x87" => "\xED\x8B\x9A", + "\xBA\x88" => "\xED\x8B\x9B", + "\xBA\x89" => "\xED\x8B\x9D", + "\xBA\x8A" => "\xED\x8B\x9E", + "\xBA\x8B" => "\xED\x8B\x9F", + "\xBA\x8C" => "\xED\x8B\xA0", + "\xBA\x8D" => "\xED\x8B\xA1", + "\xBA\x8E" => "\xED\x8B\xA2", + "\xBA\x8F" => "\xED\x8B\xA3", + "\xBA\x90" => "\xED\x8B\xA6", + "\xBA\x91" => "\xED\x8B\xA7", + "\xBA\x92" => "\xED\x8B\xA8", + "\xBA\x93" => "\xED\x8B\xA9", + "\xBA\x94" => "\xED\x8B\xAA", + "\xBA\x95" => "\xED\x8B\xAB", + "\xBA\x96" => "\xED\x8B\xAC", + "\xBA\x97" => "\xED\x8B\xAD", + "\xBA\x98" => "\xED\x8B\xAE", + "\xBA\x99" => "\xED\x8B\xAF", + "\xBA\x9A" => "\xED\x8B\xB2", + "\xBA\x9B" => "\xED\x8B\xB3", + "\xBA\x9C" => "\xED\x8B\xB5", + "\xBA\x9D" => "\xED\x8B\xB6", + "\xBA\x9E" => "\xED\x8B\xB7", + "\xBA\x9F" => "\xED\x8B\xB9", + "\xBA\xA0" => "\xED\x8B\xBA", + "\xBA\xA1" => "\xEB\xB2\x99", + "\xBA\xA2" => "\xEB\xB2\x9A", + "\xBA\xA3" => "\xEB\xB2\xA0", + "\xBA\xA4" => "\xEB\xB2\xA1", + "\xBA\xA5" => "\xEB\xB2\xA4", + "\xBA\xA6" => "\xEB\xB2\xA7", + "\xBA\xA7" => "\xEB\xB2\xA8", + "\xBA\xA8" => "\xEB\xB2\xB0", + "\xBA\xA9" => "\xEB\xB2\xB1", + "\xBA\xAA" => "\xEB\xB2\xB3", + "\xBA\xAB" => "\xEB\xB2\xB4", + "\xBA\xAC" => "\xEB\xB2\xB5", + "\xBA\xAD" => "\xEB\xB2\xBC", + "\xBA\xAE" => "\xEB\xB2\xBD", + "\xBA\xAF" => "\xEB\xB3\x80", + "\xBA\xB0" => "\xEB\xB3\x84", + "\xBA\xB1" => "\xEB\xB3\x8D", + "\xBA\xB2" => "\xEB\xB3\x8F", + "\xBA\xB3" => "\xEB\xB3\x90", + "\xBA\xB4" => "\xEB\xB3\x91", + "\xBA\xB5" => "\xEB\xB3\x95", + "\xBA\xB6" => "\xEB\xB3\x98", + "\xBA\xB7" => "\xEB\xB3\x9C", + "\xBA\xB8" => "\xEB\xB3\xB4", + "\xBA\xB9" => "\xEB\xB3\xB5", + "\xBA\xBA" => "\xEB\xB3\xB6", + "\xBA\xBB" => "\xEB\xB3\xB8", + "\xBA\xBC" => "\xEB\xB3\xBC", + "\xBA\xBD" => "\xEB\xB4\x84", + "\xBA\xBE" => "\xEB\xB4\x85", + "\xBA\xBF" => "\xEB\xB4\x87", + "\xBA\xC0" => "\xEB\xB4\x89", + "\xBA\xC1" => "\xEB\xB4\x90", + "\xBA\xC2" => "\xEB\xB4\x94", + "\xBA\xC3" => "\xEB\xB4\xA4", + "\xBA\xC4" => "\xEB\xB4\xAC", + "\xBA\xC5" => "\xEB\xB5\x80", + "\xBA\xC6" => "\xEB\xB5\x88", + "\xBA\xC7" => "\xEB\xB5\x89", + "\xBA\xC8" => "\xEB\xB5\x8C", + "\xBA\xC9" => "\xEB\xB5\x90", + "\xBA\xCA" => "\xEB\xB5\x98", + "\xBA\xCB" => "\xEB\xB5\x99", + "\xBA\xCC" => "\xEB\xB5\xA4", + "\xBA\xCD" => "\xEB\xB5\xA8", + "\xBA\xCE" => "\xEB\xB6\x80", + "\xBA\xCF" => "\xEB\xB6\x81", + "\xBA\xD0" => "\xEB\xB6\x84", + "\xBA\xD1" => "\xEB\xB6\x87", + "\xBA\xD2" => "\xEB\xB6\x88", + "\xBA\xD3" => "\xEB\xB6\x89", + "\xBA\xD4" => "\xEB\xB6\x8A", + "\xBA\xD5" => "\xEB\xB6\x90", + "\xBA\xD6" => "\xEB\xB6\x91", + "\xBA\xD7" => "\xEB\xB6\x93", + "\xBA\xD8" => "\xEB\xB6\x95", + "\xBA\xD9" => "\xEB\xB6\x99", + "\xBA\xDA" => "\xEB\xB6\x9A", + "\xBA\xDB" => "\xEB\xB6\x9C", + "\xBA\xDC" => "\xEB\xB6\xA4", + "\xBA\xDD" => "\xEB\xB6\xB0", + "\xBA\xDE" => "\xEB\xB6\xB8", + "\xBA\xDF" => "\xEB\xB7\x94", + "\xBA\xE0" => "\xEB\xB7\x95", + "\xBA\xE1" => "\xEB\xB7\x98", + "\xBA\xE2" => "\xEB\xB7\x9C", + "\xBA\xE3" => "\xEB\xB7\xA9", + "\xBA\xE4" => "\xEB\xB7\xB0", + "\xBA\xE5" => "\xEB\xB7\xB4", + "\xBA\xE6" => "\xEB\xB7\xB8", + "\xBA\xE7" => "\xEB\xB8\x80", + "\xBA\xE8" => "\xEB\xB8\x83", + "\xBA\xE9" => "\xEB\xB8\x85", + "\xBA\xEA" => "\xEB\xB8\x8C", + "\xBA\xEB" => "\xEB\xB8\x8D", + "\xBA\xEC" => "\xEB\xB8\x90", + "\xBA\xED" => "\xEB\xB8\x94", + "\xBA\xEE" => "\xEB\xB8\x9C", + "\xBA\xEF" => "\xEB\xB8\x9D", + "\xBA\xF0" => "\xEB\xB8\x9F", + "\xBA\xF1" => "\xEB\xB9\x84", + "\xBA\xF2" => "\xEB\xB9\x85", + "\xBA\xF3" => "\xEB\xB9\x88", + "\xBA\xF4" => "\xEB\xB9\x8C", + "\xBA\xF5" => "\xEB\xB9\x8E", + "\xBA\xF6" => "\xEB\xB9\x94", + "\xBA\xF7" => "\xEB\xB9\x95", + "\xBA\xF8" => "\xEB\xB9\x97", + "\xBA\xF9" => "\xEB\xB9\x99", + "\xBA\xFA" => "\xEB\xB9\x9A", + "\xBA\xFB" => "\xEB\xB9\x9B", + "\xBA\xFC" => "\xEB\xB9\xA0", + "\xBA\xFD" => "\xEB\xB9\xA1", + "\xBA\xFE" => "\xEB\xB9\xA4", + "\xBB\x41" => "\xED\x8B\xBB", + "\xBB\x42" => "\xED\x8B\xBC", + "\xBB\x43" => "\xED\x8B\xBD", + "\xBB\x44" => "\xED\x8B\xBE", + "\xBB\x45" => "\xED\x8B\xBF", + "\xBB\x46" => "\xED\x8C\x82", + "\xBB\x47" => "\xED\x8C\x84", + "\xBB\x48" => "\xED\x8C\x86", + "\xBB\x49" => "\xED\x8C\x87", + "\xBB\x4A" => "\xED\x8C\x88", + "\xBB\x4B" => "\xED\x8C\x89", + "\xBB\x4C" => "\xED\x8C\x8A", + "\xBB\x4D" => "\xED\x8C\x8B", + "\xBB\x4E" => "\xED\x8C\x8F", + "\xBB\x4F" => "\xED\x8C\x91", + "\xBB\x50" => "\xED\x8C\x92", + "\xBB\x51" => "\xED\x8C\x93", + "\xBB\x52" => "\xED\x8C\x95", + "\xBB\x53" => "\xED\x8C\x97", + "\xBB\x54" => "\xED\x8C\x98", + "\xBB\x55" => "\xED\x8C\x99", + "\xBB\x56" => "\xED\x8C\x9A", + "\xBB\x57" => "\xED\x8C\x9B", + "\xBB\x58" => "\xED\x8C\x9E", + "\xBB\x59" => "\xED\x8C\xA2", + "\xBB\x5A" => "\xED\x8C\xA3", + "\xBB\x61" => "\xED\x8C\xA4", + "\xBB\x62" => "\xED\x8C\xA6", + "\xBB\x63" => "\xED\x8C\xA7", + "\xBB\x64" => "\xED\x8C\xAA", + "\xBB\x65" => "\xED\x8C\xAB", + "\xBB\x66" => "\xED\x8C\xAD", + "\xBB\x67" => "\xED\x8C\xAE", + "\xBB\x68" => "\xED\x8C\xAF", + "\xBB\x69" => "\xED\x8C\xB1", + "\xBB\x6A" => "\xED\x8C\xB2", + "\xBB\x6B" => "\xED\x8C\xB3", + "\xBB\x6C" => "\xED\x8C\xB4", + "\xBB\x6D" => "\xED\x8C\xB5", + "\xBB\x6E" => "\xED\x8C\xB6", + "\xBB\x6F" => "\xED\x8C\xB7", + "\xBB\x70" => "\xED\x8C\xBA", + "\xBB\x71" => "\xED\x8C\xBE", + "\xBB\x72" => "\xED\x8C\xBF", + "\xBB\x73" => "\xED\x8D\x80", + "\xBB\x74" => "\xED\x8D\x81", + "\xBB\x75" => "\xED\x8D\x82", + "\xBB\x76" => "\xED\x8D\x83", + "\xBB\x77" => "\xED\x8D\x86", + "\xBB\x78" => "\xED\x8D\x87", + "\xBB\x79" => "\xED\x8D\x88", + "\xBB\x7A" => "\xED\x8D\x89", + "\xBB\x81" => "\xED\x8D\x8A", + "\xBB\x82" => "\xED\x8D\x8B", + "\xBB\x83" => "\xED\x8D\x8C", + "\xBB\x84" => "\xED\x8D\x8D", + "\xBB\x85" => "\xED\x8D\x8E", + "\xBB\x86" => "\xED\x8D\x8F", + "\xBB\x87" => "\xED\x8D\x90", + "\xBB\x88" => "\xED\x8D\x91", + "\xBB\x89" => "\xED\x8D\x92", + "\xBB\x8A" => "\xED\x8D\x93", + "\xBB\x8B" => "\xED\x8D\x94", + "\xBB\x8C" => "\xED\x8D\x95", + "\xBB\x8D" => "\xED\x8D\x96", + "\xBB\x8E" => "\xED\x8D\x97", + "\xBB\x8F" => "\xED\x8D\x98", + "\xBB\x90" => "\xED\x8D\x99", + "\xBB\x91" => "\xED\x8D\x9A", + "\xBB\x92" => "\xED\x8D\x9B", + "\xBB\x93" => "\xED\x8D\x9C", + "\xBB\x94" => "\xED\x8D\x9D", + "\xBB\x95" => "\xED\x8D\x9E", + "\xBB\x96" => "\xED\x8D\x9F", + "\xBB\x97" => "\xED\x8D\xA0", + "\xBB\x98" => "\xED\x8D\xA1", + "\xBB\x99" => "\xED\x8D\xA2", + "\xBB\x9A" => "\xED\x8D\xA3", + "\xBB\x9B" => "\xED\x8D\xA4", + "\xBB\x9C" => "\xED\x8D\xA5", + "\xBB\x9D" => "\xED\x8D\xA6", + "\xBB\x9E" => "\xED\x8D\xA7", + "\xBB\x9F" => "\xED\x8D\xA8", + "\xBB\xA0" => "\xED\x8D\xA9", + "\xBB\xA1" => "\xEB\xB9\xA8", + "\xBB\xA2" => "\xEB\xB9\xAA", + "\xBB\xA3" => "\xEB\xB9\xB0", + "\xBB\xA4" => "\xEB\xB9\xB1", + "\xBB\xA5" => "\xEB\xB9\xB3", + "\xBB\xA6" => "\xEB\xB9\xB4", + "\xBB\xA7" => "\xEB\xB9\xB5", + "\xBB\xA8" => "\xEB\xB9\xBB", + "\xBB\xA9" => "\xEB\xB9\xBC", + "\xBB\xAA" => "\xEB\xB9\xBD", + "\xBB\xAB" => "\xEB\xBA\x80", + "\xBB\xAC" => "\xEB\xBA\x84", + "\xBB\xAD" => "\xEB\xBA\x8C", + "\xBB\xAE" => "\xEB\xBA\x8D", + "\xBB\xAF" => "\xEB\xBA\x8F", + "\xBB\xB0" => "\xEB\xBA\x90", + "\xBB\xB1" => "\xEB\xBA\x91", + "\xBB\xB2" => "\xEB\xBA\x98", + "\xBB\xB3" => "\xEB\xBA\x99", + "\xBB\xB4" => "\xEB\xBA\xA8", + "\xBB\xB5" => "\xEB\xBB\x90", + "\xBB\xB6" => "\xEB\xBB\x91", + "\xBB\xB7" => "\xEB\xBB\x94", + "\xBB\xB8" => "\xEB\xBB\x97", + "\xBB\xB9" => "\xEB\xBB\x98", + "\xBB\xBA" => "\xEB\xBB\xA0", + "\xBB\xBB" => "\xEB\xBB\xA3", + "\xBB\xBC" => "\xEB\xBB\xA4", + "\xBB\xBD" => "\xEB\xBB\xA5", + "\xBB\xBE" => "\xEB\xBB\xAC", + "\xBB\xBF" => "\xEB\xBC\x81", + "\xBB\xC0" => "\xEB\xBC\x88", + "\xBB\xC1" => "\xEB\xBC\x89", + "\xBB\xC2" => "\xEB\xBC\x98", + "\xBB\xC3" => "\xEB\xBC\x99", + "\xBB\xC4" => "\xEB\xBC\x9B", + "\xBB\xC5" => "\xEB\xBC\x9C", + "\xBB\xC6" => "\xEB\xBC\x9D", + "\xBB\xC7" => "\xEB\xBD\x80", + "\xBB\xC8" => "\xEB\xBD\x81", + "\xBB\xC9" => "\xEB\xBD\x84", + "\xBB\xCA" => "\xEB\xBD\x88", + "\xBB\xCB" => "\xEB\xBD\x90", + "\xBB\xCC" => "\xEB\xBD\x91", + "\xBB\xCD" => "\xEB\xBD\x95", + "\xBB\xCE" => "\xEB\xBE\x94", + "\xBB\xCF" => "\xEB\xBE\xB0", + "\xBB\xD0" => "\xEB\xBF\x85", + "\xBB\xD1" => "\xEB\xBF\x8C", + "\xBB\xD2" => "\xEB\xBF\x8D", + "\xBB\xD3" => "\xEB\xBF\x90", + "\xBB\xD4" => "\xEB\xBF\x94", + "\xBB\xD5" => "\xEB\xBF\x9C", + "\xBB\xD6" => "\xEB\xBF\x9F", + "\xBB\xD7" => "\xEB\xBF\xA1", + "\xBB\xD8" => "\xEC\x80\xBC", + "\xBB\xD9" => "\xEC\x81\x91", + "\xBB\xDA" => "\xEC\x81\x98", + "\xBB\xDB" => "\xEC\x81\x9C", + "\xBB\xDC" => "\xEC\x81\xA0", + "\xBB\xDD" => "\xEC\x81\xA8", + "\xBB\xDE" => "\xEC\x81\xA9", + "\xBB\xDF" => "\xEC\x82\x90", + "\xBB\xE0" => "\xEC\x82\x91", + "\xBB\xE1" => "\xEC\x82\x94", + "\xBB\xE2" => "\xEC\x82\x98", + "\xBB\xE3" => "\xEC\x82\xA0", + "\xBB\xE4" => "\xEC\x82\xA1", + "\xBB\xE5" => "\xEC\x82\xA3", + "\xBB\xE6" => "\xEC\x82\xA5", + "\xBB\xE7" => "\xEC\x82\xAC", + "\xBB\xE8" => "\xEC\x82\xAD", + "\xBB\xE9" => "\xEC\x82\xAF", + "\xBB\xEA" => "\xEC\x82\xB0", + "\xBB\xEB" => "\xEC\x82\xB3", + "\xBB\xEC" => "\xEC\x82\xB4", + "\xBB\xED" => "\xEC\x82\xB5", + "\xBB\xEE" => "\xEC\x82\xB6", + "\xBB\xEF" => "\xEC\x82\xBC", + "\xBB\xF0" => "\xEC\x82\xBD", + "\xBB\xF1" => "\xEC\x82\xBF", + "\xBB\xF2" => "\xEC\x83\x80", + "\xBB\xF3" => "\xEC\x83\x81", + "\xBB\xF4" => "\xEC\x83\x85", + "\xBB\xF5" => "\xEC\x83\x88", + "\xBB\xF6" => "\xEC\x83\x89", + "\xBB\xF7" => "\xEC\x83\x8C", + "\xBB\xF8" => "\xEC\x83\x90", + "\xBB\xF9" => "\xEC\x83\x98", + "\xBB\xFA" => "\xEC\x83\x99", + "\xBB\xFB" => "\xEC\x83\x9B", + "\xBB\xFC" => "\xEC\x83\x9C", + "\xBB\xFD" => "\xEC\x83\x9D", + "\xBB\xFE" => "\xEC\x83\xA4", + "\xBC\x41" => "\xED\x8D\xAA", + "\xBC\x42" => "\xED\x8D\xAB", + "\xBC\x43" => "\xED\x8D\xAC", + "\xBC\x44" => "\xED\x8D\xAD", + "\xBC\x45" => "\xED\x8D\xAE", + "\xBC\x46" => "\xED\x8D\xAF", + "\xBC\x47" => "\xED\x8D\xB0", + "\xBC\x48" => "\xED\x8D\xB1", + "\xBC\x49" => "\xED\x8D\xB2", + "\xBC\x4A" => "\xED\x8D\xB3", + "\xBC\x4B" => "\xED\x8D\xB4", + "\xBC\x4C" => "\xED\x8D\xB5", + "\xBC\x4D" => "\xED\x8D\xB6", + "\xBC\x4E" => "\xED\x8D\xB7", + "\xBC\x4F" => "\xED\x8D\xB8", + "\xBC\x50" => "\xED\x8D\xB9", + "\xBC\x51" => "\xED\x8D\xBA", + "\xBC\x52" => "\xED\x8D\xBB", + "\xBC\x53" => "\xED\x8D\xBE", + "\xBC\x54" => "\xED\x8D\xBF", + "\xBC\x55" => "\xED\x8E\x81", + "\xBC\x56" => "\xED\x8E\x82", + "\xBC\x57" => "\xED\x8E\x83", + "\xBC\x58" => "\xED\x8E\x85", + "\xBC\x59" => "\xED\x8E\x86", + "\xBC\x5A" => "\xED\x8E\x87", + "\xBC\x61" => "\xED\x8E\x88", + "\xBC\x62" => "\xED\x8E\x89", + "\xBC\x63" => "\xED\x8E\x8A", + "\xBC\x64" => "\xED\x8E\x8B", + "\xBC\x65" => "\xED\x8E\x8E", + "\xBC\x66" => "\xED\x8E\x92", + "\xBC\x67" => "\xED\x8E\x93", + "\xBC\x68" => "\xED\x8E\x94", + "\xBC\x69" => "\xED\x8E\x95", + "\xBC\x6A" => "\xED\x8E\x96", + "\xBC\x6B" => "\xED\x8E\x97", + "\xBC\x6C" => "\xED\x8E\x9A", + "\xBC\x6D" => "\xED\x8E\x9B", + "\xBC\x6E" => "\xED\x8E\x9D", + "\xBC\x6F" => "\xED\x8E\x9E", + "\xBC\x70" => "\xED\x8E\x9F", + "\xBC\x71" => "\xED\x8E\xA1", + "\xBC\x72" => "\xED\x8E\xA2", + "\xBC\x73" => "\xED\x8E\xA3", + "\xBC\x74" => "\xED\x8E\xA4", + "\xBC\x75" => "\xED\x8E\xA5", + "\xBC\x76" => "\xED\x8E\xA6", + "\xBC\x77" => "\xED\x8E\xA7", + "\xBC\x78" => "\xED\x8E\xAA", + "\xBC\x79" => "\xED\x8E\xAC", + "\xBC\x7A" => "\xED\x8E\xAE", + "\xBC\x81" => "\xED\x8E\xAF", + "\xBC\x82" => "\xED\x8E\xB0", + "\xBC\x83" => "\xED\x8E\xB1", + "\xBC\x84" => "\xED\x8E\xB2", + "\xBC\x85" => "\xED\x8E\xB3", + "\xBC\x86" => "\xED\x8E\xB5", + "\xBC\x87" => "\xED\x8E\xB6", + "\xBC\x88" => "\xED\x8E\xB7", + "\xBC\x89" => "\xED\x8E\xB9", + "\xBC\x8A" => "\xED\x8E\xBA", + "\xBC\x8B" => "\xED\x8E\xBB", + "\xBC\x8C" => "\xED\x8E\xBD", + "\xBC\x8D" => "\xED\x8E\xBE", + "\xBC\x8E" => "\xED\x8E\xBF", + "\xBC\x8F" => "\xED\x8F\x80", + "\xBC\x90" => "\xED\x8F\x81", + "\xBC\x91" => "\xED\x8F\x82", + "\xBC\x92" => "\xED\x8F\x83", + "\xBC\x93" => "\xED\x8F\x86", + "\xBC\x94" => "\xED\x8F\x87", + "\xBC\x95" => "\xED\x8F\x8A", + "\xBC\x96" => "\xED\x8F\x8B", + "\xBC\x97" => "\xED\x8F\x8C", + "\xBC\x98" => "\xED\x8F\x8D", + "\xBC\x99" => "\xED\x8F\x8E", + "\xBC\x9A" => "\xED\x8F\x8F", + "\xBC\x9B" => "\xED\x8F\x91", + "\xBC\x9C" => "\xED\x8F\x92", + "\xBC\x9D" => "\xED\x8F\x93", + "\xBC\x9E" => "\xED\x8F\x94", + "\xBC\x9F" => "\xED\x8F\x95", + "\xBC\xA0" => "\xED\x8F\x96", + "\xBC\xA1" => "\xEC\x83\xA5", + "\xBC\xA2" => "\xEC\x83\xA8", + "\xBC\xA3" => "\xEC\x83\xAC", + "\xBC\xA4" => "\xEC\x83\xB4", + "\xBC\xA5" => "\xEC\x83\xB5", + "\xBC\xA6" => "\xEC\x83\xB7", + "\xBC\xA7" => "\xEC\x83\xB9", + "\xBC\xA8" => "\xEC\x84\x80", + "\xBC\xA9" => "\xEC\x84\x84", + "\xBC\xAA" => "\xEC\x84\x88", + "\xBC\xAB" => "\xEC\x84\x90", + "\xBC\xAC" => "\xEC\x84\x95", + "\xBC\xAD" => "\xEC\x84\x9C", + "\xBC\xAE" => "\xEC\x84\x9D", + "\xBC\xAF" => "\xEC\x84\x9E", + "\xBC\xB0" => "\xEC\x84\x9F", + "\xBC\xB1" => "\xEC\x84\xA0", + "\xBC\xB2" => "\xEC\x84\xA3", + "\xBC\xB3" => "\xEC\x84\xA4", + "\xBC\xB4" => "\xEC\x84\xA6", + "\xBC\xB5" => "\xEC\x84\xA7", + "\xBC\xB6" => "\xEC\x84\xAC", + "\xBC\xB7" => "\xEC\x84\xAD", + "\xBC\xB8" => "\xEC\x84\xAF", + "\xBC\xB9" => "\xEC\x84\xB0", + "\xBC\xBA" => "\xEC\x84\xB1", + "\xBC\xBB" => "\xEC\x84\xB6", + "\xBC\xBC" => "\xEC\x84\xB8", + "\xBC\xBD" => "\xEC\x84\xB9", + "\xBC\xBE" => "\xEC\x84\xBC", + "\xBC\xBF" => "\xEC\x85\x80", + "\xBC\xC0" => "\xEC\x85\x88", + "\xBC\xC1" => "\xEC\x85\x89", + "\xBC\xC2" => "\xEC\x85\x8B", + "\xBC\xC3" => "\xEC\x85\x8C", + "\xBC\xC4" => "\xEC\x85\x8D", + "\xBC\xC5" => "\xEC\x85\x94", + "\xBC\xC6" => "\xEC\x85\x95", + "\xBC\xC7" => "\xEC\x85\x98", + "\xBC\xC8" => "\xEC\x85\x9C", + "\xBC\xC9" => "\xEC\x85\xA4", + "\xBC\xCA" => "\xEC\x85\xA5", + "\xBC\xCB" => "\xEC\x85\xA7", + "\xBC\xCC" => "\xEC\x85\xA8", + "\xBC\xCD" => "\xEC\x85\xA9", + "\xBC\xCE" => "\xEC\x85\xB0", + "\xBC\xCF" => "\xEC\x85\xB4", + "\xBC\xD0" => "\xEC\x85\xB8", + "\xBC\xD1" => "\xEC\x86\x85", + "\xBC\xD2" => "\xEC\x86\x8C", + "\xBC\xD3" => "\xEC\x86\x8D", + "\xBC\xD4" => "\xEC\x86\x8E", + "\xBC\xD5" => "\xEC\x86\x90", + "\xBC\xD6" => "\xEC\x86\x94", + "\xBC\xD7" => "\xEC\x86\x96", + "\xBC\xD8" => "\xEC\x86\x9C", + "\xBC\xD9" => "\xEC\x86\x9D", + "\xBC\xDA" => "\xEC\x86\x9F", + "\xBC\xDB" => "\xEC\x86\xA1", + "\xBC\xDC" => "\xEC\x86\xA5", + "\xBC\xDD" => "\xEC\x86\xA8", + "\xBC\xDE" => "\xEC\x86\xA9", + "\xBC\xDF" => "\xEC\x86\xAC", + "\xBC\xE0" => "\xEC\x86\xB0", + "\xBC\xE1" => "\xEC\x86\xBD", + "\xBC\xE2" => "\xEC\x87\x84", + "\xBC\xE3" => "\xEC\x87\x88", + "\xBC\xE4" => "\xEC\x87\x8C", + "\xBC\xE5" => "\xEC\x87\x94", + "\xBC\xE6" => "\xEC\x87\x97", + "\xBC\xE7" => "\xEC\x87\x98", + "\xBC\xE8" => "\xEC\x87\xA0", + "\xBC\xE9" => "\xEC\x87\xA4", + "\xBC\xEA" => "\xEC\x87\xA8", + "\xBC\xEB" => "\xEC\x87\xB0", + "\xBC\xEC" => "\xEC\x87\xB1", + "\xBC\xED" => "\xEC\x87\xB3", + "\xBC\xEE" => "\xEC\x87\xBC", + "\xBC\xEF" => "\xEC\x87\xBD", + "\xBC\xF0" => "\xEC\x88\x80", + "\xBC\xF1" => "\xEC\x88\x84", + "\xBC\xF2" => "\xEC\x88\x8C", + "\xBC\xF3" => "\xEC\x88\x8D", + "\xBC\xF4" => "\xEC\x88\x8F", + "\xBC\xF5" => "\xEC\x88\x91", + "\xBC\xF6" => "\xEC\x88\x98", + "\xBC\xF7" => "\xEC\x88\x99", + "\xBC\xF8" => "\xEC\x88\x9C", + "\xBC\xF9" => "\xEC\x88\x9F", + "\xBC\xFA" => "\xEC\x88\xA0", + "\xBC\xFB" => "\xEC\x88\xA8", + "\xBC\xFC" => "\xEC\x88\xA9", + "\xBC\xFD" => "\xEC\x88\xAB", + "\xBC\xFE" => "\xEC\x88\xAD", + "\xBD\x41" => "\xED\x8F\x97", + "\xBD\x42" => "\xED\x8F\x99", + "\xBD\x43" => "\xED\x8F\x9A", + "\xBD\x44" => "\xED\x8F\x9B", + "\xBD\x45" => "\xED\x8F\x9C", + "\xBD\x46" => "\xED\x8F\x9D", + "\xBD\x47" => "\xED\x8F\x9E", + "\xBD\x48" => "\xED\x8F\x9F", + "\xBD\x49" => "\xED\x8F\xA0", + "\xBD\x4A" => "\xED\x8F\xA2", + "\xBD\x4B" => "\xED\x8F\xA4", + "\xBD\x4C" => "\xED\x8F\xA5", + "\xBD\x4D" => "\xED\x8F\xA6", + "\xBD\x4E" => "\xED\x8F\xA7", + "\xBD\x4F" => "\xED\x8F\xA8", + "\xBD\x50" => "\xED\x8F\xA9", + "\xBD\x51" => "\xED\x8F\xAA", + "\xBD\x52" => "\xED\x8F\xAB", + "\xBD\x53" => "\xED\x8F\xAE", + "\xBD\x54" => "\xED\x8F\xAF", + "\xBD\x55" => "\xED\x8F\xB1", + "\xBD\x56" => "\xED\x8F\xB2", + "\xBD\x57" => "\xED\x8F\xB3", + "\xBD\x58" => "\xED\x8F\xB5", + "\xBD\x59" => "\xED\x8F\xB6", + "\xBD\x5A" => "\xED\x8F\xB7", + "\xBD\x61" => "\xED\x8F\xB8", + "\xBD\x62" => "\xED\x8F\xB9", + "\xBD\x63" => "\xED\x8F\xBA", + "\xBD\x64" => "\xED\x8F\xBB", + "\xBD\x65" => "\xED\x8F\xBE", + "\xBD\x66" => "\xED\x90\x80", + "\xBD\x67" => "\xED\x90\x82", + "\xBD\x68" => "\xED\x90\x83", + "\xBD\x69" => "\xED\x90\x84", + "\xBD\x6A" => "\xED\x90\x85", + "\xBD\x6B" => "\xED\x90\x86", + "\xBD\x6C" => "\xED\x90\x87", + "\xBD\x6D" => "\xED\x90\x89", + "\xBD\x6E" => "\xED\x90\x8A", + "\xBD\x6F" => "\xED\x90\x8B", + "\xBD\x70" => "\xED\x90\x8C", + "\xBD\x71" => "\xED\x90\x8D", + "\xBD\x72" => "\xED\x90\x8E", + "\xBD\x73" => "\xED\x90\x8F", + "\xBD\x74" => "\xED\x90\x90", + "\xBD\x75" => "\xED\x90\x91", + "\xBD\x76" => "\xED\x90\x92", + "\xBD\x77" => "\xED\x90\x93", + "\xBD\x78" => "\xED\x90\x94", + "\xBD\x79" => "\xED\x90\x95", + "\xBD\x7A" => "\xED\x90\x96", + "\xBD\x81" => "\xED\x90\x97", + "\xBD\x82" => "\xED\x90\x98", + "\xBD\x83" => "\xED\x90\x99", + "\xBD\x84" => "\xED\x90\x9A", + "\xBD\x85" => "\xED\x90\x9B", + "\xBD\x86" => "\xED\x90\x9C", + "\xBD\x87" => "\xED\x90\x9E", + "\xBD\x88" => "\xED\x90\x9F", + "\xBD\x89" => "\xED\x90\xA0", + "\xBD\x8A" => "\xED\x90\xA1", + "\xBD\x8B" => "\xED\x90\xA2", + "\xBD\x8C" => "\xED\x90\xA3", + "\xBD\x8D" => "\xED\x90\xA4", + "\xBD\x8E" => "\xED\x90\xA5", + "\xBD\x8F" => "\xED\x90\xA6", + "\xBD\x90" => "\xED\x90\xA7", + "\xBD\x91" => "\xED\x90\xA8", + "\xBD\x92" => "\xED\x90\xA9", + "\xBD\x93" => "\xED\x90\xAA", + "\xBD\x94" => "\xED\x90\xAB", + "\xBD\x95" => "\xED\x90\xAC", + "\xBD\x96" => "\xED\x90\xAD", + "\xBD\x97" => "\xED\x90\xAE", + "\xBD\x98" => "\xED\x90\xAF", + "\xBD\x99" => "\xED\x90\xB0", + "\xBD\x9A" => "\xED\x90\xB1", + "\xBD\x9B" => "\xED\x90\xB2", + "\xBD\x9C" => "\xED\x90\xB3", + "\xBD\x9D" => "\xED\x90\xB4", + "\xBD\x9E" => "\xED\x90\xB5", + "\xBD\x9F" => "\xED\x90\xB6", + "\xBD\xA0" => "\xED\x90\xB7", + "\xBD\xA1" => "\xEC\x88\xAF", + "\xBD\xA2" => "\xEC\x88\xB1", + "\xBD\xA3" => "\xEC\x88\xB2", + "\xBD\xA4" => "\xEC\x88\xB4", + "\xBD\xA5" => "\xEC\x89\x88", + "\xBD\xA6" => "\xEC\x89\x90", + "\xBD\xA7" => "\xEC\x89\x91", + "\xBD\xA8" => "\xEC\x89\x94", + "\xBD\xA9" => "\xEC\x89\x98", + "\xBD\xAA" => "\xEC\x89\xA0", + "\xBD\xAB" => "\xEC\x89\xA5", + "\xBD\xAC" => "\xEC\x89\xAC", + "\xBD\xAD" => "\xEC\x89\xAD", + "\xBD\xAE" => "\xEC\x89\xB0", + "\xBD\xAF" => "\xEC\x89\xB4", + "\xBD\xB0" => "\xEC\x89\xBC", + "\xBD\xB1" => "\xEC\x89\xBD", + "\xBD\xB2" => "\xEC\x89\xBF", + "\xBD\xB3" => "\xEC\x8A\x81", + "\xBD\xB4" => "\xEC\x8A\x88", + "\xBD\xB5" => "\xEC\x8A\x89", + "\xBD\xB6" => "\xEC\x8A\x90", + "\xBD\xB7" => "\xEC\x8A\x98", + "\xBD\xB8" => "\xEC\x8A\x9B", + "\xBD\xB9" => "\xEC\x8A\x9D", + "\xBD\xBA" => "\xEC\x8A\xA4", + "\xBD\xBB" => "\xEC\x8A\xA5", + "\xBD\xBC" => "\xEC\x8A\xA8", + "\xBD\xBD" => "\xEC\x8A\xAC", + "\xBD\xBE" => "\xEC\x8A\xAD", + "\xBD\xBF" => "\xEC\x8A\xB4", + "\xBD\xC0" => "\xEC\x8A\xB5", + "\xBD\xC1" => "\xEC\x8A\xB7", + "\xBD\xC2" => "\xEC\x8A\xB9", + "\xBD\xC3" => "\xEC\x8B\x9C", + "\xBD\xC4" => "\xEC\x8B\x9D", + "\xBD\xC5" => "\xEC\x8B\xA0", + "\xBD\xC6" => "\xEC\x8B\xA3", + "\xBD\xC7" => "\xEC\x8B\xA4", + "\xBD\xC8" => "\xEC\x8B\xAB", + "\xBD\xC9" => "\xEC\x8B\xAC", + "\xBD\xCA" => "\xEC\x8B\xAD", + "\xBD\xCB" => "\xEC\x8B\xAF", + "\xBD\xCC" => "\xEC\x8B\xB1", + "\xBD\xCD" => "\xEC\x8B\xB6", + "\xBD\xCE" => "\xEC\x8B\xB8", + "\xBD\xCF" => "\xEC\x8B\xB9", + "\xBD\xD0" => "\xEC\x8B\xBB", + "\xBD\xD1" => "\xEC\x8B\xBC", + "\xBD\xD2" => "\xEC\x8C\x80", + "\xBD\xD3" => "\xEC\x8C\x88", + "\xBD\xD4" => "\xEC\x8C\x89", + "\xBD\xD5" => "\xEC\x8C\x8C", + "\xBD\xD6" => "\xEC\x8C\x8D", + "\xBD\xD7" => "\xEC\x8C\x93", + "\xBD\xD8" => "\xEC\x8C\x94", + "\xBD\xD9" => "\xEC\x8C\x95", + "\xBD\xDA" => "\xEC\x8C\x98", + "\xBD\xDB" => "\xEC\x8C\x9C", + "\xBD\xDC" => "\xEC\x8C\xA4", + "\xBD\xDD" => "\xEC\x8C\xA5", + "\xBD\xDE" => "\xEC\x8C\xA8", + "\xBD\xDF" => "\xEC\x8C\xA9", + "\xBD\xE0" => "\xEC\x8D\x85", + "\xBD\xE1" => "\xEC\x8D\xA8", + "\xBD\xE2" => "\xEC\x8D\xA9", + "\xBD\xE3" => "\xEC\x8D\xAC", + "\xBD\xE4" => "\xEC\x8D\xB0", + "\xBD\xE5" => "\xEC\x8D\xB2", + "\xBD\xE6" => "\xEC\x8D\xB8", + "\xBD\xE7" => "\xEC\x8D\xB9", + "\xBD\xE8" => "\xEC\x8D\xBC", + "\xBD\xE9" => "\xEC\x8D\xBD", + "\xBD\xEA" => "\xEC\x8E\x84", + "\xBD\xEB" => "\xEC\x8E\x88", + "\xBD\xEC" => "\xEC\x8E\x8C", + "\xBD\xED" => "\xEC\x8F\x80", + "\xBD\xEE" => "\xEC\x8F\x98", + "\xBD\xEF" => "\xEC\x8F\x99", + "\xBD\xF0" => "\xEC\x8F\x9C", + "\xBD\xF1" => "\xEC\x8F\x9F", + "\xBD\xF2" => "\xEC\x8F\xA0", + "\xBD\xF3" => "\xEC\x8F\xA2", + "\xBD\xF4" => "\xEC\x8F\xA8", + "\xBD\xF5" => "\xEC\x8F\xA9", + "\xBD\xF6" => "\xEC\x8F\xAD", + "\xBD\xF7" => "\xEC\x8F\xB4", + "\xBD\xF8" => "\xEC\x8F\xB5", + "\xBD\xF9" => "\xEC\x8F\xB8", + "\xBD\xFA" => "\xEC\x90\x88", + "\xBD\xFB" => "\xEC\x90\x90", + "\xBD\xFC" => "\xEC\x90\xA4", + "\xBD\xFD" => "\xEC\x90\xAC", + "\xBD\xFE" => "\xEC\x90\xB0", + "\xBE\x41" => "\xED\x90\xB8", + "\xBE\x42" => "\xED\x90\xB9", + "\xBE\x43" => "\xED\x90\xBA", + "\xBE\x44" => "\xED\x90\xBB", + "\xBE\x45" => "\xED\x90\xBC", + "\xBE\x46" => "\xED\x90\xBD", + "\xBE\x47" => "\xED\x90\xBE", + "\xBE\x48" => "\xED\x90\xBF", + "\xBE\x49" => "\xED\x91\x81", + "\xBE\x4A" => "\xED\x91\x82", + "\xBE\x4B" => "\xED\x91\x83", + "\xBE\x4C" => "\xED\x91\x85", + "\xBE\x4D" => "\xED\x91\x86", + "\xBE\x4E" => "\xED\x91\x87", + "\xBE\x4F" => "\xED\x91\x88", + "\xBE\x50" => "\xED\x91\x89", + "\xBE\x51" => "\xED\x91\x8A", + "\xBE\x52" => "\xED\x91\x8B", + "\xBE\x53" => "\xED\x91\x8C", + "\xBE\x54" => "\xED\x91\x8D", + "\xBE\x55" => "\xED\x91\x8E", + "\xBE\x56" => "\xED\x91\x8F", + "\xBE\x57" => "\xED\x91\x90", + "\xBE\x58" => "\xED\x91\x91", + "\xBE\x59" => "\xED\x91\x92", + "\xBE\x5A" => "\xED\x91\x93", + "\xBE\x61" => "\xED\x91\x94", + "\xBE\x62" => "\xED\x91\x95", + "\xBE\x63" => "\xED\x91\x96", + "\xBE\x64" => "\xED\x91\x97", + "\xBE\x65" => "\xED\x91\x98", + "\xBE\x66" => "\xED\x91\x99", + "\xBE\x67" => "\xED\x91\x9A", + "\xBE\x68" => "\xED\x91\x9B", + "\xBE\x69" => "\xED\x91\x9D", + "\xBE\x6A" => "\xED\x91\x9E", + "\xBE\x6B" => "\xED\x91\x9F", + "\xBE\x6C" => "\xED\x91\xA1", + "\xBE\x6D" => "\xED\x91\xA2", + "\xBE\x6E" => "\xED\x91\xA3", + "\xBE\x6F" => "\xED\x91\xA5", + "\xBE\x70" => "\xED\x91\xA6", + "\xBE\x71" => "\xED\x91\xA7", + "\xBE\x72" => "\xED\x91\xA8", + "\xBE\x73" => "\xED\x91\xA9", + "\xBE\x74" => "\xED\x91\xAA", + "\xBE\x75" => "\xED\x91\xAB", + "\xBE\x76" => "\xED\x91\xAC", + "\xBE\x77" => "\xED\x91\xAE", + "\xBE\x78" => "\xED\x91\xB0", + "\xBE\x79" => "\xED\x91\xB1", + "\xBE\x7A" => "\xED\x91\xB2", + "\xBE\x81" => "\xED\x91\xB3", + "\xBE\x82" => "\xED\x91\xB4", + "\xBE\x83" => "\xED\x91\xB5", + "\xBE\x84" => "\xED\x91\xB6", + "\xBE\x85" => "\xED\x91\xB7", + "\xBE\x86" => "\xED\x91\xBA", + "\xBE\x87" => "\xED\x91\xBB", + "\xBE\x88" => "\xED\x91\xBD", + "\xBE\x89" => "\xED\x91\xBE", + "\xBE\x8A" => "\xED\x92\x81", + "\xBE\x8B" => "\xED\x92\x83", + "\xBE\x8C" => "\xED\x92\x84", + "\xBE\x8D" => "\xED\x92\x85", + "\xBE\x8E" => "\xED\x92\x86", + "\xBE\x8F" => "\xED\x92\x87", + "\xBE\x90" => "\xED\x92\x8A", + "\xBE\x91" => "\xED\x92\x8C", + "\xBE\x92" => "\xED\x92\x8E", + "\xBE\x93" => "\xED\x92\x8F", + "\xBE\x94" => "\xED\x92\x90", + "\xBE\x95" => "\xED\x92\x91", + "\xBE\x96" => "\xED\x92\x92", + "\xBE\x97" => "\xED\x92\x93", + "\xBE\x98" => "\xED\x92\x95", + "\xBE\x99" => "\xED\x92\x96", + "\xBE\x9A" => "\xED\x92\x97", + "\xBE\x9B" => "\xED\x92\x98", + "\xBE\x9C" => "\xED\x92\x99", + "\xBE\x9D" => "\xED\x92\x9A", + "\xBE\x9E" => "\xED\x92\x9B", + "\xBE\x9F" => "\xED\x92\x9C", + "\xBE\xA0" => "\xED\x92\x9D", + "\xBE\xA1" => "\xEC\x90\xB4", + "\xBE\xA2" => "\xEC\x90\xBC", + "\xBE\xA3" => "\xEC\x90\xBD", + "\xBE\xA4" => "\xEC\x91\x88", + "\xBE\xA5" => "\xEC\x91\xA4", + "\xBE\xA6" => "\xEC\x91\xA5", + "\xBE\xA7" => "\xEC\x91\xA8", + "\xBE\xA8" => "\xEC\x91\xAC", + "\xBE\xA9" => "\xEC\x91\xB4", + "\xBE\xAA" => "\xEC\x91\xB5", + "\xBE\xAB" => "\xEC\x91\xB9", + "\xBE\xAC" => "\xEC\x92\x80", + "\xBE\xAD" => "\xEC\x92\x94", + "\xBE\xAE" => "\xEC\x92\x9C", + "\xBE\xAF" => "\xEC\x92\xB8", + "\xBE\xB0" => "\xEC\x92\xBC", + "\xBE\xB1" => "\xEC\x93\xA9", + "\xBE\xB2" => "\xEC\x93\xB0", + "\xBE\xB3" => "\xEC\x93\xB1", + "\xBE\xB4" => "\xEC\x93\xB4", + "\xBE\xB5" => "\xEC\x93\xB8", + "\xBE\xB6" => "\xEC\x93\xBA", + "\xBE\xB7" => "\xEC\x93\xBF", + "\xBE\xB8" => "\xEC\x94\x80", + "\xBE\xB9" => "\xEC\x94\x81", + "\xBE\xBA" => "\xEC\x94\x8C", + "\xBE\xBB" => "\xEC\x94\x90", + "\xBE\xBC" => "\xEC\x94\x94", + "\xBE\xBD" => "\xEC\x94\x9C", + "\xBE\xBE" => "\xEC\x94\xA8", + "\xBE\xBF" => "\xEC\x94\xA9", + "\xBE\xC0" => "\xEC\x94\xAC", + "\xBE\xC1" => "\xEC\x94\xB0", + "\xBE\xC2" => "\xEC\x94\xB8", + "\xBE\xC3" => "\xEC\x94\xB9", + "\xBE\xC4" => "\xEC\x94\xBB", + "\xBE\xC5" => "\xEC\x94\xBD", + "\xBE\xC6" => "\xEC\x95\x84", + "\xBE\xC7" => "\xEC\x95\x85", + "\xBE\xC8" => "\xEC\x95\x88", + "\xBE\xC9" => "\xEC\x95\x89", + "\xBE\xCA" => "\xEC\x95\x8A", + "\xBE\xCB" => "\xEC\x95\x8C", + "\xBE\xCC" => "\xEC\x95\x8D", + "\xBE\xCD" => "\xEC\x95\x8E", + "\xBE\xCE" => "\xEC\x95\x93", + "\xBE\xCF" => "\xEC\x95\x94", + "\xBE\xD0" => "\xEC\x95\x95", + "\xBE\xD1" => "\xEC\x95\x97", + "\xBE\xD2" => "\xEC\x95\x98", + "\xBE\xD3" => "\xEC\x95\x99", + "\xBE\xD4" => "\xEC\x95\x9D", + "\xBE\xD5" => "\xEC\x95\x9E", + "\xBE\xD6" => "\xEC\x95\xA0", + "\xBE\xD7" => "\xEC\x95\xA1", + "\xBE\xD8" => "\xEC\x95\xA4", + "\xBE\xD9" => "\xEC\x95\xA8", + "\xBE\xDA" => "\xEC\x95\xB0", + "\xBE\xDB" => "\xEC\x95\xB1", + "\xBE\xDC" => "\xEC\x95\xB3", + "\xBE\xDD" => "\xEC\x95\xB4", + "\xBE\xDE" => "\xEC\x95\xB5", + "\xBE\xDF" => "\xEC\x95\xBC", + "\xBE\xE0" => "\xEC\x95\xBD", + "\xBE\xE1" => "\xEC\x96\x80", + "\xBE\xE2" => "\xEC\x96\x84", + "\xBE\xE3" => "\xEC\x96\x87", + "\xBE\xE4" => "\xEC\x96\x8C", + "\xBE\xE5" => "\xEC\x96\x8D", + "\xBE\xE6" => "\xEC\x96\x8F", + "\xBE\xE7" => "\xEC\x96\x91", + "\xBE\xE8" => "\xEC\x96\x95", + "\xBE\xE9" => "\xEC\x96\x97", + "\xBE\xEA" => "\xEC\x96\x98", + "\xBE\xEB" => "\xEC\x96\x9C", + "\xBE\xEC" => "\xEC\x96\xA0", + "\xBE\xED" => "\xEC\x96\xA9", + "\xBE\xEE" => "\xEC\x96\xB4", + "\xBE\xEF" => "\xEC\x96\xB5", + "\xBE\xF0" => "\xEC\x96\xB8", + "\xBE\xF1" => "\xEC\x96\xB9", + "\xBE\xF2" => "\xEC\x96\xBB", + "\xBE\xF3" => "\xEC\x96\xBC", + "\xBE\xF4" => "\xEC\x96\xBD", + "\xBE\xF5" => "\xEC\x96\xBE", + "\xBE\xF6" => "\xEC\x97\x84", + "\xBE\xF7" => "\xEC\x97\x85", + "\xBE\xF8" => "\xEC\x97\x86", + "\xBE\xF9" => "\xEC\x97\x87", + "\xBE\xFA" => "\xEC\x97\x88", + "\xBE\xFB" => "\xEC\x97\x89", + "\xBE\xFC" => "\xEC\x97\x8A", + "\xBE\xFD" => "\xEC\x97\x8C", + "\xBE\xFE" => "\xEC\x97\x8E", + "\xBF\x41" => "\xED\x92\x9E", + "\xBF\x42" => "\xED\x92\x9F", + "\xBF\x43" => "\xED\x92\xA0", + "\xBF\x44" => "\xED\x92\xA1", + "\xBF\x45" => "\xED\x92\xA2", + "\xBF\x46" => "\xED\x92\xA3", + "\xBF\x47" => "\xED\x92\xA4", + "\xBF\x48" => "\xED\x92\xA5", + "\xBF\x49" => "\xED\x92\xA6", + "\xBF\x4A" => "\xED\x92\xA7", + "\xBF\x4B" => "\xED\x92\xA8", + "\xBF\x4C" => "\xED\x92\xAA", + "\xBF\x4D" => "\xED\x92\xAB", + "\xBF\x4E" => "\xED\x92\xAC", + "\xBF\x4F" => "\xED\x92\xAD", + "\xBF\x50" => "\xED\x92\xAE", + "\xBF\x51" => "\xED\x92\xAF", + "\xBF\x52" => "\xED\x92\xB0", + "\xBF\x53" => "\xED\x92\xB1", + "\xBF\x54" => "\xED\x92\xB2", + "\xBF\x55" => "\xED\x92\xB3", + "\xBF\x56" => "\xED\x92\xB4", + "\xBF\x57" => "\xED\x92\xB5", + "\xBF\x58" => "\xED\x92\xB6", + "\xBF\x59" => "\xED\x92\xB7", + "\xBF\x5A" => "\xED\x92\xB8", + "\xBF\x61" => "\xED\x92\xB9", + "\xBF\x62" => "\xED\x92\xBA", + "\xBF\x63" => "\xED\x92\xBB", + "\xBF\x64" => "\xED\x92\xBC", + "\xBF\x65" => "\xED\x92\xBD", + "\xBF\x66" => "\xED\x92\xBE", + "\xBF\x67" => "\xED\x92\xBF", + "\xBF\x68" => "\xED\x93\x80", + "\xBF\x69" => "\xED\x93\x81", + "\xBF\x6A" => "\xED\x93\x82", + "\xBF\x6B" => "\xED\x93\x83", + "\xBF\x6C" => "\xED\x93\x84", + "\xBF\x6D" => "\xED\x93\x85", + "\xBF\x6E" => "\xED\x93\x86", + "\xBF\x6F" => "\xED\x93\x87", + "\xBF\x70" => "\xED\x93\x88", + "\xBF\x71" => "\xED\x93\x89", + "\xBF\x72" => "\xED\x93\x8A", + "\xBF\x73" => "\xED\x93\x8B", + "\xBF\x74" => "\xED\x93\x8D", + "\xBF\x75" => "\xED\x93\x8E", + "\xBF\x76" => "\xED\x93\x8F", + "\xBF\x77" => "\xED\x93\x91", + "\xBF\x78" => "\xED\x93\x92", + "\xBF\x79" => "\xED\x93\x93", + "\xBF\x7A" => "\xED\x93\x95", + "\xBF\x81" => "\xED\x93\x96", + "\xBF\x82" => "\xED\x93\x97", + "\xBF\x83" => "\xED\x93\x98", + "\xBF\x84" => "\xED\x93\x99", + "\xBF\x85" => "\xED\x93\x9A", + "\xBF\x86" => "\xED\x93\x9B", + "\xBF\x87" => "\xED\x93\x9D", + "\xBF\x88" => "\xED\x93\x9E", + "\xBF\x89" => "\xED\x93\xA0", + "\xBF\x8A" => "\xED\x93\xA1", + "\xBF\x8B" => "\xED\x93\xA2", + "\xBF\x8C" => "\xED\x93\xA3", + "\xBF\x8D" => "\xED\x93\xA4", + "\xBF\x8E" => "\xED\x93\xA5", + "\xBF\x8F" => "\xED\x93\xA6", + "\xBF\x90" => "\xED\x93\xA7", + "\xBF\x91" => "\xED\x93\xA9", + "\xBF\x92" => "\xED\x93\xAA", + "\xBF\x93" => "\xED\x93\xAB", + "\xBF\x94" => "\xED\x93\xAD", + "\xBF\x95" => "\xED\x93\xAE", + "\xBF\x96" => "\xED\x93\xAF", + "\xBF\x97" => "\xED\x93\xB1", + "\xBF\x98" => "\xED\x93\xB2", + "\xBF\x99" => "\xED\x93\xB3", + "\xBF\x9A" => "\xED\x93\xB4", + "\xBF\x9B" => "\xED\x93\xB5", + "\xBF\x9C" => "\xED\x93\xB6", + "\xBF\x9D" => "\xED\x93\xB7", + "\xBF\x9E" => "\xED\x93\xB9", + "\xBF\x9F" => "\xED\x93\xBA", + "\xBF\xA0" => "\xED\x93\xBC", + "\xBF\xA1" => "\xEC\x97\x90", + "\xBF\xA2" => "\xEC\x97\x91", + "\xBF\xA3" => "\xEC\x97\x94", + "\xBF\xA4" => "\xEC\x97\x98", + "\xBF\xA5" => "\xEC\x97\xA0", + "\xBF\xA6" => "\xEC\x97\xA1", + "\xBF\xA7" => "\xEC\x97\xA3", + "\xBF\xA8" => "\xEC\x97\xA5", + "\xBF\xA9" => "\xEC\x97\xAC", + "\xBF\xAA" => "\xEC\x97\xAD", + "\xBF\xAB" => "\xEC\x97\xAE", + "\xBF\xAC" => "\xEC\x97\xB0", + "\xBF\xAD" => "\xEC\x97\xB4", + "\xBF\xAE" => "\xEC\x97\xB6", + "\xBF\xAF" => "\xEC\x97\xB7", + "\xBF\xB0" => "\xEC\x97\xBC", + "\xBF\xB1" => "\xEC\x97\xBD", + "\xBF\xB2" => "\xEC\x97\xBE", + "\xBF\xB3" => "\xEC\x97\xBF", + "\xBF\xB4" => "\xEC\x98\x80", + "\xBF\xB5" => "\xEC\x98\x81", + "\xBF\xB6" => "\xEC\x98\x85", + "\xBF\xB7" => "\xEC\x98\x86", + "\xBF\xB8" => "\xEC\x98\x87", + "\xBF\xB9" => "\xEC\x98\x88", + "\xBF\xBA" => "\xEC\x98\x8C", + "\xBF\xBB" => "\xEC\x98\x90", + "\xBF\xBC" => "\xEC\x98\x98", + "\xBF\xBD" => "\xEC\x98\x99", + "\xBF\xBE" => "\xEC\x98\x9B", + "\xBF\xBF" => "\xEC\x98\x9C", + "\xBF\xC0" => "\xEC\x98\xA4", + "\xBF\xC1" => "\xEC\x98\xA5", + "\xBF\xC2" => "\xEC\x98\xA8", + "\xBF\xC3" => "\xEC\x98\xAC", + "\xBF\xC4" => "\xEC\x98\xAD", + "\xBF\xC5" => "\xEC\x98\xAE", + "\xBF\xC6" => "\xEC\x98\xB0", + "\xBF\xC7" => "\xEC\x98\xB3", + "\xBF\xC8" => "\xEC\x98\xB4", + "\xBF\xC9" => "\xEC\x98\xB5", + "\xBF\xCA" => "\xEC\x98\xB7", + "\xBF\xCB" => "\xEC\x98\xB9", + "\xBF\xCC" => "\xEC\x98\xBB", + "\xBF\xCD" => "\xEC\x99\x80", + "\xBF\xCE" => "\xEC\x99\x81", + "\xBF\xCF" => "\xEC\x99\x84", + "\xBF\xD0" => "\xEC\x99\x88", + "\xBF\xD1" => "\xEC\x99\x90", + "\xBF\xD2" => "\xEC\x99\x91", + "\xBF\xD3" => "\xEC\x99\x93", + "\xBF\xD4" => "\xEC\x99\x94", + "\xBF\xD5" => "\xEC\x99\x95", + "\xBF\xD6" => "\xEC\x99\x9C", + "\xBF\xD7" => "\xEC\x99\x9D", + "\xBF\xD8" => "\xEC\x99\xA0", + "\xBF\xD9" => "\xEC\x99\xAC", + "\xBF\xDA" => "\xEC\x99\xAF", + "\xBF\xDB" => "\xEC\x99\xB1", + "\xBF\xDC" => "\xEC\x99\xB8", + "\xBF\xDD" => "\xEC\x99\xB9", + "\xBF\xDE" => "\xEC\x99\xBC", + "\xBF\xDF" => "\xEC\x9A\x80", + "\xBF\xE0" => "\xEC\x9A\x88", + "\xBF\xE1" => "\xEC\x9A\x89", + "\xBF\xE2" => "\xEC\x9A\x8B", + "\xBF\xE3" => "\xEC\x9A\x8D", + "\xBF\xE4" => "\xEC\x9A\x94", + "\xBF\xE5" => "\xEC\x9A\x95", + "\xBF\xE6" => "\xEC\x9A\x98", + "\xBF\xE7" => "\xEC\x9A\x9C", + "\xBF\xE8" => "\xEC\x9A\xA4", + "\xBF\xE9" => "\xEC\x9A\xA5", + "\xBF\xEA" => "\xEC\x9A\xA7", + "\xBF\xEB" => "\xEC\x9A\xA9", + "\xBF\xEC" => "\xEC\x9A\xB0", + "\xBF\xED" => "\xEC\x9A\xB1", + "\xBF\xEE" => "\xEC\x9A\xB4", + "\xBF\xEF" => "\xEC\x9A\xB8", + "\xBF\xF0" => "\xEC\x9A\xB9", + "\xBF\xF1" => "\xEC\x9A\xBA", + "\xBF\xF2" => "\xEC\x9B\x80", + "\xBF\xF3" => "\xEC\x9B\x81", + "\xBF\xF4" => "\xEC\x9B\x83", + "\xBF\xF5" => "\xEC\x9B\x85", + "\xBF\xF6" => "\xEC\x9B\x8C", + "\xBF\xF7" => "\xEC\x9B\x8D", + "\xBF\xF8" => "\xEC\x9B\x90", + "\xBF\xF9" => "\xEC\x9B\x94", + "\xBF\xFA" => "\xEC\x9B\x9C", + "\xBF\xFB" => "\xEC\x9B\x9D", + "\xBF\xFC" => "\xEC\x9B\xA0", + "\xBF\xFD" => "\xEC\x9B\xA1", + "\xBF\xFE" => "\xEC\x9B\xA8", + "\xC0\x41" => "\xED\x93\xBE", + "\xC0\x42" => "\xED\x93\xBF", + "\xC0\x43" => "\xED\x94\x80", + "\xC0\x44" => "\xED\x94\x81", + "\xC0\x45" => "\xED\x94\x82", + "\xC0\x46" => "\xED\x94\x83", + "\xC0\x47" => "\xED\x94\x85", + "\xC0\x48" => "\xED\x94\x86", + "\xC0\x49" => "\xED\x94\x87", + "\xC0\x4A" => "\xED\x94\x89", + "\xC0\x4B" => "\xED\x94\x8A", + "\xC0\x4C" => "\xED\x94\x8B", + "\xC0\x4D" => "\xED\x94\x8D", + "\xC0\x4E" => "\xED\x94\x8E", + "\xC0\x4F" => "\xED\x94\x8F", + "\xC0\x50" => "\xED\x94\x90", + "\xC0\x51" => "\xED\x94\x91", + "\xC0\x52" => "\xED\x94\x92", + "\xC0\x53" => "\xED\x94\x93", + "\xC0\x54" => "\xED\x94\x96", + "\xC0\x55" => "\xED\x94\x98", + "\xC0\x56" => "\xED\x94\x99", + "\xC0\x57" => "\xED\x94\x9A", + "\xC0\x58" => "\xED\x94\x9B", + "\xC0\x59" => "\xED\x94\x9C", + "\xC0\x5A" => "\xED\x94\x9D", + "\xC0\x61" => "\xED\x94\x9E", + "\xC0\x62" => "\xED\x94\x9F", + "\xC0\x63" => "\xED\x94\xA0", + "\xC0\x64" => "\xED\x94\xA1", + "\xC0\x65" => "\xED\x94\xA2", + "\xC0\x66" => "\xED\x94\xA3", + "\xC0\x67" => "\xED\x94\xA4", + "\xC0\x68" => "\xED\x94\xA5", + "\xC0\x69" => "\xED\x94\xA6", + "\xC0\x6A" => "\xED\x94\xA7", + "\xC0\x6B" => "\xED\x94\xA8", + "\xC0\x6C" => "\xED\x94\xA9", + "\xC0\x6D" => "\xED\x94\xAA", + "\xC0\x6E" => "\xED\x94\xAB", + "\xC0\x6F" => "\xED\x94\xAC", + "\xC0\x70" => "\xED\x94\xAD", + "\xC0\x71" => "\xED\x94\xAE", + "\xC0\x72" => "\xED\x94\xAF", + "\xC0\x73" => "\xED\x94\xB0", + "\xC0\x74" => "\xED\x94\xB1", + "\xC0\x75" => "\xED\x94\xB2", + "\xC0\x76" => "\xED\x94\xB3", + "\xC0\x77" => "\xED\x94\xB4", + "\xC0\x78" => "\xED\x94\xB5", + "\xC0\x79" => "\xED\x94\xB6", + "\xC0\x7A" => "\xED\x94\xB7", + "\xC0\x81" => "\xED\x94\xB8", + "\xC0\x82" => "\xED\x94\xB9", + "\xC0\x83" => "\xED\x94\xBA", + "\xC0\x84" => "\xED\x94\xBB", + "\xC0\x85" => "\xED\x94\xBE", + "\xC0\x86" => "\xED\x94\xBF", + "\xC0\x87" => "\xED\x95\x81", + "\xC0\x88" => "\xED\x95\x82", + "\xC0\x89" => "\xED\x95\x83", + "\xC0\x8A" => "\xED\x95\x85", + "\xC0\x8B" => "\xED\x95\x86", + "\xC0\x8C" => "\xED\x95\x87", + "\xC0\x8D" => "\xED\x95\x88", + "\xC0\x8E" => "\xED\x95\x89", + "\xC0\x8F" => "\xED\x95\x8A", + "\xC0\x90" => "\xED\x95\x8B", + "\xC0\x91" => "\xED\x95\x8E", + "\xC0\x92" => "\xED\x95\x90", + "\xC0\x93" => "\xED\x95\x92", + "\xC0\x94" => "\xED\x95\x93", + "\xC0\x95" => "\xED\x95\x94", + "\xC0\x96" => "\xED\x95\x95", + "\xC0\x97" => "\xED\x95\x96", + "\xC0\x98" => "\xED\x95\x97", + "\xC0\x99" => "\xED\x95\x9A", + "\xC0\x9A" => "\xED\x95\x9B", + "\xC0\x9B" => "\xED\x95\x9D", + "\xC0\x9C" => "\xED\x95\x9E", + "\xC0\x9D" => "\xED\x95\x9F", + "\xC0\x9E" => "\xED\x95\xA1", + "\xC0\x9F" => "\xED\x95\xA2", + "\xC0\xA0" => "\xED\x95\xA3", + "\xC0\xA1" => "\xEC\x9B\xA9", + "\xC0\xA2" => "\xEC\x9B\xAC", + "\xC0\xA3" => "\xEC\x9B\xB0", + "\xC0\xA4" => "\xEC\x9B\xB8", + "\xC0\xA5" => "\xEC\x9B\xB9", + "\xC0\xA6" => "\xEC\x9B\xBD", + "\xC0\xA7" => "\xEC\x9C\x84", + "\xC0\xA8" => "\xEC\x9C\x85", + "\xC0\xA9" => "\xEC\x9C\x88", + "\xC0\xAA" => "\xEC\x9C\x8C", + "\xC0\xAB" => "\xEC\x9C\x94", + "\xC0\xAC" => "\xEC\x9C\x95", + "\xC0\xAD" => "\xEC\x9C\x97", + "\xC0\xAE" => "\xEC\x9C\x99", + "\xC0\xAF" => "\xEC\x9C\xA0", + "\xC0\xB0" => "\xEC\x9C\xA1", + "\xC0\xB1" => "\xEC\x9C\xA4", + "\xC0\xB2" => "\xEC\x9C\xA8", + "\xC0\xB3" => "\xEC\x9C\xB0", + "\xC0\xB4" => "\xEC\x9C\xB1", + "\xC0\xB5" => "\xEC\x9C\xB3", + "\xC0\xB6" => "\xEC\x9C\xB5", + "\xC0\xB7" => "\xEC\x9C\xB7", + "\xC0\xB8" => "\xEC\x9C\xBC", + "\xC0\xB9" => "\xEC\x9C\xBD", + "\xC0\xBA" => "\xEC\x9D\x80", + "\xC0\xBB" => "\xEC\x9D\x84", + "\xC0\xBC" => "\xEC\x9D\x8A", + "\xC0\xBD" => "\xEC\x9D\x8C", + "\xC0\xBE" => "\xEC\x9D\x8D", + "\xC0\xBF" => "\xEC\x9D\x8F", + "\xC0\xC0" => "\xEC\x9D\x91", + "\xC0\xC1" => "\xEC\x9D\x92", + "\xC0\xC2" => "\xEC\x9D\x93", + "\xC0\xC3" => "\xEC\x9D\x94", + "\xC0\xC4" => "\xEC\x9D\x95", + "\xC0\xC5" => "\xEC\x9D\x96", + "\xC0\xC6" => "\xEC\x9D\x97", + "\xC0\xC7" => "\xEC\x9D\x98", + "\xC0\xC8" => "\xEC\x9D\x9C", + "\xC0\xC9" => "\xEC\x9D\xA0", + "\xC0\xCA" => "\xEC\x9D\xA8", + "\xC0\xCB" => "\xEC\x9D\xAB", + "\xC0\xCC" => "\xEC\x9D\xB4", + "\xC0\xCD" => "\xEC\x9D\xB5", + "\xC0\xCE" => "\xEC\x9D\xB8", + "\xC0\xCF" => "\xEC\x9D\xBC", + "\xC0\xD0" => "\xEC\x9D\xBD", + "\xC0\xD1" => "\xEC\x9D\xBE", + "\xC0\xD2" => "\xEC\x9E\x83", + "\xC0\xD3" => "\xEC\x9E\x84", + "\xC0\xD4" => "\xEC\x9E\x85", + "\xC0\xD5" => "\xEC\x9E\x87", + "\xC0\xD6" => "\xEC\x9E\x88", + "\xC0\xD7" => "\xEC\x9E\x89", + "\xC0\xD8" => "\xEC\x9E\x8A", + "\xC0\xD9" => "\xEC\x9E\x8E", + "\xC0\xDA" => "\xEC\x9E\x90", + "\xC0\xDB" => "\xEC\x9E\x91", + "\xC0\xDC" => "\xEC\x9E\x94", + "\xC0\xDD" => "\xEC\x9E\x96", + "\xC0\xDE" => "\xEC\x9E\x97", + "\xC0\xDF" => "\xEC\x9E\x98", + "\xC0\xE0" => "\xEC\x9E\x9A", + "\xC0\xE1" => "\xEC\x9E\xA0", + "\xC0\xE2" => "\xEC\x9E\xA1", + "\xC0\xE3" => "\xEC\x9E\xA3", + "\xC0\xE4" => "\xEC\x9E\xA4", + "\xC0\xE5" => "\xEC\x9E\xA5", + "\xC0\xE6" => "\xEC\x9E\xA6", + "\xC0\xE7" => "\xEC\x9E\xAC", + "\xC0\xE8" => "\xEC\x9E\xAD", + "\xC0\xE9" => "\xEC\x9E\xB0", + "\xC0\xEA" => "\xEC\x9E\xB4", + "\xC0\xEB" => "\xEC\x9E\xBC", + "\xC0\xEC" => "\xEC\x9E\xBD", + "\xC0\xED" => "\xEC\x9E\xBF", + "\xC0\xEE" => "\xEC\x9F\x80", + "\xC0\xEF" => "\xEC\x9F\x81", + "\xC0\xF0" => "\xEC\x9F\x88", + "\xC0\xF1" => "\xEC\x9F\x89", + "\xC0\xF2" => "\xEC\x9F\x8C", + "\xC0\xF3" => "\xEC\x9F\x8E", + "\xC0\xF4" => "\xEC\x9F\x90", + "\xC0\xF5" => "\xEC\x9F\x98", + "\xC0\xF6" => "\xEC\x9F\x9D", + "\xC0\xF7" => "\xEC\x9F\xA4", + "\xC0\xF8" => "\xEC\x9F\xA8", + "\xC0\xF9" => "\xEC\x9F\xAC", + "\xC0\xFA" => "\xEC\xA0\x80", + "\xC0\xFB" => "\xEC\xA0\x81", + "\xC0\xFC" => "\xEC\xA0\x84", + "\xC0\xFD" => "\xEC\xA0\x88", + "\xC0\xFE" => "\xEC\xA0\x8A", + "\xC1\x41" => "\xED\x95\xA4", + "\xC1\x42" => "\xED\x95\xA6", + "\xC1\x43" => "\xED\x95\xA7", + "\xC1\x44" => "\xED\x95\xAA", + "\xC1\x45" => "\xED\x95\xAC", + "\xC1\x46" => "\xED\x95\xAE", + "\xC1\x47" => "\xED\x95\xAF", + "\xC1\x48" => "\xED\x95\xB0", + "\xC1\x49" => "\xED\x95\xB1", + "\xC1\x4A" => "\xED\x95\xB2", + "\xC1\x4B" => "\xED\x95\xB3", + "\xC1\x4C" => "\xED\x95\xB6", + "\xC1\x4D" => "\xED\x95\xB7", + "\xC1\x4E" => "\xED\x95\xB9", + "\xC1\x4F" => "\xED\x95\xBA", + "\xC1\x50" => "\xED\x95\xBB", + "\xC1\x51" => "\xED\x95\xBD", + "\xC1\x52" => "\xED\x95\xBE", + "\xC1\x53" => "\xED\x95\xBF", + "\xC1\x54" => "\xED\x96\x80", + "\xC1\x55" => "\xED\x96\x81", + "\xC1\x56" => "\xED\x96\x82", + "\xC1\x57" => "\xED\x96\x83", + "\xC1\x58" => "\xED\x96\x86", + "\xC1\x59" => "\xED\x96\x8A", + "\xC1\x5A" => "\xED\x96\x8B", + "\xC1\x61" => "\xED\x96\x8C", + "\xC1\x62" => "\xED\x96\x8D", + "\xC1\x63" => "\xED\x96\x8E", + "\xC1\x64" => "\xED\x96\x8F", + "\xC1\x65" => "\xED\x96\x91", + "\xC1\x66" => "\xED\x96\x92", + "\xC1\x67" => "\xED\x96\x93", + "\xC1\x68" => "\xED\x96\x94", + "\xC1\x69" => "\xED\x96\x95", + "\xC1\x6A" => "\xED\x96\x96", + "\xC1\x6B" => "\xED\x96\x97", + "\xC1\x6C" => "\xED\x96\x98", + "\xC1\x6D" => "\xED\x96\x99", + "\xC1\x6E" => "\xED\x96\x9A", + "\xC1\x6F" => "\xED\x96\x9B", + "\xC1\x70" => "\xED\x96\x9C", + "\xC1\x71" => "\xED\x96\x9D", + "\xC1\x72" => "\xED\x96\x9E", + "\xC1\x73" => "\xED\x96\x9F", + "\xC1\x74" => "\xED\x96\xA0", + "\xC1\x75" => "\xED\x96\xA1", + "\xC1\x76" => "\xED\x96\xA2", + "\xC1\x77" => "\xED\x96\xA3", + "\xC1\x78" => "\xED\x96\xA4", + "\xC1\x79" => "\xED\x96\xA6", + "\xC1\x7A" => "\xED\x96\xA7", + "\xC1\x81" => "\xED\x96\xA8", + "\xC1\x82" => "\xED\x96\xA9", + "\xC1\x83" => "\xED\x96\xAA", + "\xC1\x84" => "\xED\x96\xAB", + "\xC1\x85" => "\xED\x96\xAC", + "\xC1\x86" => "\xED\x96\xAD", + "\xC1\x87" => "\xED\x96\xAE", + "\xC1\x88" => "\xED\x96\xAF", + "\xC1\x89" => "\xED\x96\xB0", + "\xC1\x8A" => "\xED\x96\xB1", + "\xC1\x8B" => "\xED\x96\xB2", + "\xC1\x8C" => "\xED\x96\xB3", + "\xC1\x8D" => "\xED\x96\xB4", + "\xC1\x8E" => "\xED\x96\xB5", + "\xC1\x8F" => "\xED\x96\xB6", + "\xC1\x90" => "\xED\x96\xB7", + "\xC1\x91" => "\xED\x96\xB8", + "\xC1\x92" => "\xED\x96\xB9", + "\xC1\x93" => "\xED\x96\xBA", + "\xC1\x94" => "\xED\x96\xBB", + "\xC1\x95" => "\xED\x96\xBC", + "\xC1\x96" => "\xED\x96\xBD", + "\xC1\x97" => "\xED\x96\xBE", + "\xC1\x98" => "\xED\x96\xBF", + "\xC1\x99" => "\xED\x97\x80", + "\xC1\x9A" => "\xED\x97\x81", + "\xC1\x9B" => "\xED\x97\x82", + "\xC1\x9C" => "\xED\x97\x83", + "\xC1\x9D" => "\xED\x97\x84", + "\xC1\x9E" => "\xED\x97\x85", + "\xC1\x9F" => "\xED\x97\x86", + "\xC1\xA0" => "\xED\x97\x87", + "\xC1\xA1" => "\xEC\xA0\x90", + "\xC1\xA2" => "\xEC\xA0\x91", + "\xC1\xA3" => "\xEC\xA0\x93", + "\xC1\xA4" => "\xEC\xA0\x95", + "\xC1\xA5" => "\xEC\xA0\x96", + "\xC1\xA6" => "\xEC\xA0\x9C", + "\xC1\xA7" => "\xEC\xA0\x9D", + "\xC1\xA8" => "\xEC\xA0\xA0", + "\xC1\xA9" => "\xEC\xA0\xA4", + "\xC1\xAA" => "\xEC\xA0\xAC", + "\xC1\xAB" => "\xEC\xA0\xAD", + "\xC1\xAC" => "\xEC\xA0\xAF", + "\xC1\xAD" => "\xEC\xA0\xB1", + "\xC1\xAE" => "\xEC\xA0\xB8", + "\xC1\xAF" => "\xEC\xA0\xBC", + "\xC1\xB0" => "\xEC\xA1\x80", + "\xC1\xB1" => "\xEC\xA1\x88", + "\xC1\xB2" => "\xEC\xA1\x89", + "\xC1\xB3" => "\xEC\xA1\x8C", + "\xC1\xB4" => "\xEC\xA1\x8D", + "\xC1\xB5" => "\xEC\xA1\x94", + "\xC1\xB6" => "\xEC\xA1\xB0", + "\xC1\xB7" => "\xEC\xA1\xB1", + "\xC1\xB8" => "\xEC\xA1\xB4", + "\xC1\xB9" => "\xEC\xA1\xB8", + "\xC1\xBA" => "\xEC\xA1\xBA", + "\xC1\xBB" => "\xEC\xA2\x80", + "\xC1\xBC" => "\xEC\xA2\x81", + "\xC1\xBD" => "\xEC\xA2\x83", + "\xC1\xBE" => "\xEC\xA2\x85", + "\xC1\xBF" => "\xEC\xA2\x86", + "\xC1\xC0" => "\xEC\xA2\x87", + "\xC1\xC1" => "\xEC\xA2\x8B", + "\xC1\xC2" => "\xEC\xA2\x8C", + "\xC1\xC3" => "\xEC\xA2\x8D", + "\xC1\xC4" => "\xEC\xA2\x94", + "\xC1\xC5" => "\xEC\xA2\x9D", + "\xC1\xC6" => "\xEC\xA2\x9F", + "\xC1\xC7" => "\xEC\xA2\xA1", + "\xC1\xC8" => "\xEC\xA2\xA8", + "\xC1\xC9" => "\xEC\xA2\xBC", + "\xC1\xCA" => "\xEC\xA2\xBD", + "\xC1\xCB" => "\xEC\xA3\x84", + "\xC1\xCC" => "\xEC\xA3\x88", + "\xC1\xCD" => "\xEC\xA3\x8C", + "\xC1\xCE" => "\xEC\xA3\x94", + "\xC1\xCF" => "\xEC\xA3\x95", + "\xC1\xD0" => "\xEC\xA3\x97", + "\xC1\xD1" => "\xEC\xA3\x99", + "\xC1\xD2" => "\xEC\xA3\xA0", + "\xC1\xD3" => "\xEC\xA3\xA1", + "\xC1\xD4" => "\xEC\xA3\xA4", + "\xC1\xD5" => "\xEC\xA3\xB5", + "\xC1\xD6" => "\xEC\xA3\xBC", + "\xC1\xD7" => "\xEC\xA3\xBD", + "\xC1\xD8" => "\xEC\xA4\x80", + "\xC1\xD9" => "\xEC\xA4\x84", + "\xC1\xDA" => "\xEC\xA4\x85", + "\xC1\xDB" => "\xEC\xA4\x86", + "\xC1\xDC" => "\xEC\xA4\x8C", + "\xC1\xDD" => "\xEC\xA4\x8D", + "\xC1\xDE" => "\xEC\xA4\x8F", + "\xC1\xDF" => "\xEC\xA4\x91", + "\xC1\xE0" => "\xEC\xA4\x98", + "\xC1\xE1" => "\xEC\xA4\xAC", + "\xC1\xE2" => "\xEC\xA4\xB4", + "\xC1\xE3" => "\xEC\xA5\x90", + "\xC1\xE4" => "\xEC\xA5\x91", + "\xC1\xE5" => "\xEC\xA5\x94", + "\xC1\xE6" => "\xEC\xA5\x98", + "\xC1\xE7" => "\xEC\xA5\xA0", + "\xC1\xE8" => "\xEC\xA5\xA1", + "\xC1\xE9" => "\xEC\xA5\xA3", + "\xC1\xEA" => "\xEC\xA5\xAC", + "\xC1\xEB" => "\xEC\xA5\xB0", + "\xC1\xEC" => "\xEC\xA5\xB4", + "\xC1\xED" => "\xEC\xA5\xBC", + "\xC1\xEE" => "\xEC\xA6\x88", + "\xC1\xEF" => "\xEC\xA6\x89", + "\xC1\xF0" => "\xEC\xA6\x8C", + "\xC1\xF1" => "\xEC\xA6\x90", + "\xC1\xF2" => "\xEC\xA6\x98", + "\xC1\xF3" => "\xEC\xA6\x99", + "\xC1\xF4" => "\xEC\xA6\x9B", + "\xC1\xF5" => "\xEC\xA6\x9D", + "\xC1\xF6" => "\xEC\xA7\x80", + "\xC1\xF7" => "\xEC\xA7\x81", + "\xC1\xF8" => "\xEC\xA7\x84", + "\xC1\xF9" => "\xEC\xA7\x87", + "\xC1\xFA" => "\xEC\xA7\x88", + "\xC1\xFB" => "\xEC\xA7\x8A", + "\xC1\xFC" => "\xEC\xA7\x90", + "\xC1\xFD" => "\xEC\xA7\x91", + "\xC1\xFE" => "\xEC\xA7\x93", + "\xC2\x41" => "\xED\x97\x8A", + "\xC2\x42" => "\xED\x97\x8B", + "\xC2\x43" => "\xED\x97\x8D", + "\xC2\x44" => "\xED\x97\x8E", + "\xC2\x45" => "\xED\x97\x8F", + "\xC2\x46" => "\xED\x97\x91", + "\xC2\x47" => "\xED\x97\x93", + "\xC2\x48" => "\xED\x97\x94", + "\xC2\x49" => "\xED\x97\x95", + "\xC2\x4A" => "\xED\x97\x96", + "\xC2\x4B" => "\xED\x97\x97", + "\xC2\x4C" => "\xED\x97\x9A", + "\xC2\x4D" => "\xED\x97\x9C", + "\xC2\x4E" => "\xED\x97\x9E", + "\xC2\x4F" => "\xED\x97\x9F", + "\xC2\x50" => "\xED\x97\xA0", + "\xC2\x51" => "\xED\x97\xA1", + "\xC2\x52" => "\xED\x97\xA2", + "\xC2\x53" => "\xED\x97\xA3", + "\xC2\x54" => "\xED\x97\xA6", + "\xC2\x55" => "\xED\x97\xA7", + "\xC2\x56" => "\xED\x97\xA9", + "\xC2\x57" => "\xED\x97\xAA", + "\xC2\x58" => "\xED\x97\xAB", + "\xC2\x59" => "\xED\x97\xAD", + "\xC2\x5A" => "\xED\x97\xAE", + "\xC2\x61" => "\xED\x97\xAF", + "\xC2\x62" => "\xED\x97\xB0", + "\xC2\x63" => "\xED\x97\xB1", + "\xC2\x64" => "\xED\x97\xB2", + "\xC2\x65" => "\xED\x97\xB3", + "\xC2\x66" => "\xED\x97\xB6", + "\xC2\x67" => "\xED\x97\xB8", + "\xC2\x68" => "\xED\x97\xBA", + "\xC2\x69" => "\xED\x97\xBB", + "\xC2\x6A" => "\xED\x97\xBC", + "\xC2\x6B" => "\xED\x97\xBD", + "\xC2\x6C" => "\xED\x97\xBE", + "\xC2\x6D" => "\xED\x97\xBF", + "\xC2\x6E" => "\xED\x98\x82", + "\xC2\x6F" => "\xED\x98\x83", + "\xC2\x70" => "\xED\x98\x85", + "\xC2\x71" => "\xED\x98\x86", + "\xC2\x72" => "\xED\x98\x87", + "\xC2\x73" => "\xED\x98\x89", + "\xC2\x74" => "\xED\x98\x8A", + "\xC2\x75" => "\xED\x98\x8B", + "\xC2\x76" => "\xED\x98\x8C", + "\xC2\x77" => "\xED\x98\x8D", + "\xC2\x78" => "\xED\x98\x8E", + "\xC2\x79" => "\xED\x98\x8F", + "\xC2\x7A" => "\xED\x98\x92", + "\xC2\x81" => "\xED\x98\x96", + "\xC2\x82" => "\xED\x98\x97", + "\xC2\x83" => "\xED\x98\x98", + "\xC2\x84" => "\xED\x98\x99", + "\xC2\x85" => "\xED\x98\x9A", + "\xC2\x86" => "\xED\x98\x9B", + "\xC2\x87" => "\xED\x98\x9D", + "\xC2\x88" => "\xED\x98\x9E", + "\xC2\x89" => "\xED\x98\x9F", + "\xC2\x8A" => "\xED\x98\xA1", + "\xC2\x8B" => "\xED\x98\xA2", + "\xC2\x8C" => "\xED\x98\xA3", + "\xC2\x8D" => "\xED\x98\xA5", + "\xC2\x8E" => "\xED\x98\xA6", + "\xC2\x8F" => "\xED\x98\xA7", + "\xC2\x90" => "\xED\x98\xA8", + "\xC2\x91" => "\xED\x98\xA9", + "\xC2\x92" => "\xED\x98\xAA", + "\xC2\x93" => "\xED\x98\xAB", + "\xC2\x94" => "\xED\x98\xAC", + "\xC2\x95" => "\xED\x98\xAE", + "\xC2\x96" => "\xED\x98\xAF", + "\xC2\x97" => "\xED\x98\xB0", + "\xC2\x98" => "\xED\x98\xB1", + "\xC2\x99" => "\xED\x98\xB2", + "\xC2\x9A" => "\xED\x98\xB3", + "\xC2\x9B" => "\xED\x98\xB4", + "\xC2\x9C" => "\xED\x98\xB5", + "\xC2\x9D" => "\xED\x98\xB6", + "\xC2\x9E" => "\xED\x98\xB7", + "\xC2\x9F" => "\xED\x98\xBA", + "\xC2\xA0" => "\xED\x98\xBB", + "\xC2\xA1" => "\xEC\xA7\x95", + "\xC2\xA2" => "\xEC\xA7\x96", + "\xC2\xA3" => "\xEC\xA7\x99", + "\xC2\xA4" => "\xEC\xA7\x9A", + "\xC2\xA5" => "\xEC\xA7\x9C", + "\xC2\xA6" => "\xEC\xA7\x9D", + "\xC2\xA7" => "\xEC\xA7\xA0", + "\xC2\xA8" => "\xEC\xA7\xA2", + "\xC2\xA9" => "\xEC\xA7\xA4", + "\xC2\xAA" => "\xEC\xA7\xA7", + "\xC2\xAB" => "\xEC\xA7\xAC", + "\xC2\xAC" => "\xEC\xA7\xAD", + "\xC2\xAD" => "\xEC\xA7\xAF", + "\xC2\xAE" => "\xEC\xA7\xB0", + "\xC2\xAF" => "\xEC\xA7\xB1", + "\xC2\xB0" => "\xEC\xA7\xB8", + "\xC2\xB1" => "\xEC\xA7\xB9", + "\xC2\xB2" => "\xEC\xA7\xBC", + "\xC2\xB3" => "\xEC\xA8\x80", + "\xC2\xB4" => "\xEC\xA8\x88", + "\xC2\xB5" => "\xEC\xA8\x89", + "\xC2\xB6" => "\xEC\xA8\x8B", + "\xC2\xB7" => "\xEC\xA8\x8C", + "\xC2\xB8" => "\xEC\xA8\x8D", + "\xC2\xB9" => "\xEC\xA8\x94", + "\xC2\xBA" => "\xEC\xA8\x98", + "\xC2\xBB" => "\xEC\xA8\xA9", + "\xC2\xBC" => "\xEC\xA9\x8C", + "\xC2\xBD" => "\xEC\xA9\x8D", + "\xC2\xBE" => "\xEC\xA9\x90", + "\xC2\xBF" => "\xEC\xA9\x94", + "\xC2\xC0" => "\xEC\xA9\x9C", + "\xC2\xC1" => "\xEC\xA9\x9D", + "\xC2\xC2" => "\xEC\xA9\x9F", + "\xC2\xC3" => "\xEC\xA9\xA0", + "\xC2\xC4" => "\xEC\xA9\xA1", + "\xC2\xC5" => "\xEC\xA9\xA8", + "\xC2\xC6" => "\xEC\xA9\xBD", + "\xC2\xC7" => "\xEC\xAA\x84", + "\xC2\xC8" => "\xEC\xAA\x98", + "\xC2\xC9" => "\xEC\xAA\xBC", + "\xC2\xCA" => "\xEC\xAA\xBD", + "\xC2\xCB" => "\xEC\xAB\x80", + "\xC2\xCC" => "\xEC\xAB\x84", + "\xC2\xCD" => "\xEC\xAB\x8C", + "\xC2\xCE" => "\xEC\xAB\x8D", + "\xC2\xCF" => "\xEC\xAB\x8F", + "\xC2\xD0" => "\xEC\xAB\x91", + "\xC2\xD1" => "\xEC\xAB\x93", + "\xC2\xD2" => "\xEC\xAB\x98", + "\xC2\xD3" => "\xEC\xAB\x99", + "\xC2\xD4" => "\xEC\xAB\xA0", + "\xC2\xD5" => "\xEC\xAB\xAC", + "\xC2\xD6" => "\xEC\xAB\xB4", + "\xC2\xD7" => "\xEC\xAC\x88", + "\xC2\xD8" => "\xEC\xAC\x90", + "\xC2\xD9" => "\xEC\xAC\x94", + "\xC2\xDA" => "\xEC\xAC\x98", + "\xC2\xDB" => "\xEC\xAC\xA0", + "\xC2\xDC" => "\xEC\xAC\xA1", + "\xC2\xDD" => "\xEC\xAD\x81", + "\xC2\xDE" => "\xEC\xAD\x88", + "\xC2\xDF" => "\xEC\xAD\x89", + "\xC2\xE0" => "\xEC\xAD\x8C", + "\xC2\xE1" => "\xEC\xAD\x90", + "\xC2\xE2" => "\xEC\xAD\x98", + "\xC2\xE3" => "\xEC\xAD\x99", + "\xC2\xE4" => "\xEC\xAD\x9D", + "\xC2\xE5" => "\xEC\xAD\xA4", + "\xC2\xE6" => "\xEC\xAD\xB8", + "\xC2\xE7" => "\xEC\xAD\xB9", + "\xC2\xE8" => "\xEC\xAE\x9C", + "\xC2\xE9" => "\xEC\xAE\xB8", + "\xC2\xEA" => "\xEC\xAF\x94", + "\xC2\xEB" => "\xEC\xAF\xA4", + "\xC2\xEC" => "\xEC\xAF\xA7", + "\xC2\xED" => "\xEC\xAF\xA9", + "\xC2\xEE" => "\xEC\xB0\x8C", + "\xC2\xEF" => "\xEC\xB0\x8D", + "\xC2\xF0" => "\xEC\xB0\x90", + "\xC2\xF1" => "\xEC\xB0\x94", + "\xC2\xF2" => "\xEC\xB0\x9C", + "\xC2\xF3" => "\xEC\xB0\x9D", + "\xC2\xF4" => "\xEC\xB0\xA1", + "\xC2\xF5" => "\xEC\xB0\xA2", + "\xC2\xF6" => "\xEC\xB0\xA7", + "\xC2\xF7" => "\xEC\xB0\xA8", + "\xC2\xF8" => "\xEC\xB0\xA9", + "\xC2\xF9" => "\xEC\xB0\xAC", + "\xC2\xFA" => "\xEC\xB0\xAE", + "\xC2\xFB" => "\xEC\xB0\xB0", + "\xC2\xFC" => "\xEC\xB0\xB8", + "\xC2\xFD" => "\xEC\xB0\xB9", + "\xC2\xFE" => "\xEC\xB0\xBB", + "\xC3\x41" => "\xED\x98\xBD", + "\xC3\x42" => "\xED\x98\xBE", + "\xC3\x43" => "\xED\x98\xBF", + "\xC3\x44" => "\xED\x99\x81", + "\xC3\x45" => "\xED\x99\x82", + "\xC3\x46" => "\xED\x99\x83", + "\xC3\x47" => "\xED\x99\x84", + "\xC3\x48" => "\xED\x99\x86", + "\xC3\x49" => "\xED\x99\x87", + "\xC3\x4A" => "\xED\x99\x8A", + "\xC3\x4B" => "\xED\x99\x8C", + "\xC3\x4C" => "\xED\x99\x8E", + "\xC3\x4D" => "\xED\x99\x8F", + "\xC3\x4E" => "\xED\x99\x90", + "\xC3\x4F" => "\xED\x99\x92", + "\xC3\x50" => "\xED\x99\x93", + "\xC3\x51" => "\xED\x99\x96", + "\xC3\x52" => "\xED\x99\x97", + "\xC3\x53" => "\xED\x99\x99", + "\xC3\x54" => "\xED\x99\x9A", + "\xC3\x55" => "\xED\x99\x9B", + "\xC3\x56" => "\xED\x99\x9D", + "\xC3\x57" => "\xED\x99\x9E", + "\xC3\x58" => "\xED\x99\x9F", + "\xC3\x59" => "\xED\x99\xA0", + "\xC3\x5A" => "\xED\x99\xA1", + "\xC3\x61" => "\xED\x99\xA2", + "\xC3\x62" => "\xED\x99\xA3", + "\xC3\x63" => "\xED\x99\xA4", + "\xC3\x64" => "\xED\x99\xA5", + "\xC3\x65" => "\xED\x99\xA6", + "\xC3\x66" => "\xED\x99\xA8", + "\xC3\x67" => "\xED\x99\xAA", + "\xC3\x68" => "\xED\x99\xAB", + "\xC3\x69" => "\xED\x99\xAC", + "\xC3\x6A" => "\xED\x99\xAD", + "\xC3\x6B" => "\xED\x99\xAE", + "\xC3\x6C" => "\xED\x99\xAF", + "\xC3\x6D" => "\xED\x99\xB2", + "\xC3\x6E" => "\xED\x99\xB3", + "\xC3\x6F" => "\xED\x99\xB5", + "\xC3\x70" => "\xED\x99\xB6", + "\xC3\x71" => "\xED\x99\xB7", + "\xC3\x72" => "\xED\x99\xB8", + "\xC3\x73" => "\xED\x99\xB9", + "\xC3\x74" => "\xED\x99\xBA", + "\xC3\x75" => "\xED\x99\xBB", + "\xC3\x76" => "\xED\x99\xBC", + "\xC3\x77" => "\xED\x99\xBD", + "\xC3\x78" => "\xED\x99\xBE", + "\xC3\x79" => "\xED\x99\xBF", + "\xC3\x7A" => "\xED\x9A\x80", + "\xC3\x81" => "\xED\x9A\x81", + "\xC3\x82" => "\xED\x9A\x82", + "\xC3\x83" => "\xED\x9A\x84", + "\xC3\x84" => "\xED\x9A\x86", + "\xC3\x85" => "\xED\x9A\x87", + "\xC3\x86" => "\xED\x9A\x88", + "\xC3\x87" => "\xED\x9A\x89", + "\xC3\x88" => "\xED\x9A\x8A", + "\xC3\x89" => "\xED\x9A\x8B", + "\xC3\x8A" => "\xED\x9A\x8E", + "\xC3\x8B" => "\xED\x9A\x8F", + "\xC3\x8C" => "\xED\x9A\x91", + "\xC3\x8D" => "\xED\x9A\x92", + "\xC3\x8E" => "\xED\x9A\x93", + "\xC3\x8F" => "\xED\x9A\x95", + "\xC3\x90" => "\xED\x9A\x96", + "\xC3\x91" => "\xED\x9A\x97", + "\xC3\x92" => "\xED\x9A\x98", + "\xC3\x93" => "\xED\x9A\x99", + "\xC3\x94" => "\xED\x9A\x9A", + "\xC3\x95" => "\xED\x9A\x9B", + "\xC3\x96" => "\xED\x9A\x9C", + "\xC3\x97" => "\xED\x9A\x9E", + "\xC3\x98" => "\xED\x9A\xA0", + "\xC3\x99" => "\xED\x9A\xA2", + "\xC3\x9A" => "\xED\x9A\xA3", + "\xC3\x9B" => "\xED\x9A\xA4", + "\xC3\x9C" => "\xED\x9A\xA5", + "\xC3\x9D" => "\xED\x9A\xA6", + "\xC3\x9E" => "\xED\x9A\xA7", + "\xC3\x9F" => "\xED\x9A\xA9", + "\xC3\xA0" => "\xED\x9A\xAA", + "\xC3\xA1" => "\xEC\xB0\xBC", + "\xC3\xA2" => "\xEC\xB0\xBD", + "\xC3\xA3" => "\xEC\xB0\xBE", + "\xC3\xA4" => "\xEC\xB1\x84", + "\xC3\xA5" => "\xEC\xB1\x85", + "\xC3\xA6" => "\xEC\xB1\x88", + "\xC3\xA7" => "\xEC\xB1\x8C", + "\xC3\xA8" => "\xEC\xB1\x94", + "\xC3\xA9" => "\xEC\xB1\x95", + "\xC3\xAA" => "\xEC\xB1\x97", + "\xC3\xAB" => "\xEC\xB1\x98", + "\xC3\xAC" => "\xEC\xB1\x99", + "\xC3\xAD" => "\xEC\xB1\xA0", + "\xC3\xAE" => "\xEC\xB1\xA4", + "\xC3\xAF" => "\xEC\xB1\xA6", + "\xC3\xB0" => "\xEC\xB1\xA8", + "\xC3\xB1" => "\xEC\xB1\xB0", + "\xC3\xB2" => "\xEC\xB1\xB5", + "\xC3\xB3" => "\xEC\xB2\x98", + "\xC3\xB4" => "\xEC\xB2\x99", + "\xC3\xB5" => "\xEC\xB2\x9C", + "\xC3\xB6" => "\xEC\xB2\xA0", + "\xC3\xB7" => "\xEC\xB2\xA8", + "\xC3\xB8" => "\xEC\xB2\xA9", + "\xC3\xB9" => "\xEC\xB2\xAB", + "\xC3\xBA" => "\xEC\xB2\xAC", + "\xC3\xBB" => "\xEC\xB2\xAD", + "\xC3\xBC" => "\xEC\xB2\xB4", + "\xC3\xBD" => "\xEC\xB2\xB5", + "\xC3\xBE" => "\xEC\xB2\xB8", + "\xC3\xBF" => "\xEC\xB2\xBC", + "\xC3\xC0" => "\xEC\xB3\x84", + "\xC3\xC1" => "\xEC\xB3\x85", + "\xC3\xC2" => "\xEC\xB3\x87", + "\xC3\xC3" => "\xEC\xB3\x89", + "\xC3\xC4" => "\xEC\xB3\x90", + "\xC3\xC5" => "\xEC\xB3\x94", + "\xC3\xC6" => "\xEC\xB3\xA4", + "\xC3\xC7" => "\xEC\xB3\xAC", + "\xC3\xC8" => "\xEC\xB3\xB0", + "\xC3\xC9" => "\xEC\xB4\x81", + "\xC3\xCA" => "\xEC\xB4\x88", + "\xC3\xCB" => "\xEC\xB4\x89", + "\xC3\xCC" => "\xEC\xB4\x8C", + "\xC3\xCD" => "\xEC\xB4\x90", + "\xC3\xCE" => "\xEC\xB4\x98", + "\xC3\xCF" => "\xEC\xB4\x99", + "\xC3\xD0" => "\xEC\xB4\x9B", + "\xC3\xD1" => "\xEC\xB4\x9D", + "\xC3\xD2" => "\xEC\xB4\xA4", + "\xC3\xD3" => "\xEC\xB4\xA8", + "\xC3\xD4" => "\xEC\xB4\xAC", + "\xC3\xD5" => "\xEC\xB4\xB9", + "\xC3\xD6" => "\xEC\xB5\x9C", + "\xC3\xD7" => "\xEC\xB5\xA0", + "\xC3\xD8" => "\xEC\xB5\xA4", + "\xC3\xD9" => "\xEC\xB5\xAC", + "\xC3\xDA" => "\xEC\xB5\xAD", + "\xC3\xDB" => "\xEC\xB5\xAF", + "\xC3\xDC" => "\xEC\xB5\xB1", + "\xC3\xDD" => "\xEC\xB5\xB8", + "\xC3\xDE" => "\xEC\xB6\x88", + "\xC3\xDF" => "\xEC\xB6\x94", + "\xC3\xE0" => "\xEC\xB6\x95", + "\xC3\xE1" => "\xEC\xB6\x98", + "\xC3\xE2" => "\xEC\xB6\x9C", + "\xC3\xE3" => "\xEC\xB6\xA4", + "\xC3\xE4" => "\xEC\xB6\xA5", + "\xC3\xE5" => "\xEC\xB6\xA7", + "\xC3\xE6" => "\xEC\xB6\xA9", + "\xC3\xE7" => "\xEC\xB6\xB0", + "\xC3\xE8" => "\xEC\xB7\x84", + "\xC3\xE9" => "\xEC\xB7\x8C", + "\xC3\xEA" => "\xEC\xB7\x90", + "\xC3\xEB" => "\xEC\xB7\xA8", + "\xC3\xEC" => "\xEC\xB7\xAC", + "\xC3\xED" => "\xEC\xB7\xB0", + "\xC3\xEE" => "\xEC\xB7\xB8", + "\xC3\xEF" => "\xEC\xB7\xB9", + "\xC3\xF0" => "\xEC\xB7\xBB", + "\xC3\xF1" => "\xEC\xB7\xBD", + "\xC3\xF2" => "\xEC\xB8\x84", + "\xC3\xF3" => "\xEC\xB8\x88", + "\xC3\xF4" => "\xEC\xB8\x8C", + "\xC3\xF5" => "\xEC\xB8\x94", + "\xC3\xF6" => "\xEC\xB8\x99", + "\xC3\xF7" => "\xEC\xB8\xA0", + "\xC3\xF8" => "\xEC\xB8\xA1", + "\xC3\xF9" => "\xEC\xB8\xA4", + "\xC3\xFA" => "\xEC\xB8\xA8", + "\xC3\xFB" => "\xEC\xB8\xB0", + "\xC3\xFC" => "\xEC\xB8\xB1", + "\xC3\xFD" => "\xEC\xB8\xB3", + "\xC3\xFE" => "\xEC\xB8\xB5", + "\xC4\x41" => "\xED\x9A\xAB", + "\xC4\x42" => "\xED\x9A\xAD", + "\xC4\x43" => "\xED\x9A\xAE", + "\xC4\x44" => "\xED\x9A\xAF", + "\xC4\x45" => "\xED\x9A\xB1", + "\xC4\x46" => "\xED\x9A\xB2", + "\xC4\x47" => "\xED\x9A\xB3", + "\xC4\x48" => "\xED\x9A\xB4", + "\xC4\x49" => "\xED\x9A\xB5", + "\xC4\x4A" => "\xED\x9A\xB6", + "\xC4\x4B" => "\xED\x9A\xB7", + "\xC4\x4C" => "\xED\x9A\xB8", + "\xC4\x4D" => "\xED\x9A\xBA", + "\xC4\x4E" => "\xED\x9A\xBC", + "\xC4\x4F" => "\xED\x9A\xBD", + "\xC4\x50" => "\xED\x9A\xBE", + "\xC4\x51" => "\xED\x9A\xBF", + "\xC4\x52" => "\xED\x9B\x80", + "\xC4\x53" => "\xED\x9B\x81", + "\xC4\x54" => "\xED\x9B\x82", + "\xC4\x55" => "\xED\x9B\x83", + "\xC4\x56" => "\xED\x9B\x86", + "\xC4\x57" => "\xED\x9B\x87", + "\xC4\x58" => "\xED\x9B\x89", + "\xC4\x59" => "\xED\x9B\x8A", + "\xC4\x5A" => "\xED\x9B\x8B", + "\xC4\x61" => "\xED\x9B\x8D", + "\xC4\x62" => "\xED\x9B\x8E", + "\xC4\x63" => "\xED\x9B\x8F", + "\xC4\x64" => "\xED\x9B\x90", + "\xC4\x65" => "\xED\x9B\x92", + "\xC4\x66" => "\xED\x9B\x93", + "\xC4\x67" => "\xED\x9B\x95", + "\xC4\x68" => "\xED\x9B\x96", + "\xC4\x69" => "\xED\x9B\x98", + "\xC4\x6A" => "\xED\x9B\x9A", + "\xC4\x6B" => "\xED\x9B\x9B", + "\xC4\x6C" => "\xED\x9B\x9C", + "\xC4\x6D" => "\xED\x9B\x9D", + "\xC4\x6E" => "\xED\x9B\x9E", + "\xC4\x6F" => "\xED\x9B\x9F", + "\xC4\x70" => "\xED\x9B\xA1", + "\xC4\x71" => "\xED\x9B\xA2", + "\xC4\x72" => "\xED\x9B\xA3", + "\xC4\x73" => "\xED\x9B\xA5", + "\xC4\x74" => "\xED\x9B\xA6", + "\xC4\x75" => "\xED\x9B\xA7", + "\xC4\x76" => "\xED\x9B\xA9", + "\xC4\x77" => "\xED\x9B\xAA", + "\xC4\x78" => "\xED\x9B\xAB", + "\xC4\x79" => "\xED\x9B\xAC", + "\xC4\x7A" => "\xED\x9B\xAD", + "\xC4\x81" => "\xED\x9B\xAE", + "\xC4\x82" => "\xED\x9B\xAF", + "\xC4\x83" => "\xED\x9B\xB1", + "\xC4\x84" => "\xED\x9B\xB2", + "\xC4\x85" => "\xED\x9B\xB3", + "\xC4\x86" => "\xED\x9B\xB4", + "\xC4\x87" => "\xED\x9B\xB6", + "\xC4\x88" => "\xED\x9B\xB7", + "\xC4\x89" => "\xED\x9B\xB8", + "\xC4\x8A" => "\xED\x9B\xB9", + "\xC4\x8B" => "\xED\x9B\xBA", + "\xC4\x8C" => "\xED\x9B\xBB", + "\xC4\x8D" => "\xED\x9B\xBE", + "\xC4\x8E" => "\xED\x9B\xBF", + "\xC4\x8F" => "\xED\x9C\x81", + "\xC4\x90" => "\xED\x9C\x82", + "\xC4\x91" => "\xED\x9C\x83", + "\xC4\x92" => "\xED\x9C\x85", + "\xC4\x93" => "\xED\x9C\x86", + "\xC4\x94" => "\xED\x9C\x87", + "\xC4\x95" => "\xED\x9C\x88", + "\xC4\x96" => "\xED\x9C\x89", + "\xC4\x97" => "\xED\x9C\x8A", + "\xC4\x98" => "\xED\x9C\x8B", + "\xC4\x99" => "\xED\x9C\x8C", + "\xC4\x9A" => "\xED\x9C\x8D", + "\xC4\x9B" => "\xED\x9C\x8E", + "\xC4\x9C" => "\xED\x9C\x8F", + "\xC4\x9D" => "\xED\x9C\x90", + "\xC4\x9E" => "\xED\x9C\x92", + "\xC4\x9F" => "\xED\x9C\x93", + "\xC4\xA0" => "\xED\x9C\x94", + "\xC4\xA1" => "\xEC\xB9\x98", + "\xC4\xA2" => "\xEC\xB9\x99", + "\xC4\xA3" => "\xEC\xB9\x9C", + "\xC4\xA4" => "\xEC\xB9\x9F", + "\xC4\xA5" => "\xEC\xB9\xA0", + "\xC4\xA6" => "\xEC\xB9\xA1", + "\xC4\xA7" => "\xEC\xB9\xA8", + "\xC4\xA8" => "\xEC\xB9\xA9", + "\xC4\xA9" => "\xEC\xB9\xAB", + "\xC4\xAA" => "\xEC\xB9\xAD", + "\xC4\xAB" => "\xEC\xB9\xB4", + "\xC4\xAC" => "\xEC\xB9\xB5", + "\xC4\xAD" => "\xEC\xB9\xB8", + "\xC4\xAE" => "\xEC\xB9\xBC", + "\xC4\xAF" => "\xEC\xBA\x84", + "\xC4\xB0" => "\xEC\xBA\x85", + "\xC4\xB1" => "\xEC\xBA\x87", + "\xC4\xB2" => "\xEC\xBA\x89", + "\xC4\xB3" => "\xEC\xBA\x90", + "\xC4\xB4" => "\xEC\xBA\x91", + "\xC4\xB5" => "\xEC\xBA\x94", + "\xC4\xB6" => "\xEC\xBA\x98", + "\xC4\xB7" => "\xEC\xBA\xA0", + "\xC4\xB8" => "\xEC\xBA\xA1", + "\xC4\xB9" => "\xEC\xBA\xA3", + "\xC4\xBA" => "\xEC\xBA\xA4", + "\xC4\xBB" => "\xEC\xBA\xA5", + "\xC4\xBC" => "\xEC\xBA\xAC", + "\xC4\xBD" => "\xEC\xBA\xAD", + "\xC4\xBE" => "\xEC\xBB\x81", + "\xC4\xBF" => "\xEC\xBB\xA4", + "\xC4\xC0" => "\xEC\xBB\xA5", + "\xC4\xC1" => "\xEC\xBB\xA8", + "\xC4\xC2" => "\xEC\xBB\xAB", + "\xC4\xC3" => "\xEC\xBB\xAC", + "\xC4\xC4" => "\xEC\xBB\xB4", + "\xC4\xC5" => "\xEC\xBB\xB5", + "\xC4\xC6" => "\xEC\xBB\xB7", + "\xC4\xC7" => "\xEC\xBB\xB8", + "\xC4\xC8" => "\xEC\xBB\xB9", + "\xC4\xC9" => "\xEC\xBC\x80", + "\xC4\xCA" => "\xEC\xBC\x81", + "\xC4\xCB" => "\xEC\xBC\x84", + "\xC4\xCC" => "\xEC\xBC\x88", + "\xC4\xCD" => "\xEC\xBC\x90", + "\xC4\xCE" => "\xEC\xBC\x91", + "\xC4\xCF" => "\xEC\xBC\x93", + "\xC4\xD0" => "\xEC\xBC\x95", + "\xC4\xD1" => "\xEC\xBC\x9C", + "\xC4\xD2" => "\xEC\xBC\xA0", + "\xC4\xD3" => "\xEC\xBC\xA4", + "\xC4\xD4" => "\xEC\xBC\xAC", + "\xC4\xD5" => "\xEC\xBC\xAD", + "\xC4\xD6" => "\xEC\xBC\xAF", + "\xC4\xD7" => "\xEC\xBC\xB0", + "\xC4\xD8" => "\xEC\xBC\xB1", + "\xC4\xD9" => "\xEC\xBC\xB8", + "\xC4\xDA" => "\xEC\xBD\x94", + "\xC4\xDB" => "\xEC\xBD\x95", + "\xC4\xDC" => "\xEC\xBD\x98", + "\xC4\xDD" => "\xEC\xBD\x9C", + "\xC4\xDE" => "\xEC\xBD\xA4", + "\xC4\xDF" => "\xEC\xBD\xA5", + "\xC4\xE0" => "\xEC\xBD\xA7", + "\xC4\xE1" => "\xEC\xBD\xA9", + "\xC4\xE2" => "\xEC\xBD\xB0", + "\xC4\xE3" => "\xEC\xBD\xB1", + "\xC4\xE4" => "\xEC\xBD\xB4", + "\xC4\xE5" => "\xEC\xBD\xB8", + "\xC4\xE6" => "\xEC\xBE\x80", + "\xC4\xE7" => "\xEC\xBE\x85", + "\xC4\xE8" => "\xEC\xBE\x8C", + "\xC4\xE9" => "\xEC\xBE\xA1", + "\xC4\xEA" => "\xEC\xBE\xA8", + "\xC4\xEB" => "\xEC\xBE\xB0", + "\xC4\xEC" => "\xEC\xBF\x84", + "\xC4\xED" => "\xEC\xBF\xA0", + "\xC4\xEE" => "\xEC\xBF\xA1", + "\xC4\xEF" => "\xEC\xBF\xA4", + "\xC4\xF0" => "\xEC\xBF\xA8", + "\xC4\xF1" => "\xEC\xBF\xB0", + "\xC4\xF2" => "\xEC\xBF\xB1", + "\xC4\xF3" => "\xEC\xBF\xB3", + "\xC4\xF4" => "\xEC\xBF\xB5", + "\xC4\xF5" => "\xEC\xBF\xBC", + "\xC4\xF6" => "\xED\x80\x80", + "\xC4\xF7" => "\xED\x80\x84", + "\xC4\xF8" => "\xED\x80\x91", + "\xC4\xF9" => "\xED\x80\x98", + "\xC4\xFA" => "\xED\x80\xAD", + "\xC4\xFB" => "\xED\x80\xB4", + "\xC4\xFC" => "\xED\x80\xB5", + "\xC4\xFD" => "\xED\x80\xB8", + "\xC4\xFE" => "\xED\x80\xBC", + "\xC5\x41" => "\xED\x9C\x95", + "\xC5\x42" => "\xED\x9C\x96", + "\xC5\x43" => "\xED\x9C\x97", + "\xC5\x44" => "\xED\x9C\x9A", + "\xC5\x45" => "\xED\x9C\x9B", + "\xC5\x46" => "\xED\x9C\x9D", + "\xC5\x47" => "\xED\x9C\x9E", + "\xC5\x48" => "\xED\x9C\x9F", + "\xC5\x49" => "\xED\x9C\xA1", + "\xC5\x4A" => "\xED\x9C\xA2", + "\xC5\x4B" => "\xED\x9C\xA3", + "\xC5\x4C" => "\xED\x9C\xA4", + "\xC5\x4D" => "\xED\x9C\xA5", + "\xC5\x4E" => "\xED\x9C\xA6", + "\xC5\x4F" => "\xED\x9C\xA7", + "\xC5\x50" => "\xED\x9C\xAA", + "\xC5\x51" => "\xED\x9C\xAC", + "\xC5\x52" => "\xED\x9C\xAE", + "\xC5\x53" => "\xED\x9C\xAF", + "\xC5\x54" => "\xED\x9C\xB0", + "\xC5\x55" => "\xED\x9C\xB1", + "\xC5\x56" => "\xED\x9C\xB2", + "\xC5\x57" => "\xED\x9C\xB3", + "\xC5\x58" => "\xED\x9C\xB6", + "\xC5\x59" => "\xED\x9C\xB7", + "\xC5\x5A" => "\xED\x9C\xB9", + "\xC5\x61" => "\xED\x9C\xBA", + "\xC5\x62" => "\xED\x9C\xBB", + "\xC5\x63" => "\xED\x9C\xBD", + "\xC5\x64" => "\xED\x9C\xBE", + "\xC5\x65" => "\xED\x9C\xBF", + "\xC5\x66" => "\xED\x9D\x80", + "\xC5\x67" => "\xED\x9D\x81", + "\xC5\x68" => "\xED\x9D\x82", + "\xC5\x69" => "\xED\x9D\x83", + "\xC5\x6A" => "\xED\x9D\x85", + "\xC5\x6B" => "\xED\x9D\x86", + "\xC5\x6C" => "\xED\x9D\x88", + "\xC5\x6D" => "\xED\x9D\x8A", + "\xC5\x6E" => "\xED\x9D\x8B", + "\xC5\x6F" => "\xED\x9D\x8C", + "\xC5\x70" => "\xED\x9D\x8D", + "\xC5\x71" => "\xED\x9D\x8E", + "\xC5\x72" => "\xED\x9D\x8F", + "\xC5\x73" => "\xED\x9D\x92", + "\xC5\x74" => "\xED\x9D\x93", + "\xC5\x75" => "\xED\x9D\x95", + "\xC5\x76" => "\xED\x9D\x9A", + "\xC5\x77" => "\xED\x9D\x9B", + "\xC5\x78" => "\xED\x9D\x9C", + "\xC5\x79" => "\xED\x9D\x9D", + "\xC5\x7A" => "\xED\x9D\x9E", + "\xC5\x81" => "\xED\x9D\x9F", + "\xC5\x82" => "\xED\x9D\xA2", + "\xC5\x83" => "\xED\x9D\xA4", + "\xC5\x84" => "\xED\x9D\xA6", + "\xC5\x85" => "\xED\x9D\xA7", + "\xC5\x86" => "\xED\x9D\xA8", + "\xC5\x87" => "\xED\x9D\xAA", + "\xC5\x88" => "\xED\x9D\xAB", + "\xC5\x89" => "\xED\x9D\xAD", + "\xC5\x8A" => "\xED\x9D\xAE", + "\xC5\x8B" => "\xED\x9D\xAF", + "\xC5\x8C" => "\xED\x9D\xB1", + "\xC5\x8D" => "\xED\x9D\xB2", + "\xC5\x8E" => "\xED\x9D\xB3", + "\xC5\x8F" => "\xED\x9D\xB5", + "\xC5\x90" => "\xED\x9D\xB6", + "\xC5\x91" => "\xED\x9D\xB7", + "\xC5\x92" => "\xED\x9D\xB8", + "\xC5\x93" => "\xED\x9D\xB9", + "\xC5\x94" => "\xED\x9D\xBA", + "\xC5\x95" => "\xED\x9D\xBB", + "\xC5\x96" => "\xED\x9D\xBE", + "\xC5\x97" => "\xED\x9D\xBF", + "\xC5\x98" => "\xED\x9E\x80", + "\xC5\x99" => "\xED\x9E\x82", + "\xC5\x9A" => "\xED\x9E\x83", + "\xC5\x9B" => "\xED\x9E\x84", + "\xC5\x9C" => "\xED\x9E\x85", + "\xC5\x9D" => "\xED\x9E\x86", + "\xC5\x9E" => "\xED\x9E\x87", + "\xC5\x9F" => "\xED\x9E\x8A", + "\xC5\xA0" => "\xED\x9E\x8B", + "\xC5\xA1" => "\xED\x81\x84", + "\xC5\xA2" => "\xED\x81\x85", + "\xC5\xA3" => "\xED\x81\x87", + "\xC5\xA4" => "\xED\x81\x89", + "\xC5\xA5" => "\xED\x81\x90", + "\xC5\xA6" => "\xED\x81\x94", + "\xC5\xA7" => "\xED\x81\x98", + "\xC5\xA8" => "\xED\x81\xA0", + "\xC5\xA9" => "\xED\x81\xAC", + "\xC5\xAA" => "\xED\x81\xAD", + "\xC5\xAB" => "\xED\x81\xB0", + "\xC5\xAC" => "\xED\x81\xB4", + "\xC5\xAD" => "\xED\x81\xBC", + "\xC5\xAE" => "\xED\x81\xBD", + "\xC5\xAF" => "\xED\x82\x81", + "\xC5\xB0" => "\xED\x82\xA4", + "\xC5\xB1" => "\xED\x82\xA5", + "\xC5\xB2" => "\xED\x82\xA8", + "\xC5\xB3" => "\xED\x82\xAC", + "\xC5\xB4" => "\xED\x82\xB4", + "\xC5\xB5" => "\xED\x82\xB5", + "\xC5\xB6" => "\xED\x82\xB7", + "\xC5\xB7" => "\xED\x82\xB9", + "\xC5\xB8" => "\xED\x83\x80", + "\xC5\xB9" => "\xED\x83\x81", + "\xC5\xBA" => "\xED\x83\x84", + "\xC5\xBB" => "\xED\x83\x88", + "\xC5\xBC" => "\xED\x83\x89", + "\xC5\xBD" => "\xED\x83\x90", + "\xC5\xBE" => "\xED\x83\x91", + "\xC5\xBF" => "\xED\x83\x93", + "\xC5\xC0" => "\xED\x83\x94", + "\xC5\xC1" => "\xED\x83\x95", + "\xC5\xC2" => "\xED\x83\x9C", + "\xC5\xC3" => "\xED\x83\x9D", + "\xC5\xC4" => "\xED\x83\xA0", + "\xC5\xC5" => "\xED\x83\xA4", + "\xC5\xC6" => "\xED\x83\xAC", + "\xC5\xC7" => "\xED\x83\xAD", + "\xC5\xC8" => "\xED\x83\xAF", + "\xC5\xC9" => "\xED\x83\xB0", + "\xC5\xCA" => "\xED\x83\xB1", + "\xC5\xCB" => "\xED\x83\xB8", + "\xC5\xCC" => "\xED\x84\x8D", + "\xC5\xCD" => "\xED\x84\xB0", + "\xC5\xCE" => "\xED\x84\xB1", + "\xC5\xCF" => "\xED\x84\xB4", + "\xC5\xD0" => "\xED\x84\xB8", + "\xC5\xD1" => "\xED\x84\xBA", + "\xC5\xD2" => "\xED\x85\x80", + "\xC5\xD3" => "\xED\x85\x81", + "\xC5\xD4" => "\xED\x85\x83", + "\xC5\xD5" => "\xED\x85\x84", + "\xC5\xD6" => "\xED\x85\x85", + "\xC5\xD7" => "\xED\x85\x8C", + "\xC5\xD8" => "\xED\x85\x8D", + "\xC5\xD9" => "\xED\x85\x90", + "\xC5\xDA" => "\xED\x85\x94", + "\xC5\xDB" => "\xED\x85\x9C", + "\xC5\xDC" => "\xED\x85\x9D", + "\xC5\xDD" => "\xED\x85\x9F", + "\xC5\xDE" => "\xED\x85\xA1", + "\xC5\xDF" => "\xED\x85\xA8", + "\xC5\xE0" => "\xED\x85\xAC", + "\xC5\xE1" => "\xED\x85\xBC", + "\xC5\xE2" => "\xED\x86\x84", + "\xC5\xE3" => "\xED\x86\x88", + "\xC5\xE4" => "\xED\x86\xA0", + "\xC5\xE5" => "\xED\x86\xA1", + "\xC5\xE6" => "\xED\x86\xA4", + "\xC5\xE7" => "\xED\x86\xA8", + "\xC5\xE8" => "\xED\x86\xB0", + "\xC5\xE9" => "\xED\x86\xB1", + "\xC5\xEA" => "\xED\x86\xB3", + "\xC5\xEB" => "\xED\x86\xB5", + "\xC5\xEC" => "\xED\x86\xBA", + "\xC5\xED" => "\xED\x86\xBC", + "\xC5\xEE" => "\xED\x87\x80", + "\xC5\xEF" => "\xED\x87\x98", + "\xC5\xF0" => "\xED\x87\xB4", + "\xC5\xF1" => "\xED\x87\xB8", + "\xC5\xF2" => "\xED\x88\x87", + "\xC5\xF3" => "\xED\x88\x89", + "\xC5\xF4" => "\xED\x88\x90", + "\xC5\xF5" => "\xED\x88\xAC", + "\xC5\xF6" => "\xED\x88\xAD", + "\xC5\xF7" => "\xED\x88\xB0", + "\xC5\xF8" => "\xED\x88\xB4", + "\xC5\xF9" => "\xED\x88\xBC", + "\xC5\xFA" => "\xED\x88\xBD", + "\xC5\xFB" => "\xED\x88\xBF", + "\xC5\xFC" => "\xED\x89\x81", + "\xC5\xFD" => "\xED\x89\x88", + "\xC5\xFE" => "\xED\x89\x9C", + "\xC6\x41" => "\xED\x9E\x8D", + "\xC6\x42" => "\xED\x9E\x8E", + "\xC6\x43" => "\xED\x9E\x8F", + "\xC6\x44" => "\xED\x9E\x91", + "\xC6\x45" => "\xED\x9E\x92", + "\xC6\x46" => "\xED\x9E\x93", + "\xC6\x47" => "\xED\x9E\x94", + "\xC6\x48" => "\xED\x9E\x95", + "\xC6\x49" => "\xED\x9E\x96", + "\xC6\x4A" => "\xED\x9E\x97", + "\xC6\x4B" => "\xED\x9E\x9A", + "\xC6\x4C" => "\xED\x9E\x9C", + "\xC6\x4D" => "\xED\x9E\x9E", + "\xC6\x4E" => "\xED\x9E\x9F", + "\xC6\x4F" => "\xED\x9E\xA0", + "\xC6\x50" => "\xED\x9E\xA1", + "\xC6\x51" => "\xED\x9E\xA2", + "\xC6\x52" => "\xED\x9E\xA3", + "\xC6\xA1" => "\xED\x89\xA4", + "\xC6\xA2" => "\xED\x8A\x80", + "\xC6\xA3" => "\xED\x8A\x81", + "\xC6\xA4" => "\xED\x8A\x84", + "\xC6\xA5" => "\xED\x8A\x88", + "\xC6\xA6" => "\xED\x8A\x90", + "\xC6\xA7" => "\xED\x8A\x91", + "\xC6\xA8" => "\xED\x8A\x95", + "\xC6\xA9" => "\xED\x8A\x9C", + "\xC6\xAA" => "\xED\x8A\xA0", + "\xC6\xAB" => "\xED\x8A\xA4", + "\xC6\xAC" => "\xED\x8A\xAC", + "\xC6\xAD" => "\xED\x8A\xB1", + "\xC6\xAE" => "\xED\x8A\xB8", + "\xC6\xAF" => "\xED\x8A\xB9", + "\xC6\xB0" => "\xED\x8A\xBC", + "\xC6\xB1" => "\xED\x8A\xBF", + "\xC6\xB2" => "\xED\x8B\x80", + "\xC6\xB3" => "\xED\x8B\x82", + "\xC6\xB4" => "\xED\x8B\x88", + "\xC6\xB5" => "\xED\x8B\x89", + "\xC6\xB6" => "\xED\x8B\x8B", + "\xC6\xB7" => "\xED\x8B\x94", + "\xC6\xB8" => "\xED\x8B\x98", + "\xC6\xB9" => "\xED\x8B\x9C", + "\xC6\xBA" => "\xED\x8B\xA4", + "\xC6\xBB" => "\xED\x8B\xA5", + "\xC6\xBC" => "\xED\x8B\xB0", + "\xC6\xBD" => "\xED\x8B\xB1", + "\xC6\xBE" => "\xED\x8B\xB4", + "\xC6\xBF" => "\xED\x8B\xB8", + "\xC6\xC0" => "\xED\x8C\x80", + "\xC6\xC1" => "\xED\x8C\x81", + "\xC6\xC2" => "\xED\x8C\x83", + "\xC6\xC3" => "\xED\x8C\x85", + "\xC6\xC4" => "\xED\x8C\x8C", + "\xC6\xC5" => "\xED\x8C\x8D", + "\xC6\xC6" => "\xED\x8C\x8E", + "\xC6\xC7" => "\xED\x8C\x90", + "\xC6\xC8" => "\xED\x8C\x94", + "\xC6\xC9" => "\xED\x8C\x96", + "\xC6\xCA" => "\xED\x8C\x9C", + "\xC6\xCB" => "\xED\x8C\x9D", + "\xC6\xCC" => "\xED\x8C\x9F", + "\xC6\xCD" => "\xED\x8C\xA0", + "\xC6\xCE" => "\xED\x8C\xA1", + "\xC6\xCF" => "\xED\x8C\xA5", + "\xC6\xD0" => "\xED\x8C\xA8", + "\xC6\xD1" => "\xED\x8C\xA9", + "\xC6\xD2" => "\xED\x8C\xAC", + "\xC6\xD3" => "\xED\x8C\xB0", + "\xC6\xD4" => "\xED\x8C\xB8", + "\xC6\xD5" => "\xED\x8C\xB9", + "\xC6\xD6" => "\xED\x8C\xBB", + "\xC6\xD7" => "\xED\x8C\xBC", + "\xC6\xD8" => "\xED\x8C\xBD", + "\xC6\xD9" => "\xED\x8D\x84", + "\xC6\xDA" => "\xED\x8D\x85", + "\xC6\xDB" => "\xED\x8D\xBC", + "\xC6\xDC" => "\xED\x8D\xBD", + "\xC6\xDD" => "\xED\x8E\x80", + "\xC6\xDE" => "\xED\x8E\x84", + "\xC6\xDF" => "\xED\x8E\x8C", + "\xC6\xE0" => "\xED\x8E\x8D", + "\xC6\xE1" => "\xED\x8E\x8F", + "\xC6\xE2" => "\xED\x8E\x90", + "\xC6\xE3" => "\xED\x8E\x91", + "\xC6\xE4" => "\xED\x8E\x98", + "\xC6\xE5" => "\xED\x8E\x99", + "\xC6\xE6" => "\xED\x8E\x9C", + "\xC6\xE7" => "\xED\x8E\xA0", + "\xC6\xE8" => "\xED\x8E\xA8", + "\xC6\xE9" => "\xED\x8E\xA9", + "\xC6\xEA" => "\xED\x8E\xAB", + "\xC6\xEB" => "\xED\x8E\xAD", + "\xC6\xEC" => "\xED\x8E\xB4", + "\xC6\xED" => "\xED\x8E\xB8", + "\xC6\xEE" => "\xED\x8E\xBC", + "\xC6\xEF" => "\xED\x8F\x84", + "\xC6\xF0" => "\xED\x8F\x85", + "\xC6\xF1" => "\xED\x8F\x88", + "\xC6\xF2" => "\xED\x8F\x89", + "\xC6\xF3" => "\xED\x8F\x90", + "\xC6\xF4" => "\xED\x8F\x98", + "\xC6\xF5" => "\xED\x8F\xA1", + "\xC6\xF6" => "\xED\x8F\xA3", + "\xC6\xF7" => "\xED\x8F\xAC", + "\xC6\xF8" => "\xED\x8F\xAD", + "\xC6\xF9" => "\xED\x8F\xB0", + "\xC6\xFA" => "\xED\x8F\xB4", + "\xC6\xFB" => "\xED\x8F\xBC", + "\xC6\xFC" => "\xED\x8F\xBD", + "\xC6\xFD" => "\xED\x8F\xBF", + "\xC6\xFE" => "\xED\x90\x81", + "\xC7\xA1" => "\xED\x90\x88", + "\xC7\xA2" => "\xED\x90\x9D", + "\xC7\xA3" => "\xED\x91\x80", + "\xC7\xA4" => "\xED\x91\x84", + "\xC7\xA5" => "\xED\x91\x9C", + "\xC7\xA6" => "\xED\x91\xA0", + "\xC7\xA7" => "\xED\x91\xA4", + "\xC7\xA8" => "\xED\x91\xAD", + "\xC7\xA9" => "\xED\x91\xAF", + "\xC7\xAA" => "\xED\x91\xB8", + "\xC7\xAB" => "\xED\x91\xB9", + "\xC7\xAC" => "\xED\x91\xBC", + "\xC7\xAD" => "\xED\x91\xBF", + "\xC7\xAE" => "\xED\x92\x80", + "\xC7\xAF" => "\xED\x92\x82", + "\xC7\xB0" => "\xED\x92\x88", + "\xC7\xB1" => "\xED\x92\x89", + "\xC7\xB2" => "\xED\x92\x8B", + "\xC7\xB3" => "\xED\x92\x8D", + "\xC7\xB4" => "\xED\x92\x94", + "\xC7\xB5" => "\xED\x92\xA9", + "\xC7\xB6" => "\xED\x93\x8C", + "\xC7\xB7" => "\xED\x93\x90", + "\xC7\xB8" => "\xED\x93\x94", + "\xC7\xB9" => "\xED\x93\x9C", + "\xC7\xBA" => "\xED\x93\x9F", + "\xC7\xBB" => "\xED\x93\xA8", + "\xC7\xBC" => "\xED\x93\xAC", + "\xC7\xBD" => "\xED\x93\xB0", + "\xC7\xBE" => "\xED\x93\xB8", + "\xC7\xBF" => "\xED\x93\xBB", + "\xC7\xC0" => "\xED\x93\xBD", + "\xC7\xC1" => "\xED\x94\x84", + "\xC7\xC2" => "\xED\x94\x88", + "\xC7\xC3" => "\xED\x94\x8C", + "\xC7\xC4" => "\xED\x94\x94", + "\xC7\xC5" => "\xED\x94\x95", + "\xC7\xC6" => "\xED\x94\x97", + "\xC7\xC7" => "\xED\x94\xBC", + "\xC7\xC8" => "\xED\x94\xBD", + "\xC7\xC9" => "\xED\x95\x80", + "\xC7\xCA" => "\xED\x95\x84", + "\xC7\xCB" => "\xED\x95\x8C", + "\xC7\xCC" => "\xED\x95\x8D", + "\xC7\xCD" => "\xED\x95\x8F", + "\xC7\xCE" => "\xED\x95\x91", + "\xC7\xCF" => "\xED\x95\x98", + "\xC7\xD0" => "\xED\x95\x99", + "\xC7\xD1" => "\xED\x95\x9C", + "\xC7\xD2" => "\xED\x95\xA0", + "\xC7\xD3" => "\xED\x95\xA5", + "\xC7\xD4" => "\xED\x95\xA8", + "\xC7\xD5" => "\xED\x95\xA9", + "\xC7\xD6" => "\xED\x95\xAB", + "\xC7\xD7" => "\xED\x95\xAD", + "\xC7\xD8" => "\xED\x95\xB4", + "\xC7\xD9" => "\xED\x95\xB5", + "\xC7\xDA" => "\xED\x95\xB8", + "\xC7\xDB" => "\xED\x95\xBC", + "\xC7\xDC" => "\xED\x96\x84", + "\xC7\xDD" => "\xED\x96\x85", + "\xC7\xDE" => "\xED\x96\x87", + "\xC7\xDF" => "\xED\x96\x88", + "\xC7\xE0" => "\xED\x96\x89", + "\xC7\xE1" => "\xED\x96\x90", + "\xC7\xE2" => "\xED\x96\xA5", + "\xC7\xE3" => "\xED\x97\x88", + "\xC7\xE4" => "\xED\x97\x89", + "\xC7\xE5" => "\xED\x97\x8C", + "\xC7\xE6" => "\xED\x97\x90", + "\xC7\xE7" => "\xED\x97\x92", + "\xC7\xE8" => "\xED\x97\x98", + "\xC7\xE9" => "\xED\x97\x99", + "\xC7\xEA" => "\xED\x97\x9B", + "\xC7\xEB" => "\xED\x97\x9D", + "\xC7\xEC" => "\xED\x97\xA4", + "\xC7\xED" => "\xED\x97\xA5", + "\xC7\xEE" => "\xED\x97\xA8", + "\xC7\xEF" => "\xED\x97\xAC", + "\xC7\xF0" => "\xED\x97\xB4", + "\xC7\xF1" => "\xED\x97\xB5", + "\xC7\xF2" => "\xED\x97\xB7", + "\xC7\xF3" => "\xED\x97\xB9", + "\xC7\xF4" => "\xED\x98\x80", + "\xC7\xF5" => "\xED\x98\x81", + "\xC7\xF6" => "\xED\x98\x84", + "\xC7\xF7" => "\xED\x98\x88", + "\xC7\xF8" => "\xED\x98\x90", + "\xC7\xF9" => "\xED\x98\x91", + "\xC7\xFA" => "\xED\x98\x93", + "\xC7\xFB" => "\xED\x98\x94", + "\xC7\xFC" => "\xED\x98\x95", + "\xC7\xFD" => "\xED\x98\x9C", + "\xC7\xFE" => "\xED\x98\xA0", + "\xC8\xA1" => "\xED\x98\xA4", + "\xC8\xA2" => "\xED\x98\xAD", + "\xC8\xA3" => "\xED\x98\xB8", + "\xC8\xA4" => "\xED\x98\xB9", + "\xC8\xA5" => "\xED\x98\xBC", + "\xC8\xA6" => "\xED\x99\x80", + "\xC8\xA7" => "\xED\x99\x85", + "\xC8\xA8" => "\xED\x99\x88", + "\xC8\xA9" => "\xED\x99\x89", + "\xC8\xAA" => "\xED\x99\x8B", + "\xC8\xAB" => "\xED\x99\x8D", + "\xC8\xAC" => "\xED\x99\x91", + "\xC8\xAD" => "\xED\x99\x94", + "\xC8\xAE" => "\xED\x99\x95", + "\xC8\xAF" => "\xED\x99\x98", + "\xC8\xB0" => "\xED\x99\x9C", + "\xC8\xB1" => "\xED\x99\xA7", + "\xC8\xB2" => "\xED\x99\xA9", + "\xC8\xB3" => "\xED\x99\xB0", + "\xC8\xB4" => "\xED\x99\xB1", + "\xC8\xB5" => "\xED\x99\xB4", + "\xC8\xB6" => "\xED\x9A\x83", + "\xC8\xB7" => "\xED\x9A\x85", + "\xC8\xB8" => "\xED\x9A\x8C", + "\xC8\xB9" => "\xED\x9A\x8D", + "\xC8\xBA" => "\xED\x9A\x90", + "\xC8\xBB" => "\xED\x9A\x94", + "\xC8\xBC" => "\xED\x9A\x9D", + "\xC8\xBD" => "\xED\x9A\x9F", + "\xC8\xBE" => "\xED\x9A\xA1", + "\xC8\xBF" => "\xED\x9A\xA8", + "\xC8\xC0" => "\xED\x9A\xAC", + "\xC8\xC1" => "\xED\x9A\xB0", + "\xC8\xC2" => "\xED\x9A\xB9", + "\xC8\xC3" => "\xED\x9A\xBB", + "\xC8\xC4" => "\xED\x9B\x84", + "\xC8\xC5" => "\xED\x9B\x85", + "\xC8\xC6" => "\xED\x9B\x88", + "\xC8\xC7" => "\xED\x9B\x8C", + "\xC8\xC8" => "\xED\x9B\x91", + "\xC8\xC9" => "\xED\x9B\x94", + "\xC8\xCA" => "\xED\x9B\x97", + "\xC8\xCB" => "\xED\x9B\x99", + "\xC8\xCC" => "\xED\x9B\xA0", + "\xC8\xCD" => "\xED\x9B\xA4", + "\xC8\xCE" => "\xED\x9B\xA8", + "\xC8\xCF" => "\xED\x9B\xB0", + "\xC8\xD0" => "\xED\x9B\xB5", + "\xC8\xD1" => "\xED\x9B\xBC", + "\xC8\xD2" => "\xED\x9B\xBD", + "\xC8\xD3" => "\xED\x9C\x80", + "\xC8\xD4" => "\xED\x9C\x84", + "\xC8\xD5" => "\xED\x9C\x91", + "\xC8\xD6" => "\xED\x9C\x98", + "\xC8\xD7" => "\xED\x9C\x99", + "\xC8\xD8" => "\xED\x9C\x9C", + "\xC8\xD9" => "\xED\x9C\xA0", + "\xC8\xDA" => "\xED\x9C\xA8", + "\xC8\xDB" => "\xED\x9C\xA9", + "\xC8\xDC" => "\xED\x9C\xAB", + "\xC8\xDD" => "\xED\x9C\xAD", + "\xC8\xDE" => "\xED\x9C\xB4", + "\xC8\xDF" => "\xED\x9C\xB5", + "\xC8\xE0" => "\xED\x9C\xB8", + "\xC8\xE1" => "\xED\x9C\xBC", + "\xC8\xE2" => "\xED\x9D\x84", + "\xC8\xE3" => "\xED\x9D\x87", + "\xC8\xE4" => "\xED\x9D\x89", + "\xC8\xE5" => "\xED\x9D\x90", + "\xC8\xE6" => "\xED\x9D\x91", + "\xC8\xE7" => "\xED\x9D\x94", + "\xC8\xE8" => "\xED\x9D\x96", + "\xC8\xE9" => "\xED\x9D\x97", + "\xC8\xEA" => "\xED\x9D\x98", + "\xC8\xEB" => "\xED\x9D\x99", + "\xC8\xEC" => "\xED\x9D\xA0", + "\xC8\xED" => "\xED\x9D\xA1", + "\xC8\xEE" => "\xED\x9D\xA3", + "\xC8\xEF" => "\xED\x9D\xA5", + "\xC8\xF0" => "\xED\x9D\xA9", + "\xC8\xF1" => "\xED\x9D\xAC", + "\xC8\xF2" => "\xED\x9D\xB0", + "\xC8\xF3" => "\xED\x9D\xB4", + "\xC8\xF4" => "\xED\x9D\xBC", + "\xC8\xF5" => "\xED\x9D\xBD", + "\xC8\xF6" => "\xED\x9E\x81", + "\xC8\xF7" => "\xED\x9E\x88", + "\xC8\xF8" => "\xED\x9E\x89", + "\xC8\xF9" => "\xED\x9E\x8C", + "\xC8\xFA" => "\xED\x9E\x90", + "\xC8\xFB" => "\xED\x9E\x98", + "\xC8\xFC" => "\xED\x9E\x99", + "\xC8\xFD" => "\xED\x9E\x9B", + "\xC8\xFE" => "\xED\x9E\x9D", + "\xCA\xA1" => "\xE4\xBC\xBD", + "\xCA\xA2" => "\xE4\xBD\xB3", + "\xCA\xA3" => "\xE5\x81\x87", + "\xCA\xA4" => "\xE5\x83\xB9", + "\xCA\xA5" => "\xE5\x8A\xA0", + "\xCA\xA6" => "\xE5\x8F\xAF", + "\xCA\xA7" => "\xE5\x91\xB5", + "\xCA\xA8" => "\xE5\x93\xA5", + "\xCA\xA9" => "\xE5\x98\x89", + "\xCA\xAA" => "\xE5\xAB\x81", + "\xCA\xAB" => "\xE5\xAE\xB6", + "\xCA\xAC" => "\xE6\x9A\x87", + "\xCA\xAD" => "\xE6\x9E\xB6", + "\xCA\xAE" => "\xE6\x9E\xB7", + "\xCA\xAF" => "\xE6\x9F\xAF", + "\xCA\xB0" => "\xE6\xAD\x8C", + "\xCA\xB1" => "\xE7\x8F\x82", + "\xCA\xB2" => "\xE7\x97\x82", + "\xCA\xB3" => "\xE7\xA8\xBC", + "\xCA\xB4" => "\xE8\x8B\x9B", + "\xCA\xB5" => "\xE8\x8C\x84", + "\xCA\xB6" => "\xE8\xA1\x97", + "\xCA\xB7" => "\xE8\xA2\x88", + "\xCA\xB8" => "\xE8\xA8\xB6", + "\xCA\xB9" => "\xE8\xB3\x88", + "\xCA\xBA" => "\xE8\xB7\x8F", + "\xCA\xBB" => "\xE8\xBB\xBB", + "\xCA\xBC" => "\xE8\xBF\xA6", + "\xCA\xBD" => "\xE9\xA7\x95", + "\xCA\xBE" => "\xE5\x88\xBB", + "\xCA\xBF" => "\xE5\x8D\xB4", + "\xCA\xC0" => "\xE5\x90\x84", + "\xCA\xC1" => "\xE6\x81\xAA", + "\xCA\xC2" => "\xE6\x85\xA4", + "\xCA\xC3" => "\xE6\xAE\xBC", + "\xCA\xC4" => "\xE7\x8F\x8F", + "\xCA\xC5" => "\xE8\x84\x9A", + "\xCA\xC6" => "\xE8\xA6\xBA", + "\xCA\xC7" => "\xE8\xA7\x92", + "\xCA\xC8" => "\xE9\x96\xA3", + "\xCA\xC9" => "\xE4\xBE\x83", + "\xCA\xCA" => "\xE5\x88\x8A", + "\xCA\xCB" => "\xE5\xA2\xBE", + "\xCA\xCC" => "\xE5\xA5\xB8", + "\xCA\xCD" => "\xE5\xA7\xA6", + "\xCA\xCE" => "\xE5\xB9\xB2", + "\xCA\xCF" => "\xE5\xB9\xB9", + "\xCA\xD0" => "\xE6\x87\x87", + "\xCA\xD1" => "\xE6\x8F\x80", + "\xCA\xD2" => "\xE6\x9D\x86", + "\xCA\xD3" => "\xE6\x9F\xAC", + "\xCA\xD4" => "\xE6\xA1\xBF", + "\xCA\xD5" => "\xE6\xBE\x97", + "\xCA\xD6" => "\xE7\x99\x8E", + "\xCA\xD7" => "\xE7\x9C\x8B", + "\xCA\xD8" => "\xE7\xA3\xB5", + "\xCA\xD9" => "\xE7\xA8\x88", + "\xCA\xDA" => "\xE7\xAB\xBF", + "\xCA\xDB" => "\xE7\xB0\xA1", + "\xCA\xDC" => "\xE8\x82\x9D", + "\xCA\xDD" => "\xE8\x89\xAE", + "\xCA\xDE" => "\xE8\x89\xB1", + "\xCA\xDF" => "\xE8\xAB\xAB", + "\xCA\xE0" => "\xE9\x96\x93", + "\xCA\xE1" => "\xE4\xB9\xAB", + "\xCA\xE2" => "\xE5\x96\x9D", + "\xCA\xE3" => "\xE6\x9B\xB7", + "\xCA\xE4" => "\xE6\xB8\xB4", + "\xCA\xE5" => "\xE7\xA2\xA3", + "\xCA\xE6" => "\xE7\xAB\xAD", + "\xCA\xE7" => "\xE8\x91\x9B", + "\xCA\xE8" => "\xE8\xA4\x90", + "\xCA\xE9" => "\xE8\x9D\x8E", + "\xCA\xEA" => "\xE9\x9E\xA8", + "\xCA\xEB" => "\xE5\x8B\x98", + "\xCA\xEC" => "\xE5\x9D\x8E", + "\xCA\xED" => "\xE5\xA0\xAA", + "\xCA\xEE" => "\xE5\xB5\x8C", + "\xCA\xEF" => "\xE6\x84\x9F", + "\xCA\xF0" => "\xE6\x86\xBE", + "\xCA\xF1" => "\xE6\x88\xA1", + "\xCA\xF2" => "\xE6\x95\xA2", + "\xCA\xF3" => "\xE6\x9F\x91", + "\xCA\xF4" => "\xE6\xA9\x84", + "\xCA\xF5" => "\xE6\xB8\x9B", + "\xCA\xF6" => "\xE7\x94\x98", + "\xCA\xF7" => "\xE7\x96\xB3", + "\xCA\xF8" => "\xE7\x9B\xA3", + "\xCA\xF9" => "\xE7\x9E\xB0", + "\xCA\xFA" => "\xE7\xB4\xBA", + "\xCA\xFB" => "\xE9\x82\xAF", + "\xCA\xFC" => "\xE9\x91\x91", + "\xCA\xFD" => "\xE9\x91\x92", + "\xCA\xFE" => "\xE9\xBE\x95", + "\xCB\xA1" => "\xE5\x8C\xA3", + "\xCB\xA2" => "\xE5\xB2\xAC", + "\xCB\xA3" => "\xE7\x94\xB2", + "\xCB\xA4" => "\xE8\x83\x9B", + "\xCB\xA5" => "\xE9\x89\x80", + "\xCB\xA6" => "\xE9\x96\x98", + "\xCB\xA7" => "\xE5\x89\x9B", + "\xCB\xA8" => "\xE5\xA0\x88", + "\xCB\xA9" => "\xE5\xA7\x9C", + "\xCB\xAA" => "\xE5\xB2\xA1", + "\xCB\xAB" => "\xE5\xB4\x97", + "\xCB\xAC" => "\xE5\xBA\xB7", + "\xCB\xAD" => "\xE5\xBC\xBA", + "\xCB\xAE" => "\xE5\xBD\x8A", + "\xCB\xAF" => "\xE6\x85\xB7", + "\xCB\xB0" => "\xE6\xB1\x9F", + "\xCB\xB1" => "\xE7\x95\xBA", + "\xCB\xB2" => "\xE7\x96\x86", + "\xCB\xB3" => "\xE7\xB3\xA0", + "\xCB\xB4" => "\xE7\xB5\xB3", + "\xCB\xB5" => "\xE7\xB6\xB1", + "\xCB\xB6" => "\xE7\xBE\x8C", + "\xCB\xB7" => "\xE8\x85\x94", + "\xCB\xB8" => "\xE8\x88\xA1", + "\xCB\xB9" => "\xE8\x96\x91", + "\xCB\xBA" => "\xE8\xA5\x81", + "\xCB\xBB" => "\xE8\xAC\x9B", + "\xCB\xBC" => "\xE9\x8B\xBC", + "\xCB\xBD" => "\xE9\x99\x8D", + "\xCB\xBE" => "\xE9\xB1\x87", + "\xCB\xBF" => "\xE4\xBB\x8B", + "\xCB\xC0" => "\xE4\xBB\xB7", + "\xCB\xC1" => "\xE5\x80\x8B", + "\xCB\xC2" => "\xE5\x87\xB1", + "\xCB\xC3" => "\xE5\xA1\x8F", + "\xCB\xC4" => "\xE6\x84\xB7", + "\xCB\xC5" => "\xE6\x84\xBE", + "\xCB\xC6" => "\xE6\x85\xA8", + "\xCB\xC7" => "\xE6\x94\xB9", + "\xCB\xC8" => "\xE6\xA7\xAA", + "\xCB\xC9" => "\xE6\xBC\x91", + "\xCB\xCA" => "\xE7\x96\xA5", + "\xCB\xCB" => "\xE7\x9A\x86", + "\xCB\xCC" => "\xE7\x9B\x96", + "\xCB\xCD" => "\xE7\xAE\x87", + "\xCB\xCE" => "\xE8\x8A\xA5", + "\xCB\xCF" => "\xE8\x93\x8B", + "\xCB\xD0" => "\xEF\xA4\x80", + "\xCB\xD1" => "\xE9\x8E\xA7", + "\xCB\xD2" => "\xE9\x96\x8B", + "\xCB\xD3" => "\xE5\x96\x80", + "\xCB\xD4" => "\xE5\xAE\xA2", + "\xCB\xD5" => "\xE5\x9D\x91", + "\xCB\xD6" => "\xEF\xA4\x81", + "\xCB\xD7" => "\xE7\xB2\xB3", + "\xCB\xD8" => "\xE7\xBE\xB9", + "\xCB\xD9" => "\xE9\x86\xB5", + "\xCB\xDA" => "\xE5\x80\xA8", + "\xCB\xDB" => "\xE5\x8E\xBB", + "\xCB\xDC" => "\xE5\xB1\x85", + "\xCB\xDD" => "\xE5\xB7\xA8", + "\xCB\xDE" => "\xE6\x8B\x92", + "\xCB\xDF" => "\xE6\x8D\xAE", + "\xCB\xE0" => "\xE6\x93\x9A", + "\xCB\xE1" => "\xE6\x93\xA7", + "\xCB\xE2" => "\xE6\xB8\xA0", + "\xCB\xE3" => "\xE7\x82\xAC", + "\xCB\xE4" => "\xE7\xA5\x9B", + "\xCB\xE5" => "\xE8\xB7\x9D", + "\xCB\xE6" => "\xE8\xB8\x9E", + "\xCB\xE7" => "\xEF\xA4\x82", + "\xCB\xE8" => "\xE9\x81\xBD", + "\xCB\xE9" => "\xE9\x89\x85", + "\xCB\xEA" => "\xE9\x8B\xB8", + "\xCB\xEB" => "\xE4\xB9\xBE", + "\xCB\xEC" => "\xE4\xBB\xB6", + "\xCB\xED" => "\xE5\x81\xA5", + "\xCB\xEE" => "\xE5\xB7\xBE", + "\xCB\xEF" => "\xE5\xBB\xBA", + "\xCB\xF0" => "\xE6\x84\x86", + "\xCB\xF1" => "\xE6\xA5\x97", + "\xCB\xF2" => "\xE8\x85\xB1", + "\xCB\xF3" => "\xE8\x99\x94", + "\xCB\xF4" => "\xE8\xB9\x87", + "\xCB\xF5" => "\xE9\x8D\xB5", + "\xCB\xF6" => "\xE9\xA8\xAB", + "\xCB\xF7" => "\xE4\xB9\x9E", + "\xCB\xF8" => "\xE5\x82\x91", + "\xCB\xF9" => "\xE6\x9D\xB0", + "\xCB\xFA" => "\xE6\xA1\x80", + "\xCB\xFB" => "\xE5\x84\x89", + "\xCB\xFC" => "\xE5\x8A\x8D", + "\xCB\xFD" => "\xE5\x8A\x92", + "\xCB\xFE" => "\xE6\xAA\xA2", + "\xCC\xA1" => "\xE7\x9E\xBC", + "\xCC\xA2" => "\xE9\x88\x90", + "\xCC\xA3" => "\xE9\xBB\x94", + "\xCC\xA4" => "\xE5\x8A\xAB", + "\xCC\xA5" => "\xE6\x80\xAF", + "\xCC\xA6" => "\xE8\xBF\xB2", + "\xCC\xA7" => "\xE5\x81\x88", + "\xCC\xA8" => "\xE6\x86\xA9", + "\xCC\xA9" => "\xE6\x8F\xAD", + "\xCC\xAA" => "\xE6\x93\x8A", + "\xCC\xAB" => "\xE6\xA0\xBC", + "\xCC\xAC" => "\xE6\xAA\x84", + "\xCC\xAD" => "\xE6\xBF\x80", + "\xCC\xAE" => "\xE8\x86\x88", + "\xCC\xAF" => "\xE8\xA6\xA1", + "\xCC\xB0" => "\xE9\x9A\x94", + "\xCC\xB1" => "\xE5\xA0\x85", + "\xCC\xB2" => "\xE7\x89\xBD", + "\xCC\xB3" => "\xE7\x8A\xAC", + "\xCC\xB4" => "\xE7\x94\x84", + "\xCC\xB5" => "\xE7\xB5\xB9", + "\xCC\xB6" => "\xE7\xB9\xAD", + "\xCC\xB7" => "\xE8\x82\xA9", + "\xCC\xB8" => "\xE8\xA6\x8B", + "\xCC\xB9" => "\xE8\xAD\xB4", + "\xCC\xBA" => "\xE9\x81\xA3", + "\xCC\xBB" => "\xE9\xB5\x91", + "\xCC\xBC" => "\xE6\x8A\x89", + "\xCC\xBD" => "\xE6\xB1\xBA", + "\xCC\xBE" => "\xE6\xBD\x94", + "\xCC\xBF" => "\xE7\xB5\x90", + "\xCC\xC0" => "\xE7\xBC\xBA", + "\xCC\xC1" => "\xE8\xA8\xA3", + "\xCC\xC2" => "\xE5\x85\xBC", + "\xCC\xC3" => "\xE6\x85\x8A", + "\xCC\xC4" => "\xE7\xAE\x9D", + "\xCC\xC5" => "\xE8\xAC\x99", + "\xCC\xC6" => "\xE9\x89\x97", + "\xCC\xC7" => "\xE9\x8E\x8C", + "\xCC\xC8" => "\xE4\xBA\xAC", + "\xCC\xC9" => "\xE4\xBF\x93", + "\xCC\xCA" => "\xE5\x80\x9E", + "\xCC\xCB" => "\xE5\x82\xBE", + "\xCC\xCC" => "\xE5\x84\x86", + "\xCC\xCD" => "\xE5\x8B\x81", + "\xCC\xCE" => "\xE5\x8B\x8D", + "\xCC\xCF" => "\xE5\x8D\xBF", + "\xCC\xD0" => "\xE5\x9D\xB0", + "\xCC\xD1" => "\xE5\xA2\x83", + "\xCC\xD2" => "\xE5\xBA\x9A", + "\xCC\xD3" => "\xE5\xBE\x91", + "\xCC\xD4" => "\xE6\x85\xB6", + "\xCC\xD5" => "\xE6\x86\xAC", + "\xCC\xD6" => "\xE6\x93\x8E", + "\xCC\xD7" => "\xE6\x95\xAC", + "\xCC\xD8" => "\xE6\x99\xAF", + "\xCC\xD9" => "\xE6\x9A\xBB", + "\xCC\xDA" => "\xE6\x9B\xB4", + "\xCC\xDB" => "\xE6\xA2\x97", + "\xCC\xDC" => "\xE6\xB6\x87", + "\xCC\xDD" => "\xE7\x82\x85", + "\xCC\xDE" => "\xE7\x83\xB1", + "\xCC\xDF" => "\xE7\x92\x9F", + "\xCC\xE0" => "\xE7\x92\xA5", + "\xCC\xE1" => "\xE7\x93\x8A", + "\xCC\xE2" => "\xE7\x97\x99", + "\xCC\xE3" => "\xE7\xA1\xAC", + "\xCC\xE4" => "\xE7\xA3\xAC", + "\xCC\xE5" => "\xE7\xAB\x9F", + "\xCC\xE6" => "\xE7\xAB\xB6", + "\xCC\xE7" => "\xE7\xB5\x85", + "\xCC\xE8" => "\xE7\xB6\x93", + "\xCC\xE9" => "\xE8\x80\x95", + "\xCC\xEA" => "\xE8\x80\xBF", + "\xCC\xEB" => "\xE8\x84\x9B", + "\xCC\xEC" => "\xE8\x8E\x96", + "\xCC\xED" => "\xE8\xAD\xA6", + "\xCC\xEE" => "\xE8\xBC\x95", + "\xCC\xEF" => "\xE9\x80\x95", + "\xCC\xF0" => "\xE9\x8F\xA1", + "\xCC\xF1" => "\xE9\xA0\x83", + "\xCC\xF2" => "\xE9\xA0\xB8", + "\xCC\xF3" => "\xE9\xA9\x9A", + "\xCC\xF4" => "\xE9\xAF\xA8", + "\xCC\xF5" => "\xE4\xBF\x82", + "\xCC\xF6" => "\xE5\x95\x93", + "\xCC\xF7" => "\xE5\xA0\xBA", + "\xCC\xF8" => "\xE5\xA5\x91", + "\xCC\xF9" => "\xE5\xAD\xA3", + "\xCC\xFA" => "\xE5\xB1\x86", + "\xCC\xFB" => "\xE6\x82\xB8", + "\xCC\xFC" => "\xE6\x88\x92", + "\xCC\xFD" => "\xE6\xA1\x82", + "\xCC\xFE" => "\xE6\xA2\xB0", + "\xCD\xA1" => "\xE6\xA3\xA8", + "\xCD\xA2" => "\xE6\xBA\xAA", + "\xCD\xA3" => "\xE7\x95\x8C", + "\xCD\xA4" => "\xE7\x99\xB8", + "\xCD\xA5" => "\xE7\xA3\x8E", + "\xCD\xA6" => "\xE7\xA8\xBD", + "\xCD\xA7" => "\xE7\xB3\xBB", + "\xCD\xA8" => "\xE7\xB9\xAB", + "\xCD\xA9" => "\xE7\xB9\xBC", + "\xCD\xAA" => "\xE8\xA8\x88", + "\xCD\xAB" => "\xE8\xAA\xA1", + "\xCD\xAC" => "\xE8\xB0\xBF", + "\xCD\xAD" => "\xE9\x9A\x8E", + "\xCD\xAE" => "\xE9\xB7\x84", + "\xCD\xAF" => "\xE5\x8F\xA4", + "\xCD\xB0" => "\xE5\x8F\xA9", + "\xCD\xB1" => "\xE5\x91\x8A", + "\xCD\xB2" => "\xE5\x91\xB1", + "\xCD\xB3" => "\xE5\x9B\xBA", + "\xCD\xB4" => "\xE5\xA7\x91", + "\xCD\xB5" => "\xE5\xAD\xA4", + "\xCD\xB6" => "\xE5\xB0\xBB", + "\xCD\xB7" => "\xE5\xBA\xAB", + "\xCD\xB8" => "\xE6\x8B\xB7", + "\xCD\xB9" => "\xE6\x94\xB7", + "\xCD\xBA" => "\xE6\x95\x85", + "\xCD\xBB" => "\xE6\x95\xB2", + "\xCD\xBC" => "\xE6\x9A\xA0", + "\xCD\xBD" => "\xE6\x9E\xAF", + "\xCD\xBE" => "\xE6\xA7\x81", + "\xCD\xBF" => "\xE6\xB2\xBD", + "\xCD\xC0" => "\xE7\x97\xBC", + "\xCD\xC1" => "\xE7\x9A\x90", + "\xCD\xC2" => "\xE7\x9D\xBE", + "\xCD\xC3" => "\xE7\xA8\xBF", + "\xCD\xC4" => "\xE7\xBE\x94", + "\xCD\xC5" => "\xE8\x80\x83", + "\xCD\xC6" => "\xE8\x82\xA1", + "\xCD\xC7" => "\xE8\x86\x8F", + "\xCD\xC8" => "\xE8\x8B\xA6", + "\xCD\xC9" => "\xE8\x8B\xBD", + "\xCD\xCA" => "\xE8\x8F\xB0", + "\xCD\xCB" => "\xE8\x97\x81", + "\xCD\xCC" => "\xE8\xA0\xB1", + "\xCD\xCD" => "\xE8\xA2\xB4", + "\xCD\xCE" => "\xE8\xAA\xA5", + "\xCD\xCF" => "\xEF\xA4\x83", + "\xCD\xD0" => "\xE8\xBE\x9C", + "\xCD\xD1" => "\xE9\x8C\xAE", + "\xCD\xD2" => "\xE9\x9B\x87", + "\xCD\xD3" => "\xE9\xA1\xA7", + "\xCD\xD4" => "\xE9\xAB\x98", + "\xCD\xD5" => "\xE9\xBC\x93", + "\xCD\xD6" => "\xE5\x93\xAD", + "\xCD\xD7" => "\xE6\x96\x9B", + "\xCD\xD8" => "\xE6\x9B\xB2", + "\xCD\xD9" => "\xE6\xA2\x8F", + "\xCD\xDA" => "\xE7\xA9\x80", + "\xCD\xDB" => "\xE8\xB0\xB7", + "\xCD\xDC" => "\xE9\xB5\xA0", + "\xCD\xDD" => "\xE5\x9B\xB0", + "\xCD\xDE" => "\xE5\x9D\xA4", + "\xCD\xDF" => "\xE5\xB4\x91", + "\xCD\xE0" => "\xE6\x98\x86", + "\xCD\xE1" => "\xE6\xA2\xB1", + "\xCD\xE2" => "\xE6\xA3\x8D", + "\xCD\xE3" => "\xE6\xBB\xBE", + "\xCD\xE4" => "\xE7\x90\xA8", + "\xCD\xE5" => "\xE8\xA2\x9E", + "\xCD\xE6" => "\xE9\xAF\xA4", + "\xCD\xE7" => "\xE6\xB1\xA8", + "\xCD\xE8" => "\xEF\xA4\x84", + "\xCD\xE9" => "\xE9\xAA\xA8", + "\xCD\xEA" => "\xE4\xBE\x9B", + "\xCD\xEB" => "\xE5\x85\xAC", + "\xCD\xEC" => "\xE5\x85\xB1", + "\xCD\xED" => "\xE5\x8A\x9F", + "\xCD\xEE" => "\xE5\xAD\x94", + "\xCD\xEF" => "\xE5\xB7\xA5", + "\xCD\xF0" => "\xE6\x81\x90", + "\xCD\xF1" => "\xE6\x81\xAD", + "\xCD\xF2" => "\xE6\x8B\xB1", + "\xCD\xF3" => "\xE6\x8E\xA7", + "\xCD\xF4" => "\xE6\x94\xBB", + "\xCD\xF5" => "\xE7\x8F\x99", + "\xCD\xF6" => "\xE7\xA9\xBA", + "\xCD\xF7" => "\xE8\x9A\xA3", + "\xCD\xF8" => "\xE8\xB2\xA2", + "\xCD\xF9" => "\xE9\x9E\x8F", + "\xCD\xFA" => "\xE4\xB8\xB2", + "\xCD\xFB" => "\xE5\xAF\xA1", + "\xCD\xFC" => "\xE6\x88\x88", + "\xCD\xFD" => "\xE6\x9E\x9C", + "\xCD\xFE" => "\xE7\x93\x9C", + "\xCE\xA1" => "\xE7\xA7\x91", + "\xCE\xA2" => "\xE8\x8F\x93", + "\xCE\xA3" => "\xE8\xAA\x87", + "\xCE\xA4" => "\xE8\xAA\xB2", + "\xCE\xA5" => "\xE8\xB7\xA8", + "\xCE\xA6" => "\xE9\x81\x8E", + "\xCE\xA7" => "\xE9\x8D\x8B", + "\xCE\xA8" => "\xE9\xA1\x86", + "\xCE\xA9" => "\xE5\xBB\x93", + "\xCE\xAA" => "\xE6\xA7\xA8", + "\xCE\xAB" => "\xE8\x97\xBF", + "\xCE\xAC" => "\xE9\x83\xAD", + "\xCE\xAD" => "\xEF\xA4\x85", + "\xCE\xAE" => "\xE5\x86\xA0", + "\xCE\xAF" => "\xE5\xAE\x98", + "\xCE\xB0" => "\xE5\xAF\xAC", + "\xCE\xB1" => "\xE6\x85\xA3", + "\xCE\xB2" => "\xE6\xA3\xBA", + "\xCE\xB3" => "\xE6\xAC\xBE", + "\xCE\xB4" => "\xE7\x81\x8C", + "\xCE\xB5" => "\xE7\x90\xAF", + "\xCE\xB6" => "\xE7\x93\x98", + "\xCE\xB7" => "\xE7\xAE\xA1", + "\xCE\xB8" => "\xE7\xBD\x90", + "\xCE\xB9" => "\xE8\x8F\x85", + "\xCE\xBA" => "\xE8\xA7\x80", + "\xCE\xBB" => "\xE8\xB2\xAB", + "\xCE\xBC" => "\xE9\x97\x9C", + "\xCE\xBD" => "\xE9\xA4\xA8", + "\xCE\xBE" => "\xE5\x88\xAE", + "\xCE\xBF" => "\xE6\x81\x9D", + "\xCE\xC0" => "\xE6\x8B\xAC", + "\xCE\xC1" => "\xE9\x80\x82", + "\xCE\xC2" => "\xE4\xBE\x8A", + "\xCE\xC3" => "\xE5\x85\x89", + "\xCE\xC4" => "\xE5\x8C\xA1", + "\xCE\xC5" => "\xE5\xA3\x99", + "\xCE\xC6" => "\xE5\xBB\xA3", + "\xCE\xC7" => "\xE6\x9B\xA0", + "\xCE\xC8" => "\xE6\xB4\xB8", + "\xCE\xC9" => "\xE7\x82\x9A", + "\xCE\xCA" => "\xE7\x8B\x82", + "\xCE\xCB" => "\xE7\x8F\x96", + "\xCE\xCC" => "\xE7\xAD\x90", + "\xCE\xCD" => "\xE8\x83\xB1", + "\xCE\xCE" => "\xE9\x91\x9B", + "\xCE\xCF" => "\xE5\x8D\xA6", + "\xCE\xD0" => "\xE6\x8E\x9B", + "\xCE\xD1" => "\xE7\xBD\xAB", + "\xCE\xD2" => "\xE4\xB9\x96", + "\xCE\xD3" => "\xE5\x82\x80", + "\xCE\xD4" => "\xE5\xA1\x8A", + "\xCE\xD5" => "\xE5\xA3\x9E", + "\xCE\xD6" => "\xE6\x80\xAA", + "\xCE\xD7" => "\xE6\x84\xA7", + "\xCE\xD8" => "\xE6\x8B\x90", + "\xCE\xD9" => "\xE6\xA7\x90", + "\xCE\xDA" => "\xE9\xAD\x81", + "\xCE\xDB" => "\xE5\xAE\x8F", + "\xCE\xDC" => "\xE7\xB4\x98", + "\xCE\xDD" => "\xE8\x82\xB1", + "\xCE\xDE" => "\xE8\xBD\x9F", + "\xCE\xDF" => "\xE4\xBA\xA4", + "\xCE\xE0" => "\xE5\x83\x91", + "\xCE\xE1" => "\xE5\x92\xAC", + "\xCE\xE2" => "\xE5\x96\xAC", + "\xCE\xE3" => "\xE5\xAC\x8C", + "\xCE\xE4" => "\xE5\xB6\xA0", + "\xCE\xE5" => "\xE5\xB7\xA7", + "\xCE\xE6" => "\xE6\x94\xAA", + "\xCE\xE7" => "\xE6\x95\x8E", + "\xCE\xE8" => "\xE6\xA0\xA1", + "\xCE\xE9" => "\xE6\xA9\x8B", + "\xCE\xEA" => "\xE7\x8B\xA1", + "\xCE\xEB" => "\xE7\x9A\x8E", + "\xCE\xEC" => "\xE7\x9F\xAF", + "\xCE\xED" => "\xE7\xB5\x9E", + "\xCE\xEE" => "\xE7\xBF\xB9", + "\xCE\xEF" => "\xE8\x86\xA0", + "\xCE\xF0" => "\xE8\x95\x8E", + "\xCE\xF1" => "\xE8\x9B\x9F", + "\xCE\xF2" => "\xE8\xBC\x83", + "\xCE\xF3" => "\xE8\xBD\x8E", + "\xCE\xF4" => "\xE9\x83\x8A", + "\xCE\xF5" => "\xE9\xA4\x83", + "\xCE\xF6" => "\xE9\xA9\x95", + "\xCE\xF7" => "\xE9\xAE\xAB", + "\xCE\xF8" => "\xE4\xB8\x98", + "\xCE\xF9" => "\xE4\xB9\x85", + "\xCE\xFA" => "\xE4\xB9\x9D", + "\xCE\xFB" => "\xE4\xBB\x87", + "\xCE\xFC" => "\xE4\xBF\xB1", + "\xCE\xFD" => "\xE5\x85\xB7", + "\xCE\xFE" => "\xE5\x8B\xBE", + "\xCF\xA1" => "\xE5\x8D\x80", + "\xCF\xA2" => "\xE5\x8F\xA3", + "\xCF\xA3" => "\xE5\x8F\xA5", + "\xCF\xA4" => "\xE5\x92\x8E", + "\xCF\xA5" => "\xE5\x98\x94", + "\xCF\xA6" => "\xE5\x9D\xB5", + "\xCF\xA7" => "\xE5\x9E\xA2", + "\xCF\xA8" => "\xE5\xAF\x87", + "\xCF\xA9" => "\xE5\xB6\x87", + "\xCF\xAA" => "\xE5\xBB\x90", + "\xCF\xAB" => "\xE6\x87\xBC", + "\xCF\xAC" => "\xE6\x8B\x98", + "\xCF\xAD" => "\xE6\x95\x91", + "\xCF\xAE" => "\xE6\x9E\xB8", + "\xCF\xAF" => "\xE6\x9F\xA9", + "\xCF\xB0" => "\xE6\xA7\x8B", + "\xCF\xB1" => "\xE6\xAD\x90", + "\xCF\xB2" => "\xE6\xAF\x86", + "\xCF\xB3" => "\xE6\xAF\xAC", + "\xCF\xB4" => "\xE6\xB1\x82", + "\xCF\xB5" => "\xE6\xBA\x9D", + "\xCF\xB6" => "\xE7\x81\xB8", + "\xCF\xB7" => "\xE7\x8B\x97", + "\xCF\xB8" => "\xE7\x8E\x96", + "\xCF\xB9" => "\xE7\x90\x83", + "\xCF\xBA" => "\xE7\x9E\xBF", + "\xCF\xBB" => "\xE7\x9F\xA9", + "\xCF\xBC" => "\xE7\xA9\xB6", + "\xCF\xBD" => "\xE7\xB5\xBF", + "\xCF\xBE" => "\xE8\x80\x89", + "\xCF\xBF" => "\xE8\x87\xBC", + "\xCF\xC0" => "\xE8\x88\x85", + "\xCF\xC1" => "\xE8\x88\x8A", + "\xCF\xC2" => "\xE8\x8B\x9F", + "\xCF\xC3" => "\xE8\xA1\xA2", + "\xCF\xC4" => "\xE8\xAC\xB3", + "\xCF\xC5" => "\xE8\xB3\xBC", + "\xCF\xC6" => "\xE8\xBB\x80", + "\xCF\xC7" => "\xE9\x80\x91", + "\xCF\xC8" => "\xE9\x82\xB1", + "\xCF\xC9" => "\xE9\x89\xA4", + "\xCF\xCA" => "\xE9\x8A\xB6", + "\xCF\xCB" => "\xE9\xA7\x92", + "\xCF\xCC" => "\xE9\xA9\x85", + "\xCF\xCD" => "\xE9\xB3\xA9", + "\xCF\xCE" => "\xE9\xB7\x97", + "\xCF\xCF" => "\xE9\xBE\x9C", + "\xCF\xD0" => "\xE5\x9C\x8B", + "\xCF\xD1" => "\xE5\xB1\x80", + "\xCF\xD2" => "\xE8\x8F\x8A", + "\xCF\xD3" => "\xE9\x9E\xA0", + "\xCF\xD4" => "\xE9\x9E\xAB", + "\xCF\xD5" => "\xE9\xBA\xB4", + "\xCF\xD6" => "\xE5\x90\x9B", + "\xCF\xD7" => "\xE7\xAA\x98", + "\xCF\xD8" => "\xE7\xBE\xA4", + "\xCF\xD9" => "\xE8\xA3\x99", + "\xCF\xDA" => "\xE8\xBB\x8D", + "\xCF\xDB" => "\xE9\x83\xA1", + "\xCF\xDC" => "\xE5\xA0\x80", + "\xCF\xDD" => "\xE5\xB1\x88", + "\xCF\xDE" => "\xE6\x8E\x98", + "\xCF\xDF" => "\xE7\xAA\x9F", + "\xCF\xE0" => "\xE5\xAE\xAE", + "\xCF\xE1" => "\xE5\xBC\x93", + "\xCF\xE2" => "\xE7\xA9\xB9", + "\xCF\xE3" => "\xE7\xAA\xAE", + "\xCF\xE4" => "\xE8\x8A\x8E", + "\xCF\xE5" => "\xE8\xBA\xAC", + "\xCF\xE6" => "\xE5\x80\xA6", + "\xCF\xE7" => "\xE5\x88\xB8", + "\xCF\xE8" => "\xE5\x8B\xB8", + "\xCF\xE9" => "\xE5\x8D\xB7", + "\xCF\xEA" => "\xE5\x9C\x88", + "\xCF\xEB" => "\xE6\x8B\xB3", + "\xCF\xEC" => "\xE6\x8D\xB2", + "\xCF\xED" => "\xE6\xAC\x8A", + "\xCF\xEE" => "\xE6\xB7\x83", + "\xCF\xEF" => "\xE7\x9C\xB7", + "\xCF\xF0" => "\xE5\x8E\xA5", + "\xCF\xF1" => "\xE7\x8D\x97", + "\xCF\xF2" => "\xE8\x95\xA8", + "\xCF\xF3" => "\xE8\xB9\xB6", + "\xCF\xF4" => "\xE9\x97\x95", + "\xCF\xF5" => "\xE6\x9C\xBA", + "\xCF\xF6" => "\xE6\xAB\x83", + "\xCF\xF7" => "\xE6\xBD\xB0", + "\xCF\xF8" => "\xE8\xA9\xAD", + "\xCF\xF9" => "\xE8\xBB\x8C", + "\xCF\xFA" => "\xE9\xA5\x8B", + "\xCF\xFB" => "\xEF\xA4\x86", + "\xCF\xFC" => "\xE6\x99\xB7", + "\xCF\xFD" => "\xE6\xAD\xB8", + "\xCF\xFE" => "\xE8\xB2\xB4", + "\xD0\xA1" => "\xE9\xAC\xBC", + "\xD0\xA2" => "\xEF\xA4\x87", + "\xD0\xA3" => "\xE5\x8F\xAB", + "\xD0\xA4" => "\xE5\x9C\xAD", + "\xD0\xA5" => "\xE5\xA5\x8E", + "\xD0\xA6" => "\xE6\x8F\x86", + "\xD0\xA7" => "\xE6\xA7\xBB", + "\xD0\xA8" => "\xE7\x8F\xAA", + "\xD0\xA9" => "\xE7\xA1\x85", + "\xD0\xAA" => "\xE7\xAA\xBA", + "\xD0\xAB" => "\xE7\xAB\x85", + "\xD0\xAC" => "\xE7\xB3\xBE", + "\xD0\xAD" => "\xE8\x91\xB5", + "\xD0\xAE" => "\xE8\xA6\x8F", + "\xD0\xAF" => "\xE8\xB5\xB3", + "\xD0\xB0" => "\xE9\x80\xB5", + "\xD0\xB1" => "\xE9\x96\xA8", + "\xD0\xB2" => "\xE5\x8B\xBB", + "\xD0\xB3" => "\xE5\x9D\x87", + "\xD0\xB4" => "\xE7\x95\x87", + "\xD0\xB5" => "\xE7\xAD\xA0", + "\xD0\xB6" => "\xE8\x8F\x8C", + "\xD0\xB7" => "\xE9\x88\x9E", + "\xD0\xB8" => "\xEF\xA4\x88", + "\xD0\xB9" => "\xE6\xA9\x98", + "\xD0\xBA" => "\xE5\x85\x8B", + "\xD0\xBB" => "\xE5\x89\x8B", + "\xD0\xBC" => "\xE5\x8A\x87", + "\xD0\xBD" => "\xE6\x88\x9F", + "\xD0\xBE" => "\xE6\xA3\x98", + "\xD0\xBF" => "\xE6\xA5\xB5", + "\xD0\xC0" => "\xE9\x9A\x99", + "\xD0\xC1" => "\xE5\x83\x85", + "\xD0\xC2" => "\xE5\x8A\xA4", + "\xD0\xC3" => "\xE5\x8B\xA4", + "\xD0\xC4" => "\xE6\x87\x83", + "\xD0\xC5" => "\xE6\x96\xA4", + "\xD0\xC6" => "\xE6\xA0\xB9", + "\xD0\xC7" => "\xE6\xA7\xBF", + "\xD0\xC8" => "\xE7\x91\xBE", + "\xD0\xC9" => "\xE7\xAD\x8B", + "\xD0\xCA" => "\xE8\x8A\xB9", + "\xD0\xCB" => "\xE8\x8F\xAB", + "\xD0\xCC" => "\xE8\xA6\xB2", + "\xD0\xCD" => "\xE8\xAC\xB9", + "\xD0\xCE" => "\xE8\xBF\x91", + "\xD0\xCF" => "\xE9\xA5\x89", + "\xD0\xD0" => "\xEF\xA4\x89", + "\xD0\xD1" => "\xE4\xBB\x8A", + "\xD0\xD2" => "\xE5\xA6\x97", + "\xD0\xD3" => "\xE6\x93\x92", + "\xD0\xD4" => "\xE6\x98\x91", + "\xD0\xD5" => "\xE6\xAA\x8E", + "\xD0\xD6" => "\xE7\x90\xB4", + "\xD0\xD7" => "\xE7\xA6\x81", + "\xD0\xD8" => "\xE7\xA6\xBD", + "\xD0\xD9" => "\xE8\x8A\xA9", + "\xD0\xDA" => "\xE8\xA1\xBE", + "\xD0\xDB" => "\xE8\xA1\xBF", + "\xD0\xDC" => "\xE8\xA5\x9F", + "\xD0\xDD" => "\xEF\xA4\x8A", + "\xD0\xDE" => "\xE9\x8C\xA6", + "\xD0\xDF" => "\xE4\xBC\x8B", + "\xD0\xE0" => "\xE5\x8F\x8A", + "\xD0\xE1" => "\xE6\x80\xA5", + "\xD0\xE2" => "\xE6\x89\xB1", + "\xD0\xE3" => "\xE6\xB1\xB2", + "\xD0\xE4" => "\xE7\xB4\x9A", + "\xD0\xE5" => "\xE7\xB5\xA6", + "\xD0\xE6" => "\xE4\xBA\x98", + "\xD0\xE7" => "\xE5\x85\xA2", + "\xD0\xE8" => "\xE7\x9F\x9C", + "\xD0\xE9" => "\xE8\x82\xAF", + "\xD0\xEA" => "\xE4\xBC\x81", + "\xD0\xEB" => "\xE4\xBC\x8E", + "\xD0\xEC" => "\xE5\x85\xB6", + "\xD0\xED" => "\xE5\x86\x80", + "\xD0\xEE" => "\xE5\x97\x9C", + "\xD0\xEF" => "\xE5\x99\xA8", + "\xD0\xF0" => "\xE5\x9C\xBB", + "\xD0\xF1" => "\xE5\x9F\xBA", + "\xD0\xF2" => "\xE5\x9F\xBC", + "\xD0\xF3" => "\xE5\xA4\x94", + "\xD0\xF4" => "\xE5\xA5\x87", + "\xD0\xF5" => "\xE5\xA6\x93", + "\xD0\xF6" => "\xE5\xAF\x84", + "\xD0\xF7" => "\xE5\xB2\x90", + "\xD0\xF8" => "\xE5\xB4\x8E", + "\xD0\xF9" => "\xE5\xB7\xB1", + "\xD0\xFA" => "\xE5\xB9\xBE", + "\xD0\xFB" => "\xE5\xBF\x8C", + "\xD0\xFC" => "\xE6\x8A\x80", + "\xD0\xFD" => "\xE6\x97\x97", + "\xD0\xFE" => "\xE6\x97\xA3", + "\xD1\xA1" => "\xE6\x9C\x9E", + "\xD1\xA2" => "\xE6\x9C\x9F", + "\xD1\xA3" => "\xE6\x9D\x9E", + "\xD1\xA4" => "\xE6\xA3\x8B", + "\xD1\xA5" => "\xE6\xA3\x84", + "\xD1\xA6" => "\xE6\xA9\x9F", + "\xD1\xA7" => "\xE6\xAC\xBA", + "\xD1\xA8" => "\xE6\xB0\xA3", + "\xD1\xA9" => "\xE6\xB1\xBD", + "\xD1\xAA" => "\xE6\xB2\x82", + "\xD1\xAB" => "\xE6\xB7\x87", + "\xD1\xAC" => "\xE7\x8E\x98", + "\xD1\xAD" => "\xE7\x90\xA6", + "\xD1\xAE" => "\xE7\x90\xAA", + "\xD1\xAF" => "\xE7\x92\x82", + "\xD1\xB0" => "\xE7\x92\xA3", + "\xD1\xB1" => "\xE7\x95\xB8", + "\xD1\xB2" => "\xE7\x95\xBF", + "\xD1\xB3" => "\xE7\xA2\x81", + "\xD1\xB4" => "\xE7\xA3\xAF", + "\xD1\xB5" => "\xE7\xA5\x81", + "\xD1\xB6" => "\xE7\xA5\x87", + "\xD1\xB7" => "\xE7\xA5\x88", + "\xD1\xB8" => "\xE7\xA5\xBA", + "\xD1\xB9" => "\xE7\xAE\x95", + "\xD1\xBA" => "\xE7\xB4\x80", + "\xD1\xBB" => "\xE7\xB6\xBA", + "\xD1\xBC" => "\xE7\xBE\x88", + "\xD1\xBD" => "\xE8\x80\x86", + "\xD1\xBE" => "\xE8\x80\xAD", + "\xD1\xBF" => "\xE8\x82\x8C", + "\xD1\xC0" => "\xE8\xA8\x98", + "\xD1\xC1" => "\xE8\xAD\x8F", + "\xD1\xC2" => "\xE8\xB1\x88", + "\xD1\xC3" => "\xE8\xB5\xB7", + "\xD1\xC4" => "\xE9\x8C\xA1", + "\xD1\xC5" => "\xE9\x8C\xA4", + "\xD1\xC6" => "\xE9\xA3\xA2", + "\xD1\xC7" => "\xE9\xA5\x91", + "\xD1\xC8" => "\xE9\xA8\x8E", + "\xD1\xC9" => "\xE9\xA8\x8F", + "\xD1\xCA" => "\xE9\xA9\xA5", + "\xD1\xCB" => "\xE9\xBA\x92", + "\xD1\xCC" => "\xE7\xB7\x8A", + "\xD1\xCD" => "\xE4\xBD\xB6", + "\xD1\xCE" => "\xE5\x90\x89", + "\xD1\xCF" => "\xE6\x8B\xAE", + "\xD1\xD0" => "\xE6\xA1\x94", + "\xD1\xD1" => "\xE9\x87\x91", + "\xD1\xD2" => "\xE5\x96\xAB", + "\xD1\xD3" => "\xE5\x84\xBA", + "\xD1\xD4" => "\xEF\xA4\x8B", + "\xD1\xD5" => "\xEF\xA4\x8C", + "\xD1\xD6" => "\xE5\xA8\x9C", + "\xD1\xD7" => "\xE6\x87\xA6", + "\xD1\xD8" => "\xEF\xA4\x8D", + "\xD1\xD9" => "\xE6\x8B\x8F", + "\xD1\xDA" => "\xE6\x8B\xBF", + "\xD1\xDB" => "\xEF\xA4\x8E", + "\xD1\xDC" => "\xEF\xA4\x8F", + "\xD1\xDD" => "\xEF\xA4\x90", + "\xD1\xDE" => "\xEF\xA4\x91", + "\xD1\xDF" => "\xEF\xA4\x92", + "\xD1\xE0" => "\xEF\xA4\x93", + "\xD1\xE1" => "\xE9\x82\xA3", + "\xD1\xE2" => "\xEF\xA4\x94", + "\xD1\xE3" => "\xEF\xA4\x95", + "\xD1\xE4" => "\xEF\xA4\x96", + "\xD1\xE5" => "\xEF\xA4\x97", + "\xD1\xE6" => "\xEF\xA4\x98", + "\xD1\xE7" => "\xE8\xAB\xBE", + "\xD1\xE8" => "\xEF\xA4\x99", + "\xD1\xE9" => "\xEF\xA4\x9A", + "\xD1\xEA" => "\xEF\xA4\x9B", + "\xD1\xEB" => "\xEF\xA4\x9C", + "\xD1\xEC" => "\xE6\x9A\x96", + "\xD1\xED" => "\xEF\xA4\x9D", + "\xD1\xEE" => "\xE7\x85\x96", + "\xD1\xEF" => "\xEF\xA4\x9E", + "\xD1\xF0" => "\xEF\xA4\x9F", + "\xD1\xF1" => "\xE9\x9B\xA3", + "\xD1\xF2" => "\xEF\xA4\xA0", + "\xD1\xF3" => "\xE6\x8D\x8F", + "\xD1\xF4" => "\xE6\x8D\xBA", + "\xD1\xF5" => "\xE5\x8D\x97", + "\xD1\xF6" => "\xEF\xA4\xA1", + "\xD1\xF7" => "\xE6\x9E\x8F", + "\xD1\xF8" => "\xE6\xA5\xA0", + "\xD1\xF9" => "\xE6\xB9\xB3", + "\xD1\xFA" => "\xEF\xA4\xA2", + "\xD1\xFB" => "\xE7\x94\xB7", + "\xD1\xFC" => "\xEF\xA4\xA3", + "\xD1\xFD" => "\xEF\xA4\xA4", + "\xD1\xFE" => "\xEF\xA4\xA5", + "\xD2\xA1" => "\xE7\xB4\x8D", + "\xD2\xA2" => "\xEF\xA4\xA6", + "\xD2\xA3" => "\xEF\xA4\xA7", + "\xD2\xA4" => "\xE8\xA1\xB2", + "\xD2\xA5" => "\xE5\x9B\x8A", + "\xD2\xA6" => "\xE5\xA8\x98", + "\xD2\xA7" => "\xEF\xA4\xA8", + "\xD2\xA8" => "\xEF\xA4\xA9", + "\xD2\xA9" => "\xEF\xA4\xAA", + "\xD2\xAA" => "\xEF\xA4\xAB", + "\xD2\xAB" => "\xEF\xA4\xAC", + "\xD2\xAC" => "\xE4\xB9\x83", + "\xD2\xAD" => "\xEF\xA4\xAD", + "\xD2\xAE" => "\xE5\x85\xA7", + "\xD2\xAF" => "\xE5\xA5\x88", + "\xD2\xB0" => "\xE6\x9F\xB0", + "\xD2\xB1" => "\xE8\x80\x90", + "\xD2\xB2" => "\xEF\xA4\xAE", + "\xD2\xB3" => "\xE5\xA5\xB3", + "\xD2\xB4" => "\xE5\xB9\xB4", + "\xD2\xB5" => "\xE6\x92\x9A", + "\xD2\xB6" => "\xE7\xA7\x8A", + "\xD2\xB7" => "\xE5\xBF\xB5", + "\xD2\xB8" => "\xE6\x81\xAC", + "\xD2\xB9" => "\xE6\x8B\x88", + "\xD2\xBA" => "\xE6\x8D\xBB", + "\xD2\xBB" => "\xE5\xAF\xA7", + "\xD2\xBC" => "\xE5\xAF\x97", + "\xD2\xBD" => "\xE5\x8A\xAA", + "\xD2\xBE" => "\xEF\xA4\xAF", + "\xD2\xBF" => "\xE5\xA5\xB4", + "\xD2\xC0" => "\xE5\xBC\xA9", + "\xD2\xC1" => "\xE6\x80\x92", + "\xD2\xC2" => "\xEF\xA4\xB0", + "\xD2\xC3" => "\xEF\xA4\xB1", + "\xD2\xC4" => "\xEF\xA4\xB2", + "\xD2\xC5" => "\xE7\x91\x99", + "\xD2\xC6" => "\xEF\xA4\xB3", + "\xD2\xC7" => "\xEF\xA4\xB4", + "\xD2\xC8" => "\xEF\xA4\xB5", + "\xD2\xC9" => "\xEF\xA4\xB6", + "\xD2\xCA" => "\xEF\xA4\xB7", + "\xD2\xCB" => "\xEF\xA4\xB8", + "\xD2\xCC" => "\xE9\xA7\x91", + "\xD2\xCD" => "\xEF\xA4\xB9", + "\xD2\xCE" => "\xEF\xA4\xBA", + "\xD2\xCF" => "\xEF\xA4\xBB", + "\xD2\xD0" => "\xEF\xA4\xBC", + "\xD2\xD1" => "\xEF\xA4\xBD", + "\xD2\xD2" => "\xEF\xA4\xBE", + "\xD2\xD3" => "\xEF\xA4\xBF", + "\xD2\xD4" => "\xEF\xA5\x80", + "\xD2\xD5" => "\xEF\xA5\x81", + "\xD2\xD6" => "\xEF\xA5\x82", + "\xD2\xD7" => "\xEF\xA5\x83", + "\xD2\xD8" => "\xE6\xBF\x83", + "\xD2\xD9" => "\xEF\xA5\x84", + "\xD2\xDA" => "\xEF\xA5\x85", + "\xD2\xDB" => "\xE8\x86\xBF", + "\xD2\xDC" => "\xE8\xBE\xB2", + "\xD2\xDD" => "\xE6\x83\xB1", + "\xD2\xDE" => "\xEF\xA5\x86", + "\xD2\xDF" => "\xEF\xA5\x87", + "\xD2\xE0" => "\xE8\x85\xA6", + "\xD2\xE1" => "\xEF\xA5\x88", + "\xD2\xE2" => "\xEF\xA5\x89", + "\xD2\xE3" => "\xE5\xB0\xBF", + "\xD2\xE4" => "\xEF\xA5\x8A", + "\xD2\xE5" => "\xEF\xA5\x8B", + "\xD2\xE6" => "\xEF\xA5\x8C", + "\xD2\xE7" => "\xEF\xA5\x8D", + "\xD2\xE8" => "\xEF\xA5\x8E", + "\xD2\xE9" => "\xEF\xA5\x8F", + "\xD2\xEA" => "\xEF\xA5\x90", + "\xD2\xEB" => "\xEF\xA5\x91", + "\xD2\xEC" => "\xE5\xAB\xA9", + "\xD2\xED" => "\xE8\xA8\xA5", + "\xD2\xEE" => "\xE6\x9D\xBB", + "\xD2\xEF" => "\xE7\xB4\x90", + "\xD2\xF0" => "\xEF\xA5\x92", + "\xD2\xF1" => "\xEF\xA5\x93", + "\xD2\xF2" => "\xEF\xA5\x94", + "\xD2\xF3" => "\xEF\xA5\x95", + "\xD2\xF4" => "\xEF\xA5\x96", + "\xD2\xF5" => "\xEF\xA5\x97", + "\xD2\xF6" => "\xE8\x83\xBD", + "\xD2\xF7" => "\xEF\xA5\x98", + "\xD2\xF8" => "\xEF\xA5\x99", + "\xD2\xF9" => "\xE5\xB0\xBC", + "\xD2\xFA" => "\xE6\xB3\xA5", + "\xD2\xFB" => "\xE5\x8C\xBF", + "\xD2\xFC" => "\xE6\xBA\xBA", + "\xD2\xFD" => "\xE5\xA4\x9A", + "\xD2\xFE" => "\xE8\x8C\xB6", + "\xD3\xA1" => "\xE4\xB8\xB9", + "\xD3\xA2" => "\xE4\xBA\xB6", + "\xD3\xA3" => "\xE4\xBD\x86", + "\xD3\xA4" => "\xE5\x96\xAE", + "\xD3\xA5" => "\xE5\x9C\x98", + "\xD3\xA6" => "\xE5\xA3\x87", + "\xD3\xA7" => "\xE5\xBD\x96", + "\xD3\xA8" => "\xE6\x96\xB7", + "\xD3\xA9" => "\xE6\x97\xA6", + "\xD3\xAA" => "\xE6\xAA\x80", + "\xD3\xAB" => "\xE6\xAE\xB5", + "\xD3\xAC" => "\xE6\xB9\x8D", + "\xD3\xAD" => "\xE7\x9F\xAD", + "\xD3\xAE" => "\xE7\xAB\xAF", + "\xD3\xAF" => "\xE7\xB0\x9E", + "\xD3\xB0" => "\xE7\xB7\x9E", + "\xD3\xB1" => "\xE8\x9B\x8B", + "\xD3\xB2" => "\xE8\xA2\x92", + "\xD3\xB3" => "\xE9\x84\xB2", + "\xD3\xB4" => "\xE9\x8D\x9B", + "\xD3\xB5" => "\xE6\x92\xBB", + "\xD3\xB6" => "\xE6\xBE\xBE", + "\xD3\xB7" => "\xE7\x8D\xBA", + "\xD3\xB8" => "\xE7\x96\xB8", + "\xD3\xB9" => "\xE9\x81\x94", + "\xD3\xBA" => "\xE5\x95\x96", + "\xD3\xBB" => "\xE5\x9D\x8D", + "\xD3\xBC" => "\xE6\x86\xBA", + "\xD3\xBD" => "\xE6\x93\x94", + "\xD3\xBE" => "\xE6\x9B\x87", + "\xD3\xBF" => "\xE6\xB7\xA1", + "\xD3\xC0" => "\xE6\xB9\x9B", + "\xD3\xC1" => "\xE6\xBD\xAD", + "\xD3\xC2" => "\xE6\xBE\xB9", + "\xD3\xC3" => "\xE7\x97\xB0", + "\xD3\xC4" => "\xE8\x81\x83", + "\xD3\xC5" => "\xE8\x86\xBD", + "\xD3\xC6" => "\xE8\x95\x81", + "\xD3\xC7" => "\xE8\xA6\x83", + "\xD3\xC8" => "\xE8\xAB\x87", + "\xD3\xC9" => "\xE8\xAD\x9A", + "\xD3\xCA" => "\xE9\x8C\x9F", + "\xD3\xCB" => "\xE6\xB2\x93", + "\xD3\xCC" => "\xE7\x95\x93", + "\xD3\xCD" => "\xE7\xAD\x94", + "\xD3\xCE" => "\xE8\xB8\x8F", + "\xD3\xCF" => "\xE9\x81\x9D", + "\xD3\xD0" => "\xE5\x94\x90", + "\xD3\xD1" => "\xE5\xA0\x82", + "\xD3\xD2" => "\xE5\xA1\x98", + "\xD3\xD3" => "\xE5\xB9\xA2", + "\xD3\xD4" => "\xE6\x88\x87", + "\xD3\xD5" => "\xE6\x92\x9E", + "\xD3\xD6" => "\xE6\xA3\xA0", + "\xD3\xD7" => "\xE7\x95\xB6", + "\xD3\xD8" => "\xE7\xB3\x96", + "\xD3\xD9" => "\xE8\x9E\xB3", + "\xD3\xDA" => "\xE9\xBB\xA8", + "\xD3\xDB" => "\xE4\xBB\xA3", + "\xD3\xDC" => "\xE5\x9E\x88", + "\xD3\xDD" => "\xE5\x9D\xAE", + "\xD3\xDE" => "\xE5\xA4\xA7", + "\xD3\xDF" => "\xE5\xB0\x8D", + "\xD3\xE0" => "\xE5\xB2\xB1", + "\xD3\xE1" => "\xE5\xB8\xB6", + "\xD3\xE2" => "\xE5\xBE\x85", + "\xD3\xE3" => "\xE6\x88\xB4", + "\xD3\xE4" => "\xE6\x93\xA1", + "\xD3\xE5" => "\xE7\x8E\xB3", + "\xD3\xE6" => "\xE8\x87\xBA", + "\xD3\xE7" => "\xE8\xA2\x8B", + "\xD3\xE8" => "\xE8\xB2\xB8", + "\xD3\xE9" => "\xE9\x9A\x8A", + "\xD3\xEA" => "\xE9\xBB\x9B", + "\xD3\xEB" => "\xE5\xAE\x85", + "\xD3\xEC" => "\xE5\xBE\xB7", + "\xD3\xED" => "\xE6\x82\xB3", + "\xD3\xEE" => "\xE5\x80\x92", + "\xD3\xEF" => "\xE5\x88\x80", + "\xD3\xF0" => "\xE5\x88\xB0", + "\xD3\xF1" => "\xE5\x9C\x96", + "\xD3\xF2" => "\xE5\xA0\xB5", + "\xD3\xF3" => "\xE5\xA1\x97", + "\xD3\xF4" => "\xE5\xB0\x8E", + "\xD3\xF5" => "\xE5\xB1\xA0", + "\xD3\xF6" => "\xE5\xB3\xB6", + "\xD3\xF7" => "\xE5\xB6\x8B", + "\xD3\xF8" => "\xE5\xBA\xA6", + "\xD3\xF9" => "\xE5\xBE\x92", + "\xD3\xFA" => "\xE6\x82\xBC", + "\xD3\xFB" => "\xE6\x8C\x91", + "\xD3\xFC" => "\xE6\x8E\x89", + "\xD3\xFD" => "\xE6\x90\x97", + "\xD3\xFE" => "\xE6\xA1\x83", + "\xD4\xA1" => "\xE6\xA3\xB9", + "\xD4\xA2" => "\xE6\xAB\x82", + "\xD4\xA3" => "\xE6\xB7\x98", + "\xD4\xA4" => "\xE6\xB8\xA1", + "\xD4\xA5" => "\xE6\xBB\x94", + "\xD4\xA6" => "\xE6\xBF\xA4", + "\xD4\xA7" => "\xE7\x87\xBE", + "\xD4\xA8" => "\xE7\x9B\x9C", + "\xD4\xA9" => "\xE7\x9D\xB9", + "\xD4\xAA" => "\xE7\xA6\xB1", + "\xD4\xAB" => "\xE7\xA8\xBB", + "\xD4\xAC" => "\xE8\x90\x84", + "\xD4\xAD" => "\xE8\xA6\xA9", + "\xD4\xAE" => "\xE8\xB3\xAD", + "\xD4\xAF" => "\xE8\xB7\xB3", + "\xD4\xB0" => "\xE8\xB9\x88", + "\xD4\xB1" => "\xE9\x80\x83", + "\xD4\xB2" => "\xE9\x80\x94", + "\xD4\xB3" => "\xE9\x81\x93", + "\xD4\xB4" => "\xE9\x83\xBD", + "\xD4\xB5" => "\xE9\x8D\x8D", + "\xD4\xB6" => "\xE9\x99\xB6", + "\xD4\xB7" => "\xE9\x9F\x9C", + "\xD4\xB8" => "\xE6\xAF\x92", + "\xD4\xB9" => "\xE7\x80\x86", + "\xD4\xBA" => "\xE7\x89\x98", + "\xD4\xBB" => "\xE7\x8A\xA2", + "\xD4\xBC" => "\xE7\x8D\xA8", + "\xD4\xBD" => "\xE7\x9D\xA3", + "\xD4\xBE" => "\xE7\xA6\xBF", + "\xD4\xBF" => "\xE7\xAF\xA4", + "\xD4\xC0" => "\xE7\xBA\x9B", + "\xD4\xC1" => "\xE8\xAE\x80", + "\xD4\xC2" => "\xE5\xA2\xA9", + "\xD4\xC3" => "\xE6\x83\x87", + "\xD4\xC4" => "\xE6\x95\xA6", + "\xD4\xC5" => "\xE6\x97\xBD", + "\xD4\xC6" => "\xE6\x9A\xBE", + "\xD4\xC7" => "\xE6\xB2\x8C", + "\xD4\xC8" => "\xE7\x84\x9E", + "\xD4\xC9" => "\xE7\x87\x89", + "\xD4\xCA" => "\xE8\xB1\x9A", + "\xD4\xCB" => "\xE9\xA0\x93", + "\xD4\xCC" => "\xE4\xB9\xAD", + "\xD4\xCD" => "\xE7\xAA\x81", + "\xD4\xCE" => "\xE4\xBB\x9D", + "\xD4\xCF" => "\xE5\x86\xAC", + "\xD4\xD0" => "\xE5\x87\x8D", + "\xD4\xD1" => "\xE5\x8B\x95", + "\xD4\xD2" => "\xE5\x90\x8C", + "\xD4\xD3" => "\xE6\x86\xA7", + "\xD4\xD4" => "\xE6\x9D\xB1", + "\xD4\xD5" => "\xE6\xA1\x90", + "\xD4\xD6" => "\xE6\xA3\x9F", + "\xD4\xD7" => "\xE6\xB4\x9E", + "\xD4\xD8" => "\xE6\xBD\xBC", + "\xD4\xD9" => "\xE7\x96\xBC", + "\xD4\xDA" => "\xE7\x9E\xB3", + "\xD4\xDB" => "\xE7\xAB\xA5", + "\xD4\xDC" => "\xE8\x83\xB4", + "\xD4\xDD" => "\xE8\x91\xA3", + "\xD4\xDE" => "\xE9\x8A\x85", + "\xD4\xDF" => "\xE5\x85\x9C", + "\xD4\xE0" => "\xE6\x96\x97", + "\xD4\xE1" => "\xE6\x9D\x9C", + "\xD4\xE2" => "\xE6\x9E\x93", + "\xD4\xE3" => "\xE7\x97\x98", + "\xD4\xE4" => "\xE7\xAB\x87", + "\xD4\xE5" => "\xE8\x8D\xB3", + "\xD4\xE6" => "\xEF\xA5\x9A", + "\xD4\xE7" => "\xE8\xB1\x86", + "\xD4\xE8" => "\xE9\x80\x97", + "\xD4\xE9" => "\xE9\xA0\xAD", + "\xD4\xEA" => "\xE5\xB1\xAF", + "\xD4\xEB" => "\xE8\x87\x80", + "\xD4\xEC" => "\xE8\x8A\x9A", + "\xD4\xED" => "\xE9\x81\x81", + "\xD4\xEE" => "\xE9\x81\xAF", + "\xD4\xEF" => "\xE9\x88\x8D", + "\xD4\xF0" => "\xE5\xBE\x97", + "\xD4\xF1" => "\xE5\xB6\x9D", + "\xD4\xF2" => "\xE6\xA9\x99", + "\xD4\xF3" => "\xE7\x87\x88", + "\xD4\xF4" => "\xE7\x99\xBB", + "\xD4\xF5" => "\xE7\xAD\x89", + "\xD4\xF6" => "\xE8\x97\xA4", + "\xD4\xF7" => "\xE8\xAC\x84", + "\xD4\xF8" => "\xE9\x84\xA7", + "\xD4\xF9" => "\xE9\xA8\xB0", + "\xD4\xFA" => "\xE5\x96\x87", + "\xD4\xFB" => "\xE6\x87\xB6", + "\xD4\xFC" => "\xEF\xA5\x9B", + "\xD4\xFD" => "\xE7\x99\xA9", + "\xD4\xFE" => "\xE7\xBE\x85", + "\xD5\xA1" => "\xE8\x98\xBF", + "\xD5\xA2" => "\xE8\x9E\xBA", + "\xD5\xA3" => "\xE8\xA3\xB8", + "\xD5\xA4" => "\xE9\x82\x8F", + "\xD5\xA5" => "\xEF\xA5\x9C", + "\xD5\xA6" => "\xE6\xB4\x9B", + "\xD5\xA7" => "\xE7\x83\x99", + "\xD5\xA8" => "\xE7\x8F\x9E", + "\xD5\xA9" => "\xE7\xB5\xA1", + "\xD5\xAA" => "\xE8\x90\xBD", + "\xD5\xAB" => "\xEF\xA5\x9D", + "\xD5\xAC" => "\xE9\x85\xAA", + "\xD5\xAD" => "\xE9\xA7\xB1", + "\xD5\xAE" => "\xEF\xA5\x9E", + "\xD5\xAF" => "\xE4\xBA\x82", + "\xD5\xB0" => "\xE5\x8D\xB5", + "\xD5\xB1" => "\xE6\xAC\x84", + "\xD5\xB2" => "\xE6\xAC\x92", + "\xD5\xB3" => "\xE7\x80\xBE", + "\xD5\xB4" => "\xE7\x88\x9B", + "\xD5\xB5" => "\xE8\x98\xAD", + "\xD5\xB6" => "\xE9\xB8\x9E", + "\xD5\xB7" => "\xE5\x89\x8C", + "\xD5\xB8" => "\xE8\xBE\xA3", + "\xD5\xB9" => "\xE5\xB5\x90", + "\xD5\xBA" => "\xE6\x93\xA5", + "\xD5\xBB" => "\xE6\x94\xAC", + "\xD5\xBC" => "\xE6\xAC\x96", + "\xD5\xBD" => "\xE6\xBF\xAB", + "\xD5\xBE" => "\xE7\xB1\x83", + "\xD5\xBF" => "\xE7\xBA\x9C", + "\xD5\xC0" => "\xE8\x97\x8D", + "\xD5\xC1" => "\xE8\xA5\xA4", + "\xD5\xC2" => "\xE8\xA6\xBD", + "\xD5\xC3" => "\xE6\x8B\x89", + "\xD5\xC4" => "\xE8\x87\x98", + "\xD5\xC5" => "\xE8\xA0\x9F", + "\xD5\xC6" => "\xE5\xBB\x8A", + "\xD5\xC7" => "\xE6\x9C\x97", + "\xD5\xC8" => "\xE6\xB5\xAA", + "\xD5\xC9" => "\xE7\x8B\xBC", + "\xD5\xCA" => "\xE7\x90\x85", + "\xD5\xCB" => "\xE7\x91\xAF", + "\xD5\xCC" => "\xE8\x9E\x82", + "\xD5\xCD" => "\xE9\x83\x9E", + "\xD5\xCE" => "\xE4\xBE\x86", + "\xD5\xCF" => "\xE5\xB4\x8D", + "\xD5\xD0" => "\xE5\xBE\xA0", + "\xD5\xD1" => "\xE8\x90\x8A", + "\xD5\xD2" => "\xE5\x86\xB7", + "\xD5\xD3" => "\xE6\x8E\xA0", + "\xD5\xD4" => "\xE7\x95\xA5", + "\xD5\xD5" => "\xE4\xBA\xAE", + "\xD5\xD6" => "\xE5\x80\x86", + "\xD5\xD7" => "\xE5\x85\xA9", + "\xD5\xD8" => "\xE5\x87\x89", + "\xD5\xD9" => "\xE6\xA2\x81", + "\xD5\xDA" => "\xE6\xA8\x91", + "\xD5\xDB" => "\xE7\xB2\xAE", + "\xD5\xDC" => "\xE7\xB2\xB1", + "\xD5\xDD" => "\xE7\xB3\xA7", + "\xD5\xDE" => "\xE8\x89\xAF", + "\xD5\xDF" => "\xE8\xAB\x92", + "\xD5\xE0" => "\xE8\xBC\x9B", + "\xD5\xE1" => "\xE9\x87\x8F", + "\xD5\xE2" => "\xE4\xBE\xB6", + "\xD5\xE3" => "\xE5\x84\xB7", + "\xD5\xE4" => "\xE5\x8B\xB5", + "\xD5\xE5" => "\xE5\x91\x82", + "\xD5\xE6" => "\xE5\xBB\xAC", + "\xD5\xE7" => "\xE6\x85\xAE", + "\xD5\xE8" => "\xE6\x88\xBE", + "\xD5\xE9" => "\xE6\x97\x85", + "\xD5\xEA" => "\xE6\xAB\x9A", + "\xD5\xEB" => "\xE6\xBF\xBE", + "\xD5\xEC" => "\xE7\xA4\xAA", + "\xD5\xED" => "\xE8\x97\x9C", + "\xD5\xEE" => "\xE8\xA0\xA3", + "\xD5\xEF" => "\xE9\x96\xAD", + "\xD5\xF0" => "\xE9\xA9\xA2", + "\xD5\xF1" => "\xE9\xA9\xAA", + "\xD5\xF2" => "\xE9\xBA\x97", + "\xD5\xF3" => "\xE9\xBB\x8E", + "\xD5\xF4" => "\xE5\x8A\x9B", + "\xD5\xF5" => "\xE6\x9B\x86", + "\xD5\xF6" => "\xE6\xAD\xB7", + "\xD5\xF7" => "\xE7\x80\x9D", + "\xD5\xF8" => "\xE7\xA4\xAB", + "\xD5\xF9" => "\xE8\xBD\xA2", + "\xD5\xFA" => "\xE9\x9D\x82", + "\xD5\xFB" => "\xE6\x86\x90", + "\xD5\xFC" => "\xE6\x88\x80", + "\xD5\xFD" => "\xE6\x94\xA3", + "\xD5\xFE" => "\xE6\xBC\xA3", + "\xD6\xA1" => "\xE7\x85\x89", + "\xD6\xA2" => "\xE7\x92\x89", + "\xD6\xA3" => "\xE7\xB7\xB4", + "\xD6\xA4" => "\xE8\x81\xAF", + "\xD6\xA5" => "\xE8\x93\xAE", + "\xD6\xA6" => "\xE8\xBC\xA6", + "\xD6\xA7" => "\xE9\x80\xA3", + "\xD6\xA8" => "\xE9\x8D\x8A", + "\xD6\xA9" => "\xE5\x86\xBD", + "\xD6\xAA" => "\xE5\x88\x97", + "\xD6\xAB" => "\xE5\x8A\xA3", + "\xD6\xAC" => "\xE6\xB4\x8C", + "\xD6\xAD" => "\xE7\x83\x88", + "\xD6\xAE" => "\xE8\xA3\x82", + "\xD6\xAF" => "\xE5\xBB\x89", + "\xD6\xB0" => "\xE6\x96\x82", + "\xD6\xB1" => "\xE6\xAE\xAE", + "\xD6\xB2" => "\xE6\xBF\x82", + "\xD6\xB3" => "\xE7\xB0\xBE", + "\xD6\xB4" => "\xE7\x8D\xB5", + "\xD6\xB5" => "\xE4\xBB\xA4", + "\xD6\xB6" => "\xE4\xBC\xB6", + "\xD6\xB7" => "\xE5\x9B\xB9", + "\xD6\xB8" => "\xEF\xA5\x9F", + "\xD6\xB9" => "\xE5\xB2\xBA", + "\xD6\xBA" => "\xE5\xB6\xBA", + "\xD6\xBB" => "\xE6\x80\x9C", + "\xD6\xBC" => "\xE7\x8E\xB2", + "\xD6\xBD" => "\xE7\xAC\xAD", + "\xD6\xBE" => "\xE7\xBE\x9A", + "\xD6\xBF" => "\xE7\xBF\x8E", + "\xD6\xC0" => "\xE8\x81\x86", + "\xD6\xC1" => "\xE9\x80\x9E", + "\xD6\xC2" => "\xE9\x88\xB4", + "\xD6\xC3" => "\xE9\x9B\xB6", + "\xD6\xC4" => "\xE9\x9D\x88", + "\xD6\xC5" => "\xE9\xA0\x98", + "\xD6\xC6" => "\xE9\xBD\xA1", + "\xD6\xC7" => "\xE4\xBE\x8B", + "\xD6\xC8" => "\xE6\xBE\xA7", + "\xD6\xC9" => "\xE7\xA6\xAE", + "\xD6\xCA" => "\xE9\x86\xB4", + "\xD6\xCB" => "\xE9\x9A\xB7", + "\xD6\xCC" => "\xE5\x8B\x9E", + "\xD6\xCD" => "\xEF\xA5\xA0", + "\xD6\xCE" => "\xE6\x92\x88", + "\xD6\xCF" => "\xE6\x93\x84", + "\xD6\xD0" => "\xE6\xAB\x93", + "\xD6\xD1" => "\xE6\xBD\x9E", + "\xD6\xD2" => "\xE7\x80\x98", + "\xD6\xD3" => "\xE7\x88\x90", + "\xD6\xD4" => "\xE7\x9B\xA7", + "\xD6\xD5" => "\xE8\x80\x81", + "\xD6\xD6" => "\xE8\x98\x86", + "\xD6\xD7" => "\xE8\x99\x9C", + "\xD6\xD8" => "\xE8\xB7\xAF", + "\xD6\xD9" => "\xE8\xBC\x85", + "\xD6\xDA" => "\xE9\x9C\xB2", + "\xD6\xDB" => "\xE9\xAD\xAF", + "\xD6\xDC" => "\xE9\xB7\xBA", + "\xD6\xDD" => "\xE9\xB9\xB5", + "\xD6\xDE" => "\xE7\xA2\x8C", + "\xD6\xDF" => "\xE7\xA5\xBF", + "\xD6\xE0" => "\xE7\xB6\xA0", + "\xD6\xE1" => "\xE8\x8F\x89", + "\xD6\xE2" => "\xE9\x8C\x84", + "\xD6\xE3" => "\xE9\xB9\xBF", + "\xD6\xE4" => "\xE9\xBA\x93", + "\xD6\xE5" => "\xE8\xAB\x96", + "\xD6\xE6" => "\xE5\xA3\x9F", + "\xD6\xE7" => "\xE5\xBC\x84", + "\xD6\xE8" => "\xE6\x9C\xA7", + "\xD6\xE9" => "\xE7\x80\xA7", + "\xD6\xEA" => "\xE7\x93\x8F", + "\xD6\xEB" => "\xE7\xB1\xA0", + "\xD6\xEC" => "\xE8\x81\xBE", + "\xD6\xED" => "\xE5\x84\xA1", + "\xD6\xEE" => "\xE7\x80\xA8", + "\xD6\xEF" => "\xE7\x89\xA2", + "\xD6\xF0" => "\xE7\xA3\x8A", + "\xD6\xF1" => "\xE8\xB3\x82", + "\xD6\xF2" => "\xE8\xB3\x9A", + "\xD6\xF3" => "\xE8\xB3\xB4", + "\xD6\xF4" => "\xE9\x9B\xB7", + "\xD6\xF5" => "\xE4\xBA\x86", + "\xD6\xF6" => "\xE5\x83\x9A", + "\xD6\xF7" => "\xE5\xAF\xAE", + "\xD6\xF8" => "\xE5\xBB\x96", + "\xD6\xF9" => "\xE6\x96\x99", + "\xD6\xFA" => "\xE7\x87\x8E", + "\xD6\xFB" => "\xE7\x99\x82", + "\xD6\xFC" => "\xE7\x9E\xAD", + "\xD6\xFD" => "\xE8\x81\x8A", + "\xD6\xFE" => "\xE8\x93\xBC", + "\xD7\xA1" => "\xE9\x81\xBC", + "\xD7\xA2" => "\xE9\xAC\xA7", + "\xD7\xA3" => "\xE9\xBE\x8D", + "\xD7\xA4" => "\xE5\xA3\x98", + "\xD7\xA5" => "\xE5\xA9\x81", + "\xD7\xA6" => "\xE5\xB1\xA2", + "\xD7\xA7" => "\xE6\xA8\x93", + "\xD7\xA8" => "\xE6\xB7\x9A", + "\xD7\xA9" => "\xE6\xBC\x8F", + "\xD7\xAA" => "\xE7\x98\xBB", + "\xD7\xAB" => "\xE7\xB4\xAF", + "\xD7\xAC" => "\xE7\xB8\xB7", + "\xD7\xAD" => "\xE8\x94\x9E", + "\xD7\xAE" => "\xE8\xA4\xB8", + "\xD7\xAF" => "\xE9\x8F\xA4", + "\xD7\xB0" => "\xE9\x99\x8B", + "\xD7\xB1" => "\xE5\x8A\x89", + "\xD7\xB2" => "\xE6\x97\x92", + "\xD7\xB3" => "\xE6\x9F\xB3", + "\xD7\xB4" => "\xE6\xA6\xB4", + "\xD7\xB5" => "\xE6\xB5\x81", + "\xD7\xB6" => "\xE6\xBA\x9C", + "\xD7\xB7" => "\xE7\x80\x8F", + "\xD7\xB8" => "\xE7\x90\x89", + "\xD7\xB9" => "\xE7\x91\xA0", + "\xD7\xBA" => "\xE7\x95\x99", + "\xD7\xBB" => "\xE7\x98\xA4", + "\xD7\xBC" => "\xE7\xA1\xAB", + "\xD7\xBD" => "\xE8\xAC\xAC", + "\xD7\xBE" => "\xE9\xA1\x9E", + "\xD7\xBF" => "\xE5\x85\xAD", + "\xD7\xC0" => "\xE6\x88\xAE", + "\xD7\xC1" => "\xE9\x99\xB8", + "\xD7\xC2" => "\xE4\xBE\x96", + "\xD7\xC3" => "\xE5\x80\xAB", + "\xD7\xC4" => "\xE5\xB4\x99", + "\xD7\xC5" => "\xE6\xB7\xAA", + "\xD7\xC6" => "\xE7\xB6\xB8", + "\xD7\xC7" => "\xE8\xBC\xAA", + "\xD7\xC8" => "\xE5\xBE\x8B", + "\xD7\xC9" => "\xE6\x85\x84", + "\xD7\xCA" => "\xE6\xA0\x97", + "\xD7\xCB" => "\xEF\xA5\xA1", + "\xD7\xCC" => "\xE9\x9A\x86", + "\xD7\xCD" => "\xE5\x8B\x92", + "\xD7\xCE" => "\xE8\x82\x8B", + "\xD7\xCF" => "\xE5\x87\x9C", + "\xD7\xD0" => "\xE5\x87\x8C", + "\xD7\xD1" => "\xE6\xA5\x9E", + "\xD7\xD2" => "\xE7\xA8\x9C", + "\xD7\xD3" => "\xE7\xB6\xBE", + "\xD7\xD4" => "\xE8\x8F\xB1", + "\xD7\xD5" => "\xE9\x99\xB5", + "\xD7\xD6" => "\xE4\xBF\x9A", + "\xD7\xD7" => "\xE5\x88\xA9", + "\xD7\xD8" => "\xE5\x8E\x98", + "\xD7\xD9" => "\xE5\x90\x8F", + "\xD7\xDA" => "\xE5\x94\x8E", + "\xD7\xDB" => "\xE5\xB1\xA5", + "\xD7\xDC" => "\xE6\x82\xA7", + "\xD7\xDD" => "\xE6\x9D\x8E", + "\xD7\xDE" => "\xE6\xA2\xA8", + "\xD7\xDF" => "\xE6\xB5\xAC", + "\xD7\xE0" => "\xE7\x8A\x81", + "\xD7\xE1" => "\xE7\x8B\xB8", + "\xD7\xE2" => "\xE7\x90\x86", + "\xD7\xE3" => "\xE7\x92\x83", + "\xD7\xE4" => "\xEF\xA5\xA2", + "\xD7\xE5" => "\xE7\x97\xA2", + "\xD7\xE6" => "\xE7\xB1\xAC", + "\xD7\xE7" => "\xE7\xBD\xB9", + "\xD7\xE8" => "\xE7\xBE\xB8", + "\xD7\xE9" => "\xE8\x8E\x89", + "\xD7\xEA" => "\xE8\xA3\x8F", + "\xD7\xEB" => "\xE8\xA3\xA1", + "\xD7\xEC" => "\xE9\x87\x8C", + "\xD7\xED" => "\xE9\x87\x90", + "\xD7\xEE" => "\xE9\x9B\xA2", + "\xD7\xEF" => "\xE9\xAF\x89", + "\xD7\xF0" => "\xE5\x90\x9D", + "\xD7\xF1" => "\xE6\xBD\xBE", + "\xD7\xF2" => "\xE7\x87\x90", + "\xD7\xF3" => "\xE7\x92\x98", + "\xD7\xF4" => "\xE8\x97\xBA", + "\xD7\xF5" => "\xE8\xBA\xAA", + "\xD7\xF6" => "\xE9\x9A\xA3", + "\xD7\xF7" => "\xE9\xB1\x97", + "\xD7\xF8" => "\xE9\xBA\x9F", + "\xD7\xF9" => "\xE6\x9E\x97", + "\xD7\xFA" => "\xE6\xB7\x8B", + "\xD7\xFB" => "\xE7\x90\xB3", + "\xD7\xFC" => "\xE8\x87\xA8", + "\xD7\xFD" => "\xE9\x9C\x96", + "\xD7\xFE" => "\xE7\xA0\xAC", + "\xD8\xA1" => "\xE7\xAB\x8B", + "\xD8\xA2" => "\xE7\xAC\xA0", + "\xD8\xA3" => "\xE7\xB2\x92", + "\xD8\xA4" => "\xE6\x91\xA9", + "\xD8\xA5" => "\xE7\x91\xAA", + "\xD8\xA6" => "\xE7\x97\xB2", + "\xD8\xA7" => "\xE7\xA2\xBC", + "\xD8\xA8" => "\xE7\xA3\xA8", + "\xD8\xA9" => "\xE9\xA6\xAC", + "\xD8\xAA" => "\xE9\xAD\x94", + "\xD8\xAB" => "\xE9\xBA\xBB", + "\xD8\xAC" => "\xE5\xAF\x9E", + "\xD8\xAD" => "\xE5\xB9\x95", + "\xD8\xAE" => "\xE6\xBC\xA0", + "\xD8\xAF" => "\xE8\x86\x9C", + "\xD8\xB0" => "\xE8\x8E\xAB", + "\xD8\xB1" => "\xE9\x82\x88", + "\xD8\xB2" => "\xE4\xB8\x87", + "\xD8\xB3" => "\xE5\x8D\x8D", + "\xD8\xB4" => "\xE5\xA8\xA9", + "\xD8\xB5" => "\xE5\xB7\x92", + "\xD8\xB6" => "\xE5\xBD\x8E", + "\xD8\xB7" => "\xE6\x85\xA2", + "\xD8\xB8" => "\xE6\x8C\xBD", + "\xD8\xB9" => "\xE6\x99\xA9", + "\xD8\xBA" => "\xE6\x9B\xBC", + "\xD8\xBB" => "\xE6\xBB\xBF", + "\xD8\xBC" => "\xE6\xBC\xAB", + "\xD8\xBD" => "\xE7\x81\xA3", + "\xD8\xBE" => "\xE7\x9E\x9E", + "\xD8\xBF" => "\xE8\x90\xAC", + "\xD8\xC0" => "\xE8\x94\x93", + "\xD8\xC1" => "\xE8\xA0\xBB", + "\xD8\xC2" => "\xE8\xBC\x93", + "\xD8\xC3" => "\xE9\xA5\x85", + "\xD8\xC4" => "\xE9\xB0\xBB", + "\xD8\xC5" => "\xE5\x94\x9C", + "\xD8\xC6" => "\xE6\x8A\xB9", + "\xD8\xC7" => "\xE6\x9C\xAB", + "\xD8\xC8" => "\xE6\xB2\xAB", + "\xD8\xC9" => "\xE8\x8C\x89", + "\xD8\xCA" => "\xE8\xA5\xAA", + "\xD8\xCB" => "\xE9\x9D\xBA", + "\xD8\xCC" => "\xE4\xBA\xA1", + "\xD8\xCD" => "\xE5\xA6\x84", + "\xD8\xCE" => "\xE5\xBF\x98", + "\xD8\xCF" => "\xE5\xBF\x99", + "\xD8\xD0" => "\xE6\x9C\x9B", + "\xD8\xD1" => "\xE7\xB6\xB2", + "\xD8\xD2" => "\xE7\xBD\x94", + "\xD8\xD3" => "\xE8\x8A\x92", + "\xD8\xD4" => "\xE8\x8C\xAB", + "\xD8\xD5" => "\xE8\x8E\xBD", + "\xD8\xD6" => "\xE8\xBC\x9E", + "\xD8\xD7" => "\xE9\x82\x99", + "\xD8\xD8" => "\xE5\x9F\x8B", + "\xD8\xD9" => "\xE5\xA6\xB9", + "\xD8\xDA" => "\xE5\xAA\x92", + "\xD8\xDB" => "\xE5\xAF\x90", + "\xD8\xDC" => "\xE6\x98\xA7", + "\xD8\xDD" => "\xE6\x9E\x9A", + "\xD8\xDE" => "\xE6\xA2\x85", + "\xD8\xDF" => "\xE6\xAF\x8F", + "\xD8\xE0" => "\xE7\x85\xA4", + "\xD8\xE1" => "\xE7\xBD\xB5", + "\xD8\xE2" => "\xE8\xB2\xB7", + "\xD8\xE3" => "\xE8\xB3\xA3", + "\xD8\xE4" => "\xE9\x82\x81", + "\xD8\xE5" => "\xE9\xAD\x85", + "\xD8\xE6" => "\xE8\x84\x88", + "\xD8\xE7" => "\xE8\xB2\x8A", + "\xD8\xE8" => "\xE9\x99\x8C", + "\xD8\xE9" => "\xE9\xA9\x80", + "\xD8\xEA" => "\xE9\xBA\xA5", + "\xD8\xEB" => "\xE5\xAD\x9F", + "\xD8\xEC" => "\xE6\xB0\x93", + "\xD8\xED" => "\xE7\x8C\x9B", + "\xD8\xEE" => "\xE7\x9B\xB2", + "\xD8\xEF" => "\xE7\x9B\x9F", + "\xD8\xF0" => "\xE8\x90\x8C", + "\xD8\xF1" => "\xE5\x86\xAA", + "\xD8\xF2" => "\xE8\xA6\x93", + "\xD8\xF3" => "\xE5\x85\x8D", + "\xD8\xF4" => "\xE5\x86\x95", + "\xD8\xF5" => "\xE5\x8B\x89", + "\xD8\xF6" => "\xE6\xA3\x89", + "\xD8\xF7" => "\xE6\xB2\x94", + "\xD8\xF8" => "\xE7\x9C\x84", + "\xD8\xF9" => "\xE7\x9C\xA0", + "\xD8\xFA" => "\xE7\xB6\xBF", + "\xD8\xFB" => "\xE7\xB7\xAC", + "\xD8\xFC" => "\xE9\x9D\xA2", + "\xD8\xFD" => "\xE9\xBA\xB5", + "\xD8\xFE" => "\xE6\xBB\x85", + "\xD9\xA1" => "\xE8\x94\x91", + "\xD9\xA2" => "\xE5\x86\xA5", + "\xD9\xA3" => "\xE5\x90\x8D", + "\xD9\xA4" => "\xE5\x91\xBD", + "\xD9\xA5" => "\xE6\x98\x8E", + "\xD9\xA6" => "\xE6\x9A\x9D", + "\xD9\xA7" => "\xE6\xA4\xA7", + "\xD9\xA8" => "\xE6\xBA\x9F", + "\xD9\xA9" => "\xE7\x9A\xBF", + "\xD9\xAA" => "\xE7\x9E\x91", + "\xD9\xAB" => "\xE8\x8C\x97", + "\xD9\xAC" => "\xE8\x93\x82", + "\xD9\xAD" => "\xE8\x9E\x9F", + "\xD9\xAE" => "\xE9\x85\xA9", + "\xD9\xAF" => "\xE9\x8A\x98", + "\xD9\xB0" => "\xE9\xB3\xB4", + "\xD9\xB1" => "\xE8\xA2\x82", + "\xD9\xB2" => "\xE4\xBE\xAE", + "\xD9\xB3" => "\xE5\x86\x92", + "\xD9\xB4" => "\xE5\x8B\x9F", + "\xD9\xB5" => "\xE5\xA7\x86", + "\xD9\xB6" => "\xE5\xB8\xBD", + "\xD9\xB7" => "\xE6\x85\x95", + "\xD9\xB8" => "\xE6\x91\xB8", + "\xD9\xB9" => "\xE6\x91\xB9", + "\xD9\xBA" => "\xE6\x9A\xAE", + "\xD9\xBB" => "\xE6\x9F\x90", + "\xD9\xBC" => "\xE6\xA8\xA1", + "\xD9\xBD" => "\xE6\xAF\x8D", + "\xD9\xBE" => "\xE6\xAF\x9B", + "\xD9\xBF" => "\xE7\x89\x9F", + "\xD9\xC0" => "\xE7\x89\xA1", + "\xD9\xC1" => "\xE7\x91\x81", + "\xD9\xC2" => "\xE7\x9C\xB8", + "\xD9\xC3" => "\xE7\x9F\x9B", + "\xD9\xC4" => "\xE8\x80\x97", + "\xD9\xC5" => "\xE8\x8A\xBC", + "\xD9\xC6" => "\xE8\x8C\x85", + "\xD9\xC7" => "\xE8\xAC\x80", + "\xD9\xC8" => "\xE8\xAC\xA8", + "\xD9\xC9" => "\xE8\xB2\x8C", + "\xD9\xCA" => "\xE6\x9C\xA8", + "\xD9\xCB" => "\xE6\xB2\x90", + "\xD9\xCC" => "\xE7\x89\xA7", + "\xD9\xCD" => "\xE7\x9B\xAE", + "\xD9\xCE" => "\xE7\x9D\xA6", + "\xD9\xCF" => "\xE7\xA9\x86", + "\xD9\xD0" => "\xE9\xB6\xA9", + "\xD9\xD1" => "\xE6\xAD\xBF", + "\xD9\xD2" => "\xE6\xB2\x92", + "\xD9\xD3" => "\xE5\xA4\xA2", + "\xD9\xD4" => "\xE6\x9C\xA6", + "\xD9\xD5" => "\xE8\x92\x99", + "\xD9\xD6" => "\xE5\x8D\xAF", + "\xD9\xD7" => "\xE5\xA2\x93", + "\xD9\xD8" => "\xE5\xA6\x99", + "\xD9\xD9" => "\xE5\xBB\x9F", + "\xD9\xDA" => "\xE6\x8F\x8F", + "\xD9\xDB" => "\xE6\x98\xB4", + "\xD9\xDC" => "\xE6\x9D\xB3", + "\xD9\xDD" => "\xE6\xB8\xBA", + "\xD9\xDE" => "\xE7\x8C\xAB", + "\xD9\xDF" => "\xE7\xAB\x97", + "\xD9\xE0" => "\xE8\x8B\x97", + "\xD9\xE1" => "\xE9\x8C\xA8", + "\xD9\xE2" => "\xE5\x8B\x99", + "\xD9\xE3" => "\xE5\xB7\xAB", + "\xD9\xE4" => "\xE6\x86\xAE", + "\xD9\xE5" => "\xE6\x87\x8B", + "\xD9\xE6" => "\xE6\x88\x8A", + "\xD9\xE7" => "\xE6\x8B\x87", + "\xD9\xE8" => "\xE6\x92\xAB", + "\xD9\xE9" => "\xE6\x97\xA0", + "\xD9\xEA" => "\xE6\xA5\x99", + "\xD9\xEB" => "\xE6\xAD\xA6", + "\xD9\xEC" => "\xE6\xAF\x8B", + "\xD9\xED" => "\xE7\x84\xA1", + "\xD9\xEE" => "\xE7\x8F\xB7", + "\xD9\xEF" => "\xE7\x95\x9D", + "\xD9\xF0" => "\xE7\xB9\x86", + "\xD9\xF1" => "\xE8\x88\x9E", + "\xD9\xF2" => "\xE8\x8C\x82", + "\xD9\xF3" => "\xE8\x95\xAA", + "\xD9\xF4" => "\xE8\xAA\xA3", + "\xD9\xF5" => "\xE8\xB2\xBF", + "\xD9\xF6" => "\xE9\x9C\xA7", + "\xD9\xF7" => "\xE9\xB5\xA1", + "\xD9\xF8" => "\xE5\xA2\xA8", + "\xD9\xF9" => "\xE9\xBB\x98", + "\xD9\xFA" => "\xE5\x80\x91", + "\xD9\xFB" => "\xE5\x88\x8E", + "\xD9\xFC" => "\xE5\x90\xBB", + "\xD9\xFD" => "\xE5\x95\x8F", + "\xD9\xFE" => "\xE6\x96\x87", + "\xDA\xA1" => "\xE6\xB1\xB6", + "\xDA\xA2" => "\xE7\xB4\x8A", + "\xDA\xA3" => "\xE7\xB4\x8B", + "\xDA\xA4" => "\xE8\x81\x9E", + "\xDA\xA5" => "\xE8\x9A\x8A", + "\xDA\xA6" => "\xE9\x96\x80", + "\xDA\xA7" => "\xE9\x9B\xAF", + "\xDA\xA8" => "\xE5\x8B\xBF", + "\xDA\xA9" => "\xE6\xB2\x95", + "\xDA\xAA" => "\xE7\x89\xA9", + "\xDA\xAB" => "\xE5\x91\xB3", + "\xDA\xAC" => "\xE5\xAA\x9A", + "\xDA\xAD" => "\xE5\xB0\xBE", + "\xDA\xAE" => "\xE5\xB5\x8B", + "\xDA\xAF" => "\xE5\xBD\x8C", + "\xDA\xB0" => "\xE5\xBE\xAE", + "\xDA\xB1" => "\xE6\x9C\xAA", + "\xDA\xB2" => "\xE6\xA2\xB6", + "\xDA\xB3" => "\xE6\xA5\xA3", + "\xDA\xB4" => "\xE6\xB8\xBC", + "\xDA\xB5" => "\xE6\xB9\x84", + "\xDA\xB6" => "\xE7\x9C\x89", + "\xDA\xB7" => "\xE7\xB1\xB3", + "\xDA\xB8" => "\xE7\xBE\x8E", + "\xDA\xB9" => "\xE8\x96\x87", + "\xDA\xBA" => "\xE8\xAC\x8E", + "\xDA\xBB" => "\xE8\xBF\xB7", + "\xDA\xBC" => "\xE9\x9D\xA1", + "\xDA\xBD" => "\xE9\xBB\xB4", + "\xDA\xBE" => "\xE5\xB2\xB7", + "\xDA\xBF" => "\xE6\x82\xB6", + "\xDA\xC0" => "\xE6\x84\x8D", + "\xDA\xC1" => "\xE6\x86\xAB", + "\xDA\xC2" => "\xE6\x95\x8F", + "\xDA\xC3" => "\xE6\x97\xBB", + "\xDA\xC4" => "\xE6\x97\xBC", + "\xDA\xC5" => "\xE6\xB0\x91", + "\xDA\xC6" => "\xE6\xB3\xAF", + "\xDA\xC7" => "\xE7\x8E\x9F", + "\xDA\xC8" => "\xE7\x8F\x89", + "\xDA\xC9" => "\xE7\xB7\xA1", + "\xDA\xCA" => "\xE9\x96\x94", + "\xDA\xCB" => "\xE5\xAF\x86", + "\xDA\xCC" => "\xE8\x9C\x9C", + "\xDA\xCD" => "\xE8\xAC\x90", + "\xDA\xCE" => "\xE5\x89\x9D", + "\xDA\xCF" => "\xE5\x8D\x9A", + "\xDA\xD0" => "\xE6\x8B\x8D", + "\xDA\xD1" => "\xE6\x90\x8F", + "\xDA\xD2" => "\xE6\x92\xB2", + "\xDA\xD3" => "\xE6\x9C\xB4", + "\xDA\xD4" => "\xE6\xA8\xB8", + "\xDA\xD5" => "\xE6\xB3\x8A", + "\xDA\xD6" => "\xE7\x8F\x80", + "\xDA\xD7" => "\xE7\x92\x9E", + "\xDA\xD8" => "\xE7\xAE\x94", + "\xDA\xD9" => "\xE7\xB2\x95", + "\xDA\xDA" => "\xE7\xB8\x9B", + "\xDA\xDB" => "\xE8\x86\x8A", + "\xDA\xDC" => "\xE8\x88\xB6", + "\xDA\xDD" => "\xE8\x96\x84", + "\xDA\xDE" => "\xE8\xBF\xAB", + "\xDA\xDF" => "\xE9\x9B\xB9", + "\xDA\xE0" => "\xE9\xA7\x81", + "\xDA\xE1" => "\xE4\xBC\xB4", + "\xDA\xE2" => "\xE5\x8D\x8A", + "\xDA\xE3" => "\xE5\x8F\x8D", + "\xDA\xE4" => "\xE5\x8F\x9B", + "\xDA\xE5" => "\xE6\x8B\x8C", + "\xDA\xE6" => "\xE6\x90\xAC", + "\xDA\xE7" => "\xE6\x94\x80", + "\xDA\xE8" => "\xE6\x96\x91", + "\xDA\xE9" => "\xE6\xA7\x83", + "\xDA\xEA" => "\xE6\xB3\xAE", + "\xDA\xEB" => "\xE6\xBD\x98", + "\xDA\xEC" => "\xE7\x8F\xAD", + "\xDA\xED" => "\xE7\x95\x94", + "\xDA\xEE" => "\xE7\x98\xA2", + "\xDA\xEF" => "\xE7\x9B\xA4", + "\xDA\xF0" => "\xE7\x9B\xBC", + "\xDA\xF1" => "\xE7\xA3\x90", + "\xDA\xF2" => "\xE7\xA3\xBB", + "\xDA\xF3" => "\xE7\xA4\xAC", + "\xDA\xF4" => "\xE7\xB5\x86", + "\xDA\xF5" => "\xE8\x88\xAC", + "\xDA\xF6" => "\xE8\x9F\xA0", + "\xDA\xF7" => "\xE8\xBF\x94", + "\xDA\xF8" => "\xE9\xA0\x92", + "\xDA\xF9" => "\xE9\xA3\xAF", + "\xDA\xFA" => "\xE5\x8B\x83", + "\xDA\xFB" => "\xE6\x8B\x94", + "\xDA\xFC" => "\xE6\x92\xA5", + "\xDA\xFD" => "\xE6\xB8\xA4", + "\xDA\xFE" => "\xE6\xBD\x91", + "\xDB\xA1" => "\xE7\x99\xBC", + "\xDB\xA2" => "\xE8\xB7\x8B", + "\xDB\xA3" => "\xE9\x86\xB1", + "\xDB\xA4" => "\xE9\x89\xA2", + "\xDB\xA5" => "\xE9\xAB\xAE", + "\xDB\xA6" => "\xE9\xAD\x83", + "\xDB\xA7" => "\xE5\x80\xA3", + "\xDB\xA8" => "\xE5\x82\x8D", + "\xDB\xA9" => "\xE5\x9D\x8A", + "\xDB\xAA" => "\xE5\xA6\xA8", + "\xDB\xAB" => "\xE5\xB0\xA8", + "\xDB\xAC" => "\xE5\xB9\x87", + "\xDB\xAD" => "\xE5\xBD\xB7", + "\xDB\xAE" => "\xE6\x88\xBF", + "\xDB\xAF" => "\xE6\x94\xBE", + "\xDB\xB0" => "\xE6\x96\xB9", + "\xDB\xB1" => "\xE6\x97\x81", + "\xDB\xB2" => "\xE6\x98\x89", + "\xDB\xB3" => "\xE6\x9E\x8B", + "\xDB\xB4" => "\xE6\xA6\x9C", + "\xDB\xB5" => "\xE6\xBB\x82", + "\xDB\xB6" => "\xE7\xA3\x85", + "\xDB\xB7" => "\xE7\xB4\xA1", + "\xDB\xB8" => "\xE8\x82\xAA", + "\xDB\xB9" => "\xE8\x86\x80", + "\xDB\xBA" => "\xE8\x88\xAB", + "\xDB\xBB" => "\xE8\x8A\xB3", + "\xDB\xBC" => "\xE8\x92\xA1", + "\xDB\xBD" => "\xE8\x9A\x8C", + "\xDB\xBE" => "\xE8\xA8\xAA", + "\xDB\xBF" => "\xE8\xAC\x97", + "\xDB\xC0" => "\xE9\x82\xA6", + "\xDB\xC1" => "\xE9\x98\xB2", + "\xDB\xC2" => "\xE9\xBE\x90", + "\xDB\xC3" => "\xE5\x80\x8D", + "\xDB\xC4" => "\xE4\xBF\xB3", + "\xDB\xC5" => "\xEF\xA5\xA3", + "\xDB\xC6" => "\xE5\x9F\xB9", + "\xDB\xC7" => "\xE5\xBE\x98", + "\xDB\xC8" => "\xE6\x8B\x9C", + "\xDB\xC9" => "\xE6\x8E\x92", + "\xDB\xCA" => "\xE6\x9D\xAF", + "\xDB\xCB" => "\xE6\xB9\x83", + "\xDB\xCC" => "\xE7\x84\x99", + "\xDB\xCD" => "\xE7\x9B\x83", + "\xDB\xCE" => "\xE8\x83\x8C", + "\xDB\xCF" => "\xE8\x83\x9A", + "\xDB\xD0" => "\xE8\xA3\xB4", + "\xDB\xD1" => "\xE8\xA3\xB5", + "\xDB\xD2" => "\xE8\xA4\x99", + "\xDB\xD3" => "\xE8\xB3\xA0", + "\xDB\xD4" => "\xE8\xBC\xA9", + "\xDB\xD5" => "\xE9\x85\x8D", + "\xDB\xD6" => "\xE9\x99\xAA", + "\xDB\xD7" => "\xE4\xBC\xAF", + "\xDB\xD8" => "\xE4\xBD\xB0", + "\xDB\xD9" => "\xE5\xB8\x9B", + "\xDB\xDA" => "\xE6\x9F\x8F", + "\xDB\xDB" => "\xE6\xA0\xA2", + "\xDB\xDC" => "\xE7\x99\xBD", + "\xDB\xDD" => "\xE7\x99\xBE", + "\xDB\xDE" => "\xE9\xAD\x84", + "\xDB\xDF" => "\xE5\xB9\xA1", + "\xDB\xE0" => "\xE6\xA8\x8A", + "\xDB\xE1" => "\xE7\x85\xA9", + "\xDB\xE2" => "\xE7\x87\x94", + "\xDB\xE3" => "\xE7\x95\xAA", + "\xDB\xE4" => "\xEF\xA5\xA4", + "\xDB\xE5" => "\xE7\xB9\x81", + "\xDB\xE6" => "\xE8\x95\x83", + "\xDB\xE7" => "\xE8\x97\xA9", + "\xDB\xE8" => "\xE9\xA3\x9C", + "\xDB\xE9" => "\xE4\xBC\x90", + "\xDB\xEA" => "\xE7\xAD\x8F", + "\xDB\xEB" => "\xE7\xBD\xB0", + "\xDB\xEC" => "\xE9\x96\xA5", + "\xDB\xED" => "\xE5\x87\xA1", + "\xDB\xEE" => "\xE5\xB8\x86", + "\xDB\xEF" => "\xE6\xA2\xB5", + "\xDB\xF0" => "\xE6\xB0\xBE", + "\xDB\xF1" => "\xE6\xB1\x8E", + "\xDB\xF2" => "\xE6\xB3\x9B", + "\xDB\xF3" => "\xE7\x8A\xAF", + "\xDB\xF4" => "\xE7\xAF\x84", + "\xDB\xF5" => "\xE8\x8C\x83", + "\xDB\xF6" => "\xE6\xB3\x95", + "\xDB\xF7" => "\xE7\x90\xBA", + "\xDB\xF8" => "\xE5\x83\xBB", + "\xDB\xF9" => "\xE5\x8A\x88", + "\xDB\xFA" => "\xE5\xA3\x81", + "\xDB\xFB" => "\xE6\x93\x98", + "\xDB\xFC" => "\xE6\xAA\x97", + "\xDB\xFD" => "\xE7\x92\xA7", + "\xDB\xFE" => "\xE7\x99\x96", + "\xDC\xA1" => "\xE7\xA2\xA7", + "\xDC\xA2" => "\xE8\x98\x97", + "\xDC\xA3" => "\xE9\x97\xA2", + "\xDC\xA4" => "\xE9\x9C\xB9", + "\xDC\xA5" => "\xEF\xA5\xA5", + "\xDC\xA6" => "\xE5\x8D\x9E", + "\xDC\xA7" => "\xE5\xBC\x81", + "\xDC\xA8" => "\xE8\xAE\x8A", + "\xDC\xA9" => "\xE8\xBE\xA8", + "\xDC\xAA" => "\xE8\xBE\xAF", + "\xDC\xAB" => "\xE9\x82\x8A", + "\xDC\xAC" => "\xE5\x88\xA5", + "\xDC\xAD" => "\xE7\x9E\xA5", + "\xDC\xAE" => "\xE9\xB1\x89", + "\xDC\xAF" => "\xE9\xBC\x88", + "\xDC\xB0" => "\xE4\xB8\x99", + "\xDC\xB1" => "\xE5\x80\x82", + "\xDC\xB2" => "\xE5\x85\xB5", + "\xDC\xB3" => "\xE5\xB1\x9B", + "\xDC\xB4" => "\xE5\xB9\xB7", + "\xDC\xB5" => "\xE6\x98\x9E", + "\xDC\xB6" => "\xE6\x98\xBA", + "\xDC\xB7" => "\xE6\x9F\x84", + "\xDC\xB8" => "\xE6\xA3\x85", + "\xDC\xB9" => "\xE7\x82\xB3", + "\xDC\xBA" => "\xE7\x94\x81", + "\xDC\xBB" => "\xE7\x97\x85", + "\xDC\xBC" => "\xE7\xA7\x89", + "\xDC\xBD" => "\xE7\xAB\x9D", + "\xDC\xBE" => "\xE8\xBC\xA7", + "\xDC\xBF" => "\xE9\xA4\xA0", + "\xDC\xC0" => "\xE9\xA8\x88", + "\xDC\xC1" => "\xE4\xBF\x9D", + "\xDC\xC2" => "\xE5\xA0\xA1", + "\xDC\xC3" => "\xE5\xA0\xB1", + "\xDC\xC4" => "\xE5\xAF\xB6", + "\xDC\xC5" => "\xE6\x99\xAE", + "\xDC\xC6" => "\xE6\xAD\xA5", + "\xDC\xC7" => "\xE6\xB4\x91", + "\xDC\xC8" => "\xE6\xB9\xBA", + "\xDC\xC9" => "\xE6\xBD\xBD", + "\xDC\xCA" => "\xE7\x8F\xA4", + "\xDC\xCB" => "\xE7\x94\xAB", + "\xDC\xCC" => "\xE8\x8F\xA9", + "\xDC\xCD" => "\xE8\xA3\x9C", + "\xDC\xCE" => "\xE8\xA4\x93", + "\xDC\xCF" => "\xE8\xAD\x9C", + "\xDC\xD0" => "\xE8\xBC\x94", + "\xDC\xD1" => "\xE4\xBC\x8F", + "\xDC\xD2" => "\xE5\x83\x95", + "\xDC\xD3" => "\xE5\x8C\x90", + "\xDC\xD4" => "\xE5\x8D\x9C", + "\xDC\xD5" => "\xE5\xAE\x93", + "\xDC\xD6" => "\xE5\xBE\xA9", + "\xDC\xD7" => "\xE6\x9C\x8D", + "\xDC\xD8" => "\xE7\xA6\x8F", + "\xDC\xD9" => "\xE8\x85\xB9", + "\xDC\xDA" => "\xE8\x8C\xAF", + "\xDC\xDB" => "\xE8\x94\x94", + "\xDC\xDC" => "\xE8\xA4\x87", + "\xDC\xDD" => "\xE8\xA6\x86", + "\xDC\xDE" => "\xE8\xBC\xB9", + "\xDC\xDF" => "\xE8\xBC\xBB", + "\xDC\xE0" => "\xE9\xA6\xA5", + "\xDC\xE1" => "\xE9\xB0\x92", + "\xDC\xE2" => "\xE6\x9C\xAC", + "\xDC\xE3" => "\xE4\xB9\xB6", + "\xDC\xE4" => "\xE4\xBF\xB8", + "\xDC\xE5" => "\xE5\xA5\x89", + "\xDC\xE6" => "\xE5\xB0\x81", + "\xDC\xE7" => "\xE5\xB3\xAF", + "\xDC\xE8" => "\xE5\xB3\xB0", + "\xDC\xE9" => "\xE6\x8D\xA7", + "\xDC\xEA" => "\xE6\xA3\x92", + "\xDC\xEB" => "\xE7\x83\xBD", + "\xDC\xEC" => "\xE7\x86\xA2", + "\xDC\xED" => "\xE7\x90\xAB", + "\xDC\xEE" => "\xE7\xB8\xAB", + "\xDC\xEF" => "\xE8\x93\xAC", + "\xDC\xF0" => "\xE8\x9C\x82", + "\xDC\xF1" => "\xE9\x80\xA2", + "\xDC\xF2" => "\xE9\x8B\x92", + "\xDC\xF3" => "\xE9\xB3\xB3", + "\xDC\xF4" => "\xE4\xB8\x8D", + "\xDC\xF5" => "\xE4\xBB\x98", + "\xDC\xF6" => "\xE4\xBF\xAF", + "\xDC\xF7" => "\xE5\x82\x85", + "\xDC\xF8" => "\xE5\x89\x96", + "\xDC\xF9" => "\xE5\x89\xAF", + "\xDC\xFA" => "\xE5\x90\xA6", + "\xDC\xFB" => "\xE5\x92\x90", + "\xDC\xFC" => "\xE5\x9F\xA0", + "\xDC\xFD" => "\xE5\xA4\xAB", + "\xDC\xFE" => "\xE5\xA9\xA6", + "\xDD\xA1" => "\xE5\xAD\x9A", + "\xDD\xA2" => "\xE5\xAD\xB5", + "\xDD\xA3" => "\xE5\xAF\x8C", + "\xDD\xA4" => "\xE5\xBA\x9C", + "\xDD\xA5" => "\xEF\xA5\xA6", + "\xDD\xA6" => "\xE6\x89\xB6", + "\xDD\xA7" => "\xE6\x95\xB7", + "\xDD\xA8" => "\xE6\x96\xA7", + "\xDD\xA9" => "\xE6\xB5\xAE", + "\xDD\xAA" => "\xE6\xBA\xA5", + "\xDD\xAB" => "\xE7\x88\xB6", + "\xDD\xAC" => "\xE7\xAC\xA6", + "\xDD\xAD" => "\xE7\xB0\xBF", + "\xDD\xAE" => "\xE7\xBC\xB6", + "\xDD\xAF" => "\xE8\x85\x90", + "\xDD\xB0" => "\xE8\x85\x91", + "\xDD\xB1" => "\xE8\x86\x9A", + "\xDD\xB2" => "\xE8\x89\x80", + "\xDD\xB3" => "\xE8\x8A\x99", + "\xDD\xB4" => "\xE8\x8E\xA9", + "\xDD\xB5" => "\xE8\xA8\x83", + "\xDD\xB6" => "\xE8\xB2\xA0", + "\xDD\xB7" => "\xE8\xB3\xA6", + "\xDD\xB8" => "\xE8\xB3\xBB", + "\xDD\xB9" => "\xE8\xB5\xB4", + "\xDD\xBA" => "\xE8\xB6\xBA", + "\xDD\xBB" => "\xE9\x83\xA8", + "\xDD\xBC" => "\xE9\x87\x9C", + "\xDD\xBD" => "\xE9\x98\x9C", + "\xDD\xBE" => "\xE9\x99\x84", + "\xDD\xBF" => "\xE9\xA7\x99", + "\xDD\xC0" => "\xE9\xB3\xA7", + "\xDD\xC1" => "\xE5\x8C\x97", + "\xDD\xC2" => "\xE5\x88\x86", + "\xDD\xC3" => "\xE5\x90\xA9", + "\xDD\xC4" => "\xE5\x99\xB4", + "\xDD\xC5" => "\xE5\xA2\xB3", + "\xDD\xC6" => "\xE5\xA5\x94", + "\xDD\xC7" => "\xE5\xA5\xAE", + "\xDD\xC8" => "\xE5\xBF\xBF", + "\xDD\xC9" => "\xE6\x86\xA4", + "\xDD\xCA" => "\xE6\x89\xAE", + "\xDD\xCB" => "\xE6\x98\x90", + "\xDD\xCC" => "\xE6\xB1\xBE", + "\xDD\xCD" => "\xE7\x84\x9A", + "\xDD\xCE" => "\xE7\x9B\x86", + "\xDD\xCF" => "\xE7\xB2\x89", + "\xDD\xD0" => "\xE7\xB3\x9E", + "\xDD\xD1" => "\xE7\xB4\x9B", + "\xDD\xD2" => "\xE8\x8A\xAC", + "\xDD\xD3" => "\xE8\xB3\x81", + "\xDD\xD4" => "\xE9\x9B\xB0", + "\xDD\xD5" => "\xEF\xA5\xA7", + "\xDD\xD6" => "\xE4\xBD\x9B", + "\xDD\xD7" => "\xE5\xBC\x97", + "\xDD\xD8" => "\xE5\xBD\xBF", + "\xDD\xD9" => "\xE6\x8B\x82", + "\xDD\xDA" => "\xE5\xB4\xA9", + "\xDD\xDB" => "\xE6\x9C\x8B", + "\xDD\xDC" => "\xE6\xA3\x9A", + "\xDD\xDD" => "\xE7\xA1\xBC", + "\xDD\xDE" => "\xE7\xB9\x83", + "\xDD\xDF" => "\xE9\xB5\xAC", + "\xDD\xE0" => "\xE4\xB8\x95", + "\xDD\xE1" => "\xE5\x82\x99", + "\xDD\xE2" => "\xE5\x8C\x95", + "\xDD\xE3" => "\xE5\x8C\xAA", + "\xDD\xE4" => "\xE5\x8D\x91", + "\xDD\xE5" => "\xE5\xA6\x83", + "\xDD\xE6" => "\xE5\xA9\xA2", + "\xDD\xE7" => "\xE5\xBA\x87", + "\xDD\xE8" => "\xE6\x82\xB2", + "\xDD\xE9" => "\xE6\x86\x8A", + "\xDD\xEA" => "\xE6\x89\x89", + "\xDD\xEB" => "\xE6\x89\xB9", + "\xDD\xEC" => "\xE6\x96\x90", + "\xDD\xED" => "\xE6\x9E\x87", + "\xDD\xEE" => "\xE6\xA6\xA7", + "\xDD\xEF" => "\xE6\xAF\x94", + "\xDD\xF0" => "\xE6\xAF\x96", + "\xDD\xF1" => "\xE6\xAF\x97", + "\xDD\xF2" => "\xE6\xAF\x98", + "\xDD\xF3" => "\xE6\xB2\xB8", + "\xDD\xF4" => "\xEF\xA5\xA8", + "\xDD\xF5" => "\xE7\x90\xB5", + "\xDD\xF6" => "\xE7\x97\xBA", + "\xDD\xF7" => "\xE7\xA0\x92", + "\xDD\xF8" => "\xE7\xA2\x91", + "\xDD\xF9" => "\xE7\xA7\x95", + "\xDD\xFA" => "\xE7\xA7\x98", + "\xDD\xFB" => "\xE7\xB2\x83", + "\xDD\xFC" => "\xE7\xB7\x8B", + "\xDD\xFD" => "\xE7\xBF\xA1", + "\xDD\xFE" => "\xE8\x82\xA5", + "\xDE\xA1" => "\xE8\x84\xBE", + "\xDE\xA2" => "\xE8\x87\x82", + "\xDE\xA3" => "\xE8\x8F\xB2", + "\xDE\xA4" => "\xE8\x9C\x9A", + "\xDE\xA5" => "\xE8\xA3\xA8", + "\xDE\xA6" => "\xE8\xAA\xB9", + "\xDE\xA7" => "\xE8\xAD\xAC", + "\xDE\xA8" => "\xE8\xB2\xBB", + "\xDE\xA9" => "\xE9\x84\x99", + "\xDE\xAA" => "\xE9\x9D\x9E", + "\xDE\xAB" => "\xE9\xA3\x9B", + "\xDE\xAC" => "\xE9\xBC\xBB", + "\xDE\xAD" => "\xE5\x9A\xAC", + "\xDE\xAE" => "\xE5\xAC\xAA", + "\xDE\xAF" => "\xE5\xBD\xAC", + "\xDE\xB0" => "\xE6\x96\x8C", + "\xDE\xB1" => "\xE6\xAA\xB3", + "\xDE\xB2" => "\xE6\xAE\xAF", + "\xDE\xB3" => "\xE6\xB5\x9C", + "\xDE\xB4" => "\xE6\xBF\xB1", + "\xDE\xB5" => "\xE7\x80\x95", + "\xDE\xB6" => "\xE7\x89\x9D", + "\xDE\xB7" => "\xE7\x8E\xAD", + "\xDE\xB8" => "\xE8\xB2\xA7", + "\xDE\xB9" => "\xE8\xB3\x93", + "\xDE\xBA" => "\xE9\xA0\xBB", + "\xDE\xBB" => "\xE6\x86\x91", + "\xDE\xBC" => "\xE6\xB0\xB7", + "\xDE\xBD" => "\xE8\x81\x98", + "\xDE\xBE" => "\xE9\xA8\x81", + "\xDE\xBF" => "\xE4\xB9\x8D", + "\xDE\xC0" => "\xE4\xBA\x8B", + "\xDE\xC1" => "\xE4\xBA\x9B", + "\xDE\xC2" => "\xE4\xBB\x95", + "\xDE\xC3" => "\xE4\xBC\xBA", + "\xDE\xC4" => "\xE4\xBC\xBC", + "\xDE\xC5" => "\xE4\xBD\xBF", + "\xDE\xC6" => "\xE4\xBF\x9F", + "\xDE\xC7" => "\xE5\x83\xBF", + "\xDE\xC8" => "\xE5\x8F\xB2", + "\xDE\xC9" => "\xE5\x8F\xB8", + "\xDE\xCA" => "\xE5\x94\x86", + "\xDE\xCB" => "\xE5\x97\xA3", + "\xDE\xCC" => "\xE5\x9B\x9B", + "\xDE\xCD" => "\xE5\xA3\xAB", + "\xDE\xCE" => "\xE5\xA5\xA2", + "\xDE\xCF" => "\xE5\xA8\x91", + "\xDE\xD0" => "\xE5\xAF\xAB", + "\xDE\xD1" => "\xE5\xAF\xBA", + "\xDE\xD2" => "\xE5\xB0\x84", + "\xDE\xD3" => "\xE5\xB7\xB3", + "\xDE\xD4" => "\xE5\xB8\xAB", + "\xDE\xD5" => "\xE5\xBE\x99", + "\xDE\xD6" => "\xE6\x80\x9D", + "\xDE\xD7" => "\xE6\x8D\xA8", + "\xDE\xD8" => "\xE6\x96\x9C", + "\xDE\xD9" => "\xE6\x96\xAF", + "\xDE\xDA" => "\xE6\x9F\xB6", + "\xDE\xDB" => "\xE6\x9F\xBB", + "\xDE\xDC" => "\xE6\xA2\xAD", + "\xDE\xDD" => "\xE6\xAD\xBB", + "\xDE\xDE" => "\xE6\xB2\x99", + "\xDE\xDF" => "\xE6\xB3\x97", + "\xDE\xE0" => "\xE6\xB8\xA3", + "\xDE\xE1" => "\xE7\x80\x89", + "\xDE\xE2" => "\xE7\x8D\x85", + "\xDE\xE3" => "\xE7\xA0\x82", + "\xDE\xE4" => "\xE7\xA4\xBE", + "\xDE\xE5" => "\xE7\xA5\x80", + "\xDE\xE6" => "\xE7\xA5\xA0", + "\xDE\xE7" => "\xE7\xA7\x81", + "\xDE\xE8" => "\xE7\xAF\xA9", + "\xDE\xE9" => "\xE7\xB4\x97", + "\xDE\xEA" => "\xE7\xB5\xB2", + "\xDE\xEB" => "\xE8\x82\x86", + "\xDE\xEC" => "\xE8\x88\x8D", + "\xDE\xED" => "\xE8\x8E\x8E", + "\xDE\xEE" => "\xE8\x93\x91", + "\xDE\xEF" => "\xE8\x9B\x87", + "\xDE\xF0" => "\xE8\xA3\x9F", + "\xDE\xF1" => "\xE8\xA9\x90", + "\xDE\xF2" => "\xE8\xA9\x9E", + "\xDE\xF3" => "\xE8\xAC\x9D", + "\xDE\xF4" => "\xE8\xB3\x9C", + "\xDE\xF5" => "\xE8\xB5\xA6", + "\xDE\xF6" => "\xE8\xBE\xAD", + "\xDE\xF7" => "\xE9\x82\xAA", + "\xDE\xF8" => "\xE9\xA3\xBC", + "\xDE\xF9" => "\xE9\xA7\x9F", + "\xDE\xFA" => "\xE9\xBA\x9D", + "\xDE\xFB" => "\xE5\x89\x8A", + "\xDE\xFC" => "\xEF\xA5\xA9", + "\xDE\xFD" => "\xE6\x9C\x94", + "\xDE\xFE" => "\xEF\xA5\xAA", + "\xDF\xA1" => "\xE5\x82\x98", + "\xDF\xA2" => "\xE5\x88\xAA", + "\xDF\xA3" => "\xE5\xB1\xB1", + "\xDF\xA4" => "\xE6\x95\xA3", + "\xDF\xA5" => "\xE6\xB1\x95", + "\xDF\xA6" => "\xE7\x8F\x8A", + "\xDF\xA7" => "\xE7\x94\xA3", + "\xDF\xA8" => "\xE7\x96\x9D", + "\xDF\xA9" => "\xE7\xAE\x97", + "\xDF\xAA" => "\xE8\x92\x9C", + "\xDF\xAB" => "\xE9\x85\xB8", + "\xDF\xAC" => "\xE9\x9C\xB0", + "\xDF\xAD" => "\xE4\xB9\xB7", + "\xDF\xAE" => "\xE6\x92\x92", + "\xDF\xAF" => "\xE6\xAE\xBA", + "\xDF\xB0" => "\xE7\x85\x9E", + "\xDF\xB1" => "\xE8\x96\xA9", + "\xDF\xB2" => "\xE4\xB8\x89", + "\xDF\xB3" => "\xEF\xA5\xAB", + "\xDF\xB4" => "\xE6\x9D\x89", + "\xDF\xB5" => "\xE6\xA3\xAE", + "\xDF\xB6" => "\xE6\xB8\x97", + "\xDF\xB7" => "\xE8\x8A\x9F", + "\xDF\xB8" => "\xE8\x94\x98", + "\xDF\xB9" => "\xE8\xA1\xAB", + "\xDF\xBA" => "\xE6\x8F\xB7", + "\xDF\xBB" => "\xE6\xBE\x81", + "\xDF\xBC" => "\xE9\x88\x92", + "\xDF\xBD" => "\xE9\xA2\xAF", + "\xDF\xBE" => "\xE4\xB8\x8A", + "\xDF\xBF" => "\xE5\x82\xB7", + "\xDF\xC0" => "\xE5\x83\x8F", + "\xDF\xC1" => "\xE5\x84\x9F", + "\xDF\xC2" => "\xE5\x95\x86", + "\xDF\xC3" => "\xE5\x96\xAA", + "\xDF\xC4" => "\xE5\x98\x97", + "\xDF\xC5" => "\xE5\xAD\x80", + "\xDF\xC6" => "\xE5\xB0\x99", + "\xDF\xC7" => "\xE5\xB3\xA0", + "\xDF\xC8" => "\xE5\xB8\xB8", + "\xDF\xC9" => "\xE5\xBA\x8A", + "\xDF\xCA" => "\xE5\xBA\xA0", + "\xDF\xCB" => "\xE5\xBB\x82", + "\xDF\xCC" => "\xE6\x83\xB3", + "\xDF\xCD" => "\xE6\xA1\x91", + "\xDF\xCE" => "\xE6\xA9\xA1", + "\xDF\xCF" => "\xE6\xB9\x98", + "\xDF\xD0" => "\xE7\x88\xBD", + "\xDF\xD1" => "\xE7\x89\x80", + "\xDF\xD2" => "\xE7\x8B\x80", + "\xDF\xD3" => "\xE7\x9B\xB8", + "\xDF\xD4" => "\xE7\xA5\xA5", + "\xDF\xD5" => "\xE7\xAE\xB1", + "\xDF\xD6" => "\xE7\xBF\x94", + "\xDF\xD7" => "\xE8\xA3\xB3", + "\xDF\xD8" => "\xE8\xA7\xB4", + "\xDF\xD9" => "\xE8\xA9\xB3", + "\xDF\xDA" => "\xE8\xB1\xA1", + "\xDF\xDB" => "\xE8\xB3\x9E", + "\xDF\xDC" => "\xE9\x9C\x9C", + "\xDF\xDD" => "\xE5\xA1\x9E", + "\xDF\xDE" => "\xE7\x92\xBD", + "\xDF\xDF" => "\xE8\xB3\xBD", + "\xDF\xE0" => "\xE5\x97\x87", + "\xDF\xE1" => "\xEF\xA5\xAC", + "\xDF\xE2" => "\xE7\xA9\xA1", + "\xDF\xE3" => "\xE7\xB4\xA2", + "\xDF\xE4" => "\xE8\x89\xB2", + "\xDF\xE5" => "\xE7\x89\xB2", + "\xDF\xE6" => "\xE7\x94\x9F", + "\xDF\xE7" => "\xE7\x94\xA5", + "\xDF\xE8" => "\xEF\xA5\xAD", + "\xDF\xE9" => "\xE7\xAC\x99", + "\xDF\xEA" => "\xE5\xA2\x85", + "\xDF\xEB" => "\xE5\xA3\xBB", + "\xDF\xEC" => "\xE5\xB6\xBC", + "\xDF\xED" => "\xE5\xBA\x8F", + "\xDF\xEE" => "\xE5\xBA\xB6", + "\xDF\xEF" => "\xE5\xBE\x90", + "\xDF\xF0" => "\xE6\x81\x95", + "\xDF\xF1" => "\xE6\x8A\x92", + "\xDF\xF2" => "\xE6\x8D\xBF", + "\xDF\xF3" => "\xE6\x95\x8D", + "\xDF\xF4" => "\xE6\x9A\x91", + "\xDF\xF5" => "\xE6\x9B\x99", + "\xDF\xF6" => "\xE6\x9B\xB8", + "\xDF\xF7" => "\xE6\xA0\x96", + "\xDF\xF8" => "\xE6\xA3\xB2", + "\xDF\xF9" => "\xE7\x8A\x80", + "\xDF\xFA" => "\xE7\x91\x9E", + "\xDF\xFB" => "\xE7\xAD\xAE", + "\xDF\xFC" => "\xE7\xB5\xAE", + "\xDF\xFD" => "\xE7\xB7\x96", + "\xDF\xFE" => "\xE7\xBD\xB2", + "\xE0\xA1" => "\xE8\x83\xA5", + "\xE0\xA2" => "\xE8\x88\x92", + "\xE0\xA3" => "\xE8\x96\xAF", + "\xE0\xA4" => "\xE8\xA5\xBF", + "\xE0\xA5" => "\xE8\xAA\x93", + "\xE0\xA6" => "\xE9\x80\x9D", + "\xE0\xA7" => "\xE9\x8B\xA4", + "\xE0\xA8" => "\xE9\xBB\x8D", + "\xE0\xA9" => "\xE9\xBC\xA0", + "\xE0\xAA" => "\xE5\xA4\x95", + "\xE0\xAB" => "\xE5\xA5\xAD", + "\xE0\xAC" => "\xE5\xB8\xAD", + "\xE0\xAD" => "\xE6\x83\x9C", + "\xE0\xAE" => "\xE6\x98\x94", + "\xE0\xAF" => "\xE6\x99\xB3", + "\xE0\xB0" => "\xE6\x9E\x90", + "\xE0\xB1" => "\xE6\xB1\x90", + "\xE0\xB2" => "\xE6\xB7\x85", + "\xE0\xB3" => "\xE6\xBD\x9F", + "\xE0\xB4" => "\xE7\x9F\xB3", + "\xE0\xB5" => "\xE7\xA2\xA9", + "\xE0\xB6" => "\xE8\x93\x86", + "\xE0\xB7" => "\xE9\x87\x8B", + "\xE0\xB8" => "\xE9\x8C\xAB", + "\xE0\xB9" => "\xE4\xBB\x99", + "\xE0\xBA" => "\xE5\x83\x8A", + "\xE0\xBB" => "\xE5\x85\x88", + "\xE0\xBC" => "\xE5\x96\x84", + "\xE0\xBD" => "\xE5\xAC\x8B", + "\xE0\xBE" => "\xE5\xAE\xA3", + "\xE0\xBF" => "\xE6\x89\x87", + "\xE0\xC0" => "\xE6\x95\xBE", + "\xE0\xC1" => "\xE6\x97\x8B", + "\xE0\xC2" => "\xE6\xB8\xB2", + "\xE0\xC3" => "\xE7\x85\xBD", + "\xE0\xC4" => "\xE7\x90\x81", + "\xE0\xC5" => "\xE7\x91\x84", + "\xE0\xC6" => "\xE7\x92\x87", + "\xE0\xC7" => "\xE7\x92\xBF", + "\xE0\xC8" => "\xE7\x99\xAC", + "\xE0\xC9" => "\xE7\xA6\xAA", + "\xE0\xCA" => "\xE7\xB7\x9A", + "\xE0\xCB" => "\xE7\xB9\x95", + "\xE0\xCC" => "\xE7\xBE\xA8", + "\xE0\xCD" => "\xE8\x85\xBA", + "\xE0\xCE" => "\xE8\x86\xB3", + "\xE0\xCF" => "\xE8\x88\xB9", + "\xE0\xD0" => "\xE8\x98\x9A", + "\xE0\xD1" => "\xE8\x9F\xAC", + "\xE0\xD2" => "\xE8\xA9\xB5", + "\xE0\xD3" => "\xE8\xB7\xA3", + "\xE0\xD4" => "\xE9\x81\xB8", + "\xE0\xD5" => "\xE9\x8A\x91", + "\xE0\xD6" => "\xE9\x90\xA5", + "\xE0\xD7" => "\xE9\xA5\x8D", + "\xE0\xD8" => "\xE9\xAE\xAE", + "\xE0\xD9" => "\xE5\x8D\xA8", + "\xE0\xDA" => "\xE5\xB1\x91", + "\xE0\xDB" => "\xE6\xA5\x94", + "\xE0\xDC" => "\xE6\xB3\x84", + "\xE0\xDD" => "\xE6\xB4\xA9", + "\xE0\xDE" => "\xE6\xB8\xAB", + "\xE0\xDF" => "\xE8\x88\x8C", + "\xE0\xE0" => "\xE8\x96\x9B", + "\xE0\xE1" => "\xE8\xA4\xBB", + "\xE0\xE2" => "\xE8\xA8\xAD", + "\xE0\xE3" => "\xE8\xAA\xAA", + "\xE0\xE4" => "\xE9\x9B\xAA", + "\xE0\xE5" => "\xE9\xBD\xA7", + "\xE0\xE6" => "\xE5\x89\xA1", + "\xE0\xE7" => "\xE6\x9A\xB9", + "\xE0\xE8" => "\xE6\xAE\xB2", + "\xE0\xE9" => "\xE7\xBA\x96", + "\xE0\xEA" => "\xE8\x9F\xBE", + "\xE0\xEB" => "\xE8\xB4\x8D", + "\xE0\xEC" => "\xE9\x96\x83", + "\xE0\xED" => "\xE9\x99\x9D", + "\xE0\xEE" => "\xE6\x94\x9D", + "\xE0\xEF" => "\xE6\xB6\x89", + "\xE0\xF0" => "\xE7\x87\xAE", + "\xE0\xF1" => "\xEF\xA5\xAE", + "\xE0\xF2" => "\xE5\x9F\x8E", + "\xE0\xF3" => "\xE5\xA7\x93", + "\xE0\xF4" => "\xE5\xAE\xAC", + "\xE0\xF5" => "\xE6\x80\xA7", + "\xE0\xF6" => "\xE6\x83\xBA", + "\xE0\xF7" => "\xE6\x88\x90", + "\xE0\xF8" => "\xE6\x98\x9F", + "\xE0\xF9" => "\xE6\x99\x9F", + "\xE0\xFA" => "\xE7\x8C\xA9", + "\xE0\xFB" => "\xE7\x8F\xB9", + "\xE0\xFC" => "\xE7\x9B\x9B", + "\xE0\xFD" => "\xE7\x9C\x81", + "\xE0\xFE" => "\xE7\xAD\xAC", + "\xE1\xA1" => "\xE8\x81\x96", + "\xE1\xA2" => "\xE8\x81\xB2", + "\xE1\xA3" => "\xE8\x85\xA5", + "\xE1\xA4" => "\xE8\xAA\xA0", + "\xE1\xA5" => "\xE9\x86\x92", + "\xE1\xA6" => "\xE4\xB8\x96", + "\xE1\xA7" => "\xE5\x8B\xA2", + "\xE1\xA8" => "\xE6\xAD\xB2", + "\xE1\xA9" => "\xE6\xB4\x97", + "\xE1\xAA" => "\xE7\xA8\x85", + "\xE1\xAB" => "\xE7\xAC\xB9", + "\xE1\xAC" => "\xE7\xB4\xB0", + "\xE1\xAD" => "\xEF\xA5\xAF", + "\xE1\xAE" => "\xE8\xB2\xB0", + "\xE1\xAF" => "\xE5\x8F\xAC", + "\xE1\xB0" => "\xE5\x98\xAF", + "\xE1\xB1" => "\xE5\xA1\x91", + "\xE1\xB2" => "\xE5\xAE\xB5", + "\xE1\xB3" => "\xE5\xB0\x8F", + "\xE1\xB4" => "\xE5\xB0\x91", + "\xE1\xB5" => "\xE5\xB7\xA2", + "\xE1\xB6" => "\xE6\x89\x80", + "\xE1\xB7" => "\xE6\x8E\x83", + "\xE1\xB8" => "\xE6\x90\x94", + "\xE1\xB9" => "\xE6\x98\xAD", + "\xE1\xBA" => "\xE6\xA2\xB3", + "\xE1\xBB" => "\xE6\xB2\xBC", + "\xE1\xBC" => "\xE6\xB6\x88", + "\xE1\xBD" => "\xE6\xBA\xAF", + "\xE1\xBE" => "\xE7\x80\x9F", + "\xE1\xBF" => "\xE7\x82\xA4", + "\xE1\xC0" => "\xE7\x87\x92", + "\xE1\xC1" => "\xE7\x94\xA6", + "\xE1\xC2" => "\xE7\x96\x8F", + "\xE1\xC3" => "\xE7\x96\x8E", + "\xE1\xC4" => "\xE7\x98\x99", + "\xE1\xC5" => "\xE7\xAC\x91", + "\xE1\xC6" => "\xE7\xAF\xA0", + "\xE1\xC7" => "\xE7\xB0\xAB", + "\xE1\xC8" => "\xE7\xB4\xA0", + "\xE1\xC9" => "\xE7\xB4\xB9", + "\xE1\xCA" => "\xE8\x94\xAC", + "\xE1\xCB" => "\xE8\x95\xAD", + "\xE1\xCC" => "\xE8\x98\x87", + "\xE1\xCD" => "\xE8\xA8\xB4", + "\xE1\xCE" => "\xE9\x80\x8D", + "\xE1\xCF" => "\xE9\x81\xA1", + "\xE1\xD0" => "\xE9\x82\xB5", + "\xE1\xD1" => "\xE9\x8A\xB7", + "\xE1\xD2" => "\xE9\x9F\xB6", + "\xE1\xD3" => "\xE9\xA8\xB7", + "\xE1\xD4" => "\xE4\xBF\x97", + "\xE1\xD5" => "\xE5\xB1\xAC", + "\xE1\xD6" => "\xE6\x9D\x9F", + "\xE1\xD7" => "\xE6\xB6\x91", + "\xE1\xD8" => "\xE7\xB2\x9F", + "\xE1\xD9" => "\xE7\xBA\x8C", + "\xE1\xDA" => "\xE8\xAC\x96", + "\xE1\xDB" => "\xE8\xB4\x96", + "\xE1\xDC" => "\xE9\x80\x9F", + "\xE1\xDD" => "\xE5\xAD\xAB", + "\xE1\xDE" => "\xE5\xB7\xBD", + "\xE1\xDF" => "\xE6\x90\x8D", + "\xE1\xE0" => "\xE8\x93\x80", + "\xE1\xE1" => "\xE9\x81\x9C", + "\xE1\xE2" => "\xE9\xA3\xA1", + "\xE1\xE3" => "\xE7\x8E\x87", + "\xE1\xE4" => "\xE5\xAE\x8B", + "\xE1\xE5" => "\xE6\x82\x9A", + "\xE1\xE6" => "\xE6\x9D\xBE", + "\xE1\xE7" => "\xE6\xB7\x9E", + "\xE1\xE8" => "\xE8\xA8\x9F", + "\xE1\xE9" => "\xE8\xAA\xA6", + "\xE1\xEA" => "\xE9\x80\x81", + "\xE1\xEB" => "\xE9\xA0\x8C", + "\xE1\xEC" => "\xE5\x88\xB7", + "\xE1\xED" => "\xEF\xA5\xB0", + "\xE1\xEE" => "\xE7\x81\x91", + "\xE1\xEF" => "\xE7\xA2\x8E", + "\xE1\xF0" => "\xE9\x8E\x96", + "\xE1\xF1" => "\xE8\xA1\xB0", + "\xE1\xF2" => "\xE9\x87\x97", + "\xE1\xF3" => "\xE4\xBF\xAE", + "\xE1\xF4" => "\xE5\x8F\x97", + "\xE1\xF5" => "\xE5\x97\xBD", + "\xE1\xF6" => "\xE5\x9B\x9A", + "\xE1\xF7" => "\xE5\x9E\x82", + "\xE1\xF8" => "\xE5\xA3\xBD", + "\xE1\xF9" => "\xE5\xAB\x82", + "\xE1\xFA" => "\xE5\xAE\x88", + "\xE1\xFB" => "\xE5\xB2\xAB", + "\xE1\xFC" => "\xE5\xB3\x80", + "\xE1\xFD" => "\xE5\xB8\xA5", + "\xE1\xFE" => "\xE6\x84\x81", + "\xE2\xA1" => "\xE6\x88\x8D", + "\xE2\xA2" => "\xE6\x89\x8B", + "\xE2\xA3" => "\xE6\x8E\x88", + "\xE2\xA4" => "\xE6\x90\x9C", + "\xE2\xA5" => "\xE6\x94\xB6", + "\xE2\xA6" => "\xE6\x95\xB8", + "\xE2\xA7" => "\xE6\xA8\xB9", + "\xE2\xA8" => "\xE6\xAE\x8A", + "\xE2\xA9" => "\xE6\xB0\xB4", + "\xE2\xAA" => "\xE6\xB4\x99", + "\xE2\xAB" => "\xE6\xBC\xB1", + "\xE2\xAC" => "\xE7\x87\xA7", + "\xE2\xAD" => "\xE7\x8B\xA9", + "\xE2\xAE" => "\xE7\x8D\xB8", + "\xE2\xAF" => "\xE7\x90\x87", + "\xE2\xB0" => "\xE7\x92\xB2", + "\xE2\xB1" => "\xE7\x98\xA6", + "\xE2\xB2" => "\xE7\x9D\xA1", + "\xE2\xB3" => "\xE7\xA7\x80", + "\xE2\xB4" => "\xE7\xA9\x97", + "\xE2\xB5" => "\xE7\xAB\xAA", + "\xE2\xB6" => "\xE7\xB2\xB9", + "\xE2\xB7" => "\xE7\xB6\x8F", + "\xE2\xB8" => "\xE7\xB6\xAC", + "\xE2\xB9" => "\xE7\xB9\xA1", + "\xE2\xBA" => "\xE7\xBE\x9E", + "\xE2\xBB" => "\xE8\x84\xA9", + "\xE2\xBC" => "\xE8\x8C\xB1", + "\xE2\xBD" => "\xE8\x92\x90", + "\xE2\xBE" => "\xE8\x93\x9A", + "\xE2\xBF" => "\xE8\x97\xAA", + "\xE2\xC0" => "\xE8\xA2\x96", + "\xE2\xC1" => "\xE8\xAA\xB0", + "\xE2\xC2" => "\xE8\xAE\x90", + "\xE2\xC3" => "\xE8\xBC\xB8", + "\xE2\xC4" => "\xE9\x81\x82", + "\xE2\xC5" => "\xE9\x82\x83", + "\xE2\xC6" => "\xE9\x85\xAC", + "\xE2\xC7" => "\xE9\x8A\x96", + "\xE2\xC8" => "\xE9\x8A\xB9", + "\xE2\xC9" => "\xE9\x9A\x8B", + "\xE2\xCA" => "\xE9\x9A\xA7", + "\xE2\xCB" => "\xE9\x9A\xA8", + "\xE2\xCC" => "\xE9\x9B\x96", + "\xE2\xCD" => "\xE9\x9C\x80", + "\xE2\xCE" => "\xE9\xA0\x88", + "\xE2\xCF" => "\xE9\xA6\x96", + "\xE2\xD0" => "\xE9\xAB\x93", + "\xE2\xD1" => "\xE9\xAC\x9A", + "\xE2\xD2" => "\xE5\x8F\x94", + "\xE2\xD3" => "\xE5\xA1\xBE", + "\xE2\xD4" => "\xE5\xA4\x99", + "\xE2\xD5" => "\xE5\xAD\xB0", + "\xE2\xD6" => "\xE5\xAE\xBF", + "\xE2\xD7" => "\xE6\xB7\x91", + "\xE2\xD8" => "\xE6\xBD\x9A", + "\xE2\xD9" => "\xE7\x86\x9F", + "\xE2\xDA" => "\xE7\x90\xA1", + "\xE2\xDB" => "\xE7\x92\xB9", + "\xE2\xDC" => "\xE8\x82\x85", + "\xE2\xDD" => "\xE8\x8F\xBD", + "\xE2\xDE" => "\xE5\xB7\xA1", + "\xE2\xDF" => "\xE5\xBE\x87", + "\xE2\xE0" => "\xE5\xBE\xAA", + "\xE2\xE1" => "\xE6\x81\x82", + "\xE2\xE2" => "\xE6\x97\xAC", + "\xE2\xE3" => "\xE6\xA0\x92", + "\xE2\xE4" => "\xE6\xA5\xAF", + "\xE2\xE5" => "\xE6\xA9\x93", + "\xE2\xE6" => "\xE6\xAE\x89", + "\xE2\xE7" => "\xE6\xB4\xB5", + "\xE2\xE8" => "\xE6\xB7\xB3", + "\xE2\xE9" => "\xE7\x8F\xA3", + "\xE2\xEA" => "\xE7\x9B\xBE", + "\xE2\xEB" => "\xE7\x9E\xAC", + "\xE2\xEC" => "\xE7\xAD\x8D", + "\xE2\xED" => "\xE7\xB4\x94", + "\xE2\xEE" => "\xE8\x84\xA3", + "\xE2\xEF" => "\xE8\x88\x9C", + "\xE2\xF0" => "\xE8\x8D\x80", + "\xE2\xF1" => "\xE8\x93\xB4", + "\xE2\xF2" => "\xE8\x95\xA3", + "\xE2\xF3" => "\xE8\xA9\xA2", + "\xE2\xF4" => "\xE8\xAB\x84", + "\xE2\xF5" => "\xE9\x86\x87", + "\xE2\xF6" => "\xE9\x8C\x9E", + "\xE2\xF7" => "\xE9\xA0\x86", + "\xE2\xF8" => "\xE9\xA6\xB4", + "\xE2\xF9" => "\xE6\x88\x8C", + "\xE2\xFA" => "\xE8\xA1\x93", + "\xE2\xFB" => "\xE8\xBF\xB0", + "\xE2\xFC" => "\xE9\x89\xA5", + "\xE2\xFD" => "\xE5\xB4\x87", + "\xE2\xFE" => "\xE5\xB4\xA7", + "\xE3\xA1" => "\xE5\xB5\xA9", + "\xE3\xA2" => "\xE7\x91\x9F", + "\xE3\xA3" => "\xE8\x86\x9D", + "\xE3\xA4" => "\xE8\x9D\xA8", + "\xE3\xA5" => "\xE6\xBF\x95", + "\xE3\xA6" => "\xE6\x8B\xBE", + "\xE3\xA7" => "\xE7\xBF\x92", + "\xE3\xA8" => "\xE8\xA4\xB6", + "\xE3\xA9" => "\xE8\xA5\xB2", + "\xE3\xAA" => "\xE4\xB8\x9E", + "\xE3\xAB" => "\xE4\xB9\x98", + "\xE3\xAC" => "\xE5\x83\xA7", + "\xE3\xAD" => "\xE5\x8B\x9D", + "\xE3\xAE" => "\xE5\x8D\x87", + "\xE3\xAF" => "\xE6\x89\xBF", + "\xE3\xB0" => "\xE6\x98\x87", + "\xE3\xB1" => "\xE7\xB9\xA9", + "\xE3\xB2" => "\xE8\xA0\x85", + "\xE3\xB3" => "\xE9\x99\x9E", + "\xE3\xB4" => "\xE4\xBE\x8D", + "\xE3\xB5" => "\xE5\x8C\x99", + "\xE3\xB6" => "\xE5\x98\xB6", + "\xE3\xB7" => "\xE5\xA7\x8B", + "\xE3\xB8" => "\xE5\xAA\xA4", + "\xE3\xB9" => "\xE5\xB0\xB8", + "\xE3\xBA" => "\xE5\xB1\x8E", + "\xE3\xBB" => "\xE5\xB1\x8D", + "\xE3\xBC" => "\xE5\xB8\x82", + "\xE3\xBD" => "\xE5\xBC\x91", + "\xE3\xBE" => "\xE6\x81\x83", + "\xE3\xBF" => "\xE6\x96\xBD", + "\xE3\xC0" => "\xE6\x98\xAF", + "\xE3\xC1" => "\xE6\x99\x82", + "\xE3\xC2" => "\xE6\x9E\xBE", + "\xE3\xC3" => "\xE6\x9F\xB4", + "\xE3\xC4" => "\xE7\x8C\x9C", + "\xE3\xC5" => "\xE7\x9F\xA2", + "\xE3\xC6" => "\xE7\xA4\xBA", + "\xE3\xC7" => "\xE7\xBF\x85", + "\xE3\xC8" => "\xE8\x92\x94", + "\xE3\xC9" => "\xE8\x93\x8D", + "\xE3\xCA" => "\xE8\xA6\x96", + "\xE3\xCB" => "\xE8\xA9\xA6", + "\xE3\xCC" => "\xE8\xA9\xA9", + "\xE3\xCD" => "\xE8\xAB\xA1", + "\xE3\xCE" => "\xE8\xB1\x95", + "\xE3\xCF" => "\xE8\xB1\xBA", + "\xE3\xD0" => "\xE5\x9F\xB4", + "\xE3\xD1" => "\xE5\xAF\x94", + "\xE3\xD2" => "\xE5\xBC\x8F", + "\xE3\xD3" => "\xE6\x81\xAF", + "\xE3\xD4" => "\xE6\x8B\xAD", + "\xE3\xD5" => "\xE6\xA4\x8D", + "\xE3\xD6" => "\xE6\xAE\x96", + "\xE3\xD7" => "\xE6\xB9\x9C", + "\xE3\xD8" => "\xE7\x86\x84", + "\xE3\xD9" => "\xE7\xAF\x92", + "\xE3\xDA" => "\xE8\x9D\x95", + "\xE3\xDB" => "\xE8\xAD\x98", + "\xE3\xDC" => "\xE8\xBB\xBE", + "\xE3\xDD" => "\xE9\xA3\x9F", + "\xE3\xDE" => "\xE9\xA3\xBE", + "\xE3\xDF" => "\xE4\xBC\xB8", + "\xE3\xE0" => "\xE4\xBE\x81", + "\xE3\xE1" => "\xE4\xBF\xA1", + "\xE3\xE2" => "\xE5\x91\xBB", + "\xE3\xE3" => "\xE5\xA8\xA0", + "\xE3\xE4" => "\xE5\xAE\xB8", + "\xE3\xE5" => "\xE6\x84\xBC", + "\xE3\xE6" => "\xE6\x96\xB0", + "\xE3\xE7" => "\xE6\x99\xA8", + "\xE3\xE8" => "\xE7\x87\xBC", + "\xE3\xE9" => "\xE7\x94\xB3", + "\xE3\xEA" => "\xE7\xA5\x9E", + "\xE3\xEB" => "\xE7\xB4\xB3", + "\xE3\xEC" => "\xE8\x85\x8E", + "\xE3\xED" => "\xE8\x87\xA3", + "\xE3\xEE" => "\xE8\x8E\x98", + "\xE3\xEF" => "\xE8\x96\xAA", + "\xE3\xF0" => "\xE8\x97\x8E", + "\xE3\xF1" => "\xE8\x9C\x83", + "\xE3\xF2" => "\xE8\xA8\x8A", + "\xE3\xF3" => "\xE8\xBA\xAB", + "\xE3\xF4" => "\xE8\xBE\x9B", + "\xE3\xF5" => "\xEF\xA5\xB1", + "\xE3\xF6" => "\xE8\xBF\x85", + "\xE3\xF7" => "\xE5\xA4\xB1", + "\xE3\xF8" => "\xE5\xAE\xA4", + "\xE3\xF9" => "\xE5\xAF\xA6", + "\xE3\xFA" => "\xE6\x82\x89", + "\xE3\xFB" => "\xE5\xAF\xA9", + "\xE3\xFC" => "\xE5\xB0\x8B", + "\xE3\xFD" => "\xE5\xBF\x83", + "\xE3\xFE" => "\xE6\xB2\x81", + "\xE4\xA1" => "\xEF\xA5\xB2", + "\xE4\xA2" => "\xE6\xB7\xB1", + "\xE4\xA3" => "\xE7\x80\x8B", + "\xE4\xA4" => "\xE7\x94\x9A", + "\xE4\xA5" => "\xE8\x8A\xAF", + "\xE4\xA6" => "\xE8\xAB\xB6", + "\xE4\xA7" => "\xE4\xBB\x80", + "\xE4\xA8" => "\xE5\x8D\x81", + "\xE4\xA9" => "\xEF\xA5\xB3", + "\xE4\xAA" => "\xE9\x9B\x99", + "\xE4\xAB" => "\xE6\xB0\x8F", + "\xE4\xAC" => "\xE4\xBA\x9E", + "\xE4\xAD" => "\xE4\xBF\x84", + "\xE4\xAE" => "\xE5\x85\x92", + "\xE4\xAF" => "\xE5\x95\x9E", + "\xE4\xB0" => "\xE5\xA8\xA5", + "\xE4\xB1" => "\xE5\xB3\xA8", + "\xE4\xB2" => "\xE6\x88\x91", + "\xE4\xB3" => "\xE7\x89\x99", + "\xE4\xB4" => "\xE8\x8A\xBD", + "\xE4\xB5" => "\xE8\x8E\xAA", + "\xE4\xB6" => "\xE8\x9B\xBE", + "\xE4\xB7" => "\xE8\xA1\x99", + "\xE4\xB8" => "\xE8\xA8\x9D", + "\xE4\xB9" => "\xE9\x98\xBF", + "\xE4\xBA" => "\xE9\x9B\x85", + "\xE4\xBB" => "\xE9\xA4\x93", + "\xE4\xBC" => "\xE9\xB4\x89", + "\xE4\xBD" => "\xE9\xB5\x9D", + "\xE4\xBE" => "\xE5\xA0\x8A", + "\xE4\xBF" => "\xE5\xB2\xB3", + "\xE4\xC0" => "\xE5\xB6\xBD", + "\xE4\xC1" => "\xE5\xB9\x84", + "\xE4\xC2" => "\xE6\x83\xA1", + "\xE4\xC3" => "\xE6\x84\x95", + "\xE4\xC4" => "\xE6\x8F\xA1", + "\xE4\xC5" => "\xE6\xA8\x82", + "\xE4\xC6" => "\xE6\xB8\xA5", + "\xE4\xC7" => "\xE9\x84\x82", + "\xE4\xC8" => "\xE9\x8D\x94", + "\xE4\xC9" => "\xE9\xA1\x8E", + "\xE4\xCA" => "\xE9\xB0\x90", + "\xE4\xCB" => "\xE9\xBD\xB7", + "\xE4\xCC" => "\xE5\xAE\x89", + "\xE4\xCD" => "\xE5\xB2\xB8", + "\xE4\xCE" => "\xE6\x8C\x89", + "\xE4\xCF" => "\xE6\x99\x8F", + "\xE4\xD0" => "\xE6\xA1\x88", + "\xE4\xD1" => "\xE7\x9C\xBC", + "\xE4\xD2" => "\xE9\x9B\x81", + "\xE4\xD3" => "\xE9\x9E\x8D", + "\xE4\xD4" => "\xE9\xA1\x94", + "\xE4\xD5" => "\xE9\xAE\x9F", + "\xE4\xD6" => "\xE6\x96\xA1", + "\xE4\xD7" => "\xE8\xAC\x81", + "\xE4\xD8" => "\xE8\xBB\x8B", + "\xE4\xD9" => "\xE9\x96\xBC", + "\xE4\xDA" => "\xE5\x94\xB5", + "\xE4\xDB" => "\xE5\xB2\xA9", + "\xE4\xDC" => "\xE5\xB7\x96", + "\xE4\xDD" => "\xE5\xBA\xB5", + "\xE4\xDE" => "\xE6\x9A\x97", + "\xE4\xDF" => "\xE7\x99\x8C", + "\xE4\xE0" => "\xE8\x8F\xB4", + "\xE4\xE1" => "\xE9\x97\x87", + "\xE4\xE2" => "\xE5\xA3\x93", + "\xE4\xE3" => "\xE6\x8A\xBC", + "\xE4\xE4" => "\xE7\x8B\x8E", + "\xE4\xE5" => "\xE9\xB4\xA8", + "\xE4\xE6" => "\xE4\xBB\xB0", + "\xE4\xE7" => "\xE5\xA4\xAE", + "\xE4\xE8" => "\xE6\x80\x8F", + "\xE4\xE9" => "\xE6\x98\xBB", + "\xE4\xEA" => "\xE6\xAE\x83", + "\xE4\xEB" => "\xE7\xA7\xA7", + "\xE4\xEC" => "\xE9\xB4\xA6", + "\xE4\xED" => "\xE5\x8E\x93", + "\xE4\xEE" => "\xE5\x93\x80", + "\xE4\xEF" => "\xE5\x9F\x83", + "\xE4\xF0" => "\xE5\xB4\x96", + "\xE4\xF1" => "\xE6\x84\x9B", + "\xE4\xF2" => "\xE6\x9B\x96", + "\xE4\xF3" => "\xE6\xB6\xAF", + "\xE4\xF4" => "\xE7\xA2\x8D", + "\xE4\xF5" => "\xE8\x89\xBE", + "\xE4\xF6" => "\xE9\x9A\x98", + "\xE4\xF7" => "\xE9\x9D\x84", + "\xE4\xF8" => "\xE5\x8E\x84", + "\xE4\xF9" => "\xE6\x89\xBC", + "\xE4\xFA" => "\xE6\x8E\x96", + "\xE4\xFB" => "\xE6\xB6\xB2", + "\xE4\xFC" => "\xE7\xB8\x8A", + "\xE4\xFD" => "\xE8\x85\x8B", + "\xE4\xFE" => "\xE9\xA1\x8D", + "\xE5\xA1" => "\xE6\xAB\xBB", + "\xE5\xA2" => "\xE7\xBD\x8C", + "\xE5\xA3" => "\xE9\xB6\xAF", + "\xE5\xA4" => "\xE9\xB8\x9A", + "\xE5\xA5" => "\xE4\xB9\x9F", + "\xE5\xA6" => "\xE5\x80\xBB", + "\xE5\xA7" => "\xE5\x86\xB6", + "\xE5\xA8" => "\xE5\xA4\x9C", + "\xE5\xA9" => "\xE6\x83\xB9", + "\xE5\xAA" => "\xE6\x8F\xB6", + "\xE5\xAB" => "\xE6\xA4\xB0", + "\xE5\xAC" => "\xE7\x88\xBA", + "\xE5\xAD" => "\xE8\x80\xB6", + "\xE5\xAE" => "\xEF\xA5\xB4", + "\xE5\xAF" => "\xE9\x87\x8E", + "\xE5\xB0" => "\xE5\xBC\xB1", + "\xE5\xB1" => "\xEF\xA5\xB5", + "\xE5\xB2" => "\xEF\xA5\xB6", + "\xE5\xB3" => "\xE7\xB4\x84", + "\xE5\xB4" => "\xE8\x8B\xA5", + "\xE5\xB5" => "\xE8\x91\xAF", + "\xE5\xB6" => "\xE8\x92\xBB", + "\xE5\xB7" => "\xE8\x97\xA5", + "\xE5\xB8" => "\xE8\xBA\x8D", + "\xE5\xB9" => "\xEF\xA5\xB7", + "\xE5\xBA" => "\xE4\xBD\xAF", + "\xE5\xBB" => "\xEF\xA5\xB8", + "\xE5\xBC" => "\xEF\xA5\xB9", + "\xE5\xBD" => "\xE5\xA3\xA4", + "\xE5\xBE" => "\xE5\xAD\x83", + "\xE5\xBF" => "\xE6\x81\x99", + "\xE5\xC0" => "\xE6\x8F\x9A", + "\xE5\xC1" => "\xE6\x94\x98", + "\xE5\xC2" => "\xE6\x95\xAD", + "\xE5\xC3" => "\xE6\x9A\x98", + "\xE5\xC4" => "\xEF\xA5\xBA", + "\xE5\xC5" => "\xE6\xA5\x8A", + "\xE5\xC6" => "\xE6\xA8\xA3", + "\xE5\xC7" => "\xE6\xB4\x8B", + "\xE5\xC8" => "\xE7\x80\x81", + "\xE5\xC9" => "\xE7\x85\xAC", + "\xE5\xCA" => "\xE7\x97\x92", + "\xE5\xCB" => "\xE7\x98\x8D", + "\xE5\xCC" => "\xE7\xA6\xB3", + "\xE5\xCD" => "\xE7\xA9\xB0", + "\xE5\xCE" => "\xEF\xA5\xBB", + "\xE5\xCF" => "\xE7\xBE\x8A", + "\xE5\xD0" => "\xEF\xA5\xBC", + "\xE5\xD1" => "\xE8\xA5\x84", + "\xE5\xD2" => "\xEF\xA5\xBD", + "\xE5\xD3" => "\xE8\xAE\x93", + "\xE5\xD4" => "\xE9\x87\x80", + "\xE5\xD5" => "\xE9\x99\xBD", + "\xE5\xD6" => "\xEF\xA5\xBE", + "\xE5\xD7" => "\xE9\xA4\x8A", + "\xE5\xD8" => "\xE5\x9C\x84", + "\xE5\xD9" => "\xE5\xBE\xA1", + "\xE5\xDA" => "\xE6\x96\xBC", + "\xE5\xDB" => "\xE6\xBC\x81", + "\xE5\xDC" => "\xE7\x98\x80", + "\xE5\xDD" => "\xE7\xA6\xA6", + "\xE5\xDE" => "\xE8\xAA\x9E", + "\xE5\xDF" => "\xE9\xA6\xAD", + "\xE5\xE0" => "\xE9\xAD\x9A", + "\xE5\xE1" => "\xE9\xBD\xAC", + "\xE5\xE2" => "\xE5\x84\x84", + "\xE5\xE3" => "\xE6\x86\xB6", + "\xE5\xE4" => "\xE6\x8A\x91", + "\xE5\xE5" => "\xE6\xAA\x8D", + "\xE5\xE6" => "\xE8\x87\x86", + "\xE5\xE7" => "\xE5\x81\x83", + "\xE5\xE8" => "\xE5\xA0\xB0", + "\xE5\xE9" => "\xE5\xBD\xA6", + "\xE5\xEA" => "\xE7\x84\x89", + "\xE5\xEB" => "\xE8\xA8\x80", + "\xE5\xEC" => "\xE8\xAB\xBA", + "\xE5\xED" => "\xE5\xAD\xBC", + "\xE5\xEE" => "\xE8\x98\x96", + "\xE5\xEF" => "\xE4\xBF\xBA", + "\xE5\xF0" => "\xE5\x84\xBC", + "\xE5\xF1" => "\xE5\x9A\xB4", + "\xE5\xF2" => "\xE5\xA5\x84", + "\xE5\xF3" => "\xE6\x8E\xA9", + "\xE5\xF4" => "\xE6\xB7\xB9", + "\xE5\xF5" => "\xE5\xB6\xAA", + "\xE5\xF6" => "\xE6\xA5\xAD", + "\xE5\xF7" => "\xE5\x86\x86", + "\xE5\xF8" => "\xE4\xBA\x88", + "\xE5\xF9" => "\xE4\xBD\x99", + "\xE5\xFA" => "\xEF\xA5\xBF", + "\xE5\xFB" => "\xEF\xA6\x80", + "\xE5\xFC" => "\xEF\xA6\x81", + "\xE5\xFD" => "\xE5\xA6\x82", + "\xE5\xFE" => "\xEF\xA6\x82", + "\xE6\xA1" => "\xEF\xA6\x83", + "\xE6\xA2" => "\xE6\xAD\x9F", + "\xE6\xA3" => "\xE6\xB1\x9D", + "\xE6\xA4" => "\xEF\xA6\x84", + "\xE6\xA5" => "\xE7\x92\xB5", + "\xE6\xA6" => "\xE7\xA4\x96", + "\xE6\xA7" => "\xEF\xA6\x85", + "\xE6\xA8" => "\xE8\x88\x87", + "\xE6\xA9" => "\xE8\x89\x85", + "\xE6\xAA" => "\xE8\x8C\xB9", + "\xE6\xAB" => "\xE8\xBC\xBF", + "\xE6\xAC" => "\xE8\xBD\x9D", + "\xE6\xAD" => "\xEF\xA6\x86", + "\xE6\xAE" => "\xE9\xA4\x98", + "\xE6\xAF" => "\xEF\xA6\x87", + "\xE6\xB0" => "\xEF\xA6\x88", + "\xE6\xB1" => "\xEF\xA6\x89", + "\xE6\xB2" => "\xE4\xBA\xA6", + "\xE6\xB3" => "\xEF\xA6\x8A", + "\xE6\xB4" => "\xE5\x9F\x9F", + "\xE6\xB5" => "\xE5\xBD\xB9", + "\xE6\xB6" => "\xE6\x98\x93", + "\xE6\xB7" => "\xEF\xA6\x8B", + "\xE6\xB8" => "\xEF\xA6\x8C", + "\xE6\xB9" => "\xE7\x96\xAB", + "\xE6\xBA" => "\xE7\xB9\xB9", + "\xE6\xBB" => "\xE8\xAD\xAF", + "\xE6\xBC" => "\xEF\xA6\x8D", + "\xE6\xBD" => "\xE9\x80\x86", + "\xE6\xBE" => "\xE9\xA9\x9B", + "\xE6\xBF" => "\xE5\x9A\xA5", + "\xE6\xC0" => "\xE5\xA0\xA7", + "\xE6\xC1" => "\xE5\xA7\xB8", + "\xE6\xC2" => "\xE5\xA8\x9F", + "\xE6\xC3" => "\xE5\xAE\xB4", + "\xE6\xC4" => "\xEF\xA6\x8E", + "\xE6\xC5" => "\xE5\xBB\xB6", + "\xE6\xC6" => "\xEF\xA6\x8F", + "\xE6\xC7" => "\xEF\xA6\x90", + "\xE6\xC8" => "\xE6\x8D\x90", + "\xE6\xC9" => "\xE6\x8C\xBB", + "\xE6\xCA" => "\xEF\xA6\x91", + "\xE6\xCB" => "\xE6\xA4\xBD", + "\xE6\xCC" => "\xE6\xB2\x87", + "\xE6\xCD" => "\xE6\xB2\xBF", + "\xE6\xCE" => "\xE6\xB6\x8E", + "\xE6\xCF" => "\xE6\xB6\x93", + "\xE6\xD0" => "\xE6\xB7\xB5", + "\xE6\xD1" => "\xE6\xBC\x94", + "\xE6\xD2" => "\xEF\xA6\x92", + "\xE6\xD3" => "\xE7\x83\x9F", + "\xE6\xD4" => "\xE7\x84\xB6", + "\xE6\xD5" => "\xE7\x85\x99", + "\xE6\xD6" => "\xEF\xA6\x93", + "\xE6\xD7" => "\xE7\x87\x83", + "\xE6\xD8" => "\xE7\x87\x95", + "\xE6\xD9" => "\xEF\xA6\x94", + "\xE6\xDA" => "\xE7\xA1\x8F", + "\xE6\xDB" => "\xE7\xA1\xAF", + "\xE6\xDC" => "\xEF\xA6\x95", + "\xE6\xDD" => "\xE7\xAD\xB5", + "\xE6\xDE" => "\xE7\xB7\xA3", + "\xE6\xDF" => "\xEF\xA6\x96", + "\xE6\xE0" => "\xE7\xB8\xAF", + "\xE6\xE1" => "\xEF\xA6\x97", + "\xE6\xE2" => "\xE8\xA1\x8D", + "\xE6\xE3" => "\xE8\xBB\x9F", + "\xE6\xE4" => "\xEF\xA6\x98", + "\xE6\xE5" => "\xEF\xA6\x99", + "\xE6\xE6" => "\xEF\xA6\x9A", + "\xE6\xE7" => "\xE9\x89\x9B", + "\xE6\xE8" => "\xEF\xA6\x9B", + "\xE6\xE9" => "\xE9\xB3\xB6", + "\xE6\xEA" => "\xEF\xA6\x9C", + "\xE6\xEB" => "\xEF\xA6\x9D", + "\xE6\xEC" => "\xEF\xA6\x9E", + "\xE6\xED" => "\xE6\x82\x85", + "\xE6\xEE" => "\xE6\xB6\x85", + "\xE6\xEF" => "\xEF\xA6\x9F", + "\xE6\xF0" => "\xE7\x86\xB1", + "\xE6\xF1" => "\xEF\xA6\xA0", + "\xE6\xF2" => "\xEF\xA6\xA1", + "\xE6\xF3" => "\xE9\x96\xB1", + "\xE6\xF4" => "\xE5\x8E\xAD", + "\xE6\xF5" => "\xEF\xA6\xA2", + "\xE6\xF6" => "\xEF\xA6\xA3", + "\xE6\xF7" => "\xEF\xA6\xA4", + "\xE6\xF8" => "\xE6\x9F\x93", + "\xE6\xF9" => "\xEF\xA6\xA5", + "\xE6\xFA" => "\xE7\x82\x8E", + "\xE6\xFB" => "\xE7\x84\xB0", + "\xE6\xFC" => "\xE7\x90\xB0", + "\xE6\xFD" => "\xE8\x89\xB6", + "\xE6\xFE" => "\xE8\x8B\x92", + "\xE7\xA1" => "\xEF\xA6\xA6", + "\xE7\xA2" => "\xE9\x96\xBB", + "\xE7\xA3" => "\xE9\xAB\xA5", + "\xE7\xA4" => "\xE9\xB9\xBD", + "\xE7\xA5" => "\xE6\x9B\x84", + "\xE7\xA6" => "\xEF\xA6\xA7", + "\xE7\xA7" => "\xE7\x87\x81", + "\xE7\xA8" => "\xE8\x91\x89", + "\xE7\xA9" => "\xEF\xA6\xA8", + "\xE7\xAA" => "\xEF\xA6\xA9", + "\xE7\xAB" => "\xE5\xA1\x8B", + "\xE7\xAC" => "\xEF\xA6\xAA", + "\xE7\xAD" => "\xEF\xA6\xAB", + "\xE7\xAE" => "\xE5\xB6\xB8", + "\xE7\xAF" => "\xE5\xBD\xB1", + "\xE7\xB0" => "\xEF\xA6\xAC", + "\xE7\xB1" => "\xE6\x98\xA0", + "\xE7\xB2" => "\xE6\x9A\x8E", + "\xE7\xB3" => "\xE6\xA5\xB9", + "\xE7\xB4" => "\xE6\xA6\xAE", + "\xE7\xB5" => "\xE6\xB0\xB8", + "\xE7\xB6" => "\xE6\xB3\xB3", + "\xE7\xB7" => "\xE6\xB8\xB6", + "\xE7\xB8" => "\xE6\xBD\x81", + "\xE7\xB9" => "\xE6\xBF\x9A", + "\xE7\xBA" => "\xE7\x80\x9B", + "\xE7\xBB" => "\xE7\x80\xAF", + "\xE7\xBC" => "\xE7\x85\x90", + "\xE7\xBD" => "\xE7\x87\x9F", + "\xE7\xBE" => "\xE7\x8D\xB0", + "\xE7\xBF" => "\xEF\xA6\xAD", + "\xE7\xC0" => "\xE7\x91\x9B", + "\xE7\xC1" => "\xEF\xA6\xAE", + "\xE7\xC2" => "\xE7\x93\x94", + "\xE7\xC3" => "\xE7\x9B\x88", + "\xE7\xC4" => "\xE7\xA9\x8E", + "\xE7\xC5" => "\xE7\xBA\x93", + "\xE7\xC6" => "\xEF\xA6\xAF", + "\xE7\xC7" => "\xEF\xA6\xB0", + "\xE7\xC8" => "\xE8\x8B\xB1", + "\xE7\xC9" => "\xE8\xA9\xA0", + "\xE7\xCA" => "\xE8\xBF\x8E", + "\xE7\xCB" => "\xEF\xA6\xB1", + "\xE7\xCC" => "\xE9\x8D\x88", + "\xE7\xCD" => "\xEF\xA6\xB2", + "\xE7\xCE" => "\xE9\x9C\x99", + "\xE7\xCF" => "\xEF\xA6\xB3", + "\xE7\xD0" => "\xEF\xA6\xB4", + "\xE7\xD1" => "\xE4\xB9\x82", + "\xE7\xD2" => "\xE5\x80\xAA", + "\xE7\xD3" => "\xEF\xA6\xB5", + "\xE7\xD4" => "\xE5\x88\x88", + "\xE7\xD5" => "\xE5\x8F\xA1", + "\xE7\xD6" => "\xE6\x9B\xB3", + "\xE7\xD7" => "\xE6\xB1\xAD", + "\xE7\xD8" => "\xE6\xBF\x8A", + "\xE7\xD9" => "\xE7\x8C\x8A", + "\xE7\xDA" => "\xE7\x9D\xBF", + "\xE7\xDB" => "\xE7\xA9\xA2", + "\xE7\xDC" => "\xE8\x8A\xAE", + "\xE7\xDD" => "\xE8\x97\x9D", + "\xE7\xDE" => "\xE8\x98\x82", + "\xE7\xDF" => "\xEF\xA6\xB6", + "\xE7\xE0" => "\xE8\xA3\x94", + "\xE7\xE1" => "\xE8\xA9\xA3", + "\xE7\xE2" => "\xE8\xAD\xBD", + "\xE7\xE3" => "\xE8\xB1\xAB", + "\xE7\xE4" => "\xEF\xA6\xB7", + "\xE7\xE5" => "\xE9\x8A\xB3", + "\xE7\xE6" => "\xEF\xA6\xB8", + "\xE7\xE7" => "\xE9\x9C\x93", + "\xE7\xE8" => "\xE9\xA0\x90", + "\xE7\xE9" => "\xE4\xBA\x94", + "\xE7\xEA" => "\xE4\xBC\x8D", + "\xE7\xEB" => "\xE4\xBF\x89", + "\xE7\xEC" => "\xE5\x82\xB2", + "\xE7\xED" => "\xE5\x8D\x88", + "\xE7\xEE" => "\xE5\x90\xBE", + "\xE7\xEF" => "\xE5\x90\xB3", + "\xE7\xF0" => "\xE5\x97\x9A", + "\xE7\xF1" => "\xE5\xA1\xA2", + "\xE7\xF2" => "\xE5\xA2\xBA", + "\xE7\xF3" => "\xE5\xA5\xA7", + "\xE7\xF4" => "\xE5\xA8\x9B", + "\xE7\xF5" => "\xE5\xAF\xA4", + "\xE7\xF6" => "\xE6\x82\x9F", + "\xE7\xF7" => "\xEF\xA6\xB9", + "\xE7\xF8" => "\xE6\x87\x8A", + "\xE7\xF9" => "\xE6\x95\x96", + "\xE7\xFA" => "\xE6\x97\xBF", + "\xE7\xFB" => "\xE6\x99\xA4", + "\xE7\xFC" => "\xE6\xA2\xA7", + "\xE7\xFD" => "\xE6\xB1\x9A", + "\xE7\xFE" => "\xE6\xBE\xB3", + "\xE8\xA1" => "\xE7\x83\x8F", + "\xE8\xA2" => "\xE7\x86\xAC", + "\xE8\xA3" => "\xE7\x8D\x92", + "\xE8\xA4" => "\xE7\xAD\xBD", + "\xE8\xA5" => "\xE8\x9C\x88", + "\xE8\xA6" => "\xE8\xAA\xA4", + "\xE8\xA7" => "\xE9\xB0\xB2", + "\xE8\xA8" => "\xE9\xBC\x87", + "\xE8\xA9" => "\xE5\xB1\x8B", + "\xE8\xAA" => "\xE6\xB2\x83", + "\xE8\xAB" => "\xE7\x8D\x84", + "\xE8\xAC" => "\xE7\x8E\x89", + "\xE8\xAD" => "\xE9\x88\xBA", + "\xE8\xAE" => "\xE6\xBA\xAB", + "\xE8\xAF" => "\xE7\x91\xA5", + "\xE8\xB0" => "\xE7\x98\x9F", + "\xE8\xB1" => "\xE7\xA9\xA9", + "\xE8\xB2" => "\xE7\xB8\x95", + "\xE8\xB3" => "\xE8\x98\x8A", + "\xE8\xB4" => "\xE5\x85\x80", + "\xE8\xB5" => "\xE5\xA3\x85", + "\xE8\xB6" => "\xE6\x93\x81", + "\xE8\xB7" => "\xE7\x93\xAE", + "\xE8\xB8" => "\xE7\x94\x95", + "\xE8\xB9" => "\xE7\x99\xB0", + "\xE8\xBA" => "\xE7\xBF\x81", + "\xE8\xBB" => "\xE9\x82\x95", + "\xE8\xBC" => "\xE9\x9B\x8D", + "\xE8\xBD" => "\xE9\xA5\x94", + "\xE8\xBE" => "\xE6\xB8\xA6", + "\xE8\xBF" => "\xE7\x93\xA6", + "\xE8\xC0" => "\xE7\xAA\xA9", + "\xE8\xC1" => "\xE7\xAA\xAA", + "\xE8\xC2" => "\xE8\x87\xA5", + "\xE8\xC3" => "\xE8\x9B\x99", + "\xE8\xC4" => "\xE8\x9D\xB8", + "\xE8\xC5" => "\xE8\xA8\x9B", + "\xE8\xC6" => "\xE5\xA9\x89", + "\xE8\xC7" => "\xE5\xAE\x8C", + "\xE8\xC8" => "\xE5\xAE\x9B", + "\xE8\xC9" => "\xE6\xA2\xA1", + "\xE8\xCA" => "\xE6\xA4\x80", + "\xE8\xCB" => "\xE6\xB5\xA3", + "\xE8\xCC" => "\xE7\x8E\xA9", + "\xE8\xCD" => "\xE7\x90\x93", + "\xE8\xCE" => "\xE7\x90\xAC", + "\xE8\xCF" => "\xE7\xA2\x97", + "\xE8\xD0" => "\xE7\xB7\xA9", + "\xE8\xD1" => "\xE7\xBF\xAB", + "\xE8\xD2" => "\xE8\x84\x98", + "\xE8\xD3" => "\xE8\x85\x95", + "\xE8\xD4" => "\xE8\x8E\x9E", + "\xE8\xD5" => "\xE8\xB1\x8C", + "\xE8\xD6" => "\xE9\x98\xAE", + "\xE8\xD7" => "\xE9\xA0\x91", + "\xE8\xD8" => "\xE6\x9B\xB0", + "\xE8\xD9" => "\xE5\xBE\x80", + "\xE8\xDA" => "\xE6\x97\xBA", + "\xE8\xDB" => "\xE6\x9E\x89", + "\xE8\xDC" => "\xE6\xB1\xAA", + "\xE8\xDD" => "\xE7\x8E\x8B", + "\xE8\xDE" => "\xE5\x80\xAD", + "\xE8\xDF" => "\xE5\xA8\x83", + "\xE8\xE0" => "\xE6\xAD\xAA", + "\xE8\xE1" => "\xE7\x9F\xAE", + "\xE8\xE2" => "\xE5\xA4\x96", + "\xE8\xE3" => "\xE5\xB5\xAC", + "\xE8\xE4" => "\xE5\xB7\x8D", + "\xE8\xE5" => "\xE7\x8C\xA5", + "\xE8\xE6" => "\xE7\x95\x8F", + "\xE8\xE7" => "\xEF\xA6\xBA", + "\xE8\xE8" => "\xEF\xA6\xBB", + "\xE8\xE9" => "\xE5\x83\xA5", + "\xE8\xEA" => "\xE5\x87\xB9", + "\xE8\xEB" => "\xE5\xA0\xAF", + "\xE8\xEC" => "\xE5\xA4\xAD", + "\xE8\xED" => "\xE5\xA6\x96", + "\xE8\xEE" => "\xE5\xA7\x9A", + "\xE8\xEF" => "\xE5\xAF\xA5", + "\xE8\xF0" => "\xEF\xA6\xBC", + "\xE8\xF1" => "\xEF\xA6\xBD", + "\xE8\xF2" => "\xE5\xB6\xA2", + "\xE8\xF3" => "\xE6\x8B\x97", + "\xE8\xF4" => "\xE6\x90\x96", + "\xE8\xF5" => "\xE6\x92\x93", + "\xE8\xF6" => "\xE6\x93\xBE", + "\xE8\xF7" => "\xEF\xA6\xBE", + "\xE8\xF8" => "\xE6\x9B\x9C", + "\xE8\xF9" => "\xEF\xA6\xBF", + "\xE8\xFA" => "\xE6\xA9\x88", + "\xE8\xFB" => "\xEF\xA7\x80", + "\xE8\xFC" => "\xE7\x87\xBF", + "\xE8\xFD" => "\xE7\x91\xA4", + "\xE8\xFE" => "\xEF\xA7\x81", + "\xE9\xA1" => "\xE7\xAA\x88", + "\xE9\xA2" => "\xE7\xAA\xAF", + "\xE9\xA3" => "\xE7\xB9\x87", + "\xE9\xA4" => "\xE7\xB9\x9E", + "\xE9\xA5" => "\xE8\x80\x80", + "\xE9\xA6" => "\xE8\x85\xB0", + "\xE9\xA7" => "\xEF\xA7\x82", + "\xE9\xA8" => "\xE8\x9F\xAF", + "\xE9\xA9" => "\xE8\xA6\x81", + "\xE9\xAA" => "\xE8\xAC\xA0", + "\xE9\xAB" => "\xE9\x81\x99", + "\xE9\xAC" => "\xEF\xA7\x83", + "\xE9\xAD" => "\xE9\x82\x80", + "\xE9\xAE" => "\xE9\xA5\x92", + "\xE9\xAF" => "\xE6\x85\xBE", + "\xE9\xB0" => "\xE6\xAC\xB2", + "\xE9\xB1" => "\xE6\xB5\xB4", + "\xE9\xB2" => "\xE7\xB8\x9F", + "\xE9\xB3" => "\xE8\xA4\xA5", + "\xE9\xB4" => "\xE8\xBE\xB1", + "\xE9\xB5" => "\xE4\xBF\x91", + "\xE9\xB6" => "\xE5\x82\xAD", + "\xE9\xB7" => "\xE5\x86\x97", + "\xE9\xB8" => "\xE5\x8B\x87", + "\xE9\xB9" => "\xE5\x9F\x87", + "\xE9\xBA" => "\xE5\xA2\x89", + "\xE9\xBB" => "\xE5\xAE\xB9", + "\xE9\xBC" => "\xE5\xBA\xB8", + "\xE9\xBD" => "\xE6\x85\x82", + "\xE9\xBE" => "\xE6\xA6\x95", + "\xE9\xBF" => "\xE6\xB6\x8C", + "\xE9\xC0" => "\xE6\xB9\xA7", + "\xE9\xC1" => "\xE6\xBA\xB6", + "\xE9\xC2" => "\xE7\x86\x94", + "\xE9\xC3" => "\xE7\x91\xA2", + "\xE9\xC4" => "\xE7\x94\xA8", + "\xE9\xC5" => "\xE7\x94\xAC", + "\xE9\xC6" => "\xE8\x81\xB3", + "\xE9\xC7" => "\xE8\x8C\xB8", + "\xE9\xC8" => "\xE8\x93\x89", + "\xE9\xC9" => "\xE8\xB8\x8A", + "\xE9\xCA" => "\xE9\x8E\x94", + "\xE9\xCB" => "\xE9\x8F\x9E", + "\xE9\xCC" => "\xEF\xA7\x84", + "\xE9\xCD" => "\xE4\xBA\x8E", + "\xE9\xCE" => "\xE4\xBD\x91", + "\xE9\xCF" => "\xE5\x81\xB6", + "\xE9\xD0" => "\xE5\x84\xAA", + "\xE9\xD1" => "\xE5\x8F\x88", + "\xE9\xD2" => "\xE5\x8F\x8B", + "\xE9\xD3" => "\xE5\x8F\xB3", + "\xE9\xD4" => "\xE5\xAE\x87", + "\xE9\xD5" => "\xE5\xAF\x93", + "\xE9\xD6" => "\xE5\xB0\xA4", + "\xE9\xD7" => "\xE6\x84\x9A", + "\xE9\xD8" => "\xE6\x86\x82", + "\xE9\xD9" => "\xE6\x97\xB4", + "\xE9\xDA" => "\xE7\x89\x9B", + "\xE9\xDB" => "\xE7\x8E\x97", + "\xE9\xDC" => "\xE7\x91\x80", + "\xE9\xDD" => "\xE7\x9B\x82", + "\xE9\xDE" => "\xE7\xA5\x90", + "\xE9\xDF" => "\xE7\xA6\x91", + "\xE9\xE0" => "\xE7\xA6\xB9", + "\xE9\xE1" => "\xE7\xB4\x86", + "\xE9\xE2" => "\xE7\xBE\xBD", + "\xE9\xE3" => "\xE8\x8A\x8B", + "\xE9\xE4" => "\xE8\x97\x95", + "\xE9\xE5" => "\xE8\x99\x9E", + "\xE9\xE6" => "\xE8\xBF\x82", + "\xE9\xE7" => "\xE9\x81\x87", + "\xE9\xE8" => "\xE9\x83\xB5", + "\xE9\xE9" => "\xE9\x87\xAA", + "\xE9\xEA" => "\xE9\x9A\x85", + "\xE9\xEB" => "\xE9\x9B\xA8", + "\xE9\xEC" => "\xE9\x9B\xA9", + "\xE9\xED" => "\xE5\x8B\x96", + "\xE9\xEE" => "\xE5\xBD\xA7", + "\xE9\xEF" => "\xE6\x97\xAD", + "\xE9\xF0" => "\xE6\x98\xB1", + "\xE9\xF1" => "\xE6\xA0\xAF", + "\xE9\xF2" => "\xE7\x85\x9C", + "\xE9\xF3" => "\xE7\xA8\xB6", + "\xE9\xF4" => "\xE9\x83\x81", + "\xE9\xF5" => "\xE9\xA0\x8A", + "\xE9\xF6" => "\xE4\xBA\x91", + "\xE9\xF7" => "\xEF\xA7\x85", + "\xE9\xF8" => "\xE6\xA9\x92", + "\xE9\xF9" => "\xE6\xAE\x9E", + "\xE9\xFA" => "\xE6\xBE\x90", + "\xE9\xFB" => "\xE7\x86\x89", + "\xE9\xFC" => "\xE8\x80\x98", + "\xE9\xFD" => "\xE8\x8A\xB8", + "\xE9\xFE" => "\xE8\x95\x93", + "\xEA\xA1" => "\xE9\x81\x8B", + "\xEA\xA2" => "\xE9\x9A\x95", + "\xEA\xA3" => "\xE9\x9B\xB2", + "\xEA\xA4" => "\xE9\x9F\xBB", + "\xEA\xA5" => "\xE8\x94\x9A", + "\xEA\xA6" => "\xE9\xAC\xB1", + "\xEA\xA7" => "\xE4\xBA\x90", + "\xEA\xA8" => "\xE7\x86\x8A", + "\xEA\xA9" => "\xE9\x9B\x84", + "\xEA\xAA" => "\xE5\x85\x83", + "\xEA\xAB" => "\xE5\x8E\x9F", + "\xEA\xAC" => "\xE5\x93\xA1", + "\xEA\xAD" => "\xE5\x9C\x93", + "\xEA\xAE" => "\xE5\x9C\x92", + "\xEA\xAF" => "\xE5\x9E\xA3", + "\xEA\xB0" => "\xE5\xAA\x9B", + "\xEA\xB1" => "\xE5\xAB\x84", + "\xEA\xB2" => "\xE5\xAF\x83", + "\xEA\xB3" => "\xE6\x80\xA8", + "\xEA\xB4" => "\xE6\x84\xBF", + "\xEA\xB5" => "\xE6\x8F\xB4", + "\xEA\xB6" => "\xE6\xB2\x85", + "\xEA\xB7" => "\xE6\xB4\xB9", + "\xEA\xB8" => "\xE6\xB9\xB2", + "\xEA\xB9" => "\xE6\xBA\x90", + "\xEA\xBA" => "\xE7\x88\xB0", + "\xEA\xBB" => "\xE7\x8C\xBF", + "\xEA\xBC" => "\xE7\x91\x97", + "\xEA\xBD" => "\xE8\x8B\x91", + "\xEA\xBE" => "\xE8\xA2\x81", + "\xEA\xBF" => "\xE8\xBD\x85", + "\xEA\xC0" => "\xE9\x81\xA0", + "\xEA\xC1" => "\xEF\xA7\x86", + "\xEA\xC2" => "\xE9\x99\xA2", + "\xEA\xC3" => "\xE9\xA1\x98", + "\xEA\xC4" => "\xE9\xB4\x9B", + "\xEA\xC5" => "\xE6\x9C\x88", + "\xEA\xC6" => "\xE8\xB6\x8A", + "\xEA\xC7" => "\xE9\x89\x9E", + "\xEA\xC8" => "\xE4\xBD\x8D", + "\xEA\xC9" => "\xE5\x81\x89", + "\xEA\xCA" => "\xE5\x83\x9E", + "\xEA\xCB" => "\xE5\x8D\xB1", + "\xEA\xCC" => "\xE5\x9C\x8D", + "\xEA\xCD" => "\xE5\xA7\x94", + "\xEA\xCE" => "\xE5\xA8\x81", + "\xEA\xCF" => "\xE5\xB0\x89", + "\xEA\xD0" => "\xE6\x85\xB0", + "\xEA\xD1" => "\xE6\x9A\x90", + "\xEA\xD2" => "\xE6\xB8\xAD", + "\xEA\xD3" => "\xE7\x88\xB2", + "\xEA\xD4" => "\xE7\x91\x8B", + "\xEA\xD5" => "\xE7\xB7\xAF", + "\xEA\xD6" => "\xE8\x83\x83", + "\xEA\xD7" => "\xE8\x90\x8E", + "\xEA\xD8" => "\xE8\x91\xA6", + "\xEA\xD9" => "\xE8\x94\xBF", + "\xEA\xDA" => "\xE8\x9D\x9F", + "\xEA\xDB" => "\xE8\xA1\x9B", + "\xEA\xDC" => "\xE8\xA4\x98", + "\xEA\xDD" => "\xE8\xAC\x82", + "\xEA\xDE" => "\xE9\x81\x95", + "\xEA\xDF" => "\xE9\x9F\x8B", + "\xEA\xE0" => "\xE9\xAD\x8F", + "\xEA\xE1" => "\xE4\xB9\xB3", + "\xEA\xE2" => "\xE4\xBE\x91", + "\xEA\xE3" => "\xE5\x84\x92", + "\xEA\xE4" => "\xE5\x85\xAA", + "\xEA\xE5" => "\xEF\xA7\x87", + "\xEA\xE6" => "\xE5\x94\xAF", + "\xEA\xE7" => "\xE5\x96\xA9", + "\xEA\xE8" => "\xE5\xAD\xBA", + "\xEA\xE9" => "\xE5\xAE\xA5", + "\xEA\xEA" => "\xE5\xB9\xBC", + "\xEA\xEB" => "\xE5\xB9\xBD", + "\xEA\xEC" => "\xE5\xBA\xBE", + "\xEA\xED" => "\xE6\x82\xA0", + "\xEA\xEE" => "\xE6\x83\x9F", + "\xEA\xEF" => "\xE6\x84\x88", + "\xEA\xF0" => "\xE6\x84\x89", + "\xEA\xF1" => "\xE6\x8F\x84", + "\xEA\xF2" => "\xE6\x94\xB8", + "\xEA\xF3" => "\xE6\x9C\x89", + "\xEA\xF4" => "\xEF\xA7\x88", + "\xEA\xF5" => "\xE6\x9F\x94", + "\xEA\xF6" => "\xE6\x9F\x9A", + "\xEA\xF7" => "\xEF\xA7\x89", + "\xEA\xF8" => "\xE6\xA5\xA1", + "\xEA\xF9" => "\xE6\xA5\xA2", + "\xEA\xFA" => "\xE6\xB2\xB9", + "\xEA\xFB" => "\xE6\xB4\xA7", + "\xEA\xFC" => "\xEF\xA7\x8A", + "\xEA\xFD" => "\xE6\xB8\xB8", + "\xEA\xFE" => "\xEF\xA7\x8B", + "\xEB\xA1" => "\xE6\xBF\xA1", + "\xEB\xA2" => "\xE7\x8C\xB6", + "\xEB\xA3" => "\xE7\x8C\xB7", + "\xEB\xA4" => "\xEF\xA7\x8C", + "\xEB\xA5" => "\xE7\x91\x9C", + "\xEB\xA6" => "\xE7\x94\xB1", + "\xEB\xA7" => "\xEF\xA7\x8D", + "\xEB\xA8" => "\xE7\x99\x92", + "\xEB\xA9" => "\xEF\xA7\x8E", + "\xEB\xAA" => "\xEF\xA7\x8F", + "\xEB\xAB" => "\xE7\xB6\xAD", + "\xEB\xAC" => "\xE8\x87\xBE", + "\xEB\xAD" => "\xE8\x90\xB8", + "\xEB\xAE" => "\xE8\xA3\x95", + "\xEB\xAF" => "\xE8\xAA\x98", + "\xEB\xB0" => "\xE8\xAB\x9B", + "\xEB\xB1" => "\xE8\xAB\xAD", + "\xEB\xB2" => "\xE8\xB8\xB0", + "\xEB\xB3" => "\xE8\xB9\x82", + "\xEB\xB4" => "\xE9\x81\x8A", + "\xEB\xB5" => "\xE9\x80\xBE", + "\xEB\xB6" => "\xE9\x81\xBA", + "\xEB\xB7" => "\xE9\x85\x89", + "\xEB\xB8" => "\xE9\x87\x89", + "\xEB\xB9" => "\xE9\x8D\xAE", + "\xEB\xBA" => "\xEF\xA7\x90", + "\xEB\xBB" => "\xEF\xA7\x91", + "\xEB\xBC" => "\xE5\xA0\x89", + "\xEB\xBD" => "\xEF\xA7\x92", + "\xEB\xBE" => "\xE6\xAF\x93", + "\xEB\xBF" => "\xE8\x82\x89", + "\xEB\xC0" => "\xE8\x82\xB2", + "\xEB\xC1" => "\xEF\xA7\x93", + "\xEB\xC2" => "\xEF\xA7\x94", + "\xEB\xC3" => "\xE5\x85\x81", + "\xEB\xC4" => "\xE5\xA5\xAB", + "\xEB\xC5" => "\xE5\xB0\xB9", + "\xEB\xC6" => "\xEF\xA7\x95", + "\xEB\xC7" => "\xEF\xA7\x96", + "\xEB\xC8" => "\xE6\xBD\xA4", + "\xEB\xC9" => "\xE7\x8E\xA7", + "\xEB\xCA" => "\xE8\x83\xA4", + "\xEB\xCB" => "\xE8\xB4\x87", + "\xEB\xCC" => "\xEF\xA7\x97", + "\xEB\xCD" => "\xE9\x88\x97", + "\xEB\xCE" => "\xE9\x96\x8F", + "\xEB\xCF" => "\xEF\xA7\x98", + "\xEB\xD0" => "\xEF\xA7\x99", + "\xEB\xD1" => "\xEF\xA7\x9A", + "\xEB\xD2" => "\xEF\xA7\x9B", + "\xEB\xD3" => "\xE8\x81\xBF", + "\xEB\xD4" => "\xE6\x88\x8E", + "\xEB\xD5" => "\xE7\x80\x9C", + "\xEB\xD6" => "\xE7\xB5\xA8", + "\xEB\xD7" => "\xE8\x9E\x8D", + "\xEB\xD8" => "\xEF\xA7\x9C", + "\xEB\xD9" => "\xE5\x9E\xA0", + "\xEB\xDA" => "\xE6\x81\xA9", + "\xEB\xDB" => "\xE6\x85\x87", + "\xEB\xDC" => "\xE6\xAE\xB7", + "\xEB\xDD" => "\xE8\xAA\xBE", + "\xEB\xDE" => "\xE9\x8A\x80", + "\xEB\xDF" => "\xE9\x9A\xB1", + "\xEB\xE0" => "\xE4\xB9\x99", + "\xEB\xE1" => "\xE5\x90\x9F", + "\xEB\xE2" => "\xE6\xB7\xAB", + "\xEB\xE3" => "\xE8\x94\xAD", + "\xEB\xE4" => "\xE9\x99\xB0", + "\xEB\xE5" => "\xE9\x9F\xB3", + "\xEB\xE6" => "\xE9\xA3\xAE", + "\xEB\xE7" => "\xE6\x8F\x96", + "\xEB\xE8" => "\xE6\xB3\xA3", + "\xEB\xE9" => "\xE9\x82\x91", + "\xEB\xEA" => "\xE5\x87\x9D", + "\xEB\xEB" => "\xE6\x87\x89", + "\xEB\xEC" => "\xE8\x86\xBA", + "\xEB\xED" => "\xE9\xB7\xB9", + "\xEB\xEE" => "\xE4\xBE\x9D", + "\xEB\xEF" => "\xE5\x80\x9A", + "\xEB\xF0" => "\xE5\x84\x80", + "\xEB\xF1" => "\xE5\xAE\x9C", + "\xEB\xF2" => "\xE6\x84\x8F", + "\xEB\xF3" => "\xE6\x87\xBF", + "\xEB\xF4" => "\xE6\x93\xAC", + "\xEB\xF5" => "\xE6\xA4\x85", + "\xEB\xF6" => "\xE6\xAF\x85", + "\xEB\xF7" => "\xE7\x96\x91", + "\xEB\xF8" => "\xE7\x9F\xA3", + "\xEB\xF9" => "\xE7\xBE\xA9", + "\xEB\xFA" => "\xE8\x89\xA4", + "\xEB\xFB" => "\xE8\x96\x8F", + "\xEB\xFC" => "\xE8\x9F\xBB", + "\xEB\xFD" => "\xE8\xA1\xA3", + "\xEB\xFE" => "\xE8\xAA\xBC", + "\xEC\xA1" => "\xE8\xAD\xB0", + "\xEC\xA2" => "\xE9\x86\xAB", + "\xEC\xA3" => "\xE4\xBA\x8C", + "\xEC\xA4" => "\xE4\xBB\xA5", + "\xEC\xA5" => "\xE4\xBC\x8A", + "\xEC\xA6" => "\xEF\xA7\x9D", + "\xEC\xA7" => "\xEF\xA7\x9E", + "\xEC\xA8" => "\xE5\xA4\xB7", + "\xEC\xA9" => "\xE5\xA7\xA8", + "\xEC\xAA" => "\xEF\xA7\x9F", + "\xEC\xAB" => "\xE5\xB7\xB2", + "\xEC\xAC" => "\xE5\xBC\x9B", + "\xEC\xAD" => "\xE5\xBD\x9B", + "\xEC\xAE" => "\xE6\x80\xA1", + "\xEC\xAF" => "\xEF\xA7\xA0", + "\xEC\xB0" => "\xEF\xA7\xA1", + "\xEC\xB1" => "\xEF\xA7\xA2", + "\xEC\xB2" => "\xEF\xA7\xA3", + "\xEC\xB3" => "\xE7\x88\xBE", + "\xEC\xB4" => "\xE7\x8F\xA5", + "\xEC\xB5" => "\xEF\xA7\xA4", + "\xEC\xB6" => "\xE7\x95\xB0", + "\xEC\xB7" => "\xE7\x97\x8D", + "\xEC\xB8" => "\xEF\xA7\xA5", + "\xEC\xB9" => "\xE7\xA7\xBB", + "\xEC\xBA" => "\xEF\xA7\xA6", + "\xEC\xBB" => "\xE8\x80\x8C", + "\xEC\xBC" => "\xE8\x80\xB3", + "\xEC\xBD" => "\xE8\x82\x84", + "\xEC\xBE" => "\xE8\x8B\xA1", + "\xEC\xBF" => "\xE8\x8D\x91", + "\xEC\xC0" => "\xEF\xA7\xA7", + "\xEC\xC1" => "\xEF\xA7\xA8", + "\xEC\xC2" => "\xE8\xB2\xBD", + "\xEC\xC3" => "\xE8\xB2\xB3", + "\xEC\xC4" => "\xE9\x82\x87", + "\xEC\xC5" => "\xEF\xA7\xA9", + "\xEC\xC6" => "\xEF\xA7\xAA", + "\xEC\xC7" => "\xE9\xA3\xB4", + "\xEC\xC8" => "\xE9\xA4\x8C", + "\xEC\xC9" => "\xEF\xA7\xAB", + "\xEC\xCA" => "\xEF\xA7\xAC", + "\xEC\xCB" => "\xE7\x80\xB7", + "\xEC\xCC" => "\xE7\x9B\x8A", + "\xEC\xCD" => "\xE7\xBF\x8A", + "\xEC\xCE" => "\xE7\xBF\x8C", + "\xEC\xCF" => "\xE7\xBF\xBC", + "\xEC\xD0" => "\xE8\xAC\x9A", + "\xEC\xD1" => "\xE4\xBA\xBA", + "\xEC\xD2" => "\xE4\xBB\x81", + "\xEC\xD3" => "\xE5\x88\x83", + "\xEC\xD4" => "\xE5\x8D\xB0", + "\xEC\xD5" => "\xEF\xA7\xAD", + "\xEC\xD6" => "\xE5\x92\xBD", + "\xEC\xD7" => "\xE5\x9B\xA0", + "\xEC\xD8" => "\xE5\xA7\xBB", + "\xEC\xD9" => "\xE5\xAF\x85", + "\xEC\xDA" => "\xE5\xBC\x95", + "\xEC\xDB" => "\xE5\xBF\x8D", + "\xEC\xDC" => "\xE6\xB9\xAE", + "\xEC\xDD" => "\xEF\xA7\xAE", + "\xEC\xDE" => "\xEF\xA7\xAF", + "\xEC\xDF" => "\xE7\xB5\xAA", + "\xEC\xE0" => "\xE8\x8C\xB5", + "\xEC\xE1" => "\xEF\xA7\xB0", + "\xEC\xE2" => "\xE8\x9A\x93", + "\xEC\xE3" => "\xE8\xAA\x8D", + "\xEC\xE4" => "\xEF\xA7\xB1", + "\xEC\xE5" => "\xE9\x9D\xAD", + "\xEC\xE6" => "\xE9\x9D\xB7", + "\xEC\xE7" => "\xEF\xA7\xB2", + "\xEC\xE8" => "\xEF\xA7\xB3", + "\xEC\xE9" => "\xE4\xB8\x80", + "\xEC\xEA" => "\xE4\xBD\x9A", + "\xEC\xEB" => "\xE4\xBD\xBE", + "\xEC\xEC" => "\xE5\xA3\xB9", + "\xEC\xED" => "\xE6\x97\xA5", + "\xEC\xEE" => "\xE6\xBA\xA2", + "\xEC\xEF" => "\xE9\x80\xB8", + "\xEC\xF0" => "\xE9\x8E\xB0", + "\xEC\xF1" => "\xE9\xA6\xB9", + "\xEC\xF2" => "\xE4\xBB\xBB", + "\xEC\xF3" => "\xE5\xA3\xAC", + "\xEC\xF4" => "\xE5\xA6\x8A", + "\xEC\xF5" => "\xE5\xA7\x99", + "\xEC\xF6" => "\xE6\x81\x81", + "\xEC\xF7" => "\xEF\xA7\xB4", + "\xEC\xF8" => "\xEF\xA7\xB5", + "\xEC\xF9" => "\xE7\xA8\x94", + "\xEC\xFA" => "\xEF\xA7\xB6", + "\xEC\xFB" => "\xE8\x8D\x8F", + "\xEC\xFC" => "\xE8\xB3\x83", + "\xEC\xFD" => "\xE5\x85\xA5", + "\xEC\xFE" => "\xE5\x8D\x84", + "\xED\xA1" => "\xEF\xA7\xB7", + "\xED\xA2" => "\xEF\xA7\xB8", + "\xED\xA3" => "\xEF\xA7\xB9", + "\xED\xA4" => "\xE4\xBB\x8D", + "\xED\xA5" => "\xE5\x89\xA9", + "\xED\xA6" => "\xE5\xAD\x95", + "\xED\xA7" => "\xE8\x8A\xBF", + "\xED\xA8" => "\xE4\xBB\x94", + "\xED\xA9" => "\xE5\x88\xBA", + "\xED\xAA" => "\xE5\x92\xA8", + "\xED\xAB" => "\xE5\xA7\x89", + "\xED\xAC" => "\xE5\xA7\xBF", + "\xED\xAD" => "\xE5\xAD\x90", + "\xED\xAE" => "\xE5\xAD\x97", + "\xED\xAF" => "\xE5\xAD\x9C", + "\xED\xB0" => "\xE6\x81\xA3", + "\xED\xB1" => "\xE6\x85\x88", + "\xED\xB2" => "\xE6\xBB\x8B", + "\xED\xB3" => "\xE7\x82\x99", + "\xED\xB4" => "\xE7\x85\xAE", + "\xED\xB5" => "\xE7\x8E\x86", + "\xED\xB6" => "\xE7\x93\xB7", + "\xED\xB7" => "\xE7\x96\xB5", + "\xED\xB8" => "\xE7\xA3\x81", + "\xED\xB9" => "\xE7\xB4\xAB", + "\xED\xBA" => "\xE8\x80\x85", + "\xED\xBB" => "\xE8\x87\xAA", + "\xED\xBC" => "\xE8\x8C\xA8", + "\xED\xBD" => "\xE8\x94\x97", + "\xED\xBE" => "\xE8\x97\x89", + "\xED\xBF" => "\xE8\xAB\xAE", + "\xED\xC0" => "\xE8\xB3\x87", + "\xED\xC1" => "\xE9\x9B\x8C", + "\xED\xC2" => "\xE4\xBD\x9C", + "\xED\xC3" => "\xE5\x8B\xBA", + "\xED\xC4" => "\xE5\x9A\xBC", + "\xED\xC5" => "\xE6\x96\xAB", + "\xED\xC6" => "\xE6\x98\xA8", + "\xED\xC7" => "\xE7\x81\xBC", + "\xED\xC8" => "\xE7\x82\xB8", + "\xED\xC9" => "\xE7\x88\xB5", + "\xED\xCA" => "\xE7\xB6\xBD", + "\xED\xCB" => "\xE8\x8A\x8D", + "\xED\xCC" => "\xE9\x85\x8C", + "\xED\xCD" => "\xE9\x9B\x80", + "\xED\xCE" => "\xE9\xB5\xB2", + "\xED\xCF" => "\xE5\xAD\xB1", + "\xED\xD0" => "\xE6\xA3\xA7", + "\xED\xD1" => "\xE6\xAE\x98", + "\xED\xD2" => "\xE6\xBD\xBA", + "\xED\xD3" => "\xE7\x9B\x9E", + "\xED\xD4" => "\xE5\xB2\x91", + "\xED\xD5" => "\xE6\x9A\xAB", + "\xED\xD6" => "\xE6\xBD\x9B", + "\xED\xD7" => "\xE7\xAE\xB4", + "\xED\xD8" => "\xE7\xB0\xAA", + "\xED\xD9" => "\xE8\xA0\xB6", + "\xED\xDA" => "\xE9\x9B\x9C", + "\xED\xDB" => "\xE4\xB8\x88", + "\xED\xDC" => "\xE4\xBB\x97", + "\xED\xDD" => "\xE5\x8C\xA0", + "\xED\xDE" => "\xE5\xA0\xB4", + "\xED\xDF" => "\xE5\xA2\xBB", + "\xED\xE0" => "\xE5\xA3\xAF", + "\xED\xE1" => "\xE5\xA5\xAC", + "\xED\xE2" => "\xE5\xB0\x87", + "\xED\xE3" => "\xE5\xB8\xB3", + "\xED\xE4" => "\xE5\xBA\x84", + "\xED\xE5" => "\xE5\xBC\xB5", + "\xED\xE6" => "\xE6\x8E\x8C", + "\xED\xE7" => "\xE6\x9A\xB2", + "\xED\xE8" => "\xE6\x9D\x96", + "\xED\xE9" => "\xE6\xA8\x9F", + "\xED\xEA" => "\xE6\xAA\xA3", + "\xED\xEB" => "\xE6\xAC\x8C", + "\xED\xEC" => "\xE6\xBC\xBF", + "\xED\xED" => "\xE7\x89\x86", + "\xED\xEE" => "\xEF\xA7\xBA", + "\xED\xEF" => "\xE7\x8D\x90", + "\xED\xF0" => "\xE7\x92\x8B", + "\xED\xF1" => "\xE7\xAB\xA0", + "\xED\xF2" => "\xE7\xB2\xA7", + "\xED\xF3" => "\xE8\x85\xB8", + "\xED\xF4" => "\xE8\x87\x9F", + "\xED\xF5" => "\xE8\x87\xA7", + "\xED\xF6" => "\xE8\x8E\x8A", + "\xED\xF7" => "\xE8\x91\xAC", + "\xED\xF8" => "\xE8\x94\xA3", + "\xED\xF9" => "\xE8\x96\x94", + "\xED\xFA" => "\xE8\x97\x8F", + "\xED\xFB" => "\xE8\xA3\x9D", + "\xED\xFC" => "\xE8\xB4\x93", + "\xED\xFD" => "\xE9\x86\xAC", + "\xED\xFE" => "\xE9\x95\xB7", + "\xEE\xA1" => "\xE9\x9A\x9C", + "\xEE\xA2" => "\xE5\x86\x8D", + "\xEE\xA3" => "\xE5\x93\x89", + "\xEE\xA4" => "\xE5\x9C\xA8", + "\xEE\xA5" => "\xE5\xAE\xB0", + "\xEE\xA6" => "\xE6\x89\x8D", + "\xEE\xA7" => "\xE6\x9D\x90", + "\xEE\xA8" => "\xE6\xA0\xBD", + "\xEE\xA9" => "\xE6\xA2\x93", + "\xEE\xAA" => "\xE6\xB8\xBD", + "\xEE\xAB" => "\xE6\xBB\x93", + "\xEE\xAC" => "\xE7\x81\xBD", + "\xEE\xAD" => "\xE7\xB8\xA1", + "\xEE\xAE" => "\xE8\xA3\x81", + "\xEE\xAF" => "\xE8\xB2\xA1", + "\xEE\xB0" => "\xE8\xBC\x89", + "\xEE\xB1" => "\xE9\xBD\x8B", + "\xEE\xB2" => "\xE9\xBD\x8E", + "\xEE\xB3" => "\xE7\x88\xAD", + "\xEE\xB4" => "\xE7\xAE\x8F", + "\xEE\xB5" => "\xE8\xAB\x8D", + "\xEE\xB6" => "\xE9\x8C\x9A", + "\xEE\xB7" => "\xE4\xBD\x87", + "\xEE\xB8" => "\xE4\xBD\x8E", + "\xEE\xB9" => "\xE5\x84\xB2", + "\xEE\xBA" => "\xE5\x92\x80", + "\xEE\xBB" => "\xE5\xA7\x90", + "\xEE\xBC" => "\xE5\xBA\x95", + "\xEE\xBD" => "\xE6\x8A\xB5", + "\xEE\xBE" => "\xE6\x9D\xB5", + "\xEE\xBF" => "\xE6\xA5\xAE", + "\xEE\xC0" => "\xE6\xA8\x97", + "\xEE\xC1" => "\xE6\xB2\xAE", + "\xEE\xC2" => "\xE6\xB8\x9A", + "\xEE\xC3" => "\xE7\x8B\x99", + "\xEE\xC4" => "\xE7\x8C\xAA", + "\xEE\xC5" => "\xE7\x96\xBD", + "\xEE\xC6" => "\xE7\xAE\xB8", + "\xEE\xC7" => "\xE7\xB4\xB5", + "\xEE\xC8" => "\xE8\x8B\xA7", + "\xEE\xC9" => "\xE8\x8F\xB9", + "\xEE\xCA" => "\xE8\x91\x97", + "\xEE\xCB" => "\xE8\x97\xB7", + "\xEE\xCC" => "\xE8\xA9\x9B", + "\xEE\xCD" => "\xE8\xB2\xAF", + "\xEE\xCE" => "\xE8\xBA\x87", + "\xEE\xCF" => "\xE9\x80\x99", + "\xEE\xD0" => "\xE9\x82\xB8", + "\xEE\xD1" => "\xE9\x9B\x8E", + "\xEE\xD2" => "\xE9\xBD\x9F", + "\xEE\xD3" => "\xE5\x8B\xA3", + "\xEE\xD4" => "\xE5\x90\x8A", + "\xEE\xD5" => "\xE5\xAB\xA1", + "\xEE\xD6" => "\xE5\xAF\x82", + "\xEE\xD7" => "\xE6\x91\x98", + "\xEE\xD8" => "\xE6\x95\xB5", + "\xEE\xD9" => "\xE6\xBB\xB4", + "\xEE\xDA" => "\xE7\x8B\x84", + "\xEE\xDB" => "\xEF\xA7\xBB", + "\xEE\xDC" => "\xE7\x9A\x84", + "\xEE\xDD" => "\xE7\xA9\x8D", + "\xEE\xDE" => "\xE7\xAC\x9B", + "\xEE\xDF" => "\xE7\xB1\x8D", + "\xEE\xE0" => "\xE7\xB8\xBE", + "\xEE\xE1" => "\xE7\xBF\x9F", + "\xEE\xE2" => "\xE8\x8D\xBB", + "\xEE\xE3" => "\xE8\xAC\xAB", + "\xEE\xE4" => "\xE8\xB3\x8A", + "\xEE\xE5" => "\xE8\xB5\xA4", + "\xEE\xE6" => "\xE8\xB7\xA1", + "\xEE\xE7" => "\xE8\xB9\x9F", + "\xEE\xE8" => "\xE8\xBF\xAA", + "\xEE\xE9" => "\xE8\xBF\xB9", + "\xEE\xEA" => "\xE9\x81\xA9", + "\xEE\xEB" => "\xE9\x8F\x91", + "\xEE\xEC" => "\xE4\xBD\x83", + "\xEE\xED" => "\xE4\xBD\xBA", + "\xEE\xEE" => "\xE5\x82\xB3", + "\xEE\xEF" => "\xE5\x85\xA8", + "\xEE\xF0" => "\xE5\x85\xB8", + "\xEE\xF1" => "\xE5\x89\x8D", + "\xEE\xF2" => "\xE5\x89\xAA", + "\xEE\xF3" => "\xE5\xA1\xA1", + "\xEE\xF4" => "\xE5\xA1\xBC", + "\xEE\xF5" => "\xE5\xA5\xA0", + "\xEE\xF6" => "\xE5\xB0\x88", + "\xEE\xF7" => "\xE5\xB1\x95", + "\xEE\xF8" => "\xE5\xBB\x9B", + "\xEE\xF9" => "\xE6\x82\x9B", + "\xEE\xFA" => "\xE6\x88\xB0", + "\xEE\xFB" => "\xE6\xA0\x93", + "\xEE\xFC" => "\xE6\xAE\xBF", + "\xEE\xFD" => "\xE6\xB0\x88", + "\xEE\xFE" => "\xE6\xBE\xB1", + "\xEF\xA1" => "\xE7\x85\x8E", + "\xEF\xA2" => "\xE7\x90\xA0", + "\xEF\xA3" => "\xE7\x94\xB0", + "\xEF\xA4" => "\xE7\x94\xB8", + "\xEF\xA5" => "\xE7\x95\x91", + "\xEF\xA6" => "\xE7\x99\xB2", + "\xEF\xA7" => "\xE7\xAD\x8C", + "\xEF\xA8" => "\xE7\xAE\x8B", + "\xEF\xA9" => "\xE7\xAE\xAD", + "\xEF\xAA" => "\xE7\xAF\x86", + "\xEF\xAB" => "\xE7\xBA\x8F", + "\xEF\xAC" => "\xE8\xA9\xAE", + "\xEF\xAD" => "\xE8\xBC\xBE", + "\xEF\xAE" => "\xE8\xBD\x89", + "\xEF\xAF" => "\xE9\x88\xBF", + "\xEF\xB0" => "\xE9\x8A\x93", + "\xEF\xB1" => "\xE9\x8C\xA2", + "\xEF\xB2" => "\xE9\x90\xAB", + "\xEF\xB3" => "\xE9\x9B\xBB", + "\xEF\xB4" => "\xE9\xA1\x9A", + "\xEF\xB5" => "\xE9\xA1\xAB", + "\xEF\xB6" => "\xE9\xA4\x9E", + "\xEF\xB7" => "\xE5\x88\x87", + "\xEF\xB8" => "\xE6\x88\xAA", + "\xEF\xB9" => "\xE6\x8A\x98", + "\xEF\xBA" => "\xE6\xB5\x99", + "\xEF\xBB" => "\xE7\x99\xA4", + "\xEF\xBC" => "\xE7\xAB\x8A", + "\xEF\xBD" => "\xE7\xAF\x80", + "\xEF\xBE" => "\xE7\xB5\xB6", + "\xEF\xBF" => "\xE5\x8D\xA0", + "\xEF\xC0" => "\xE5\xB2\xBE", + "\xEF\xC1" => "\xE5\xBA\x97", + "\xEF\xC2" => "\xE6\xBC\xB8", + "\xEF\xC3" => "\xE7\x82\xB9", + "\xEF\xC4" => "\xE7\xB2\x98", + "\xEF\xC5" => "\xE9\x9C\x91", + "\xEF\xC6" => "\xE9\xAE\x8E", + "\xEF\xC7" => "\xE9\xBB\x9E", + "\xEF\xC8" => "\xE6\x8E\xA5", + "\xEF\xC9" => "\xE6\x91\xBA", + "\xEF\xCA" => "\xE8\x9D\xB6", + "\xEF\xCB" => "\xE4\xB8\x81", + "\xEF\xCC" => "\xE4\xBA\x95", + "\xEF\xCD" => "\xE4\xBA\xAD", + "\xEF\xCE" => "\xE5\x81\x9C", + "\xEF\xCF" => "\xE5\x81\xB5", + "\xEF\xD0" => "\xE5\x91\x88", + "\xEF\xD1" => "\xE5\xA7\x83", + "\xEF\xD2" => "\xE5\xAE\x9A", + "\xEF\xD3" => "\xE5\xB9\x80", + "\xEF\xD4" => "\xE5\xBA\xAD", + "\xEF\xD5" => "\xE5\xBB\xB7", + "\xEF\xD6" => "\xE5\xBE\x81", + "\xEF\xD7" => "\xE6\x83\x85", + "\xEF\xD8" => "\xE6\x8C\xBA", + "\xEF\xD9" => "\xE6\x94\xBF", + "\xEF\xDA" => "\xE6\x95\xB4", + "\xEF\xDB" => "\xE6\x97\x8C", + "\xEF\xDC" => "\xE6\x99\xB6", + "\xEF\xDD" => "\xE6\x99\xB8", + "\xEF\xDE" => "\xE6\x9F\xBE", + "\xEF\xDF" => "\xE6\xA5\xA8", + "\xEF\xE0" => "\xE6\xAA\x89", + "\xEF\xE1" => "\xE6\xAD\xA3", + "\xEF\xE2" => "\xE6\xB1\x80", + "\xEF\xE3" => "\xE6\xB7\x80", + "\xEF\xE4" => "\xE6\xB7\xA8", + "\xEF\xE5" => "\xE6\xB8\x9F", + "\xEF\xE6" => "\xE6\xB9\x9E", + "\xEF\xE7" => "\xE7\x80\x9E", + "\xEF\xE8" => "\xE7\x82\xA1", + "\xEF\xE9" => "\xE7\x8E\x8E", + "\xEF\xEA" => "\xE7\x8F\xBD", + "\xEF\xEB" => "\xE7\x94\xBA", + "\xEF\xEC" => "\xE7\x9D\x9B", + "\xEF\xED" => "\xE7\xA2\x87", + "\xEF\xEE" => "\xE7\xA6\x8E", + "\xEF\xEF" => "\xE7\xA8\x8B", + "\xEF\xF0" => "\xE7\xA9\xBD", + "\xEF\xF1" => "\xE7\xB2\xBE", + "\xEF\xF2" => "\xE7\xB6\x8E", + "\xEF\xF3" => "\xE8\x89\x87", + "\xEF\xF4" => "\xE8\xA8\x82", + "\xEF\xF5" => "\xE8\xAB\xAA", + "\xEF\xF6" => "\xE8\xB2\x9E", + "\xEF\xF7" => "\xE9\x84\xAD", + "\xEF\xF8" => "\xE9\x85\x8A", + "\xEF\xF9" => "\xE9\x87\x98", + "\xEF\xFA" => "\xE9\x89\xA6", + "\xEF\xFB" => "\xE9\x8B\x8C", + "\xEF\xFC" => "\xE9\x8C\xA0", + "\xEF\xFD" => "\xE9\x9C\x86", + "\xEF\xFE" => "\xE9\x9D\x96", + "\xF0\xA1" => "\xE9\x9D\x9C", + "\xF0\xA2" => "\xE9\xA0\x82", + "\xF0\xA3" => "\xE9\xBC\x8E", + "\xF0\xA4" => "\xE5\x88\xB6", + "\xF0\xA5" => "\xE5\x8A\x91", + "\xF0\xA6" => "\xE5\x95\xBC", + "\xF0\xA7" => "\xE5\xA0\xA4", + "\xF0\xA8" => "\xE5\xB8\x9D", + "\xF0\xA9" => "\xE5\xBC\x9F", + "\xF0\xAA" => "\xE6\x82\x8C", + "\xF0\xAB" => "\xE6\x8F\x90", + "\xF0\xAC" => "\xE6\xA2\xAF", + "\xF0\xAD" => "\xE6\xBF\x9F", + "\xF0\xAE" => "\xE7\xA5\xAD", + "\xF0\xAF" => "\xE7\xAC\xAC", + "\xF0\xB0" => "\xE8\x87\x8D", + "\xF0\xB1" => "\xE8\x96\xBA", + "\xF0\xB2" => "\xE8\xA3\xBD", + "\xF0\xB3" => "\xE8\xAB\xB8", + "\xF0\xB4" => "\xE8\xB9\x84", + "\xF0\xB5" => "\xE9\x86\x8D", + "\xF0\xB6" => "\xE9\x99\xA4", + "\xF0\xB7" => "\xE9\x9A\x9B", + "\xF0\xB8" => "\xE9\x9C\xBD", + "\xF0\xB9" => "\xE9\xA1\x8C", + "\xF0\xBA" => "\xE9\xBD\x8A", + "\xF0\xBB" => "\xE4\xBF\x8E", + "\xF0\xBC" => "\xE5\x85\x86", + "\xF0\xBD" => "\xE5\x87\x8B", + "\xF0\xBE" => "\xE5\x8A\xA9", + "\xF0\xBF" => "\xE5\x98\xB2", + "\xF0\xC0" => "\xE5\xBC\x94", + "\xF0\xC1" => "\xE5\xBD\xAB", + "\xF0\xC2" => "\xE6\x8E\xAA", + "\xF0\xC3" => "\xE6\x93\x8D", + "\xF0\xC4" => "\xE6\x97\xA9", + "\xF0\xC5" => "\xE6\x99\x81", + "\xF0\xC6" => "\xE6\x9B\xBA", + "\xF0\xC7" => "\xE6\x9B\xB9", + "\xF0\xC8" => "\xE6\x9C\x9D", + "\xF0\xC9" => "\xE6\xA2\x9D", + "\xF0\xCA" => "\xE6\xA3\x97", + "\xF0\xCB" => "\xE6\xA7\xBD", + "\xF0\xCC" => "\xE6\xBC\x95", + "\xF0\xCD" => "\xE6\xBD\xAE", + "\xF0\xCE" => "\xE7\x85\xA7", + "\xF0\xCF" => "\xE7\x87\xA5", + "\xF0\xD0" => "\xE7\x88\xAA", + "\xF0\xD1" => "\xE7\x92\xAA", + "\xF0\xD2" => "\xE7\x9C\xBA", + "\xF0\xD3" => "\xE7\xA5\x96", + "\xF0\xD4" => "\xE7\xA5\x9A", + "\xF0\xD5" => "\xE7\xA7\x9F", + "\xF0\xD6" => "\xE7\xA8\xA0", + "\xF0\xD7" => "\xE7\xAA\x95", + "\xF0\xD8" => "\xE7\xB2\x97", + "\xF0\xD9" => "\xE7\xB3\x9F", + "\xF0\xDA" => "\xE7\xB5\x84", + "\xF0\xDB" => "\xE7\xB9\xB0", + "\xF0\xDC" => "\xE8\x82\x87", + "\xF0\xDD" => "\xE8\x97\xBB", + "\xF0\xDE" => "\xE8\x9A\xA4", + "\xF0\xDF" => "\xE8\xA9\x94", + "\xF0\xE0" => "\xE8\xAA\xBF", + "\xF0\xE1" => "\xE8\xB6\x99", + "\xF0\xE2" => "\xE8\xBA\x81", + "\xF0\xE3" => "\xE9\x80\xA0", + "\xF0\xE4" => "\xE9\x81\xAD", + "\xF0\xE5" => "\xE9\x87\xA3", + "\xF0\xE6" => "\xE9\x98\xBB", + "\xF0\xE7" => "\xE9\x9B\x95", + "\xF0\xE8" => "\xE9\xB3\xA5", + "\xF0\xE9" => "\xE6\x97\x8F", + "\xF0\xEA" => "\xE7\xB0\x87", + "\xF0\xEB" => "\xE8\xB6\xB3", + "\xF0\xEC" => "\xE9\x8F\x83", + "\xF0\xED" => "\xE5\xAD\x98", + "\xF0\xEE" => "\xE5\xB0\x8A", + "\xF0\xEF" => "\xE5\x8D\x92", + "\xF0\xF0" => "\xE6\x8B\x99", + "\xF0\xF1" => "\xE7\x8C\x9D", + "\xF0\xF2" => "\xE5\x80\xA7", + "\xF0\xF3" => "\xE5\xAE\x97", + "\xF0\xF4" => "\xE5\xBE\x9E", + "\xF0\xF5" => "\xE6\x82\xB0", + "\xF0\xF6" => "\xE6\x85\xAB", + "\xF0\xF7" => "\xE6\xA3\x95", + "\xF0\xF8" => "\xE6\xB7\x99", + "\xF0\xF9" => "\xE7\x90\xAE", + "\xF0\xFA" => "\xE7\xA8\xAE", + "\xF0\xFB" => "\xE7\xB5\x82", + "\xF0\xFC" => "\xE7\xB6\x9C", + "\xF0\xFD" => "\xE7\xB8\xB1", + "\xF0\xFE" => "\xE8\x85\xAB", + "\xF1\xA1" => "\xE8\xB8\xAA", + "\xF1\xA2" => "\xE8\xB8\xB5", + "\xF1\xA3" => "\xE9\x8D\xBE", + "\xF1\xA4" => "\xE9\x90\x98", + "\xF1\xA5" => "\xE4\xBD\x90", + "\xF1\xA6" => "\xE5\x9D\x90", + "\xF1\xA7" => "\xE5\xB7\xA6", + "\xF1\xA8" => "\xE5\xBA\xA7", + "\xF1\xA9" => "\xE6\x8C\xAB", + "\xF1\xAA" => "\xE7\xBD\xAA", + "\xF1\xAB" => "\xE4\xB8\xBB", + "\xF1\xAC" => "\xE4\xBD\x8F", + "\xF1\xAD" => "\xE4\xBE\x8F", + "\xF1\xAE" => "\xE5\x81\x9A", + "\xF1\xAF" => "\xE5\xA7\x9D", + "\xF1\xB0" => "\xE8\x83\x84", + "\xF1\xB1" => "\xE5\x91\xAA", + "\xF1\xB2" => "\xE5\x91\xA8", + "\xF1\xB3" => "\xE5\x97\xBE", + "\xF1\xB4" => "\xE5\xA5\x8F", + "\xF1\xB5" => "\xE5\xAE\x99", + "\xF1\xB6" => "\xE5\xB7\x9E", + "\xF1\xB7" => "\xE5\xBB\x9A", + "\xF1\xB8" => "\xE6\x99\x9D", + "\xF1\xB9" => "\xE6\x9C\xB1", + "\xF1\xBA" => "\xE6\x9F\xB1", + "\xF1\xBB" => "\xE6\xA0\xAA", + "\xF1\xBC" => "\xE6\xB3\xA8", + "\xF1\xBD" => "\xE6\xB4\xB2", + "\xF1\xBE" => "\xE6\xB9\x8A", + "\xF1\xBF" => "\xE6\xBE\x8D", + "\xF1\xC0" => "\xE7\x82\xB7", + "\xF1\xC1" => "\xE7\x8F\xA0", + "\xF1\xC2" => "\xE7\x96\x87", + "\xF1\xC3" => "\xE7\xB1\x8C", + "\xF1\xC4" => "\xE7\xB4\x82", + "\xF1\xC5" => "\xE7\xB4\xAC", + "\xF1\xC6" => "\xE7\xB6\xA2", + "\xF1\xC7" => "\xE8\x88\x9F", + "\xF1\xC8" => "\xE8\x9B\x9B", + "\xF1\xC9" => "\xE8\xA8\xBB", + "\xF1\xCA" => "\xE8\xAA\x85", + "\xF1\xCB" => "\xE8\xB5\xB0", + "\xF1\xCC" => "\xE8\xBA\x8A", + "\xF1\xCD" => "\xE8\xBC\xB3", + "\xF1\xCE" => "\xE9\x80\xB1", + "\xF1\xCF" => "\xE9\x85\x8E", + "\xF1\xD0" => "\xE9\x85\x92", + "\xF1\xD1" => "\xE9\x91\x84", + "\xF1\xD2" => "\xE9\xA7\x90", + "\xF1\xD3" => "\xE7\xAB\xB9", + "\xF1\xD4" => "\xE7\xB2\xA5", + "\xF1\xD5" => "\xE4\xBF\x8A", + "\xF1\xD6" => "\xE5\x84\x81", + "\xF1\xD7" => "\xE5\x87\x86", + "\xF1\xD8" => "\xE5\x9F\x88", + "\xF1\xD9" => "\xE5\xAF\xAF", + "\xF1\xDA" => "\xE5\xB3\xBB", + "\xF1\xDB" => "\xE6\x99\x99", + "\xF1\xDC" => "\xE6\xA8\xBD", + "\xF1\xDD" => "\xE6\xB5\x9A", + "\xF1\xDE" => "\xE6\xBA\x96", + "\xF1\xDF" => "\xE6\xBF\xAC", + "\xF1\xE0" => "\xE7\x84\x8C", + "\xF1\xE1" => "\xE7\x95\xAF", + "\xF1\xE2" => "\xE7\xAB\xA3", + "\xF1\xE3" => "\xE8\xA0\xA2", + "\xF1\xE4" => "\xE9\x80\xA1", + "\xF1\xE5" => "\xE9\x81\xB5", + "\xF1\xE6" => "\xE9\x9B\x8B", + "\xF1\xE7" => "\xE9\xA7\xBF", + "\xF1\xE8" => "\xE8\x8C\x81", + "\xF1\xE9" => "\xE4\xB8\xAD", + "\xF1\xEA" => "\xE4\xBB\xB2", + "\xF1\xEB" => "\xE8\xA1\x86", + "\xF1\xEC" => "\xE9\x87\x8D", + "\xF1\xED" => "\xE5\x8D\xBD", + "\xF1\xEE" => "\xE6\xAB\x9B", + "\xF1\xEF" => "\xE6\xA5\xAB", + "\xF1\xF0" => "\xE6\xB1\x81", + "\xF1\xF1" => "\xE8\x91\xBA", + "\xF1\xF2" => "\xE5\xA2\x9E", + "\xF1\xF3" => "\xE6\x86\x8E", + "\xF1\xF4" => "\xE6\x9B\xBE", + "\xF1\xF5" => "\xE6\x8B\xAF", + "\xF1\xF6" => "\xE7\x83\x9D", + "\xF1\xF7" => "\xE7\x94\x91", + "\xF1\xF8" => "\xE7\x97\x87", + "\xF1\xF9" => "\xE7\xB9\x92", + "\xF1\xFA" => "\xE8\x92\xB8", + "\xF1\xFB" => "\xE8\xAD\x89", + "\xF1\xFC" => "\xE8\xB4\x88", + "\xF1\xFD" => "\xE4\xB9\x8B", + "\xF1\xFE" => "\xE5\x8F\xAA", + "\xF2\xA1" => "\xE5\x92\xAB", + "\xF2\xA2" => "\xE5\x9C\xB0", + "\xF2\xA3" => "\xE5\x9D\x80", + "\xF2\xA4" => "\xE5\xBF\x97", + "\xF2\xA5" => "\xE6\x8C\x81", + "\xF2\xA6" => "\xE6\x8C\x87", + "\xF2\xA7" => "\xE6\x91\xAF", + "\xF2\xA8" => "\xE6\x94\xAF", + "\xF2\xA9" => "\xE6\x97\xA8", + "\xF2\xAA" => "\xE6\x99\xBA", + "\xF2\xAB" => "\xE6\x9E\x9D", + "\xF2\xAC" => "\xE6\x9E\xB3", + "\xF2\xAD" => "\xE6\xAD\xA2", + "\xF2\xAE" => "\xE6\xB1\xA0", + "\xF2\xAF" => "\xE6\xB2\x9A", + "\xF2\xB0" => "\xE6\xBC\xAC", + "\xF2\xB1" => "\xE7\x9F\xA5", + "\xF2\xB2" => "\xE7\xA0\xA5", + "\xF2\xB3" => "\xE7\xA5\x89", + "\xF2\xB4" => "\xE7\xA5\x97", + "\xF2\xB5" => "\xE7\xB4\x99", + "\xF2\xB6" => "\xE8\x82\xA2", + "\xF2\xB7" => "\xE8\x84\x82", + "\xF2\xB8" => "\xE8\x87\xB3", + "\xF2\xB9" => "\xE8\x8A\x9D", + "\xF2\xBA" => "\xE8\x8A\xB7", + "\xF2\xBB" => "\xE8\x9C\x98", + "\xF2\xBC" => "\xE8\xAA\x8C", + "\xF2\xBD" => "\xEF\xA7\xBC", + "\xF2\xBE" => "\xE8\xB4\x84", + "\xF2\xBF" => "\xE8\xB6\xBE", + "\xF2\xC0" => "\xE9\x81\xB2", + "\xF2\xC1" => "\xE7\x9B\xB4", + "\xF2\xC2" => "\xE7\xA8\x99", + "\xF2\xC3" => "\xE7\xA8\xB7", + "\xF2\xC4" => "\xE7\xB9\x94", + "\xF2\xC5" => "\xE8\x81\xB7", + "\xF2\xC6" => "\xE5\x94\x87", + "\xF2\xC7" => "\xE5\x97\x94", + "\xF2\xC8" => "\xE5\xA1\xB5", + "\xF2\xC9" => "\xE6\x8C\xAF", + "\xF2\xCA" => "\xE6\x90\xA2", + "\xF2\xCB" => "\xE6\x99\x89", + "\xF2\xCC" => "\xE6\x99\x8B", + "\xF2\xCD" => "\xE6\xA1\xAD", + "\xF2\xCE" => "\xE6\xA6\x9B", + "\xF2\xCF" => "\xE6\xAE\x84", + "\xF2\xD0" => "\xE6\xB4\xA5", + "\xF2\xD1" => "\xE6\xBA\xB1", + "\xF2\xD2" => "\xE7\x8F\x8D", + "\xF2\xD3" => "\xE7\x91\xA8", + "\xF2\xD4" => "\xE7\x92\xA1", + "\xF2\xD5" => "\xE7\x95\x9B", + "\xF2\xD6" => "\xE7\x96\xB9", + "\xF2\xD7" => "\xE7\x9B\xA1", + "\xF2\xD8" => "\xE7\x9C\x9E", + "\xF2\xD9" => "\xE7\x9E\x8B", + "\xF2\xDA" => "\xE7\xA7\xA6", + "\xF2\xDB" => "\xE7\xB8\x89", + "\xF2\xDC" => "\xE7\xB8\x9D", + "\xF2\xDD" => "\xE8\x87\xBB", + "\xF2\xDE" => "\xE8\x94\xAF", + "\xF2\xDF" => "\xE8\xA2\x97", + "\xF2\xE0" => "\xE8\xA8\xBA", + "\xF2\xE1" => "\xE8\xB3\x91", + "\xF2\xE2" => "\xE8\xBB\xAB", + "\xF2\xE3" => "\xE8\xBE\xB0", + "\xF2\xE4" => "\xE9\x80\xB2", + "\xF2\xE5" => "\xE9\x8E\xAD", + "\xF2\xE6" => "\xE9\x99\xA3", + "\xF2\xE7" => "\xE9\x99\xB3", + "\xF2\xE8" => "\xE9\x9C\x87", + "\xF2\xE9" => "\xE4\xBE\x84", + "\xF2\xEA" => "\xE5\x8F\xB1", + "\xF2\xEB" => "\xE5\xA7\xAA", + "\xF2\xEC" => "\xE5\xAB\x89", + "\xF2\xED" => "\xE5\xB8\x99", + "\xF2\xEE" => "\xE6\xA1\x8E", + "\xF2\xEF" => "\xE7\x93\x86", + "\xF2\xF0" => "\xE7\x96\xBE", + "\xF2\xF1" => "\xE7\xA7\xA9", + "\xF2\xF2" => "\xE7\xAA\x92", + "\xF2\xF3" => "\xE8\x86\xA3", + "\xF2\xF4" => "\xE8\x9B\xAD", + "\xF2\xF5" => "\xE8\xB3\xAA", + "\xF2\xF6" => "\xE8\xB7\x8C", + "\xF2\xF7" => "\xE8\xBF\xAD", + "\xF2\xF8" => "\xE6\x96\x9F", + "\xF2\xF9" => "\xE6\x9C\x95", + "\xF2\xFA" => "\xEF\xA7\xBD", + "\xF2\xFB" => "\xE5\x9F\xB7", + "\xF2\xFC" => "\xE6\xBD\x97", + "\xF2\xFD" => "\xE7\xB7\x9D", + "\xF2\xFE" => "\xE8\xBC\xAF", + "\xF3\xA1" => "\xE9\x8F\xB6", + "\xF3\xA2" => "\xE9\x9B\x86", + "\xF3\xA3" => "\xE5\xBE\xB5", + "\xF3\xA4" => "\xE6\x87\xB2", + "\xF3\xA5" => "\xE6\xBE\x84", + "\xF3\xA6" => "\xE4\xB8\x94", + "\xF3\xA7" => "\xE4\xBE\x98", + "\xF3\xA8" => "\xE5\x80\x9F", + "\xF3\xA9" => "\xE5\x8F\x89", + "\xF3\xAA" => "\xE5\x97\x9F", + "\xF3\xAB" => "\xE5\xB5\xAF", + "\xF3\xAC" => "\xE5\xB7\xAE", + "\xF3\xAD" => "\xE6\xAC\xA1", + "\xF3\xAE" => "\xE6\xAD\xA4", + "\xF3\xAF" => "\xE7\xA3\x8B", + "\xF3\xB0" => "\xE7\xAE\x9A", + "\xF3\xB1" => "\xEF\xA7\xBE", + "\xF3\xB2" => "\xE8\xB9\x89", + "\xF3\xB3" => "\xE8\xBB\x8A", + "\xF3\xB4" => "\xE9\x81\xAE", + "\xF3\xB5" => "\xE6\x8D\x89", + "\xF3\xB6" => "\xE6\x90\xBE", + "\xF3\xB7" => "\xE7\x9D\x80", + "\xF3\xB8" => "\xE7\xAA\x84", + "\xF3\xB9" => "\xE9\x8C\xAF", + "\xF3\xBA" => "\xE9\x91\xBF", + "\xF3\xBB" => "\xE9\xBD\xAA", + "\xF3\xBC" => "\xE6\x92\xB0", + "\xF3\xBD" => "\xE6\xBE\xAF", + "\xF3\xBE" => "\xE7\x87\xA6", + "\xF3\xBF" => "\xE7\x92\xA8", + "\xF3\xC0" => "\xE7\x93\x9A", + "\xF3\xC1" => "\xE7\xAB\x84", + "\xF3\xC2" => "\xE7\xB0\x92", + "\xF3\xC3" => "\xE7\xBA\x82", + "\xF3\xC4" => "\xE7\xB2\xB2", + "\xF3\xC5" => "\xE7\xBA\x98", + "\xF3\xC6" => "\xE8\xAE\x9A", + "\xF3\xC7" => "\xE8\xB4\x8A", + "\xF3\xC8" => "\xE9\x91\xBD", + "\xF3\xC9" => "\xE9\xA4\x90", + "\xF3\xCA" => "\xE9\xA5\x8C", + "\xF3\xCB" => "\xE5\x88\xB9", + "\xF3\xCC" => "\xE5\xAF\x9F", + "\xF3\xCD" => "\xE6\x93\xA6", + "\xF3\xCE" => "\xE6\x9C\xAD", + "\xF3\xCF" => "\xE7\xB4\xAE", + "\xF3\xD0" => "\xE5\x83\xAD", + "\xF3\xD1" => "\xE5\x8F\x83", + "\xF3\xD2" => "\xE5\xA1\xB9", + "\xF3\xD3" => "\xE6\x85\x98", + "\xF3\xD4" => "\xE6\x85\x99", + "\xF3\xD5" => "\xE6\x87\xBA", + "\xF3\xD6" => "\xE6\x96\xAC", + "\xF3\xD7" => "\xE7\xAB\x99", + "\xF3\xD8" => "\xE8\xAE\x92", + "\xF3\xD9" => "\xE8\xAE\x96", + "\xF3\xDA" => "\xE5\x80\x89", + "\xF3\xDB" => "\xE5\x80\xA1", + "\xF3\xDC" => "\xE5\x89\xB5", + "\xF3\xDD" => "\xE5\x94\xB1", + "\xF3\xDE" => "\xE5\xA8\xBC", + "\xF3\xDF" => "\xE5\xBB\xA0", + "\xF3\xE0" => "\xE5\xBD\xB0", + "\xF3\xE1" => "\xE6\x84\xB4", + "\xF3\xE2" => "\xE6\x95\x9E", + "\xF3\xE3" => "\xE6\x98\x8C", + "\xF3\xE4" => "\xE6\x98\xB6", + "\xF3\xE5" => "\xE6\x9A\xA2", + "\xF3\xE6" => "\xE6\xA7\x8D", + "\xF3\xE7" => "\xE6\xBB\x84", + "\xF3\xE8" => "\xE6\xBC\xB2", + "\xF3\xE9" => "\xE7\x8C\x96", + "\xF3\xEA" => "\xE7\x98\xA1", + "\xF3\xEB" => "\xE7\xAA\x93", + "\xF3\xEC" => "\xE8\x84\xB9", + "\xF3\xED" => "\xE8\x89\x99", + "\xF3\xEE" => "\xE8\x8F\x96", + "\xF3\xEF" => "\xE8\x92\xBC", + "\xF3\xF0" => "\xE5\x82\xB5", + "\xF3\xF1" => "\xE5\x9F\xB0", + "\xF3\xF2" => "\xE5\xAF\x80", + "\xF3\xF3" => "\xE5\xAF\xA8", + "\xF3\xF4" => "\xE5\xBD\xA9", + "\xF3\xF5" => "\xE6\x8E\xA1", + "\xF3\xF6" => "\xE7\xA0\xA6", + "\xF3\xF7" => "\xE7\xB6\xB5", + "\xF3\xF8" => "\xE8\x8F\x9C", + "\xF3\xF9" => "\xE8\x94\xA1", + "\xF3\xFA" => "\xE9\x87\x87", + "\xF3\xFB" => "\xE9\x87\xB5", + "\xF3\xFC" => "\xE5\x86\x8A", + "\xF3\xFD" => "\xE6\x9F\xB5", + "\xF3\xFE" => "\xE7\xAD\x96", + "\xF4\xA1" => "\xE8\xB2\xAC", + "\xF4\xA2" => "\xE5\x87\x84", + "\xF4\xA3" => "\xE5\xA6\xBB", + "\xF4\xA4" => "\xE6\x82\xBD", + "\xF4\xA5" => "\xE8\x99\x95", + "\xF4\xA6" => "\xE5\x80\x9C", + "\xF4\xA7" => "\xEF\xA7\xBF", + "\xF4\xA8" => "\xE5\x89\x94", + "\xF4\xA9" => "\xE5\xB0\xBA", + "\xF4\xAA" => "\xE6\x85\xBD", + "\xF4\xAB" => "\xE6\x88\x9A", + "\xF4\xAC" => "\xE6\x8B\x93", + "\xF4\xAD" => "\xE6\x93\xB2", + "\xF4\xAE" => "\xE6\x96\xA5", + "\xF4\xAF" => "\xE6\xBB\x8C", + "\xF4\xB0" => "\xE7\x98\xA0", + "\xF4\xB1" => "\xE8\x84\x8A", + "\xF4\xB2" => "\xE8\xB9\xA0", + "\xF4\xB3" => "\xE9\x99\x9F", + "\xF4\xB4" => "\xE9\x9A\xBB", + "\xF4\xB5" => "\xE4\xBB\x9F", + "\xF4\xB6" => "\xE5\x8D\x83", + "\xF4\xB7" => "\xE5\x96\x98", + "\xF4\xB8" => "\xE5\xA4\xA9", + "\xF4\xB9" => "\xE5\xB7\x9D", + "\xF4\xBA" => "\xE6\x93\x85", + "\xF4\xBB" => "\xE6\xB3\x89", + "\xF4\xBC" => "\xE6\xB7\xBA", + "\xF4\xBD" => "\xE7\x8E\x94", + "\xF4\xBE" => "\xE7\xA9\xBF", + "\xF4\xBF" => "\xE8\x88\x9B", + "\xF4\xC0" => "\xE8\x96\xA6", + "\xF4\xC1" => "\xE8\xB3\xA4", + "\xF4\xC2" => "\xE8\xB8\x90", + "\xF4\xC3" => "\xE9\x81\xB7", + "\xF4\xC4" => "\xE9\x87\xA7", + "\xF4\xC5" => "\xE9\x97\xA1", + "\xF4\xC6" => "\xE9\x98\xA1", + "\xF4\xC7" => "\xE9\x9F\x86", + "\xF4\xC8" => "\xE5\x87\xB8", + "\xF4\xC9" => "\xE5\x93\xB2", + "\xF4\xCA" => "\xE5\x96\x86", + "\xF4\xCB" => "\xE5\xBE\xB9", + "\xF4\xCC" => "\xE6\x92\xA4", + "\xF4\xCD" => "\xE6\xBE\x88", + "\xF4\xCE" => "\xE7\xB6\xB4", + "\xF4\xCF" => "\xE8\xBC\x9F", + "\xF4\xD0" => "\xE8\xBD\x8D", + "\xF4\xD1" => "\xE9\x90\xB5", + "\xF4\xD2" => "\xE5\x83\x89", + "\xF4\xD3" => "\xE5\xB0\x96", + "\xF4\xD4" => "\xE6\xB2\xBE", + "\xF4\xD5" => "\xE6\xB7\xBB", + "\xF4\xD6" => "\xE7\x94\x9B", + "\xF4\xD7" => "\xE7\x9E\xBB", + "\xF4\xD8" => "\xE7\xB0\xBD", + "\xF4\xD9" => "\xE7\xB1\xA4", + "\xF4\xDA" => "\xE8\xA9\xB9", + "\xF4\xDB" => "\xE8\xAB\x82", + "\xF4\xDC" => "\xE5\xA0\x9E", + "\xF4\xDD" => "\xE5\xA6\xBE", + "\xF4\xDE" => "\xE5\xB8\x96", + "\xF4\xDF" => "\xE6\x8D\xB7", + "\xF4\xE0" => "\xE7\x89\x92", + "\xF4\xE1" => "\xE7\x96\x8A", + "\xF4\xE2" => "\xE7\x9D\xAB", + "\xF4\xE3" => "\xE8\xAB\x9C", + "\xF4\xE4" => "\xE8\xB2\xBC", + "\xF4\xE5" => "\xE8\xBC\x92", + "\xF4\xE6" => "\xE5\xBB\xB3", + "\xF4\xE7" => "\xE6\x99\xB4", + "\xF4\xE8" => "\xE6\xB7\xB8", + "\xF4\xE9" => "\xE8\x81\xBD", + "\xF4\xEA" => "\xE8\x8F\x81", + "\xF4\xEB" => "\xE8\xAB\x8B", + "\xF4\xEC" => "\xE9\x9D\x91", + "\xF4\xED" => "\xE9\xAF\x96", + "\xF4\xEE" => "\xEF\xA8\x80", + "\xF4\xEF" => "\xE5\x89\x83", + "\xF4\xF0" => "\xE6\x9B\xBF", + "\xF4\xF1" => "\xE6\xB6\x95", + "\xF4\xF2" => "\xE6\xBB\xAF", + "\xF4\xF3" => "\xE7\xB7\xA0", + "\xF4\xF4" => "\xE8\xAB\xA6", + "\xF4\xF5" => "\xE9\x80\xAE", + "\xF4\xF6" => "\xE9\x81\x9E", + "\xF4\xF7" => "\xE9\xAB\x94", + "\xF4\xF8" => "\xE5\x88\x9D", + "\xF4\xF9" => "\xE5\x89\xBF", + "\xF4\xFA" => "\xE5\x93\xA8", + "\xF4\xFB" => "\xE6\x86\x94", + "\xF4\xFC" => "\xE6\x8A\x84", + "\xF4\xFD" => "\xE6\x8B\x9B", + "\xF4\xFE" => "\xE6\xA2\xA2", + "\xF5\xA1" => "\xE6\xA4\x92", + "\xF5\xA2" => "\xE6\xA5\x9A", + "\xF5\xA3" => "\xE6\xA8\xB5", + "\xF5\xA4" => "\xE7\x82\x92", + "\xF5\xA5" => "\xE7\x84\xA6", + "\xF5\xA6" => "\xE7\xA1\x9D", + "\xF5\xA7" => "\xE7\xA4\x81", + "\xF5\xA8" => "\xE7\xA4\x8E", + "\xF5\xA9" => "\xE7\xA7\x92", + "\xF5\xAA" => "\xE7\xA8\x8D", + "\xF5\xAB" => "\xE8\x82\x96", + "\xF5\xAC" => "\xE8\x89\xB8", + "\xF5\xAD" => "\xE8\x8B\x95", + "\xF5\xAE" => "\xE8\x8D\x89", + "\xF5\xAF" => "\xE8\x95\x89", + "\xF5\xB0" => "\xE8\xB2\x82", + "\xF5\xB1" => "\xE8\xB6\x85", + "\xF5\xB2" => "\xE9\x85\xA2", + "\xF5\xB3" => "\xE9\x86\x8B", + "\xF5\xB4" => "\xE9\x86\xAE", + "\xF5\xB5" => "\xE4\xBF\x83", + "\xF5\xB6" => "\xE5\x9B\x91", + "\xF5\xB7" => "\xE7\x87\xAD", + "\xF5\xB8" => "\xE7\x9F\x97", + "\xF5\xB9" => "\xE8\x9C\x80", + "\xF5\xBA" => "\xE8\xA7\xB8", + "\xF5\xBB" => "\xE5\xAF\xB8", + "\xF5\xBC" => "\xE5\xBF\x96", + "\xF5\xBD" => "\xE6\x9D\x91", + "\xF5\xBE" => "\xE9\x82\xA8", + "\xF5\xBF" => "\xE5\x8F\xA2", + "\xF5\xC0" => "\xE5\xA1\x9A", + "\xF5\xC1" => "\xE5\xAF\xB5", + "\xF5\xC2" => "\xE6\x82\xA4", + "\xF5\xC3" => "\xE6\x86\x81", + "\xF5\xC4" => "\xE6\x91\xA0", + "\xF5\xC5" => "\xE7\xB8\xBD", + "\xF5\xC6" => "\xE8\x81\xB0", + "\xF5\xC7" => "\xE8\x94\xA5", + "\xF5\xC8" => "\xE9\x8A\x83", + "\xF5\xC9" => "\xE6\x92\xAE", + "\xF5\xCA" => "\xE5\x82\xAC", + "\xF5\xCB" => "\xE5\xB4\x94", + "\xF5\xCC" => "\xE6\x9C\x80", + "\xF5\xCD" => "\xE5\xA2\x9C", + "\xF5\xCE" => "\xE6\x8A\xBD", + "\xF5\xCF" => "\xE6\x8E\xA8", + "\xF5\xD0" => "\xE6\xA4\x8E", + "\xF5\xD1" => "\xE6\xA5\xB8", + "\xF5\xD2" => "\xE6\xA8\x9E", + "\xF5\xD3" => "\xE6\xB9\xAB", + "\xF5\xD4" => "\xE7\x9A\xBA", + "\xF5\xD5" => "\xE7\xA7\x8B", + "\xF5\xD6" => "\xE8\x8A\xBB", + "\xF5\xD7" => "\xE8\x90\xA9", + "\xF5\xD8" => "\xE8\xAB\x8F", + "\xF5\xD9" => "\xE8\xB6\xA8", + "\xF5\xDA" => "\xE8\xBF\xBD", + "\xF5\xDB" => "\xE9\x84\x92", + "\xF5\xDC" => "\xE9\x85\x8B", + "\xF5\xDD" => "\xE9\x86\x9C", + "\xF5\xDE" => "\xE9\x8C\x90", + "\xF5\xDF" => "\xE9\x8C\x98", + "\xF5\xE0" => "\xE9\x8E\x9A", + "\xF5\xE1" => "\xE9\x9B\x9B", + "\xF5\xE2" => "\xE9\xA8\xB6", + "\xF5\xE3" => "\xE9\xB0\x8D", + "\xF5\xE4" => "\xE4\xB8\x91", + "\xF5\xE5" => "\xE7\x95\x9C", + "\xF5\xE6" => "\xE7\xA5\x9D", + "\xF5\xE7" => "\xE7\xAB\xBA", + "\xF5\xE8" => "\xE7\xAD\x91", + "\xF5\xE9" => "\xE7\xAF\x89", + "\xF5\xEA" => "\xE7\xB8\xAE", + "\xF5\xEB" => "\xE8\x93\x84", + "\xF5\xEC" => "\xE8\xB9\x99", + "\xF5\xED" => "\xE8\xB9\xB4", + "\xF5\xEE" => "\xE8\xBB\xB8", + "\xF5\xEF" => "\xE9\x80\x90", + "\xF5\xF0" => "\xE6\x98\xA5", + "\xF5\xF1" => "\xE6\xA4\xBF", + "\xF5\xF2" => "\xE7\x91\x83", + "\xF5\xF3" => "\xE5\x87\xBA", + "\xF5\xF4" => "\xE6\x9C\xAE", + "\xF5\xF5" => "\xE9\xBB\x9C", + "\xF5\xF6" => "\xE5\x85\x85", + "\xF5\xF7" => "\xE5\xBF\xA0", + "\xF5\xF8" => "\xE6\xB2\x96", + "\xF5\xF9" => "\xE8\x9F\xB2", + "\xF5\xFA" => "\xE8\xA1\x9D", + "\xF5\xFB" => "\xE8\xA1\xB7", + "\xF5\xFC" => "\xE6\x82\xB4", + "\xF5\xFD" => "\xE8\x86\xB5", + "\xF5\xFE" => "\xE8\x90\x83", + "\xF6\xA1" => "\xE8\xB4\x85", + "\xF6\xA2" => "\xE5\x8F\x96", + "\xF6\xA3" => "\xE5\x90\xB9", + "\xF6\xA4" => "\xE5\x98\xB4", + "\xF6\xA5" => "\xE5\xA8\xB6", + "\xF6\xA6" => "\xE5\xB0\xB1", + "\xF6\xA7" => "\xE7\x82\x8A", + "\xF6\xA8" => "\xE7\xBF\xA0", + "\xF6\xA9" => "\xE8\x81\x9A", + "\xF6\xAA" => "\xE8\x84\x86", + "\xF6\xAB" => "\xE8\x87\xAD", + "\xF6\xAC" => "\xE8\xB6\xA3", + "\xF6\xAD" => "\xE9\x86\x89", + "\xF6\xAE" => "\xE9\xA9\x9F", + "\xF6\xAF" => "\xE9\xB7\xB2", + "\xF6\xB0" => "\xE5\x81\xB4", + "\xF6\xB1" => "\xE4\xBB\x84", + "\xF6\xB2" => "\xE5\x8E\xA0", + "\xF6\xB3" => "\xE6\x83\xBB", + "\xF6\xB4" => "\xE6\xB8\xAC", + "\xF6\xB5" => "\xE5\xB1\xA4", + "\xF6\xB6" => "\xE4\xBE\x88", + "\xF6\xB7" => "\xE5\x80\xA4", + "\xF6\xB8" => "\xE5\x97\xA4", + "\xF6\xB9" => "\xE5\xB3\x99", + "\xF6\xBA" => "\xE5\xB9\x9F", + "\xF6\xBB" => "\xE6\x81\xA5", + "\xF6\xBC" => "\xE6\xA2\x94", + "\xF6\xBD" => "\xE6\xB2\xBB", + "\xF6\xBE" => "\xE6\xB7\x84", + "\xF6\xBF" => "\xE7\x86\xBE", + "\xF6\xC0" => "\xE7\x97\x94", + "\xF6\xC1" => "\xE7\x97\xB4", + "\xF6\xC2" => "\xE7\x99\xA1", + "\xF6\xC3" => "\xE7\xA8\x9A", + "\xF6\xC4" => "\xE7\xA9\x89", + "\xF6\xC5" => "\xE7\xB7\x87", + "\xF6\xC6" => "\xE7\xB7\xBB", + "\xF6\xC7" => "\xE7\xBD\xAE", + "\xF6\xC8" => "\xE8\x87\xB4", + "\xF6\xC9" => "\xE8\x9A\xA9", + "\xF6\xCA" => "\xE8\xBC\x9C", + "\xF6\xCB" => "\xE9\x9B\x89", + "\xF6\xCC" => "\xE9\xA6\xB3", + "\xF6\xCD" => "\xE9\xBD\x92", + "\xF6\xCE" => "\xE5\x89\x87", + "\xF6\xCF" => "\xE5\x8B\x85", + "\xF6\xD0" => "\xE9\xA3\xAD", + "\xF6\xD1" => "\xE8\xA6\xAA", + "\xF6\xD2" => "\xE4\xB8\x83", + "\xF6\xD3" => "\xE6\x9F\x92", + "\xF6\xD4" => "\xE6\xBC\x86", + "\xF6\xD5" => "\xE4\xBE\xB5", + "\xF6\xD6" => "\xE5\xAF\xA2", + "\xF6\xD7" => "\xE6\x9E\x95", + "\xF6\xD8" => "\xE6\xB2\x88", + "\xF6\xD9" => "\xE6\xB5\xB8", + "\xF6\xDA" => "\xE7\x90\x9B", + "\xF6\xDB" => "\xE7\xA0\xA7", + "\xF6\xDC" => "\xE9\x87\x9D", + "\xF6\xDD" => "\xE9\x8D\xBC", + "\xF6\xDE" => "\xE8\x9F\x84", + "\xF6\xDF" => "\xE7\xA7\xA4", + "\xF6\xE0" => "\xE7\xA8\xB1", + "\xF6\xE1" => "\xE5\xBF\xAB", + "\xF6\xE2" => "\xE4\xBB\x96", + "\xF6\xE3" => "\xE5\x92\xA4", + "\xF6\xE4" => "\xE5\x94\xBE", + "\xF6\xE5" => "\xE5\xA2\xAE", + "\xF6\xE6" => "\xE5\xA6\xA5", + "\xF6\xE7" => "\xE6\x83\xB0", + "\xF6\xE8" => "\xE6\x89\x93", + "\xF6\xE9" => "\xE6\x8B\x96", + "\xF6\xEA" => "\xE6\x9C\xB6", + "\xF6\xEB" => "\xE6\xA5\x95", + "\xF6\xEC" => "\xE8\x88\xB5", + "\xF6\xED" => "\xE9\x99\x80", + "\xF6\xEE" => "\xE9\xA6\xB1", + "\xF6\xEF" => "\xE9\xA7\x9D", + "\xF6\xF0" => "\xE5\x80\xAC", + "\xF6\xF1" => "\xE5\x8D\x93", + "\xF6\xF2" => "\xE5\x95\x84", + "\xF6\xF3" => "\xE5\x9D\xBC", + "\xF6\xF4" => "\xEF\xA8\x81", + "\xF6\xF5" => "\xE6\x89\x98", + "\xF6\xF6" => "\xEF\xA8\x82", + "\xF6\xF7" => "\xE6\x93\xA2", + "\xF6\xF8" => "\xE6\x99\xAB", + "\xF6\xF9" => "\xE6\x9F\x9D", + "\xF6\xFA" => "\xE6\xBF\x81", + "\xF6\xFB" => "\xE6\xBF\xAF", + "\xF6\xFC" => "\xE7\x90\xA2", + "\xF6\xFD" => "\xE7\x90\xB8", + "\xF6\xFE" => "\xE8\xA8\x97", + "\xF7\xA1" => "\xE9\x90\xB8", + "\xF7\xA2" => "\xE5\x91\x91", + "\xF7\xA3" => "\xE5\x98\x86", + "\xF7\xA4" => "\xE5\x9D\xA6", + "\xF7\xA5" => "\xE5\xBD\x88", + "\xF7\xA6" => "\xE6\x86\x9A", + "\xF7\xA7" => "\xE6\xAD\x8E", + "\xF7\xA8" => "\xE7\x81\x98", + "\xF7\xA9" => "\xE7\x82\xAD", + "\xF7\xAA" => "\xE7\xB6\xBB", + "\xF7\xAB" => "\xE8\xAA\x95", + "\xF7\xAC" => "\xE5\xA5\xAA", + "\xF7\xAD" => "\xE8\x84\xAB", + "\xF7\xAE" => "\xE6\x8E\xA2", + "\xF7\xAF" => "\xE7\x9C\x88", + "\xF7\xB0" => "\xE8\x80\xBD", + "\xF7\xB1" => "\xE8\xB2\xAA", + "\xF7\xB2" => "\xE5\xA1\x94", + "\xF7\xB3" => "\xE6\x90\xAD", + "\xF7\xB4" => "\xE6\xA6\xBB", + "\xF7\xB5" => "\xE5\xAE\x95", + "\xF7\xB6" => "\xE5\xB8\x91", + "\xF7\xB7" => "\xE6\xB9\xAF", + "\xF7\xB8" => "\xEF\xA8\x83", + "\xF7\xB9" => "\xE8\x95\xA9", + "\xF7\xBA" => "\xE5\x85\x8C", + "\xF7\xBB" => "\xE5\x8F\xB0", + "\xF7\xBC" => "\xE5\xA4\xAA", + "\xF7\xBD" => "\xE6\x80\xA0", + "\xF7\xBE" => "\xE6\x85\x8B", + "\xF7\xBF" => "\xE6\xAE\x86", + "\xF7\xC0" => "\xE6\xB1\xB0", + "\xF7\xC1" => "\xE6\xB3\xB0", + "\xF7\xC2" => "\xE7\xAC\x9E", + "\xF7\xC3" => "\xE8\x83\x8E", + "\xF7\xC4" => "\xE8\x8B\x94", + "\xF7\xC5" => "\xE8\xB7\x86", + "\xF7\xC6" => "\xE9\x82\xB0", + "\xF7\xC7" => "\xE9\xA2\xB1", + "\xF7\xC8" => "\xEF\xA8\x84", + "\xF7\xC9" => "\xE6\x93\x87", + "\xF7\xCA" => "\xE6\xBE\xA4", + "\xF7\xCB" => "\xE6\x92\x91", + "\xF7\xCC" => "\xE6\x94\x84", + "\xF7\xCD" => "\xE5\x85\x8E", + "\xF7\xCE" => "\xE5\x90\x90", + "\xF7\xCF" => "\xE5\x9C\x9F", + "\xF7\xD0" => "\xE8\xA8\x8E", + "\xF7\xD1" => "\xE6\x85\x9F", + "\xF7\xD2" => "\xE6\xA1\xB6", + "\xF7\xD3" => "\xEF\xA8\x85", + "\xF7\xD4" => "\xE7\x97\x9B", + "\xF7\xD5" => "\xE7\xAD\x92", + "\xF7\xD6" => "\xE7\xB5\xB1", + "\xF7\xD7" => "\xE9\x80\x9A", + "\xF7\xD8" => "\xE5\xA0\x86", + "\xF7\xD9" => "\xE6\xA7\x8C", + "\xF7\xDA" => "\xE8\x85\xBF", + "\xF7\xDB" => "\xE8\xA4\xAA", + "\xF7\xDC" => "\xE9\x80\x80", + "\xF7\xDD" => "\xE9\xA0\xB9", + "\xF7\xDE" => "\xE5\x81\xB8", + "\xF7\xDF" => "\xE5\xA5\x97", + "\xF7\xE0" => "\xE5\xA6\xAC", + "\xF7\xE1" => "\xE6\x8A\x95", + "\xF7\xE2" => "\xE9\x80\x8F", + "\xF7\xE3" => "\xE9\xAC\xAA", + "\xF7\xE4" => "\xE6\x85\x9D", + "\xF7\xE5" => "\xE7\x89\xB9", + "\xF7\xE6" => "\xE9\x97\x96", + "\xF7\xE7" => "\xE5\x9D\xA1", + "\xF7\xE8" => "\xE5\xA9\x86", + "\xF7\xE9" => "\xE5\xB7\xB4", + "\xF7\xEA" => "\xE6\x8A\x8A", + "\xF7\xEB" => "\xE6\x92\xAD", + "\xF7\xEC" => "\xE6\x93\xBA", + "\xF7\xED" => "\xE6\x9D\xB7", + "\xF7\xEE" => "\xE6\xB3\xA2", + "\xF7\xEF" => "\xE6\xB4\xBE", + "\xF7\xF0" => "\xE7\x88\xAC", + "\xF7\xF1" => "\xE7\x90\xB6", + "\xF7\xF2" => "\xE7\xA0\xB4", + "\xF7\xF3" => "\xE7\xBD\xB7", + "\xF7\xF4" => "\xE8\x8A\xAD", + "\xF7\xF5" => "\xE8\xB7\x9B", + "\xF7\xF6" => "\xE9\xA0\x97", + "\xF7\xF7" => "\xE5\x88\xA4", + "\xF7\xF8" => "\xE5\x9D\x82", + "\xF7\xF9" => "\xE6\x9D\xBF", + "\xF7\xFA" => "\xE7\x89\x88", + "\xF7\xFB" => "\xE7\x93\xA3", + "\xF7\xFC" => "\xE8\xB2\xA9", + "\xF7\xFD" => "\xE8\xBE\xA6", + "\xF7\xFE" => "\xE9\x88\x91", + "\xF8\xA1" => "\xE9\x98\xAA", + "\xF8\xA2" => "\xE5\x85\xAB", + "\xF8\xA3" => "\xE5\x8F\xAD", + "\xF8\xA4" => "\xE6\x8D\x8C", + "\xF8\xA5" => "\xE4\xBD\xA9", + "\xF8\xA6" => "\xE5\x94\x84", + "\xF8\xA7" => "\xE6\x82\x96", + "\xF8\xA8" => "\xE6\x95\x97", + "\xF8\xA9" => "\xE6\xB2\x9B", + "\xF8\xAA" => "\xE6\xB5\xBF", + "\xF8\xAB" => "\xE7\x89\x8C", + "\xF8\xAC" => "\xE7\x8B\xBD", + "\xF8\xAD" => "\xE7\xA8\x97", + "\xF8\xAE" => "\xE8\xA6\x87", + "\xF8\xAF" => "\xE8\xB2\x9D", + "\xF8\xB0" => "\xE5\xBD\xAD", + "\xF8\xB1" => "\xE6\xBE\x8E", + "\xF8\xB2" => "\xE7\x83\xB9", + "\xF8\xB3" => "\xE8\x86\xA8", + "\xF8\xB4" => "\xE6\x84\x8E", + "\xF8\xB5" => "\xE4\xBE\xBF", + "\xF8\xB6" => "\xE5\x81\x8F", + "\xF8\xB7" => "\xE6\x89\x81", + "\xF8\xB8" => "\xE7\x89\x87", + "\xF8\xB9" => "\xE7\xAF\x87", + "\xF8\xBA" => "\xE7\xB7\xA8", + "\xF8\xBB" => "\xE7\xBF\xA9", + "\xF8\xBC" => "\xE9\x81\x8D", + "\xF8\xBD" => "\xE9\x9E\xAD", + "\xF8\xBE" => "\xE9\xA8\x99", + "\xF8\xBF" => "\xE8\xB2\xB6", + "\xF8\xC0" => "\xE5\x9D\xAA", + "\xF8\xC1" => "\xE5\xB9\xB3", + "\xF8\xC2" => "\xE6\x9E\xB0", + "\xF8\xC3" => "\xE8\x90\x8D", + "\xF8\xC4" => "\xE8\xA9\x95", + "\xF8\xC5" => "\xE5\x90\xA0", + "\xF8\xC6" => "\xE5\xAC\x96", + "\xF8\xC7" => "\xE5\xB9\xA3", + "\xF8\xC8" => "\xE5\xBB\xA2", + "\xF8\xC9" => "\xE5\xBC\x8A", + "\xF8\xCA" => "\xE6\x96\x83", + "\xF8\xCB" => "\xE8\x82\xBA", + "\xF8\xCC" => "\xE8\x94\xBD", + "\xF8\xCD" => "\xE9\x96\x89", + "\xF8\xCE" => "\xE9\x99\x9B", + "\xF8\xCF" => "\xE4\xBD\x88", + "\xF8\xD0" => "\xE5\x8C\x85", + "\xF8\xD1" => "\xE5\x8C\x8D", + "\xF8\xD2" => "\xE5\x8C\x8F", + "\xF8\xD3" => "\xE5\x92\x86", + "\xF8\xD4" => "\xE5\x93\xBA", + "\xF8\xD5" => "\xE5\x9C\x83", + "\xF8\xD6" => "\xE5\xB8\x83", + "\xF8\xD7" => "\xE6\x80\x96", + "\xF8\xD8" => "\xE6\x8A\x9B", + "\xF8\xD9" => "\xE6\x8A\xB1", + "\xF8\xDA" => "\xE6\x8D\x95", + "\xF8\xDB" => "\xEF\xA8\x86", + "\xF8\xDC" => "\xE6\xB3\xA1", + "\xF8\xDD" => "\xE6\xB5\xA6", + "\xF8\xDE" => "\xE7\x96\xB1", + "\xF8\xDF" => "\xE7\xA0\xB2", + "\xF8\xE0" => "\xE8\x83\x9E", + "\xF8\xE1" => "\xE8\x84\xAF", + "\xF8\xE2" => "\xE8\x8B\x9E", + "\xF8\xE3" => "\xE8\x91\xA1", + "\xF8\xE4" => "\xE8\x92\xB2", + "\xF8\xE5" => "\xE8\xA2\x8D", + "\xF8\xE6" => "\xE8\xA4\x92", + "\xF8\xE7" => "\xE9\x80\x8B", + "\xF8\xE8" => "\xE9\x8B\xAA", + "\xF8\xE9" => "\xE9\xA3\xBD", + "\xF8\xEA" => "\xE9\xAE\x91", + "\xF8\xEB" => "\xE5\xB9\x85", + "\xF8\xEC" => "\xE6\x9A\xB4", + "\xF8\xED" => "\xE6\x9B\x9D", + "\xF8\xEE" => "\xE7\x80\x91", + "\xF8\xEF" => "\xE7\x88\x86", + "\xF8\xF0" => "\xEF\xA8\x87", + "\xF8\xF1" => "\xE4\xBF\xB5", + "\xF8\xF2" => "\xE5\x89\xBD", + "\xF8\xF3" => "\xE5\xBD\xAA", + "\xF8\xF4" => "\xE6\x85\x93", + "\xF8\xF5" => "\xE6\x9D\x93", + "\xF8\xF6" => "\xE6\xA8\x99", + "\xF8\xF7" => "\xE6\xBC\x82", + "\xF8\xF8" => "\xE7\x93\xA2", + "\xF8\xF9" => "\xE7\xA5\xA8", + "\xF8\xFA" => "\xE8\xA1\xA8", + "\xF8\xFB" => "\xE8\xB1\xB9", + "\xF8\xFC" => "\xE9\xA3\x87", + "\xF8\xFD" => "\xE9\xA3\x84", + "\xF8\xFE" => "\xE9\xA9\x83", + "\xF9\xA1" => "\xE5\x93\x81", + "\xF9\xA2" => "\xE7\xA8\x9F", + "\xF9\xA3" => "\xE6\xA5\x93", + "\xF9\xA4" => "\xE8\xAB\xB7", + "\xF9\xA5" => "\xE8\xB1\x8A", + "\xF9\xA6" => "\xE9\xA2\xA8", + "\xF9\xA7" => "\xE9\xA6\xAE", + "\xF9\xA8" => "\xE5\xBD\xBC", + "\xF9\xA9" => "\xE6\x8A\xAB", + "\xF9\xAA" => "\xE7\x96\xB2", + "\xF9\xAB" => "\xE7\x9A\xAE", + "\xF9\xAC" => "\xE8\xA2\xAB", + "\xF9\xAD" => "\xE9\x81\xBF", + "\xF9\xAE" => "\xE9\x99\x82", + "\xF9\xAF" => "\xE5\x8C\xB9", + "\xF9\xB0" => "\xE5\xBC\xBC", + "\xF9\xB1" => "\xE5\xBF\x85", + "\xF9\xB2" => "\xE6\xB3\x8C", + "\xF9\xB3" => "\xE7\x8F\x8C", + "\xF9\xB4" => "\xE7\x95\xA2", + "\xF9\xB5" => "\xE7\x96\x8B", + "\xF9\xB6" => "\xE7\xAD\x86", + "\xF9\xB7" => "\xE8\x8B\xBE", + "\xF9\xB8" => "\xE9\xA6\x9D", + "\xF9\xB9" => "\xE4\xB9\x8F", + "\xF9\xBA" => "\xE9\x80\xBC", + "\xF9\xBB" => "\xE4\xB8\x8B", + "\xF9\xBC" => "\xE4\xBD\x95", + "\xF9\xBD" => "\xE5\x8E\xA6", + "\xF9\xBE" => "\xE5\xA4\x8F", + "\xF9\xBF" => "\xE5\xBB\x88", + "\xF9\xC0" => "\xE6\x98\xB0", + "\xF9\xC1" => "\xE6\xB2\xB3", + "\xF9\xC2" => "\xE7\x91\x95", + "\xF9\xC3" => "\xE8\x8D\xB7", + "\xF9\xC4" => "\xE8\x9D\xA6", + "\xF9\xC5" => "\xE8\xB3\x80", + "\xF9\xC6" => "\xE9\x81\x90", + "\xF9\xC7" => "\xE9\x9C\x9E", + "\xF9\xC8" => "\xE9\xB0\x95", + "\xF9\xC9" => "\xE5\xA3\x91", + "\xF9\xCA" => "\xE5\xAD\xB8", + "\xF9\xCB" => "\xE8\x99\x90", + "\xF9\xCC" => "\xE8\xAC\x94", + "\xF9\xCD" => "\xE9\xB6\xB4", + "\xF9\xCE" => "\xE5\xAF\x92", + "\xF9\xCF" => "\xE6\x81\xA8", + "\xF9\xD0" => "\xE6\x82\x8D", + "\xF9\xD1" => "\xE6\x97\xB1", + "\xF9\xD2" => "\xE6\xB1\x97", + "\xF9\xD3" => "\xE6\xBC\xA2", + "\xF9\xD4" => "\xE6\xBE\xA3", + "\xF9\xD5" => "\xE7\x80\x9A", + "\xF9\xD6" => "\xE7\xBD\x95", + "\xF9\xD7" => "\xE7\xBF\xB0", + "\xF9\xD8" => "\xE9\x96\x91", + "\xF9\xD9" => "\xE9\x96\x92", + "\xF9\xDA" => "\xE9\x99\x90", + "\xF9\xDB" => "\xE9\x9F\x93", + "\xF9\xDC" => "\xE5\x89\xB2", + "\xF9\xDD" => "\xE8\xBD\x84", + "\xF9\xDE" => "\xE5\x87\xBD", + "\xF9\xDF" => "\xE5\x90\xAB", + "\xF9\xE0" => "\xE5\x92\xB8", + "\xF9\xE1" => "\xE5\x95\xA3", + "\xF9\xE2" => "\xE5\x96\x8A", + "\xF9\xE3" => "\xE6\xAA\xBB", + "\xF9\xE4" => "\xE6\xB6\xB5", + "\xF9\xE5" => "\xE7\xB7\x98", + "\xF9\xE6" => "\xE8\x89\xA6", + "\xF9\xE7" => "\xE9\x8A\x9C", + "\xF9\xE8" => "\xE9\x99\xB7", + "\xF9\xE9" => "\xE9\xB9\xB9", + "\xF9\xEA" => "\xE5\x90\x88", + "\xF9\xEB" => "\xE5\x93\x88", + "\xF9\xEC" => "\xE7\x9B\x92", + "\xF9\xED" => "\xE8\x9B\xA4", + "\xF9\xEE" => "\xE9\x96\xA4", + "\xF9\xEF" => "\xE9\x97\x94", + "\xF9\xF0" => "\xE9\x99\x9C", + "\xF9\xF1" => "\xE4\xBA\xA2", + "\xF9\xF2" => "\xE4\xBC\x89", + "\xF9\xF3" => "\xE5\xA7\xAE", + "\xF9\xF4" => "\xE5\xAB\xA6", + "\xF9\xF5" => "\xE5\xB7\xB7", + "\xF9\xF6" => "\xE6\x81\x92", + "\xF9\xF7" => "\xE6\x8A\x97", + "\xF9\xF8" => "\xE6\x9D\xAD", + "\xF9\xF9" => "\xE6\xA1\x81", + "\xF9\xFA" => "\xE6\xB2\x86", + "\xF9\xFB" => "\xE6\xB8\xAF", + "\xF9\xFC" => "\xE7\xBC\xB8", + "\xF9\xFD" => "\xE8\x82\x9B", + "\xF9\xFE" => "\xE8\x88\xAA", + "\xFA\xA1" => "\xEF\xA8\x88", + "\xFA\xA2" => "\xEF\xA8\x89", + "\xFA\xA3" => "\xE9\xA0\x85", + "\xFA\xA4" => "\xE4\xBA\xA5", + "\xFA\xA5" => "\xE5\x81\x95", + "\xFA\xA6" => "\xE5\x92\xB3", + "\xFA\xA7" => "\xE5\x9E\x93", + "\xFA\xA8" => "\xE5\xA5\x9A", + "\xFA\xA9" => "\xE5\xAD\xA9", + "\xFA\xAA" => "\xE5\xAE\xB3", + "\xFA\xAB" => "\xE6\x87\x88", + "\xFA\xAC" => "\xE6\xA5\xB7", + "\xFA\xAD" => "\xE6\xB5\xB7", + "\xFA\xAE" => "\xE7\x80\xA3", + "\xFA\xAF" => "\xE8\x9F\xB9", + "\xFA\xB0" => "\xE8\xA7\xA3", + "\xFA\xB1" => "\xE8\xA9\xB2", + "\xFA\xB2" => "\xE8\xAB\xA7", + "\xFA\xB3" => "\xE9\x82\x82", + "\xFA\xB4" => "\xE9\xA7\xAD", + "\xFA\xB5" => "\xE9\xAA\xB8", + "\xFA\xB6" => "\xE5\x8A\xBE", + "\xFA\xB7" => "\xE6\xA0\xB8", + "\xFA\xB8" => "\xE5\x80\x96", + "\xFA\xB9" => "\xE5\xB9\xB8", + "\xFA\xBA" => "\xE6\x9D\x8F", + "\xFA\xBB" => "\xE8\x8D\x87", + "\xFA\xBC" => "\xE8\xA1\x8C", + "\xFA\xBD" => "\xE4\xBA\xAB", + "\xFA\xBE" => "\xE5\x90\x91", + "\xFA\xBF" => "\xE5\x9A\xAE", + "\xFA\xC0" => "\xE7\x8F\xA6", + "\xFA\xC1" => "\xE9\x84\x95", + "\xFA\xC2" => "\xE9\x9F\xBF", + "\xFA\xC3" => "\xE9\xA4\x89", + "\xFA\xC4" => "\xE9\xA5\x97", + "\xFA\xC5" => "\xE9\xA6\x99", + "\xFA\xC6" => "\xE5\x99\x93", + "\xFA\xC7" => "\xE5\xA2\x9F", + "\xFA\xC8" => "\xE8\x99\x9B", + "\xFA\xC9" => "\xE8\xA8\xB1", + "\xFA\xCA" => "\xE6\x86\xB2", + "\xFA\xCB" => "\xE6\xAB\xB6", + "\xFA\xCC" => "\xE7\x8D\xBB", + "\xFA\xCD" => "\xE8\xBB\x92", + "\xFA\xCE" => "\xE6\xAD\x87", + "\xFA\xCF" => "\xE9\x9A\xAA", + "\xFA\xD0" => "\xE9\xA9\x97", + "\xFA\xD1" => "\xE5\xA5\x95", + "\xFA\xD2" => "\xE7\x88\x80", + "\xFA\xD3" => "\xE8\xB5\xAB", + "\xFA\xD4" => "\xE9\x9D\xA9", + "\xFA\xD5" => "\xE4\xBF\x94", + "\xFA\xD6" => "\xE5\xB3\xB4", + "\xFA\xD7" => "\xE5\xBC\xA6", + "\xFA\xD8" => "\xE6\x87\xB8", + "\xFA\xD9" => "\xE6\x99\x9B", + "\xFA\xDA" => "\xE6\xB3\xAB", + "\xFA\xDB" => "\xE7\x82\xAB", + "\xFA\xDC" => "\xE7\x8E\x84", + "\xFA\xDD" => "\xE7\x8E\xB9", + "\xFA\xDE" => "\xE7\x8F\xBE", + "\xFA\xDF" => "\xE7\x9C\xA9", + "\xFA\xE0" => "\xE7\x9D\x8D", + "\xFA\xE1" => "\xE7\xB5\x83", + "\xFA\xE2" => "\xE7\xB5\xA2", + "\xFA\xE3" => "\xE7\xB8\xA3", + "\xFA\xE4" => "\xE8\x88\xB7", + "\xFA\xE5" => "\xE8\xA1\x92", + "\xFA\xE6" => "\xEF\xA8\x8A", + "\xFA\xE7" => "\xE8\xB3\xA2", + "\xFA\xE8" => "\xE9\x89\x89", + "\xFA\xE9" => "\xE9\xA1\xAF", + "\xFA\xEA" => "\xE5\xAD\x91", + "\xFA\xEB" => "\xE7\xA9\xB4", + "\xFA\xEC" => "\xE8\xA1\x80", + "\xFA\xED" => "\xE9\xA0\x81", + "\xFA\xEE" => "\xE5\xAB\x8C", + "\xFA\xEF" => "\xE4\xBF\xA0", + "\xFA\xF0" => "\xE5\x8D\x94", + "\xFA\xF1" => "\xE5\xA4\xBE", + "\xFA\xF2" => "\xE5\xB3\xBD", + "\xFA\xF3" => "\xE6\x8C\xBE", + "\xFA\xF4" => "\xE6\xB5\xB9", + "\xFA\xF5" => "\xE7\x8B\xB9", + "\xFA\xF6" => "\xE8\x84\x85", + "\xFA\xF7" => "\xE8\x84\x87", + "\xFA\xF8" => "\xE8\x8E\xA2", + "\xFA\xF9" => "\xE9\x8B\x8F", + "\xFA\xFA" => "\xE9\xA0\xB0", + "\xFA\xFB" => "\xE4\xBA\xA8", + "\xFA\xFC" => "\xE5\x85\x84", + "\xFA\xFD" => "\xE5\x88\x91", + "\xFA\xFE" => "\xE5\x9E\x8B", + "\xFB\xA1" => "\xE5\xBD\xA2", + "\xFB\xA2" => "\xE6\xB3\x82", + "\xFB\xA3" => "\xE6\xBB\x8E", + "\xFB\xA4" => "\xE7\x80\x85", + "\xFB\xA5" => "\xE7\x81\x90", + "\xFB\xA6" => "\xE7\x82\xAF", + "\xFB\xA7" => "\xE7\x86\x92", + "\xFB\xA8" => "\xE7\x8F\xA9", + "\xFB\xA9" => "\xE7\x91\xA9", + "\xFB\xAA" => "\xE8\x8D\x8A", + "\xFB\xAB" => "\xE8\x9E\xA2", + "\xFB\xAC" => "\xE8\xA1\xA1", + "\xFB\xAD" => "\xE9\x80\x88", + "\xFB\xAE" => "\xE9\x82\xA2", + "\xFB\xAF" => "\xE9\x8E\xA3", + "\xFB\xB0" => "\xE9\xA6\xA8", + "\xFB\xB1" => "\xE5\x85\xAE", + "\xFB\xB2" => "\xE5\xBD\x97", + "\xFB\xB3" => "\xE6\x83\xA0", + "\xFB\xB4" => "\xE6\x85\xA7", + "\xFB\xB5" => "\xE6\x9A\xB3", + "\xFB\xB6" => "\xE8\x95\x99", + "\xFB\xB7" => "\xE8\xB9\x8A", + "\xFB\xB8" => "\xE9\x86\xAF", + "\xFB\xB9" => "\xE9\x9E\x8B", + "\xFB\xBA" => "\xE4\xB9\x8E", + "\xFB\xBB" => "\xE4\xBA\x92", + "\xFB\xBC" => "\xE5\x91\xBC", + "\xFB\xBD" => "\xE5\xA3\x95", + "\xFB\xBE" => "\xE5\xA3\xBA", + "\xFB\xBF" => "\xE5\xA5\xBD", + "\xFB\xC0" => "\xE5\xB2\xB5", + "\xFB\xC1" => "\xE5\xBC\xA7", + "\xFB\xC2" => "\xE6\x88\xB6", + "\xFB\xC3" => "\xE6\x89\x88", + "\xFB\xC4" => "\xE6\x98\x8A", + "\xFB\xC5" => "\xE6\x99\xA7", + "\xFB\xC6" => "\xE6\xAF\xAB", + "\xFB\xC7" => "\xE6\xB5\xA9", + "\xFB\xC8" => "\xE6\xB7\x8F", + "\xFB\xC9" => "\xE6\xB9\x96", + "\xFB\xCA" => "\xE6\xBB\xB8", + "\xFB\xCB" => "\xE6\xBE\x94", + "\xFB\xCC" => "\xE6\xBF\xA0", + "\xFB\xCD" => "\xE6\xBF\xA9", + "\xFB\xCE" => "\xE7\x81\x9D", + "\xFB\xCF" => "\xE7\x8B\x90", + "\xFB\xD0" => "\xE7\x90\xA5", + "\xFB\xD1" => "\xE7\x91\x9A", + "\xFB\xD2" => "\xE7\x93\xA0", + "\xFB\xD3" => "\xE7\x9A\x93", + "\xFB\xD4" => "\xE7\xA5\x9C", + "\xFB\xD5" => "\xE7\xB3\x8A", + "\xFB\xD6" => "\xE7\xB8\x9E", + "\xFB\xD7" => "\xE8\x83\xA1", + "\xFB\xD8" => "\xE8\x8A\xA6", + "\xFB\xD9" => "\xE8\x91\xAB", + "\xFB\xDA" => "\xE8\x92\xBF", + "\xFB\xDB" => "\xE8\x99\x8E", + "\xFB\xDC" => "\xE8\x99\x9F", + "\xFB\xDD" => "\xE8\x9D\xB4", + "\xFB\xDE" => "\xE8\xAD\xB7", + "\xFB\xDF" => "\xE8\xB1\xAA", + "\xFB\xE0" => "\xE9\x8E\xAC", + "\xFB\xE1" => "\xE9\xA0\x80", + "\xFB\xE2" => "\xE9\xA1\xA5", + "\xFB\xE3" => "\xE6\x83\x91", + "\xFB\xE4" => "\xE6\x88\x96", + "\xFB\xE5" => "\xE9\x85\xB7", + "\xFB\xE6" => "\xE5\xA9\x9A", + "\xFB\xE7" => "\xE6\x98\x8F", + "\xFB\xE8" => "\xE6\xB7\xB7", + "\xFB\xE9" => "\xE6\xB8\xBE", + "\xFB\xEA" => "\xE7\x90\xBF", + "\xFB\xEB" => "\xE9\xAD\x82", + "\xFB\xEC" => "\xE5\xBF\xBD", + "\xFB\xED" => "\xE6\x83\x9A", + "\xFB\xEE" => "\xE7\xAC\x8F", + "\xFB\xEF" => "\xE5\x93\x84", + "\xFB\xF0" => "\xE5\xBC\x98", + "\xFB\xF1" => "\xE6\xB1\x9E", + "\xFB\xF2" => "\xE6\xB3\x93", + "\xFB\xF3" => "\xE6\xB4\xAA", + "\xFB\xF4" => "\xE7\x83\x98", + "\xFB\xF5" => "\xE7\xB4\x85", + "\xFB\xF6" => "\xE8\x99\xB9", + "\xFB\xF7" => "\xE8\xA8\x8C", + "\xFB\xF8" => "\xE9\xB4\xBB", + "\xFB\xF9" => "\xE5\x8C\x96", + "\xFB\xFA" => "\xE5\x92\x8C", + "\xFB\xFB" => "\xE5\xAC\x85", + "\xFB\xFC" => "\xE6\xA8\xBA", + "\xFB\xFD" => "\xE7\x81\xAB", + "\xFB\xFE" => "\xE7\x95\xB5", + "\xFC\xA1" => "\xE7\xA6\x8D", + "\xFC\xA2" => "\xE7\xA6\xBE", + "\xFC\xA3" => "\xE8\x8A\xB1", + "\xFC\xA4" => "\xE8\x8F\xAF", + "\xFC\xA5" => "\xE8\xA9\xB1", + "\xFC\xA6" => "\xE8\xAD\x81", + "\xFC\xA7" => "\xE8\xB2\xA8", + "\xFC\xA8" => "\xE9\x9D\xB4", + "\xFC\xA9" => "\xEF\xA8\x8B", + "\xFC\xAA" => "\xE6\x93\xB4", + "\xFC\xAB" => "\xE6\x94\xAB", + "\xFC\xAC" => "\xE7\xA2\xBA", + "\xFC\xAD" => "\xE7\xA2\xBB", + "\xFC\xAE" => "\xE7\xA9\xAB", + "\xFC\xAF" => "\xE4\xB8\xB8", + "\xFC\xB0" => "\xE5\x96\x9A", + "\xFC\xB1" => "\xE5\xA5\x90", + "\xFC\xB2" => "\xE5\xAE\xA6", + "\xFC\xB3" => "\xE5\xB9\xBB", + "\xFC\xB4" => "\xE6\x82\xA3", + "\xFC\xB5" => "\xE6\x8F\x9B", + "\xFC\xB6" => "\xE6\xAD\xA1", + "\xFC\xB7" => "\xE6\x99\xA5", + "\xFC\xB8" => "\xE6\xA1\x93", + "\xFC\xB9" => "\xE6\xB8\x99", + "\xFC\xBA" => "\xE7\x85\xA5", + "\xFC\xBB" => "\xE7\x92\xB0", + "\xFC\xBC" => "\xE7\xB4\x88", + "\xFC\xBD" => "\xE9\x82\x84", + "\xFC\xBE" => "\xE9\xA9\xA9", + "\xFC\xBF" => "\xE9\xB0\xA5", + "\xFC\xC0" => "\xE6\xB4\xBB", + "\xFC\xC1" => "\xE6\xBB\x91", + "\xFC\xC2" => "\xE7\x8C\xBE", + "\xFC\xC3" => "\xE8\xB1\x81", + "\xFC\xC4" => "\xE9\x97\x8A", + "\xFC\xC5" => "\xE5\x87\xB0", + "\xFC\xC6" => "\xE5\xB9\x8C", + "\xFC\xC7" => "\xE5\xBE\xA8", + "\xFC\xC8" => "\xE6\x81\x8D", + "\xFC\xC9" => "\xE6\x83\xB6", + "\xFC\xCA" => "\xE6\x84\xB0", + "\xFC\xCB" => "\xE6\x85\x8C", + "\xFC\xCC" => "\xE6\x99\x83", + "\xFC\xCD" => "\xE6\x99\x84", + "\xFC\xCE" => "\xE6\xA6\xA5", + "\xFC\xCF" => "\xE6\xB3\x81", + "\xFC\xD0" => "\xE6\xB9\x9F", + "\xFC\xD1" => "\xE6\xBB\x89", + "\xFC\xD2" => "\xE6\xBD\xA2", + "\xFC\xD3" => "\xE7\x85\x8C", + "\xFC\xD4" => "\xE7\x92\x9C", + "\xFC\xD5" => "\xE7\x9A\x87", + "\xFC\xD6" => "\xE7\xAF\x81", + "\xFC\xD7" => "\xE7\xB0\xA7", + "\xFC\xD8" => "\xE8\x8D\x92", + "\xFC\xD9" => "\xE8\x9D\x97", + "\xFC\xDA" => "\xE9\x81\x91", + "\xFC\xDB" => "\xE9\x9A\x8D", + "\xFC\xDC" => "\xE9\xBB\x83", + "\xFC\xDD" => "\xE5\x8C\xAF", + "\xFC\xDE" => "\xE5\x9B\x9E", + "\xFC\xDF" => "\xE5\xBB\xBB", + "\xFC\xE0" => "\xE5\xBE\x8A", + "\xFC\xE1" => "\xE6\x81\xA2", + "\xFC\xE2" => "\xE6\x82\x94", + "\xFC\xE3" => "\xE6\x87\xB7", + "\xFC\xE4" => "\xE6\x99\xA6", + "\xFC\xE5" => "\xE6\x9C\x83", + "\xFC\xE6" => "\xE6\xAA\x9C", + "\xFC\xE7" => "\xE6\xB7\xAE", + "\xFC\xE8" => "\xE6\xBE\xAE", + "\xFC\xE9" => "\xE7\x81\xB0", + "\xFC\xEA" => "\xE7\x8D\xAA", + "\xFC\xEB" => "\xE7\xB9\xAA", + "\xFC\xEC" => "\xE8\x86\xBE", + "\xFC\xED" => "\xE8\x8C\xB4", + "\xFC\xEE" => "\xE8\x9B\x94", + "\xFC\xEF" => "\xE8\xAA\xA8", + "\xFC\xF0" => "\xE8\xB3\x84", + "\xFC\xF1" => "\xE5\x8A\x83", + "\xFC\xF2" => "\xE7\x8D\xB2", + "\xFC\xF3" => "\xE5\xAE\x96", + "\xFC\xF4" => "\xE6\xA9\xAB", + "\xFC\xF5" => "\xE9\x90\x84", + "\xFC\xF6" => "\xE5\x93\xAE", + "\xFC\xF7" => "\xE5\x9A\x86", + "\xFC\xF8" => "\xE5\xAD\x9D", + "\xFC\xF9" => "\xE6\x95\x88", + "\xFC\xFA" => "\xE6\x96\x85", + "\xFC\xFB" => "\xE6\x9B\x89", + "\xFC\xFC" => "\xE6\xA2\x9F", + "\xFC\xFD" => "\xE6\xB6\x8D", + "\xFC\xFE" => "\xE6\xB7\x86", + "\xFD\xA1" => "\xE7\x88\xBB", + "\xFD\xA2" => "\xE8\x82\xB4", + "\xFD\xA3" => "\xE9\x85\xB5", + "\xFD\xA4" => "\xE9\xA9\x8D", + "\xFD\xA5" => "\xE4\xBE\xAF", + "\xFD\xA6" => "\xE5\x80\x99", + "\xFD\xA7" => "\xE5\x8E\x9A", + "\xFD\xA8" => "\xE5\x90\x8E", + "\xFD\xA9" => "\xE5\x90\xBC", + "\xFD\xAA" => "\xE5\x96\x89", + "\xFD\xAB" => "\xE5\x97\x85", + "\xFD\xAC" => "\xE5\xB8\xBF", + "\xFD\xAD" => "\xE5\xBE\x8C", + "\xFD\xAE" => "\xE6\x9C\xBD", + "\xFD\xAF" => "\xE7\x85\xA6", + "\xFD\xB0" => "\xE7\x8F\x9D", + "\xFD\xB1" => "\xE9\x80\x85", + "\xFD\xB2" => "\xE5\x8B\x9B", + "\xFD\xB3" => "\xE5\x8B\xB3", + "\xFD\xB4" => "\xE5\xA1\xA4", + "\xFD\xB5" => "\xE5\xA3\x8E", + "\xFD\xB6" => "\xE7\x84\x84", + "\xFD\xB7" => "\xE7\x86\x8F", + "\xFD\xB8" => "\xE7\x87\xBB", + "\xFD\xB9" => "\xE8\x96\xB0", + "\xFD\xBA" => "\xE8\xA8\x93", + "\xFD\xBB" => "\xE6\x9A\x88", + "\xFD\xBC" => "\xE8\x96\xA8", + "\xFD\xBD" => "\xE5\x96\xA7", + "\xFD\xBE" => "\xE6\x9A\x84", + "\xFD\xBF" => "\xE7\x85\x8A", + "\xFD\xC0" => "\xE8\x90\xB1", + "\xFD\xC1" => "\xE5\x8D\x89", + "\xFD\xC2" => "\xE5\x96\x99", + "\xFD\xC3" => "\xE6\xAF\x81", + "\xFD\xC4" => "\xE5\xBD\x99", + "\xFD\xC5" => "\xE5\xBE\xBD", + "\xFD\xC6" => "\xE6\x8F\xAE", + "\xFD\xC7" => "\xE6\x9A\x89", + "\xFD\xC8" => "\xE7\x85\x87", + "\xFD\xC9" => "\xE8\xAB\xB1", + "\xFD\xCA" => "\xE8\xBC\x9D", + "\xFD\xCB" => "\xE9\xBA\xBE", + "\xFD\xCC" => "\xE4\xBC\x91", + "\xFD\xCD" => "\xE6\x90\xBA", + "\xFD\xCE" => "\xE7\x83\x8B", + "\xFD\xCF" => "\xE7\x95\xA6", + "\xFD\xD0" => "\xE8\x99\xA7", + "\xFD\xD1" => "\xE6\x81\xA4", + "\xFD\xD2" => "\xE8\xAD\x8E", + "\xFD\xD3" => "\xE9\xB7\xB8", + "\xFD\xD4" => "\xE5\x85\x87", + "\xFD\xD5" => "\xE5\x87\xB6", + "\xFD\xD6" => "\xE5\x8C\x88", + "\xFD\xD7" => "\xE6\xB4\xB6", + "\xFD\xD8" => "\xE8\x83\xB8", + "\xFD\xD9" => "\xE9\xBB\x91", + "\xFD\xDA" => "\xE6\x98\x95", + "\xFD\xDB" => "\xE6\xAC\xA3", + "\xFD\xDC" => "\xE7\x82\x98", + "\xFD\xDD" => "\xE7\x97\x95", + "\xFD\xDE" => "\xE5\x90\x83", + "\xFD\xDF" => "\xE5\xB1\xB9", + "\xFD\xE0" => "\xE7\xB4\x87", + "\xFD\xE1" => "\xE8\xA8\x96", + "\xFD\xE2" => "\xE6\xAC\xA0", + "\xFD\xE3" => "\xE6\xAC\xBD", + "\xFD\xE4" => "\xE6\xAD\x86", + "\xFD\xE5" => "\xE5\x90\xB8", + "\xFD\xE6" => "\xE6\x81\xB0", + "\xFD\xE7" => "\xE6\xB4\xBD", + "\xFD\xE8" => "\xE7\xBF\x95", + "\xFD\xE9" => "\xE8\x88\x88", + "\xFD\xEA" => "\xE5\x83\x96", + "\xFD\xEB" => "\xE5\x87\x9E", + "\xFD\xEC" => "\xE5\x96\x9C", + "\xFD\xED" => "\xE5\x99\xAB", + "\xFD\xEE" => "\xE5\x9B\x8D", + "\xFD\xEF" => "\xE5\xA7\xAC", + "\xFD\xF0" => "\xE5\xAC\x89", + "\xFD\xF1" => "\xE5\xB8\x8C", + "\xFD\xF2" => "\xE6\x86\x99", + "\xFD\xF3" => "\xE6\x86\x98", + "\xFD\xF4" => "\xE6\x88\xB1", + "\xFD\xF5" => "\xE6\x99\x9E", + "\xFD\xF6" => "\xE6\x9B\xA6", + "\xFD\xF7" => "\xE7\x86\x99", + "\xFD\xF8" => "\xE7\x86\xB9", + "\xFD\xF9" => "\xE7\x86\xBA", + "\xFD\xFA" => "\xE7\x8A\xA7", + "\xFD\xFB" => "\xE7\xA6\xA7", + "\xFD\xFC" => "\xE7\xA8\x80", + "\xFD\xFD" => "\xE7\xBE\xB2", + "\xFD\xFE" => "\xE8\xA9\xB0", + ); + return strtr($string, $transform); +} + +function big5($string) +{ + static $transform = array( + "\xA1\x40" => "\xE3\x80\x80", + "\xA1\x41" => "\xEF\xBC\x8C", + "\xA1\x42" => "\xE3\x80\x81", + "\xA1\x43" => "\xE3\x80\x82", + "\xA1\x44" => "\xEF\xBC\x8E", + "\xA1\x45" => "\xE2\x80\xA2", + "\xA1\x46" => "\xEF\xBC\x9B", + "\xA1\x47" => "\xEF\xBC\x9A", + "\xA1\x48" => "\xEF\xBC\x9F", + "\xA1\x49" => "\xEF\xBC\x81", + "\xA1\x4A" => "\xEF\xB8\xB0", + "\xA1\x4B" => "\xE2\x80\xA6", + "\xA1\x4C" => "\xE2\x80\xA5", + "\xA1\x4D" => "\xEF\xB9\x90", + "\xA1\x4E" => "\xEF\xBD\xA4", + "\xA1\x4F" => "\xEF\xB9\x92", + "\xA1\x50" => "\xC2\xB7", + "\xA1\x51" => "\xEF\xB9\x94", + "\xA1\x52" => "\xEF\xB9\x95", + "\xA1\x53" => "\xEF\xB9\x96", + "\xA1\x54" => "\xEF\xB9\x97", + "\xA1\x55" => "\xEF\xBD\x9C", + "\xA1\x56" => "\xE2\x80\x93", + "\xA1\x57" => "\xEF\xB8\xB1", + "\xA1\x58" => "\xE2\x80\x94", + "\xA1\x59" => "\xEF\xB8\xB3", + "\xA1\x5A" => "\xEF\xBF\xBD", + "\xA1\x5B" => "\xEF\xB8\xB4", + "\xA1\x5C" => "\xEF\xB9\x8F", + "\xA1\x5D" => "\xEF\xBC\x88", + "\xA1\x5E" => "\xEF\xBC\x89", + "\xA1\x5F" => "\xEF\xB8\xB5", + "\xA1\x60" => "\xEF\xB8\xB6", + "\xA1\x61" => "\xEF\xBD\x9B", + "\xA1\x62" => "\xEF\xBD\x9D", + "\xA1\x63" => "\xEF\xB8\xB7", + "\xA1\x64" => "\xEF\xB8\xB8", + "\xA1\x65" => "\xE3\x80\x94", + "\xA1\x66" => "\xE3\x80\x95", + "\xA1\x67" => "\xEF\xB8\xB9", + "\xA1\x68" => "\xEF\xB8\xBA", + "\xA1\x69" => "\xE3\x80\x90", + "\xA1\x6A" => "\xE3\x80\x91", + "\xA1\x6B" => "\xEF\xB8\xBB", + "\xA1\x6C" => "\xEF\xB8\xBC", + "\xA1\x6D" => "\xE3\x80\x8A", + "\xA1\x6E" => "\xE3\x80\x8B", + "\xA1\x6F" => "\xEF\xB8\xBD", + "\xA1\x70" => "\xEF\xB8\xBE", + "\xA1\x71" => "\xE3\x80\x88", + "\xA1\x72" => "\xE3\x80\x89", + "\xA1\x73" => "\xEF\xB8\xBF", + "\xA1\x74" => "\xEF\xB9\x80", + "\xA1\x75" => "\xE3\x80\x8C", + "\xA1\x76" => "\xE3\x80\x8D", + "\xA1\x77" => "\xEF\xB9\x81", + "\xA1\x78" => "\xEF\xB9\x82", + "\xA1\x79" => "\xE3\x80\x8E", + "\xA1\x7A" => "\xE3\x80\x8F", + "\xA1\x7B" => "\xEF\xB9\x83", + "\xA1\x7C" => "\xEF\xB9\x84", + "\xA1\x7D" => "\xEF\xB9\x99", + "\xA1\x7E" => "\xEF\xB9\x9A", + "\xA1\xA1" => "\xEF\xB9\x9B", + "\xA1\xA2" => "\xEF\xB9\x9C", + "\xA1\xA3" => "\xEF\xB9\x9D", + "\xA1\xA4" => "\xEF\xB9\x9E", + "\xA1\xA5" => "\xE2\x80\x98", + "\xA1\xA6" => "\xE2\x80\x99", + "\xA1\xA7" => "\xE2\x80\x9C", + "\xA1\xA8" => "\xE2\x80\x9D", + "\xA1\xA9" => "\xE3\x80\x9D", + "\xA1\xAA" => "\xE3\x80\x9E", + "\xA1\xAB" => "\xE2\x80\xB5", + "\xA1\xAC" => "\xE2\x80\xB2", + "\xA1\xAD" => "\xEF\xBC\x83", + "\xA1\xAE" => "\xEF\xBC\x86", + "\xA1\xAF" => "\xEF\xBC\x8A", + "\xA1\xB0" => "\xE2\x80\xBB", + "\xA1\xB1" => "\xC2\xA7", + "\xA1\xB2" => "\xE3\x80\x83", + "\xA1\xB3" => "\xE2\x97\x8B", + "\xA1\xB4" => "\xE2\x97\x8F", + "\xA1\xB5" => "\xE2\x96\xB3", + "\xA1\xB6" => "\xE2\x96\xB2", + "\xA1\xB7" => "\xE2\x97\x8E", + "\xA1\xB8" => "\xE2\x98\x86", + "\xA1\xB9" => "\xE2\x98\x85", + "\xA1\xBA" => "\xE2\x97\x87", + "\xA1\xBB" => "\xE2\x97\x86", + "\xA1\xBC" => "\xE2\x96\xA1", + "\xA1\xBD" => "\xE2\x96\xA0", + "\xA1\xBE" => "\xE2\x96\xBD", + "\xA1\xBF" => "\xE2\x96\xBC", + "\xA1\xC0" => "\xE3\x8A\xA3", + "\xA1\xC1" => "\xE2\x84\x85", + "\xA1\xC2" => "\xE2\x80\xBE", + "\xA1\xC3" => "\xEF\xBF\xBD", + "\xA1\xC4" => "\xEF\xBC\xBF", + "\xA1\xC5" => "\xEF\xBF\xBD", + "\xA1\xC6" => "\xEF\xB9\x89", + "\xA1\xC7" => "\xEF\xB9\x8A", + "\xA1\xC8" => "\xEF\xB9\x8D", + "\xA1\xC9" => "\xEF\xB9\x8E", + "\xA1\xCA" => "\xEF\xB9\x8B", + "\xA1\xCB" => "\xEF\xB9\x8C", + "\xA1\xCC" => "\xEF\xB9\x9F", + "\xA1\xCD" => "\xEF\xB9\xA0", + "\xA1\xCE" => "\xEF\xB9\xA1", + "\xA1\xCF" => "\xEF\xBC\x8B", + "\xA1\xD0" => "\xEF\xBC\x8D", + "\xA1\xD1" => "\xC3\x97", + "\xA1\xD2" => "\xC3\xB7", + "\xA1\xD3" => "\xC2\xB1", + "\xA1\xD4" => "\xE2\x88\x9A", + "\xA1\xD5" => "\xEF\xBC\x9C", + "\xA1\xD6" => "\xEF\xBC\x9E", + "\xA1\xD7" => "\xEF\xBC\x9D", + "\xA1\xD8" => "\xE2\x89\xA6", + "\xA1\xD9" => "\xE2\x89\xA7", + "\xA1\xDA" => "\xE2\x89\xA0", + "\xA1\xDB" => "\xE2\x88\x9E", + "\xA1\xDC" => "\xE2\x89\x92", + "\xA1\xDD" => "\xE2\x89\xA1", + "\xA1\xDE" => "\xEF\xB9\xA2", + "\xA1\xDF" => "\xEF\xB9\xA3", + "\xA1\xE0" => "\xEF\xB9\xA4", + "\xA1\xE1" => "\xEF\xB9\xA5", + "\xA1\xE2" => "\xEF\xB9\xA6", + "\xA1\xE3" => "\xE2\x88\xBC", + "\xA1\xE4" => "\xE2\x88\xA9", + "\xA1\xE5" => "\xE2\x88\xAA", + "\xA1\xE6" => "\xE2\x8A\xA5", + "\xA1\xE7" => "\xE2\x88\xA0", + "\xA1\xE8" => "\xE2\x88\x9F", + "\xA1\xE9" => "\xE2\x8A\xBF", + "\xA1\xEA" => "\xE3\x8F\x92", + "\xA1\xEB" => "\xE3\x8F\x91", + "\xA1\xEC" => "\xE2\x88\xAB", + "\xA1\xED" => "\xE2\x88\xAE", + "\xA1\xEE" => "\xE2\x88\xB5", + "\xA1\xEF" => "\xE2\x88\xB4", + "\xA1\xF0" => "\xE2\x99\x80", + "\xA1\xF1" => "\xE2\x99\x82", + "\xA1\xF2" => "\xE2\x99\x81", + "\xA1\xF3" => "\xE2\x98\x89", + "\xA1\xF4" => "\xE2\x86\x91", + "\xA1\xF5" => "\xE2\x86\x93", + "\xA1\xF6" => "\xE2\x86\x90", + "\xA1\xF7" => "\xE2\x86\x92", + "\xA1\xF8" => "\xE2\x86\x96", + "\xA1\xF9" => "\xE2\x86\x97", + "\xA1\xFA" => "\xE2\x86\x99", + "\xA1\xFB" => "\xE2\x86\x98", + "\xA1\xFC" => "\xE2\x88\xA5", + "\xA1\xFD" => "\xE2\x88\xA3", + "\xA1\xFE" => "\xEF\xBF\xBD", + "\xA2\x40" => "\xEF\xBF\xBD", + "\xA2\x41" => "\xEF\xBC\x8F", + "\xA2\x42" => "\xEF\xBC\xBC", + "\xA2\x43" => "\xEF\xBC\x84", + "\xA2\x44" => "\xC2\xA5", + "\xA2\x45" => "\xE3\x80\x92", + "\xA2\x46" => "\xC2\xA2", + "\xA2\x47" => "\xC2\xA3", + "\xA2\x48" => "\xEF\xBC\x85", + "\xA2\x49" => "\xEF\xBC\xA0", + "\xA2\x4A" => "\xE2\x84\x83", + "\xA2\x4B" => "\xE2\x84\x89", + "\xA2\x4C" => "\xEF\xB9\xA9", + "\xA2\x4D" => "\xEF\xB9\xAA", + "\xA2\x4E" => "\xEF\xB9\xAB", + "\xA2\x4F" => "\xE3\x8F\x95", + "\xA2\x50" => "\xE3\x8E\x9C", + "\xA2\x51" => "\xE3\x8E\x9D", + "\xA2\x52" => "\xE3\x8E\x9E", + "\xA2\x53" => "\xE3\x8F\x8E", + "\xA2\x54" => "\xE3\x8E\xA1", + "\xA2\x55" => "\xE3\x8E\x8E", + "\xA2\x56" => "\xE3\x8E\x8F", + "\xA2\x57" => "\xE3\x8F\x84", + "\xA2\x58" => "\xC2\xB0", + "\xA2\x59" => "\xE5\x85\x99", + "\xA2\x5A" => "\xE5\x85\x9B", + "\xA2\x5B" => "\xE5\x85\x9E", + "\xA2\x5C" => "\xE5\x85\x9D", + "\xA2\x5D" => "\xE5\x85\xA1", + "\xA2\x5E" => "\xE5\x85\xA3", + "\xA2\x5F" => "\xE5\x97\xA7", + "\xA2\x60" => "\xE7\x93\xA9", + "\xA2\x61" => "\xE7\xB3\x8E", + "\xA2\x62" => "\xE2\x96\x81", + "\xA2\x63" => "\xE2\x96\x82", + "\xA2\x64" => "\xE2\x96\x83", + "\xA2\x65" => "\xE2\x96\x84", + "\xA2\x66" => "\xE2\x96\x85", + "\xA2\x67" => "\xE2\x96\x86", + "\xA2\x68" => "\xE2\x96\x87", + "\xA2\x69" => "\xE2\x96\x88", + "\xA2\x6A" => "\xE2\x96\x8F", + "\xA2\x6B" => "\xE2\x96\x8E", + "\xA2\x6C" => "\xE2\x96\x8D", + "\xA2\x6D" => "\xE2\x96\x8C", + "\xA2\x6E" => "\xE2\x96\x8B", + "\xA2\x6F" => "\xE2\x96\x8A", + "\xA2\x70" => "\xE2\x96\x89", + "\xA2\x71" => "\xE2\x94\xBC", + "\xA2\x72" => "\xE2\x94\xB4", + "\xA2\x73" => "\xE2\x94\xAC", + "\xA2\x74" => "\xE2\x94\xA4", + "\xA2\x75" => "\xE2\x94\x9C", + "\xA2\x76" => "\xE2\x96\x94", + "\xA2\x77" => "\xE2\x94\x80", + "\xA2\x78" => "\xE2\x94\x82", + "\xA2\x79" => "\xE2\x96\x95", + "\xA2\x7A" => "\xE2\x94\x8C", + "\xA2\x7B" => "\xE2\x94\x90", + "\xA2\x7C" => "\xE2\x94\x94", + "\xA2\x7D" => "\xE2\x94\x98", + "\xA2\x7E" => "\xE2\x95\xAD", + "\xA2\xA1" => "\xE2\x95\xAE", + "\xA2\xA2" => "\xE2\x95\xB0", + "\xA2\xA3" => "\xE2\x95\xAF", + "\xA2\xA4" => "\xE2\x95\x90", + "\xA2\xA5" => "\xE2\x95\x9E", + "\xA2\xA6" => "\xE2\x95\xAA", + "\xA2\xA7" => "\xE2\x95\xA1", + "\xA2\xA8" => "\xE2\x97\xA2", + "\xA2\xA9" => "\xE2\x97\xA3", + "\xA2\xAA" => "\xE2\x97\xA5", + "\xA2\xAB" => "\xE2\x97\xA4", + "\xA2\xAC" => "\xE2\x95\xB1", + "\xA2\xAD" => "\xE2\x95\xB2", + "\xA2\xAE" => "\xE2\x95\xB3", + "\xA2\xAF" => "\xEF\xBC\x90", + "\xA2\xB0" => "\xEF\xBC\x91", + "\xA2\xB1" => "\xEF\xBC\x92", + "\xA2\xB2" => "\xEF\xBC\x93", + "\xA2\xB3" => "\xEF\xBC\x94", + "\xA2\xB4" => "\xEF\xBC\x95", + "\xA2\xB5" => "\xEF\xBC\x96", + "\xA2\xB6" => "\xEF\xBC\x97", + "\xA2\xB7" => "\xEF\xBC\x98", + "\xA2\xB8" => "\xEF\xBC\x99", + "\xA2\xB9" => "\xE2\x85\xA0", + "\xA2\xBA" => "\xE2\x85\xA1", + "\xA2\xBB" => "\xE2\x85\xA2", + "\xA2\xBC" => "\xE2\x85\xA3", + "\xA2\xBD" => "\xE2\x85\xA4", + "\xA2\xBE" => "\xE2\x85\xA5", + "\xA2\xBF" => "\xE2\x85\xA6", + "\xA2\xC0" => "\xE2\x85\xA7", + "\xA2\xC1" => "\xE2\x85\xA8", + "\xA2\xC2" => "\xE2\x85\xA9", + "\xA2\xC3" => "\xE3\x80\xA1", + "\xA2\xC4" => "\xE3\x80\xA2", + "\xA2\xC5" => "\xE3\x80\xA3", + "\xA2\xC6" => "\xE3\x80\xA4", + "\xA2\xC7" => "\xE3\x80\xA5", + "\xA2\xC8" => "\xE3\x80\xA6", + "\xA2\xC9" => "\xE3\x80\xA7", + "\xA2\xCA" => "\xE3\x80\xA8", + "\xA2\xCB" => "\xE3\x80\xA9", + "\xA2\xCC" => "\xEF\xBF\xBD", + "\xA2\xCD" => "\xE5\x8D\x84", + "\xA2\xCE" => "\xEF\xBF\xBD", + "\xA2\xCF" => "\xEF\xBC\xA1", + "\xA2\xD0" => "\xEF\xBC\xA2", + "\xA2\xD1" => "\xEF\xBC\xA3", + "\xA2\xD2" => "\xEF\xBC\xA4", + "\xA2\xD3" => "\xEF\xBC\xA5", + "\xA2\xD4" => "\xEF\xBC\xA6", + "\xA2\xD5" => "\xEF\xBC\xA7", + "\xA2\xD6" => "\xEF\xBC\xA8", + "\xA2\xD7" => "\xEF\xBC\xA9", + "\xA2\xD8" => "\xEF\xBC\xAA", + "\xA2\xD9" => "\xEF\xBC\xAB", + "\xA2\xDA" => "\xEF\xBC\xAC", + "\xA2\xDB" => "\xEF\xBC\xAD", + "\xA2\xDC" => "\xEF\xBC\xAE", + "\xA2\xDD" => "\xEF\xBC\xAF", + "\xA2\xDE" => "\xEF\xBC\xB0", + "\xA2\xDF" => "\xEF\xBC\xB1", + "\xA2\xE0" => "\xEF\xBC\xB2", + "\xA2\xE1" => "\xEF\xBC\xB3", + "\xA2\xE2" => "\xEF\xBC\xB4", + "\xA2\xE3" => "\xEF\xBC\xB5", + "\xA2\xE4" => "\xEF\xBC\xB6", + "\xA2\xE5" => "\xEF\xBC\xB7", + "\xA2\xE6" => "\xEF\xBC\xB8", + "\xA2\xE7" => "\xEF\xBC\xB9", + "\xA2\xE8" => "\xEF\xBC\xBA", + "\xA2\xE9" => "\xEF\xBD\x81", + "\xA2\xEA" => "\xEF\xBD\x82", + "\xA2\xEB" => "\xEF\xBD\x83", + "\xA2\xEC" => "\xEF\xBD\x84", + "\xA2\xED" => "\xEF\xBD\x85", + "\xA2\xEE" => "\xEF\xBD\x86", + "\xA2\xEF" => "\xEF\xBD\x87", + "\xA2\xF0" => "\xEF\xBD\x88", + "\xA2\xF1" => "\xEF\xBD\x89", + "\xA2\xF2" => "\xEF\xBD\x8A", + "\xA2\xF3" => "\xEF\xBD\x8B", + "\xA2\xF4" => "\xEF\xBD\x8C", + "\xA2\xF5" => "\xEF\xBD\x8D", + "\xA2\xF6" => "\xEF\xBD\x8E", + "\xA2\xF7" => "\xEF\xBD\x8F", + "\xA2\xF8" => "\xEF\xBD\x90", + "\xA2\xF9" => "\xEF\xBD\x91", + "\xA2\xFA" => "\xEF\xBD\x92", + "\xA2\xFB" => "\xEF\xBD\x93", + "\xA2\xFC" => "\xEF\xBD\x94", + "\xA2\xFD" => "\xEF\xBD\x95", + "\xA2\xFE" => "\xEF\xBD\x96", + "\xA3\x40" => "\xEF\xBD\x97", + "\xA3\x41" => "\xEF\xBD\x98", + "\xA3\x42" => "\xEF\xBD\x99", + "\xA3\x43" => "\xEF\xBD\x9A", + "\xA3\x44" => "\xCE\x91", + "\xA3\x45" => "\xCE\x92", + "\xA3\x46" => "\xCE\x93", + "\xA3\x47" => "\xCE\x94", + "\xA3\x48" => "\xCE\x95", + "\xA3\x49" => "\xCE\x96", + "\xA3\x4A" => "\xCE\x97", + "\xA3\x4B" => "\xCE\x98", + "\xA3\x4C" => "\xCE\x99", + "\xA3\x4D" => "\xCE\x9A", + "\xA3\x4E" => "\xCE\x9B", + "\xA3\x4F" => "\xCE\x9C", + "\xA3\x50" => "\xCE\x9D", + "\xA3\x51" => "\xCE\x9E", + "\xA3\x52" => "\xCE\x9F", + "\xA3\x53" => "\xCE\xA0", + "\xA3\x54" => "\xCE\xA1", + "\xA3\x55" => "\xCE\xA3", + "\xA3\x56" => "\xCE\xA4", + "\xA3\x57" => "\xCE\xA5", + "\xA3\x58" => "\xCE\xA6", + "\xA3\x59" => "\xCE\xA7", + "\xA3\x5A" => "\xCE\xA8", + "\xA3\x5B" => "\xCE\xA9", + "\xA3\x5C" => "\xCE\xB1", + "\xA3\x5D" => "\xCE\xB2", + "\xA3\x5E" => "\xCE\xB3", + "\xA3\x5F" => "\xCE\xB4", + "\xA3\x60" => "\xCE\xB5", + "\xA3\x61" => "\xCE\xB6", + "\xA3\x62" => "\xCE\xB7", + "\xA3\x63" => "\xCE\xB8", + "\xA3\x64" => "\xCE\xB9", + "\xA3\x65" => "\xCE\xBA", + "\xA3\x66" => "\xCE\xBB", + "\xA3\x67" => "\xCE\xBC", + "\xA3\x68" => "\xCE\xBD", + "\xA3\x69" => "\xCE\xBE", + "\xA3\x6A" => "\xCE\xBF", + "\xA3\x6B" => "\xCF\x80", + "\xA3\x6C" => "\xCF\x81", + "\xA3\x6D" => "\xCF\x83", + "\xA3\x6E" => "\xCF\x84", + "\xA3\x6F" => "\xCF\x85", + "\xA3\x70" => "\xCF\x86", + "\xA3\x71" => "\xCF\x87", + "\xA3\x72" => "\xCF\x88", + "\xA3\x73" => "\xCF\x89", + "\xA3\x74" => "\xE3\x84\x85", + "\xA3\x75" => "\xE3\x84\x86", + "\xA3\x76" => "\xE3\x84\x87", + "\xA3\x77" => "\xE3\x84\x88", + "\xA3\x78" => "\xE3\x84\x89", + "\xA3\x79" => "\xE3\x84\x8A", + "\xA3\x7A" => "\xE3\x84\x8B", + "\xA3\x7B" => "\xE3\x84\x8C", + "\xA3\x7C" => "\xE3\x84\x8D", + "\xA3\x7D" => "\xE3\x84\x8E", + "\xA3\x7E" => "\xE3\x84\x8F", + "\xA3\xA1" => "\xE3\x84\x90", + "\xA3\xA2" => "\xE3\x84\x91", + "\xA3\xA3" => "\xE3\x84\x92", + "\xA3\xA4" => "\xE3\x84\x93", + "\xA3\xA5" => "\xE3\x84\x94", + "\xA3\xA6" => "\xE3\x84\x95", + "\xA3\xA7" => "\xE3\x84\x96", + "\xA3\xA8" => "\xE3\x84\x97", + "\xA3\xA9" => "\xE3\x84\x98", + "\xA3\xAA" => "\xE3\x84\x99", + "\xA3\xAB" => "\xE3\x84\x9A", + "\xA3\xAC" => "\xE3\x84\x9B", + "\xA3\xAD" => "\xE3\x84\x9C", + "\xA3\xAE" => "\xE3\x84\x9D", + "\xA3\xAF" => "\xE3\x84\x9E", + "\xA3\xB0" => "\xE3\x84\x9F", + "\xA3\xB1" => "\xE3\x84\xA0", + "\xA3\xB2" => "\xE3\x84\xA1", + "\xA3\xB3" => "\xE3\x84\xA2", + "\xA3\xB4" => "\xE3\x84\xA3", + "\xA3\xB5" => "\xE3\x84\xA4", + "\xA3\xB6" => "\xE3\x84\xA5", + "\xA3\xB7" => "\xE3\x84\xA6", + "\xA3\xB8" => "\xE3\x84\xA7", + "\xA3\xB9" => "\xE3\x84\xA8", + "\xA3\xBA" => "\xE3\x84\xA9", + "\xA3\xBB" => "\xCB\x99", + "\xA3\xBC" => "\xCB\x89", + "\xA3\xBD" => "\xCB\x8A", + "\xA3\xBE" => "\xCB\x87", + "\xA3\xBF" => "\xCB\x8B", + "\xA4\x40" => "\xE4\xB8\x80", + "\xA4\x41" => "\xE4\xB9\x99", + "\xA4\x42" => "\xE4\xB8\x81", + "\xA4\x43" => "\xE4\xB8\x83", + "\xA4\x44" => "\xE4\xB9\x83", + "\xA4\x45" => "\xE4\xB9\x9D", + "\xA4\x46" => "\xE4\xBA\x86", + "\xA4\x47" => "\xE4\xBA\x8C", + "\xA4\x48" => "\xE4\xBA\xBA", + "\xA4\x49" => "\xE5\x84\xBF", + "\xA4\x4A" => "\xE5\x85\xA5", + "\xA4\x4B" => "\xE5\x85\xAB", + "\xA4\x4C" => "\xE5\x87\xA0", + "\xA4\x4D" => "\xE5\x88\x80", + "\xA4\x4E" => "\xE5\x88\x81", + "\xA4\x4F" => "\xE5\x8A\x9B", + "\xA4\x50" => "\xE5\x8C\x95", + "\xA4\x51" => "\xE5\x8D\x81", + "\xA4\x52" => "\xE5\x8D\x9C", + "\xA4\x53" => "\xE5\x8F\x88", + "\xA4\x54" => "\xE4\xB8\x89", + "\xA4\x55" => "\xE4\xB8\x8B", + "\xA4\x56" => "\xE4\xB8\x88", + "\xA4\x57" => "\xE4\xB8\x8A", + "\xA4\x58" => "\xE4\xB8\xAB", + "\xA4\x59" => "\xE4\xB8\xB8", + "\xA4\x5A" => "\xE5\x87\xA1", + "\xA4\x5B" => "\xE4\xB9\x85", + "\xA4\x5C" => "\xE4\xB9\x88", + "\xA4\x5D" => "\xE4\xB9\x9F", + "\xA4\x5E" => "\xE4\xB9\x9E", + "\xA4\x5F" => "\xE4\xBA\x8E", + "\xA4\x60" => "\xE4\xBA\xA1", + "\xA4\x61" => "\xE5\x85\x80", + "\xA4\x62" => "\xE5\x88\x83", + "\xA4\x63" => "\xE5\x8B\xBA", + "\xA4\x64" => "\xE5\x8D\x83", + "\xA4\x65" => "\xE5\x8F\x89", + "\xA4\x66" => "\xE5\x8F\xA3", + "\xA4\x67" => "\xE5\x9C\x9F", + "\xA4\x68" => "\xE5\xA3\xAB", + "\xA4\x69" => "\xE5\xA4\x95", + "\xA4\x6A" => "\xE5\xA4\xA7", + "\xA4\x6B" => "\xE5\xA5\xB3", + "\xA4\x6C" => "\xE5\xAD\x90", + "\xA4\x6D" => "\xE5\xAD\x91", + "\xA4\x6E" => "\xE5\xAD\x93", + "\xA4\x6F" => "\xE5\xAF\xB8", + "\xA4\x70" => "\xE5\xB0\x8F", + "\xA4\x71" => "\xE5\xB0\xA2", + "\xA4\x72" => "\xE5\xB0\xB8", + "\xA4\x73" => "\xE5\xB1\xB1", + "\xA4\x74" => "\xE5\xB7\x9D", + "\xA4\x75" => "\xE5\xB7\xA5", + "\xA4\x76" => "\xE5\xB7\xB1", + "\xA4\x77" => "\xE5\xB7\xB2", + "\xA4\x78" => "\xE5\xB7\xB3", + "\xA4\x79" => "\xE5\xB7\xBE", + "\xA4\x7A" => "\xE5\xB9\xB2", + "\xA4\x7B" => "\xE5\xBB\xBE", + "\xA4\x7C" => "\xE5\xBC\x8B", + "\xA4\x7D" => "\xE5\xBC\x93", + "\xA4\x7E" => "\xE6\x89\x8D", + "\xA4\xA1" => "\xE4\xB8\x91", + "\xA4\xA2" => "\xE4\xB8\x90", + "\xA4\xA3" => "\xE4\xB8\x8D", + "\xA4\xA4" => "\xE4\xB8\xAD", + "\xA4\xA5" => "\xE4\xB8\xB0", + "\xA4\xA6" => "\xE4\xB8\xB9", + "\xA4\xA7" => "\xE4\xB9\x8B", + "\xA4\xA8" => "\xE5\xB0\xB9", + "\xA4\xA9" => "\xE4\xBA\x88", + "\xA4\xAA" => "\xE4\xBA\x91", + "\xA4\xAB" => "\xE4\xBA\x95", + "\xA4\xAC" => "\xE4\xBA\x92", + "\xA4\xAD" => "\xE4\xBA\x94", + "\xA4\xAE" => "\xE4\xBA\xA2", + "\xA4\xAF" => "\xE4\xBB\x81", + "\xA4\xB0" => "\xE4\xBB\x80", + "\xA4\xB1" => "\xE4\xBB\x83", + "\xA4\xB2" => "\xE4\xBB\x86", + "\xA4\xB3" => "\xE4\xBB\x87", + "\xA4\xB4" => "\xE4\xBB\x8D", + "\xA4\xB5" => "\xE4\xBB\x8A", + "\xA4\xB6" => "\xE4\xBB\x8B", + "\xA4\xB7" => "\xE4\xBB\x84", + "\xA4\xB8" => "\xE5\x85\x83", + "\xA4\xB9" => "\xE5\x85\x81", + "\xA4\xBA" => "\xE5\x85\xA7", + "\xA4\xBB" => "\xE5\x85\xAD", + "\xA4\xBC" => "\xE5\x85\xAE", + "\xA4\xBD" => "\xE5\x85\xAC", + "\xA4\xBE" => "\xE5\x86\x97", + "\xA4\xBF" => "\xE5\x87\xB6", + "\xA4\xC0" => "\xE5\x88\x86", + "\xA4\xC1" => "\xE5\x88\x87", + "\xA4\xC2" => "\xE5\x88\x88", + "\xA4\xC3" => "\xE5\x8B\xBB", + "\xA4\xC4" => "\xE5\x8B\xBE", + "\xA4\xC5" => "\xE5\x8B\xBF", + "\xA4\xC6" => "\xE5\x8C\x96", + "\xA4\xC7" => "\xE5\x8C\xB9", + "\xA4\xC8" => "\xE5\x8D\x88", + "\xA4\xC9" => "\xE5\x8D\x87", + "\xA4\xCA" => "\xE5\x8D\x85", + "\xA4\xCB" => "\xE5\x8D\x9E", + "\xA4\xCC" => "\xE5\x8E\x84", + "\xA4\xCD" => "\xE5\x8F\x8B", + "\xA4\xCE" => "\xE5\x8F\x8A", + "\xA4\xCF" => "\xE5\x8F\x8D", + "\xA4\xD0" => "\xE5\xA3\xAC", + "\xA4\xD1" => "\xE5\xA4\xA9", + "\xA4\xD2" => "\xE5\xA4\xAB", + "\xA4\xD3" => "\xE5\xA4\xAA", + "\xA4\xD4" => "\xE5\xA4\xAD", + "\xA4\xD5" => "\xE5\xAD\x94", + "\xA4\xD6" => "\xE5\xB0\x91", + "\xA4\xD7" => "\xE5\xB0\xA4", + "\xA4\xD8" => "\xE5\xB0\xBA", + "\xA4\xD9" => "\xE5\xB1\xAF", + "\xA4\xDA" => "\xE5\xB7\xB4", + "\xA4\xDB" => "\xE5\xB9\xBB", + "\xA4\xDC" => "\xE5\xBB\xBF", + "\xA4\xDD" => "\xE5\xBC\x94", + "\xA4\xDE" => "\xE5\xBC\x95", + "\xA4\xDF" => "\xE5\xBF\x83", + "\xA4\xE0" => "\xE6\x88\x88", + "\xA4\xE1" => "\xE6\x88\xB6", + "\xA4\xE2" => "\xE6\x89\x8B", + "\xA4\xE3" => "\xE6\x89\x8E", + "\xA4\xE4" => "\xE6\x94\xAF", + "\xA4\xE5" => "\xE6\x96\x87", + "\xA4\xE6" => "\xE6\x96\x97", + "\xA4\xE7" => "\xE6\x96\xA4", + "\xA4\xE8" => "\xE6\x96\xB9", + "\xA4\xE9" => "\xE6\x97\xA5", + "\xA4\xEA" => "\xE6\x9B\xB0", + "\xA4\xEB" => "\xE6\x9C\x88", + "\xA4\xEC" => "\xE6\x9C\xA8", + "\xA4\xED" => "\xE6\xAC\xA0", + "\xA4\xEE" => "\xE6\xAD\xA2", + "\xA4\xEF" => "\xE6\xAD\xB9", + "\xA4\xF0" => "\xE6\xAF\x8B", + "\xA4\xF1" => "\xE6\xAF\x94", + "\xA4\xF2" => "\xE6\xAF\x9B", + "\xA4\xF3" => "\xE6\xB0\x8F", + "\xA4\xF4" => "\xE6\xB0\xB4", + "\xA4\xF5" => "\xE7\x81\xAB", + "\xA4\xF6" => "\xE7\x88\xAA", + "\xA4\xF7" => "\xE7\x88\xB6", + "\xA4\xF8" => "\xE7\x88\xBB", + "\xA4\xF9" => "\xE7\x89\x87", + "\xA4\xFA" => "\xE7\x89\x99", + "\xA4\xFB" => "\xE7\x89\x9B", + "\xA4\xFC" => "\xE7\x8A\xAC", + "\xA4\xFD" => "\xE7\x8E\x8B", + "\xA4\xFE" => "\xE4\xB8\x99", + "\xA5\x40" => "\xE4\xB8\x96", + "\xA5\x41" => "\xE4\xB8\x95", + "\xA5\x42" => "\xE4\xB8\x94", + "\xA5\x43" => "\xE4\xB8\x98", + "\xA5\x44" => "\xE4\xB8\xBB", + "\xA5\x45" => "\xE4\xB9\x8D", + "\xA5\x46" => "\xE4\xB9\x8F", + "\xA5\x47" => "\xE4\xB9\x8E", + "\xA5\x48" => "\xE4\xBB\xA5", + "\xA5\x49" => "\xE4\xBB\x98", + "\xA5\x4A" => "\xE4\xBB\x94", + "\xA5\x4B" => "\xE4\xBB\x95", + "\xA5\x4C" => "\xE4\xBB\x96", + "\xA5\x4D" => "\xE4\xBB\x97", + "\xA5\x4E" => "\xE4\xBB\xA3", + "\xA5\x4F" => "\xE4\xBB\xA4", + "\xA5\x50" => "\xE4\xBB\x99", + "\xA5\x51" => "\xE4\xBB\x9E", + "\xA5\x52" => "\xE5\x85\x85", + "\xA5\x53" => "\xE5\x85\x84", + "\xA5\x54" => "\xE5\x86\x89", + "\xA5\x55" => "\xE5\x86\x8A", + "\xA5\x56" => "\xE5\x86\xAC", + "\xA5\x57" => "\xE5\x87\xB9", + "\xA5\x58" => "\xE5\x87\xBA", + "\xA5\x59" => "\xE5\x87\xB8", + "\xA5\x5A" => "\xE5\x88\x8A", + "\xA5\x5B" => "\xE5\x8A\xA0", + "\xA5\x5C" => "\xE5\x8A\x9F", + "\xA5\x5D" => "\xE5\x8C\x85", + "\xA5\x5E" => "\xE5\x8C\x86", + "\xA5\x5F" => "\xE5\x8C\x97", + "\xA5\x60" => "\xE5\x8C\x9D", + "\xA5\x61" => "\xE4\xBB\x9F", + "\xA5\x62" => "\xE5\x8D\x8A", + "\xA5\x63" => "\xE5\x8D\x89", + "\xA5\x64" => "\xE5\x8D\xA1", + "\xA5\x65" => "\xE5\x8D\xA0", + "\xA5\x66" => "\xE5\x8D\xAF", + "\xA5\x67" => "\xE5\x8D\xAE", + "\xA5\x68" => "\xE5\x8E\xBB", + "\xA5\x69" => "\xE5\x8F\xAF", + "\xA5\x6A" => "\xE5\x8F\xA4", + "\xA5\x6B" => "\xE5\x8F\xB3", + "\xA5\x6C" => "\xE5\x8F\xAC", + "\xA5\x6D" => "\xE5\x8F\xAE", + "\xA5\x6E" => "\xE5\x8F\xA9", + "\xA5\x6F" => "\xE5\x8F\xA8", + "\xA5\x70" => "\xE5\x8F\xBC", + "\xA5\x71" => "\xE5\x8F\xB8", + "\xA5\x72" => "\xE5\x8F\xB5", + "\xA5\x73" => "\xE5\x8F\xAB", + "\xA5\x74" => "\xE5\x8F\xA6", + "\xA5\x75" => "\xE5\x8F\xAA", + "\xA5\x76" => "\xE5\x8F\xB2", + "\xA5\x77" => "\xE5\x8F\xB1", + "\xA5\x78" => "\xE5\x8F\xB0", + "\xA5\x79" => "\xE5\x8F\xA5", + "\xA5\x7A" => "\xE5\x8F\xAD", + "\xA5\x7B" => "\xE5\x8F\xBB", + "\xA5\x7C" => "\xE5\x9B\x9B", + "\xA5\x7D" => "\xE5\x9B\x9A", + "\xA5\x7E" => "\xE5\xA4\x96", + "\xA5\xA1" => "\xE5\xA4\xAE", + "\xA5\xA2" => "\xE5\xA4\xB1", + "\xA5\xA3" => "\xE5\xA5\xB4", + "\xA5\xA4" => "\xE5\xA5\xB6", + "\xA5\xA5" => "\xE5\xAD\x95", + "\xA5\xA6" => "\xE5\xAE\x83", + "\xA5\xA7" => "\xE5\xB0\xBC", + "\xA5\xA8" => "\xE5\xB7\xA8", + "\xA5\xA9" => "\xE5\xB7\xA7", + "\xA5\xAA" => "\xE5\xB7\xA6", + "\xA5\xAB" => "\xE5\xB8\x82", + "\xA5\xAC" => "\xE5\xB8\x83", + "\xA5\xAD" => "\xE5\xB9\xB3", + "\xA5\xAE" => "\xE5\xB9\xBC", + "\xA5\xAF" => "\xE5\xBC\x81", + "\xA5\xB0" => "\xE5\xBC\x98", + "\xA5\xB1" => "\xE5\xBC\x97", + "\xA5\xB2" => "\xE5\xBF\x85", + "\xA5\xB3" => "\xE6\x88\x8A", + "\xA5\xB4" => "\xE6\x89\x93", + "\xA5\xB5" => "\xE6\x89\x94", + "\xA5\xB6" => "\xE6\x89\x92", + "\xA5\xB7" => "\xE6\x89\x91", + "\xA5\xB8" => "\xE6\x96\xA5", + "\xA5\xB9" => "\xE6\x97\xA6", + "\xA5\xBA" => "\xE6\x9C\xAE", + "\xA5\xBB" => "\xE6\x9C\xAC", + "\xA5\xBC" => "\xE6\x9C\xAA", + "\xA5\xBD" => "\xE6\x9C\xAB", + "\xA5\xBE" => "\xE6\x9C\xAD", + "\xA5\xBF" => "\xE6\xAD\xA3", + "\xA5\xC0" => "\xE6\xAF\x8D", + "\xA5\xC1" => "\xE6\xB0\x91", + "\xA5\xC2" => "\xE6\xB0\x90", + "\xA5\xC3" => "\xE6\xB0\xB8", + "\xA5\xC4" => "\xE6\xB1\x81", + "\xA5\xC5" => "\xE6\xB1\x80", + "\xA5\xC6" => "\xE6\xB0\xBE", + "\xA5\xC7" => "\xE7\x8A\xAF", + "\xA5\xC8" => "\xE7\x8E\x84", + "\xA5\xC9" => "\xE7\x8E\x89", + "\xA5\xCA" => "\xE7\x93\x9C", + "\xA5\xCB" => "\xE7\x93\xA6", + "\xA5\xCC" => "\xE7\x94\x98", + "\xA5\xCD" => "\xE7\x94\x9F", + "\xA5\xCE" => "\xE7\x94\xA8", + "\xA5\xCF" => "\xE7\x94\xA9", + "\xA5\xD0" => "\xE7\x94\xB0", + "\xA5\xD1" => "\xE7\x94\xB1", + "\xA5\xD2" => "\xE7\x94\xB2", + "\xA5\xD3" => "\xE7\x94\xB3", + "\xA5\xD4" => "\xE7\x96\x8B", + "\xA5\xD5" => "\xE7\x99\xBD", + "\xA5\xD6" => "\xE7\x9A\xAE", + "\xA5\xD7" => "\xE7\x9A\xBF", + "\xA5\xD8" => "\xE7\x9B\xAE", + "\xA5\xD9" => "\xE7\x9F\x9B", + "\xA5\xDA" => "\xE7\x9F\xA2", + "\xA5\xDB" => "\xE7\x9F\xB3", + "\xA5\xDC" => "\xE7\xA4\xBA", + "\xA5\xDD" => "\xE7\xA6\xBE", + "\xA5\xDE" => "\xE7\xA9\xB4", + "\xA5\xDF" => "\xE7\xAB\x8B", + "\xA5\xE0" => "\xE4\xB8\x9E", + "\xA5\xE1" => "\xE4\xB8\x9F", + "\xA5\xE2" => "\xE4\xB9\x92", + "\xA5\xE3" => "\xE4\xB9\x93", + "\xA5\xE4" => "\xE4\xB9\xA9", + "\xA5\xE5" => "\xE4\xBA\x99", + "\xA5\xE6" => "\xE4\xBA\xA4", + "\xA5\xE7" => "\xE4\xBA\xA6", + "\xA5\xE8" => "\xE4\xBA\xA5", + "\xA5\xE9" => "\xE4\xBB\xBF", + "\xA5\xEA" => "\xE4\xBC\x89", + "\xA5\xEB" => "\xE4\xBC\x99", + "\xA5\xEC" => "\xE4\xBC\x8A", + "\xA5\xED" => "\xE4\xBC\x95", + "\xA5\xEE" => "\xE4\xBC\x8D", + "\xA5\xEF" => "\xE4\xBC\x90", + "\xA5\xF0" => "\xE4\xBC\x91", + "\xA5\xF1" => "\xE4\xBC\x8F", + "\xA5\xF2" => "\xE4\xBB\xB2", + "\xA5\xF3" => "\xE4\xBB\xB6", + "\xA5\xF4" => "\xE4\xBB\xBB", + "\xA5\xF5" => "\xE4\xBB\xB0", + "\xA5\xF6" => "\xE4\xBB\xB3", + "\xA5\xF7" => "\xE4\xBB\xBD", + "\xA5\xF8" => "\xE4\xBC\x81", + "\xA5\xF9" => "\xE4\xBC\x8B", + "\xA5\xFA" => "\xE5\x85\x89", + "\xA5\xFB" => "\xE5\x85\x87", + "\xA5\xFC" => "\xE5\x85\x86", + "\xA5\xFD" => "\xE5\x85\x88", + "\xA5\xFE" => "\xE5\x85\xA8", + "\xA6\x40" => "\xE5\x85\xB1", + "\xA6\x41" => "\xE5\x86\x8D", + "\xA6\x42" => "\xE5\x86\xB0", + "\xA6\x43" => "\xE5\x88\x97", + "\xA6\x44" => "\xE5\x88\x91", + "\xA6\x45" => "\xE5\x88\x92", + "\xA6\x46" => "\xE5\x88\x8E", + "\xA6\x47" => "\xE5\x88\x96", + "\xA6\x48" => "\xE5\x8A\xA3", + "\xA6\x49" => "\xE5\x8C\x88", + "\xA6\x4A" => "\xE5\x8C\xA1", + "\xA6\x4B" => "\xE5\x8C\xA0", + "\xA6\x4C" => "\xE5\x8D\xB0", + "\xA6\x4D" => "\xE5\x8D\xB1", + "\xA6\x4E" => "\xE5\x90\x89", + "\xA6\x4F" => "\xE5\x90\x8F", + "\xA6\x50" => "\xE5\x90\x8C", + "\xA6\x51" => "\xE5\x90\x8A", + "\xA6\x52" => "\xE5\x90\x90", + "\xA6\x53" => "\xE5\x90\x81", + "\xA6\x54" => "\xE5\x90\x8B", + "\xA6\x55" => "\xE5\x90\x84", + "\xA6\x56" => "\xE5\x90\x91", + "\xA6\x57" => "\xE5\x90\x8D", + "\xA6\x58" => "\xE5\x90\x88", + "\xA6\x59" => "\xE5\x90\x83", + "\xA6\x5A" => "\xE5\x90\x8E", + "\xA6\x5B" => "\xE5\x90\x86", + "\xA6\x5C" => "\xE5\x90\x92", + "\xA6\x5D" => "\xE5\x9B\xA0", + "\xA6\x5E" => "\xE5\x9B\x9E", + "\xA6\x5F" => "\xE5\x9B\x9D", + "\xA6\x60" => "\xE5\x9C\xB3", + "\xA6\x61" => "\xE5\x9C\xB0", + "\xA6\x62" => "\xE5\x9C\xA8", + "\xA6\x63" => "\xE5\x9C\xAD", + "\xA6\x64" => "\xE5\x9C\xAC", + "\xA6\x65" => "\xE5\x9C\xAF", + "\xA6\x66" => "\xE5\x9C\xA9", + "\xA6\x67" => "\xE5\xA4\x99", + "\xA6\x68" => "\xE5\xA4\x9A", + "\xA6\x69" => "\xE5\xA4\xB7", + "\xA6\x6A" => "\xE5\xA4\xB8", + "\xA6\x6B" => "\xE5\xA6\x84", + "\xA6\x6C" => "\xE5\xA5\xB8", + "\xA6\x6D" => "\xE5\xA6\x83", + "\xA6\x6E" => "\xE5\xA5\xBD", + "\xA6\x6F" => "\xE5\xA5\xB9", + "\xA6\x70" => "\xE5\xA6\x82", + "\xA6\x71" => "\xE5\xA6\x81", + "\xA6\x72" => "\xE5\xAD\x97", + "\xA6\x73" => "\xE5\xAD\x98", + "\xA6\x74" => "\xE5\xAE\x87", + "\xA6\x75" => "\xE5\xAE\x88", + "\xA6\x76" => "\xE5\xAE\x85", + "\xA6\x77" => "\xE5\xAE\x89", + "\xA6\x78" => "\xE5\xAF\xBA", + "\xA6\x79" => "\xE5\xB0\x96", + "\xA6\x7A" => "\xE5\xB1\xB9", + "\xA6\x7B" => "\xE5\xB7\x9E", + "\xA6\x7C" => "\xE5\xB8\x86", + "\xA6\x7D" => "\xE5\xB9\xB6", + "\xA6\x7E" => "\xE5\xB9\xB4", + "\xA6\xA1" => "\xE5\xBC\x8F", + "\xA6\xA2" => "\xE5\xBC\x9B", + "\xA6\xA3" => "\xE5\xBF\x99", + "\xA6\xA4" => "\xE5\xBF\x96", + "\xA6\xA5" => "\xE6\x88\x8E", + "\xA6\xA6" => "\xE6\x88\x8C", + "\xA6\xA7" => "\xE6\x88\x8D", + "\xA6\xA8" => "\xE6\x88\x90", + "\xA6\xA9" => "\xE6\x89\xA3", + "\xA6\xAA" => "\xE6\x89\x9B", + "\xA6\xAB" => "\xE6\x89\x98", + "\xA6\xAC" => "\xE6\x94\xB6", + "\xA6\xAD" => "\xE6\x97\xA9", + "\xA6\xAE" => "\xE6\x97\xA8", + "\xA6\xAF" => "\xE6\x97\xAC", + "\xA6\xB0" => "\xE6\x97\xAD", + "\xA6\xB1" => "\xE6\x9B\xB2", + "\xA6\xB2" => "\xE6\x9B\xB3", + "\xA6\xB3" => "\xE6\x9C\x89", + "\xA6\xB4" => "\xE6\x9C\xBD", + "\xA6\xB5" => "\xE6\x9C\xB4", + "\xA6\xB6" => "\xE6\x9C\xB1", + "\xA6\xB7" => "\xE6\x9C\xB5", + "\xA6\xB8" => "\xE6\xAC\xA1", + "\xA6\xB9" => "\xE6\xAD\xA4", + "\xA6\xBA" => "\xE6\xAD\xBB", + "\xA6\xBB" => "\xE6\xB0\x96", + "\xA6\xBC" => "\xE6\xB1\x9D", + "\xA6\xBD" => "\xE6\xB1\x97", + "\xA6\xBE" => "\xE6\xB1\x99", + "\xA6\xBF" => "\xE6\xB1\x9F", + "\xA6\xC0" => "\xE6\xB1\xA0", + "\xA6\xC1" => "\xE6\xB1\x90", + "\xA6\xC2" => "\xE6\xB1\x95", + "\xA6\xC3" => "\xE6\xB1\xA1", + "\xA6\xC4" => "\xE6\xB1\x9B", + "\xA6\xC5" => "\xE6\xB1\x8D", + "\xA6\xC6" => "\xE6\xB1\x8E", + "\xA6\xC7" => "\xE7\x81\xB0", + "\xA6\xC8" => "\xE7\x89\x9F", + "\xA6\xC9" => "\xE7\x89\x9D", + "\xA6\xCA" => "\xE7\x99\xBE", + "\xA6\xCB" => "\xE7\xAB\xB9", + "\xA6\xCC" => "\xE7\xB1\xB3", + "\xA6\xCD" => "\xE7\xB3\xB8", + "\xA6\xCE" => "\xE7\xBC\xB6", + "\xA6\xCF" => "\xE7\xBE\x8A", + "\xA6\xD0" => "\xE7\xBE\xBD", + "\xA6\xD1" => "\xE8\x80\x81", + "\xA6\xD2" => "\xE8\x80\x83", + "\xA6\xD3" => "\xE8\x80\x8C", + "\xA6\xD4" => "\xE8\x80\x92", + "\xA6\xD5" => "\xE8\x80\xB3", + "\xA6\xD6" => "\xE8\x81\xBF", + "\xA6\xD7" => "\xE8\x82\x89", + "\xA6\xD8" => "\xE8\x82\x8B", + "\xA6\xD9" => "\xE8\x82\x8C", + "\xA6\xDA" => "\xE8\x87\xA3", + "\xA6\xDB" => "\xE8\x87\xAA", + "\xA6\xDC" => "\xE8\x87\xB3", + "\xA6\xDD" => "\xE8\x87\xBC", + "\xA6\xDE" => "\xE8\x88\x8C", + "\xA6\xDF" => "\xE8\x88\x9B", + "\xA6\xE0" => "\xE8\x88\x9F", + "\xA6\xE1" => "\xE8\x89\xAE", + "\xA6\xE2" => "\xE8\x89\xB2", + "\xA6\xE3" => "\xE8\x89\xBE", + "\xA6\xE4" => "\xE8\x99\xAB", + "\xA6\xE5" => "\xE8\xA1\x80", + "\xA6\xE6" => "\xE8\xA1\x8C", + "\xA6\xE7" => "\xE8\xA1\xA3", + "\xA6\xE8" => "\xE8\xA5\xBF", + "\xA6\xE9" => "\xE9\x98\xA1", + "\xA6\xEA" => "\xE4\xB8\xB2", + "\xA6\xEB" => "\xE4\xBA\xA8", + "\xA6\xEC" => "\xE4\xBD\x8D", + "\xA6\xED" => "\xE4\xBD\x8F", + "\xA6\xEE" => "\xE4\xBD\x87", + "\xA6\xEF" => "\xE4\xBD\x97", + "\xA6\xF0" => "\xE4\xBD\x9E", + "\xA6\xF1" => "\xE4\xBC\xB4", + "\xA6\xF2" => "\xE4\xBD\x9B", + "\xA6\xF3" => "\xE4\xBD\x95", + "\xA6\xF4" => "\xE4\xBC\xB0", + "\xA6\xF5" => "\xE4\xBD\x90", + "\xA6\xF6" => "\xE4\xBD\x91", + "\xA6\xF7" => "\xE4\xBC\xBD", + "\xA6\xF8" => "\xE4\xBC\xBA", + "\xA6\xF9" => "\xE4\xBC\xB8", + "\xA6\xFA" => "\xE4\xBD\x83", + "\xA6\xFB" => "\xE4\xBD\x94", + "\xA6\xFC" => "\xE4\xBC\xBC", + "\xA6\xFD" => "\xE4\xBD\x86", + "\xA6\xFE" => "\xE4\xBD\xA3", + "\xA7\x40" => "\xE4\xBD\x9C", + "\xA7\x41" => "\xE4\xBD\xA0", + "\xA7\x42" => "\xE4\xBC\xAF", + "\xA7\x43" => "\xE4\xBD\x8E", + "\xA7\x44" => "\xE4\xBC\xB6", + "\xA7\x45" => "\xE4\xBD\x99", + "\xA7\x46" => "\xE4\xBD\x9D", + "\xA7\x47" => "\xE4\xBD\x88", + "\xA7\x48" => "\xE4\xBD\x9A", + "\xA7\x49" => "\xE5\x85\x8C", + "\xA7\x4A" => "\xE5\x85\x8B", + "\xA7\x4B" => "\xE5\x85\x8D", + "\xA7\x4C" => "\xE5\x85\xB5", + "\xA7\x4D" => "\xE5\x86\xB6", + "\xA7\x4E" => "\xE5\x86\xB7", + "\xA7\x4F" => "\xE5\x88\xA5", + "\xA7\x50" => "\xE5\x88\xA4", + "\xA7\x51" => "\xE5\x88\xA9", + "\xA7\x52" => "\xE5\x88\xAA", + "\xA7\x53" => "\xE5\x88\xA8", + "\xA7\x54" => "\xE5\x8A\xAB", + "\xA7\x55" => "\xE5\x8A\xA9", + "\xA7\x56" => "\xE5\x8A\xAA", + "\xA7\x57" => "\xE5\x8A\xAC", + "\xA7\x58" => "\xE5\x8C\xA3", + "\xA7\x59" => "\xE5\x8D\xB3", + "\xA7\x5A" => "\xE5\x8D\xB5", + "\xA7\x5B" => "\xE5\x90\x9D", + "\xA7\x5C" => "\xE5\x90\xAD", + "\xA7\x5D" => "\xE5\x90\x9E", + "\xA7\x5E" => "\xE5\x90\xBE", + "\xA7\x5F" => "\xE5\x90\xA6", + "\xA7\x60" => "\xE5\x91\x8E", + "\xA7\x61" => "\xE5\x90\xA7", + "\xA7\x62" => "\xE5\x91\x86", + "\xA7\x63" => "\xE5\x91\x83", + "\xA7\x64" => "\xE5\x90\xB3", + "\xA7\x65" => "\xE5\x91\x88", + "\xA7\x66" => "\xE5\x91\x82", + "\xA7\x67" => "\xE5\x90\x9B", + "\xA7\x68" => "\xE5\x90\xA9", + "\xA7\x69" => "\xE5\x91\x8A", + "\xA7\x6A" => "\xE5\x90\xB9", + "\xA7\x6B" => "\xE5\x90\xBB", + "\xA7\x6C" => "\xE5\x90\xB8", + "\xA7\x6D" => "\xE5\x90\xAE", + "\xA7\x6E" => "\xE5\x90\xB5", + "\xA7\x6F" => "\xE5\x90\xB6", + "\xA7\x70" => "\xE5\x90\xA0", + "\xA7\x71" => "\xE5\x90\xBC", + "\xA7\x72" => "\xE5\x91\x80", + "\xA7\x73" => "\xE5\x90\xB1", + "\xA7\x74" => "\xE5\x90\xAB", + "\xA7\x75" => "\xE5\x90\x9F", + "\xA7\x76" => "\xE5\x90\xAC", + "\xA7\x77" => "\xE5\x9B\xAA", + "\xA7\x78" => "\xE5\x9B\xB0", + "\xA7\x79" => "\xE5\x9B\xA4", + "\xA7\x7A" => "\xE5\x9B\xAB", + "\xA7\x7B" => "\xE5\x9D\x8A", + "\xA7\x7C" => "\xE5\x9D\x91", + "\xA7\x7D" => "\xE5\x9D\x80", + "\xA7\x7E" => "\xE5\x9D\x8D", + "\xA7\xA1" => "\xE5\x9D\x87", + "\xA7\xA2" => "\xE5\x9D\x8E", + "\xA7\xA3" => "\xE5\x9C\xBE", + "\xA7\xA4" => "\xE5\x9D\x90", + "\xA7\xA5" => "\xE5\x9D\x8F", + "\xA7\xA6" => "\xE5\x9C\xBB", + "\xA7\xA7" => "\xE5\xA3\xAF", + "\xA7\xA8" => "\xE5\xA4\xBE", + "\xA7\xA9" => "\xE5\xA6\x9D", + "\xA7\xAA" => "\xE5\xA6\x92", + "\xA7\xAB" => "\xE5\xA6\xA8", + "\xA7\xAC" => "\xE5\xA6\x9E", + "\xA7\xAD" => "\xE5\xA6\xA3", + "\xA7\xAE" => "\xE5\xA6\x99", + "\xA7\xAF" => "\xE5\xA6\x96", + "\xA7\xB0" => "\xE5\xA6\x8D", + "\xA7\xB1" => "\xE5\xA6\xA4", + "\xA7\xB2" => "\xE5\xA6\x93", + "\xA7\xB3" => "\xE5\xA6\x8A", + "\xA7\xB4" => "\xE5\xA6\xA5", + "\xA7\xB5" => "\xE5\xAD\x9D", + "\xA7\xB6" => "\xE5\xAD\x9C", + "\xA7\xB7" => "\xE5\xAD\x9A", + "\xA7\xB8" => "\xE5\xAD\x9B", + "\xA7\xB9" => "\xE5\xAE\x8C", + "\xA7\xBA" => "\xE5\xAE\x8B", + "\xA7\xBB" => "\xE5\xAE\x8F", + "\xA7\xBC" => "\xE5\xB0\xAC", + "\xA7\xBD" => "\xE5\xB1\x80", + "\xA7\xBE" => "\xE5\xB1\x81", + "\xA7\xBF" => "\xE5\xB0\xBF", + "\xA7\xC0" => "\xE5\xB0\xBE", + "\xA7\xC1" => "\xE5\xB2\x90", + "\xA7\xC2" => "\xE5\xB2\x91", + "\xA7\xC3" => "\xE5\xB2\x94", + "\xA7\xC4" => "\xE5\xB2\x8C", + "\xA7\xC5" => "\xE5\xB7\xAB", + "\xA7\xC6" => "\xE5\xB8\x8C", + "\xA7\xC7" => "\xE5\xBA\x8F", + "\xA7\xC8" => "\xE5\xBA\x87", + "\xA7\xC9" => "\xE5\xBA\x8A", + "\xA7\xCA" => "\xE5\xBB\xB7", + "\xA7\xCB" => "\xE5\xBC\x84", + "\xA7\xCC" => "\xE5\xBC\x9F", + "\xA7\xCD" => "\xE5\xBD\xA4", + "\xA7\xCE" => "\xE5\xBD\xA2", + "\xA7\xCF" => "\xE5\xBD\xB7", + "\xA7\xD0" => "\xE5\xBD\xB9", + "\xA7\xD1" => "\xE5\xBF\x98", + "\xA7\xD2" => "\xE5\xBF\x8C", + "\xA7\xD3" => "\xE5\xBF\x97", + "\xA7\xD4" => "\xE5\xBF\x8D", + "\xA7\xD5" => "\xE5\xBF\xB1", + "\xA7\xD6" => "\xE5\xBF\xAB", + "\xA7\xD7" => "\xE5\xBF\xB8", + "\xA7\xD8" => "\xE5\xBF\xAA", + "\xA7\xD9" => "\xE6\x88\x92", + "\xA7\xDA" => "\xE6\x88\x91", + "\xA7\xDB" => "\xE6\x8A\x84", + "\xA7\xDC" => "\xE6\x8A\x97", + "\xA7\xDD" => "\xE6\x8A\x96", + "\xA7\xDE" => "\xE6\x8A\x80", + "\xA7\xDF" => "\xE6\x89\xB6", + "\xA7\xE0" => "\xE6\x8A\x89", + "\xA7\xE1" => "\xE6\x89\xAD", + "\xA7\xE2" => "\xE6\x8A\x8A", + "\xA7\xE3" => "\xE6\x89\xBC", + "\xA7\xE4" => "\xE6\x89\xBE", + "\xA7\xE5" => "\xE6\x89\xB9", + "\xA7\xE6" => "\xE6\x89\xB3", + "\xA7\xE7" => "\xE6\x8A\x92", + "\xA7\xE8" => "\xE6\x89\xAF", + "\xA7\xE9" => "\xE6\x8A\x98", + "\xA7\xEA" => "\xE6\x89\xAE", + "\xA7\xEB" => "\xE6\x8A\x95", + "\xA7\xEC" => "\xE6\x8A\x93", + "\xA7\xED" => "\xE6\x8A\x91", + "\xA7\xEE" => "\xE6\x8A\x86", + "\xA7\xEF" => "\xE6\x94\xB9", + "\xA7\xF0" => "\xE6\x94\xBB", + "\xA7\xF1" => "\xE6\x94\xB8", + "\xA7\xF2" => "\xE6\x97\xB1", + "\xA7\xF3" => "\xE6\x9B\xB4", + "\xA7\xF4" => "\xE6\x9D\x9F", + "\xA7\xF5" => "\xE6\x9D\x8E", + "\xA7\xF6" => "\xE6\x9D\x8F", + "\xA7\xF7" => "\xE6\x9D\x90", + "\xA7\xF8" => "\xE6\x9D\x91", + "\xA7\xF9" => "\xE6\x9D\x9C", + "\xA7\xFA" => "\xE6\x9D\x96", + "\xA7\xFB" => "\xE6\x9D\x9E", + "\xA7\xFC" => "\xE6\x9D\x89", + "\xA7\xFD" => "\xE6\x9D\x86", + "\xA7\xFE" => "\xE6\x9D\xA0", + "\xA8\x40" => "\xE6\x9D\x93", + "\xA8\x41" => "\xE6\x9D\x97", + "\xA8\x42" => "\xE6\xAD\xA5", + "\xA8\x43" => "\xE6\xAF\x8F", + "\xA8\x44" => "\xE6\xB1\x82", + "\xA8\x45" => "\xE6\xB1\x9E", + "\xA8\x46" => "\xE6\xB2\x99", + "\xA8\x47" => "\xE6\xB2\x81", + "\xA8\x48" => "\xE6\xB2\x88", + "\xA8\x49" => "\xE6\xB2\x89", + "\xA8\x4A" => "\xE6\xB2\x85", + "\xA8\x4B" => "\xE6\xB2\x9B", + "\xA8\x4C" => "\xE6\xB1\xAA", + "\xA8\x4D" => "\xE6\xB1\xBA", + "\xA8\x4E" => "\xE6\xB2\x90", + "\xA8\x4F" => "\xE6\xB1\xB0", + "\xA8\x50" => "\xE6\xB2\x8C", + "\xA8\x51" => "\xE6\xB1\xA8", + "\xA8\x52" => "\xE6\xB2\x96", + "\xA8\x53" => "\xE6\xB2\x92", + "\xA8\x54" => "\xE6\xB1\xBD", + "\xA8\x55" => "\xE6\xB2\x83", + "\xA8\x56" => "\xE6\xB1\xB2", + "\xA8\x57" => "\xE6\xB1\xBE", + "\xA8\x58" => "\xE6\xB1\xB4", + "\xA8\x59" => "\xE6\xB2\x86", + "\xA8\x5A" => "\xE6\xB1\xB6", + "\xA8\x5B" => "\xE6\xB2\x8D", + "\xA8\x5C" => "\xE6\xB2\x94", + "\xA8\x5D" => "\xE6\xB2\x98", + "\xA8\x5E" => "\xE6\xB2\x82", + "\xA8\x5F" => "\xE7\x81\xB6", + "\xA8\x60" => "\xE7\x81\xBC", + "\xA8\x61" => "\xE7\x81\xBD", + "\xA8\x62" => "\xE7\x81\xB8", + "\xA8\x63" => "\xE7\x89\xA2", + "\xA8\x64" => "\xE7\x89\xA1", + "\xA8\x65" => "\xE7\x89\xA0", + "\xA8\x66" => "\xE7\x8B\x84", + "\xA8\x67" => "\xE7\x8B\x82", + "\xA8\x68" => "\xE7\x8E\x96", + "\xA8\x69" => "\xE7\x94\xAC", + "\xA8\x6A" => "\xE7\x94\xAB", + "\xA8\x6B" => "\xE7\x94\xB7", + "\xA8\x6C" => "\xE7\x94\xB8", + "\xA8\x6D" => "\xE7\x9A\x82", + "\xA8\x6E" => "\xE7\x9B\xAF", + "\xA8\x6F" => "\xE7\x9F\xA3", + "\xA8\x70" => "\xE7\xA7\x81", + "\xA8\x71" => "\xE7\xA7\x80", + "\xA8\x72" => "\xE7\xA6\xBF", + "\xA8\x73" => "\xE7\xA9\xB6", + "\xA8\x74" => "\xE7\xB3\xBB", + "\xA8\x75" => "\xE7\xBD\x95", + "\xA8\x76" => "\xE8\x82\x96", + "\xA8\x77" => "\xE8\x82\x93", + "\xA8\x78" => "\xE8\x82\x9D", + "\xA8\x79" => "\xE8\x82\x98", + "\xA8\x7A" => "\xE8\x82\x9B", + "\xA8\x7B" => "\xE8\x82\x9A", + "\xA8\x7C" => "\xE8\x82\xB2", + "\xA8\x7D" => "\xE8\x89\xAF", + "\xA8\x7E" => "\xE8\x8A\x92", + "\xA8\xA1" => "\xE8\x8A\x8B", + "\xA8\xA2" => "\xE8\x8A\x8D", + "\xA8\xA3" => "\xE8\xA6\x8B", + "\xA8\xA4" => "\xE8\xA7\x92", + "\xA8\xA5" => "\xE8\xA8\x80", + "\xA8\xA6" => "\xE8\xB0\xB7", + "\xA8\xA7" => "\xE8\xB1\x86", + "\xA8\xA8" => "\xE8\xB1\x95", + "\xA8\xA9" => "\xE8\xB2\x9D", + "\xA8\xAA" => "\xE8\xB5\xA4", + "\xA8\xAB" => "\xE8\xB5\xB0", + "\xA8\xAC" => "\xE8\xB6\xB3", + "\xA8\xAD" => "\xE8\xBA\xAB", + "\xA8\xAE" => "\xE8\xBB\x8A", + "\xA8\xAF" => "\xE8\xBE\x9B", + "\xA8\xB0" => "\xE8\xBE\xB0", + "\xA8\xB1" => "\xE8\xBF\x82", + "\xA8\xB2" => "\xE8\xBF\x86", + "\xA8\xB3" => "\xE8\xBF\x85", + "\xA8\xB4" => "\xE8\xBF\x84", + "\xA8\xB5" => "\xE5\xB7\xA1", + "\xA8\xB6" => "\xE9\x82\x91", + "\xA8\xB7" => "\xE9\x82\xA2", + "\xA8\xB8" => "\xE9\x82\xAA", + "\xA8\xB9" => "\xE9\x82\xA6", + "\xA8\xBA" => "\xE9\x82\xA3", + "\xA8\xBB" => "\xE9\x85\x89", + "\xA8\xBC" => "\xE9\x87\x86", + "\xA8\xBD" => "\xE9\x87\x8C", + "\xA8\xBE" => "\xE9\x98\xB2", + "\xA8\xBF" => "\xE9\x98\xAE", + "\xA8\xC0" => "\xE9\x98\xB1", + "\xA8\xC1" => "\xE9\x98\xAA", + "\xA8\xC2" => "\xE9\x98\xAC", + "\xA8\xC3" => "\xE4\xB8\xA6", + "\xA8\xC4" => "\xE4\xB9\x96", + "\xA8\xC5" => "\xE4\xB9\xB3", + "\xA8\xC6" => "\xE4\xBA\x8B", + "\xA8\xC7" => "\xE4\xBA\x9B", + "\xA8\xC8" => "\xE4\xBA\x9E", + "\xA8\xC9" => "\xE4\xBA\xAB", + "\xA8\xCA" => "\xE4\xBA\xAC", + "\xA8\xCB" => "\xE4\xBD\xAF", + "\xA8\xCC" => "\xE4\xBE\x9D", + "\xA8\xCD" => "\xE4\xBE\x8D", + "\xA8\xCE" => "\xE4\xBD\xB3", + "\xA8\xCF" => "\xE4\xBD\xBF", + "\xA8\xD0" => "\xE4\xBD\xAC", + "\xA8\xD1" => "\xE4\xBE\x9B", + "\xA8\xD2" => "\xE4\xBE\x8B", + "\xA8\xD3" => "\xE4\xBE\x86", + "\xA8\xD4" => "\xE4\xBE\x83", + "\xA8\xD5" => "\xE4\xBD\xB0", + "\xA8\xD6" => "\xE4\xBD\xB5", + "\xA8\xD7" => "\xE4\xBE\x88", + "\xA8\xD8" => "\xE4\xBD\xA9", + "\xA8\xD9" => "\xE4\xBD\xBB", + "\xA8\xDA" => "\xE4\xBE\x96", + "\xA8\xDB" => "\xE4\xBD\xBE", + "\xA8\xDC" => "\xE4\xBE\x8F", + "\xA8\xDD" => "\xE4\xBE\x91", + "\xA8\xDE" => "\xE4\xBD\xBA", + "\xA8\xDF" => "\xE5\x85\x94", + "\xA8\xE0" => "\xE5\x85\x92", + "\xA8\xE1" => "\xE5\x85\x95", + "\xA8\xE2" => "\xE5\x85\xA9", + "\xA8\xE3" => "\xE5\x85\xB7", + "\xA8\xE4" => "\xE5\x85\xB6", + "\xA8\xE5" => "\xE5\x85\xB8", + "\xA8\xE6" => "\xE5\x86\xBD", + "\xA8\xE7" => "\xE5\x87\xBD", + "\xA8\xE8" => "\xE5\x88\xBB", + "\xA8\xE9" => "\xE5\x88\xB8", + "\xA8\xEA" => "\xE5\x88\xB7", + "\xA8\xEB" => "\xE5\x88\xBA", + "\xA8\xEC" => "\xE5\x88\xB0", + "\xA8\xED" => "\xE5\x88\xAE", + "\xA8\xEE" => "\xE5\x88\xB6", + "\xA8\xEF" => "\xE5\x89\x81", + "\xA8\xF0" => "\xE5\x8A\xBE", + "\xA8\xF1" => "\xE5\x8A\xBB", + "\xA8\xF2" => "\xE5\x8D\x92", + "\xA8\xF3" => "\xE5\x8D\x94", + "\xA8\xF4" => "\xE5\x8D\x93", + "\xA8\xF5" => "\xE5\x8D\x91", + "\xA8\xF6" => "\xE5\x8D\xA6", + "\xA8\xF7" => "\xE5\x8D\xB7", + "\xA8\xF8" => "\xE5\x8D\xB8", + "\xA8\xF9" => "\xE5\x8D\xB9", + "\xA8\xFA" => "\xE5\x8F\x96", + "\xA8\xFB" => "\xE5\x8F\x94", + "\xA8\xFC" => "\xE5\x8F\x97", + "\xA8\xFD" => "\xE5\x91\xB3", + "\xA8\xFE" => "\xE5\x91\xB5", + "\xA9\x40" => "\xE5\x92\x96", + "\xA9\x41" => "\xE5\x91\xB8", + "\xA9\x42" => "\xE5\x92\x95", + "\xA9\x43" => "\xE5\x92\x80", + "\xA9\x44" => "\xE5\x91\xBB", + "\xA9\x45" => "\xE5\x91\xB7", + "\xA9\x46" => "\xE5\x92\x84", + "\xA9\x47" => "\xE5\x92\x92", + "\xA9\x48" => "\xE5\x92\x86", + "\xA9\x49" => "\xE5\x91\xBC", + "\xA9\x4A" => "\xE5\x92\x90", + "\xA9\x4B" => "\xE5\x91\xB1", + "\xA9\x4C" => "\xE5\x91\xB6", + "\xA9\x4D" => "\xE5\x92\x8C", + "\xA9\x4E" => "\xE5\x92\x9A", + "\xA9\x4F" => "\xE5\x91\xA2", + "\xA9\x50" => "\xE5\x91\xA8", + "\xA9\x51" => "\xE5\x92\x8B", + "\xA9\x52" => "\xE5\x91\xBD", + "\xA9\x53" => "\xE5\x92\x8E", + "\xA9\x54" => "\xE5\x9B\xBA", + "\xA9\x55" => "\xE5\x9E\x83", + "\xA9\x56" => "\xE5\x9D\xB7", + "\xA9\x57" => "\xE5\x9D\xAA", + "\xA9\x58" => "\xE5\x9D\xA9", + "\xA9\x59" => "\xE5\x9D\xA1", + "\xA9\x5A" => "\xE5\x9D\xA6", + "\xA9\x5B" => "\xE5\x9D\xA4", + "\xA9\x5C" => "\xE5\x9D\xBC", + "\xA9\x5D" => "\xE5\xA4\x9C", + "\xA9\x5E" => "\xE5\xA5\x89", + "\xA9\x5F" => "\xE5\xA5\x87", + "\xA9\x60" => "\xE5\xA5\x88", + "\xA9\x61" => "\xE5\xA5\x84", + "\xA9\x62" => "\xE5\xA5\x94", + "\xA9\x63" => "\xE5\xA6\xBE", + "\xA9\x64" => "\xE5\xA6\xBB", + "\xA9\x65" => "\xE5\xA7\x94", + "\xA9\x66" => "\xE5\xA6\xB9", + "\xA9\x67" => "\xE5\xA6\xAE", + "\xA9\x68" => "\xE5\xA7\x91", + "\xA9\x69" => "\xE5\xA7\x86", + "\xA9\x6A" => "\xE5\xA7\x90", + "\xA9\x6B" => "\xE5\xA7\x8D", + "\xA9\x6C" => "\xE5\xA7\x8B", + "\xA9\x6D" => "\xE5\xA7\x93", + "\xA9\x6E" => "\xE5\xA7\x8A", + "\xA9\x6F" => "\xE5\xA6\xAF", + "\xA9\x70" => "\xE5\xA6\xB3", + "\xA9\x71" => "\xE5\xA7\x92", + "\xA9\x72" => "\xE5\xA7\x85", + "\xA9\x73" => "\xE5\xAD\x9F", + "\xA9\x74" => "\xE5\xAD\xA4", + "\xA9\x75" => "\xE5\xAD\xA3", + "\xA9\x76" => "\xE5\xAE\x97", + "\xA9\x77" => "\xE5\xAE\x9A", + "\xA9\x78" => "\xE5\xAE\x98", + "\xA9\x79" => "\xE5\xAE\x9C", + "\xA9\x7A" => "\xE5\xAE\x99", + "\xA9\x7B" => "\xE5\xAE\x9B", + "\xA9\x7C" => "\xE5\xB0\x9A", + "\xA9\x7D" => "\xE5\xB1\x88", + "\xA9\x7E" => "\xE5\xB1\x85", + "\xA9\xA1" => "\xE5\xB1\x86", + "\xA9\xA2" => "\xE5\xB2\xB7", + "\xA9\xA3" => "\xE5\xB2\xA1", + "\xA9\xA4" => "\xE5\xB2\xB8", + "\xA9\xA5" => "\xE5\xB2\xA9", + "\xA9\xA6" => "\xE5\xB2\xAB", + "\xA9\xA7" => "\xE5\xB2\xB1", + "\xA9\xA8" => "\xE5\xB2\xB3", + "\xA9\xA9" => "\xE5\xB8\x98", + "\xA9\xAA" => "\xE5\xB8\x9A", + "\xA9\xAB" => "\xE5\xB8\x96", + "\xA9\xAC" => "\xE5\xB8\x95", + "\xA9\xAD" => "\xE5\xB8\x9B", + "\xA9\xAE" => "\xE5\xB8\x91", + "\xA9\xAF" => "\xE5\xB9\xB8", + "\xA9\xB0" => "\xE5\xBA\x9A", + "\xA9\xB1" => "\xE5\xBA\x97", + "\xA9\xB2" => "\xE5\xBA\x9C", + "\xA9\xB3" => "\xE5\xBA\x95", + "\xA9\xB4" => "\xE5\xBA\x96", + "\xA9\xB5" => "\xE5\xBB\xB6", + "\xA9\xB6" => "\xE5\xBC\xA6", + "\xA9\xB7" => "\xE5\xBC\xA7", + "\xA9\xB8" => "\xE5\xBC\xA9", + "\xA9\xB9" => "\xE5\xBE\x80", + "\xA9\xBA" => "\xE5\xBE\x81", + "\xA9\xBB" => "\xE5\xBD\xBF", + "\xA9\xBC" => "\xE5\xBD\xBC", + "\xA9\xBD" => "\xE5\xBF\x9D", + "\xA9\xBE" => "\xE5\xBF\xA0", + "\xA9\xBF" => "\xE5\xBF\xBD", + "\xA9\xC0" => "\xE5\xBF\xB5", + "\xA9\xC1" => "\xE5\xBF\xBF", + "\xA9\xC2" => "\xE6\x80\x8F", + "\xA9\xC3" => "\xE6\x80\x94", + "\xA9\xC4" => "\xE6\x80\xAF", + "\xA9\xC5" => "\xE6\x80\xB5", + "\xA9\xC6" => "\xE6\x80\x96", + "\xA9\xC7" => "\xE6\x80\xAA", + "\xA9\xC8" => "\xE6\x80\x95", + "\xA9\xC9" => "\xE6\x80\xA1", + "\xA9\xCA" => "\xE6\x80\xA7", + "\xA9\xCB" => "\xE6\x80\xA9", + "\xA9\xCC" => "\xE6\x80\xAB", + "\xA9\xCD" => "\xE6\x80\x9B", + "\xA9\xCE" => "\xE6\x88\x96", + "\xA9\xCF" => "\xE6\x88\x95", + "\xA9\xD0" => "\xE6\x88\xBF", + "\xA9\xD1" => "\xE6\x88\xBE", + "\xA9\xD2" => "\xE6\x89\x80", + "\xA9\xD3" => "\xE6\x89\xBF", + "\xA9\xD4" => "\xE6\x8B\x89", + "\xA9\xD5" => "\xE6\x8B\x8C", + "\xA9\xD6" => "\xE6\x8B\x84", + "\xA9\xD7" => "\xE6\x8A\xBF", + "\xA9\xD8" => "\xE6\x8B\x82", + "\xA9\xD9" => "\xE6\x8A\xB9", + "\xA9\xDA" => "\xE6\x8B\x92", + "\xA9\xDB" => "\xE6\x8B\x9B", + "\xA9\xDC" => "\xE6\x8A\xAB", + "\xA9\xDD" => "\xE6\x8B\x93", + "\xA9\xDE" => "\xE6\x8B\x94", + "\xA9\xDF" => "\xE6\x8B\x8B", + "\xA9\xE0" => "\xE6\x8B\x88", + "\xA9\xE1" => "\xE6\x8A\xA8", + "\xA9\xE2" => "\xE6\x8A\xBD", + "\xA9\xE3" => "\xE6\x8A\xBC", + "\xA9\xE4" => "\xE6\x8B\x90", + "\xA9\xE5" => "\xE6\x8B\x99", + "\xA9\xE6" => "\xE6\x8B\x87", + "\xA9\xE7" => "\xE6\x8B\x8D", + "\xA9\xE8" => "\xE6\x8A\xB5", + "\xA9\xE9" => "\xE6\x8B\x9A", + "\xA9\xEA" => "\xE6\x8A\xB1", + "\xA9\xEB" => "\xE6\x8B\x98", + "\xA9\xEC" => "\xE6\x8B\x96", + "\xA9\xED" => "\xE6\x8B\x97", + "\xA9\xEE" => "\xE6\x8B\x86", + "\xA9\xEF" => "\xE6\x8A\xAC", + "\xA9\xF0" => "\xE6\x8B\x8E", + "\xA9\xF1" => "\xE6\x94\xBE", + "\xA9\xF2" => "\xE6\x96\xA7", + "\xA9\xF3" => "\xE6\x96\xBC", + "\xA9\xF4" => "\xE6\x97\xBA", + "\xA9\xF5" => "\xE6\x98\x94", + "\xA9\xF6" => "\xE6\x98\x93", + "\xA9\xF7" => "\xE6\x98\x8C", + "\xA9\xF8" => "\xE6\x98\x86", + "\xA9\xF9" => "\xE6\x98\x82", + "\xA9\xFA" => "\xE6\x98\x8E", + "\xA9\xFB" => "\xE6\x98\x80", + "\xA9\xFC" => "\xE6\x98\x8F", + "\xA9\xFD" => "\xE6\x98\x95", + "\xA9\xFE" => "\xE6\x98\x8A", + "\xAA\x40" => "\xE6\x98\x87", + "\xAA\x41" => "\xE6\x9C\x8D", + "\xAA\x42" => "\xE6\x9C\x8B", + "\xAA\x43" => "\xE6\x9D\xAD", + "\xAA\x44" => "\xE6\x9E\x8B", + "\xAA\x45" => "\xE6\x9E\x95", + "\xAA\x46" => "\xE6\x9D\xB1", + "\xAA\x47" => "\xE6\x9E\x9C", + "\xAA\x48" => "\xE6\x9D\xB3", + "\xAA\x49" => "\xE6\x9D\xB7", + "\xAA\x4A" => "\xE6\x9E\x87", + "\xAA\x4B" => "\xE6\x9E\x9D", + "\xAA\x4C" => "\xE6\x9E\x97", + "\xAA\x4D" => "\xE6\x9D\xAF", + "\xAA\x4E" => "\xE6\x9D\xB0", + "\xAA\x4F" => "\xE6\x9D\xBF", + "\xAA\x50" => "\xE6\x9E\x89", + "\xAA\x51" => "\xE6\x9D\xBE", + "\xAA\x52" => "\xE6\x9E\x90", + "\xAA\x53" => "\xE6\x9D\xB5", + "\xAA\x54" => "\xE6\x9E\x9A", + "\xAA\x55" => "\xE6\x9E\x93", + "\xAA\x56" => "\xE6\x9D\xBC", + "\xAA\x57" => "\xE6\x9D\xAA", + "\xAA\x58" => "\xE6\x9D\xB2", + "\xAA\x59" => "\xE6\xAC\xA3", + "\xAA\x5A" => "\xE6\xAD\xA6", + "\xAA\x5B" => "\xE6\xAD\xA7", + "\xAA\x5C" => "\xE6\xAD\xBF", + "\xAA\x5D" => "\xE6\xB0\x93", + "\xAA\x5E" => "\xE6\xB0\x9B", + "\xAA\x5F" => "\xE6\xB3\xA3", + "\xAA\x60" => "\xE6\xB3\xA8", + "\xAA\x61" => "\xE6\xB3\xB3", + "\xAA\x62" => "\xE6\xB2\xB1", + "\xAA\x63" => "\xE6\xB3\x8C", + "\xAA\x64" => "\xE6\xB3\xA5", + "\xAA\x65" => "\xE6\xB2\xB3", + "\xAA\x66" => "\xE6\xB2\xBD", + "\xAA\x67" => "\xE6\xB2\xBE", + "\xAA\x68" => "\xE6\xB2\xBC", + "\xAA\x69" => "\xE6\xB3\xA2", + "\xAA\x6A" => "\xE6\xB2\xAB", + "\xAA\x6B" => "\xE6\xB3\x95", + "\xAA\x6C" => "\xE6\xB3\x93", + "\xAA\x6D" => "\xE6\xB2\xB8", + "\xAA\x6E" => "\xE6\xB3\x84", + "\xAA\x6F" => "\xE6\xB2\xB9", + "\xAA\x70" => "\xE6\xB3\x81", + "\xAA\x71" => "\xE6\xB2\xAE", + "\xAA\x72" => "\xE6\xB3\x97", + "\xAA\x73" => "\xE6\xB3\x85", + "\xAA\x74" => "\xE6\xB3\xB1", + "\xAA\x75" => "\xE6\xB2\xBF", + "\xAA\x76" => "\xE6\xB2\xBB", + "\xAA\x77" => "\xE6\xB3\xA1", + "\xAA\x78" => "\xE6\xB3\x9B", + "\xAA\x79" => "\xE6\xB3\x8A", + "\xAA\x7A" => "\xE6\xB2\xAC", + "\xAA\x7B" => "\xE6\xB3\xAF", + "\xAA\x7C" => "\xE6\xB3\x9C", + "\xAA\x7D" => "\xE6\xB3\x96", + "\xAA\x7E" => "\xE6\xB3\xA0", + "\xAA\xA1" => "\xE7\x82\x95", + "\xAA\xA2" => "\xE7\x82\x8E", + "\xAA\xA3" => "\xE7\x82\x92", + "\xAA\xA4" => "\xE7\x82\x8A", + "\xAA\xA5" => "\xE7\x82\x99", + "\xAA\xA6" => "\xE7\x88\xAC", + "\xAA\xA7" => "\xE7\x88\xAD", + "\xAA\xA8" => "\xE7\x88\xB8", + "\xAA\xA9" => "\xE7\x89\x88", + "\xAA\xAA" => "\xE7\x89\xA7", + "\xAA\xAB" => "\xE7\x89\xA9", + "\xAA\xAC" => "\xE7\x8B\x80", + "\xAA\xAD" => "\xE7\x8B\x8E", + "\xAA\xAE" => "\xE7\x8B\x99", + "\xAA\xAF" => "\xE7\x8B\x97", + "\xAA\xB0" => "\xE7\x8B\x90", + "\xAA\xB1" => "\xE7\x8E\xA9", + "\xAA\xB2" => "\xE7\x8E\xA8", + "\xAA\xB3" => "\xE7\x8E\x9F", + "\xAA\xB4" => "\xE7\x8E\xAB", + "\xAA\xB5" => "\xE7\x8E\xA5", + "\xAA\xB6" => "\xE7\x94\xBD", + "\xAA\xB7" => "\xE7\x96\x9D", + "\xAA\xB8" => "\xE7\x96\x99", + "\xAA\xB9" => "\xE7\x96\x9A", + "\xAA\xBA" => "\xE7\x9A\x84", + "\xAA\xBB" => "\xE7\x9B\x82", + "\xAA\xBC" => "\xE7\x9B\xB2", + "\xAA\xBD" => "\xE7\x9B\xB4", + "\xAA\xBE" => "\xE7\x9F\xA5", + "\xAA\xBF" => "\xE7\x9F\xBD", + "\xAA\xC0" => "\xE7\xA4\xBE", + "\xAA\xC1" => "\xE7\xA5\x80", + "\xAA\xC2" => "\xE7\xA5\x81", + "\xAA\xC3" => "\xE7\xA7\x89", + "\xAA\xC4" => "\xE7\xA7\x88", + "\xAA\xC5" => "\xE7\xA9\xBA", + "\xAA\xC6" => "\xE7\xA9\xB9", + "\xAA\xC7" => "\xE7\xAB\xBA", + "\xAA\xC8" => "\xE7\xB3\xBE", + "\xAA\xC9" => "\xE7\xBD\x94", + "\xAA\xCA" => "\xE7\xBE\x8C", + "\xAA\xCB" => "\xE7\xBE\x8B", + "\xAA\xCC" => "\xE8\x80\x85", + "\xAA\xCD" => "\xE8\x82\xBA", + "\xAA\xCE" => "\xE8\x82\xA5", + "\xAA\xCF" => "\xE8\x82\xA2", + "\xAA\xD0" => "\xE8\x82\xB1", + "\xAA\xD1" => "\xE8\x82\xA1", + "\xAA\xD2" => "\xE8\x82\xAB", + "\xAA\xD3" => "\xE8\x82\xA9", + "\xAA\xD4" => "\xE8\x82\xB4", + "\xAA\xD5" => "\xE8\x82\xAA", + "\xAA\xD6" => "\xE8\x82\xAF", + "\xAA\xD7" => "\xE8\x87\xA5", + "\xAA\xD8" => "\xE8\x87\xBE", + "\xAA\xD9" => "\xE8\x88\x8D", + "\xAA\xDA" => "\xE8\x8A\xB3", + "\xAA\xDB" => "\xE8\x8A\x9D", + "\xAA\xDC" => "\xE8\x8A\x99", + "\xAA\xDD" => "\xE8\x8A\xAD", + "\xAA\xDE" => "\xE8\x8A\xBD", + "\xAA\xDF" => "\xE8\x8A\x9F", + "\xAA\xE0" => "\xE8\x8A\xB9", + "\xAA\xE1" => "\xE8\x8A\xB1", + "\xAA\xE2" => "\xE8\x8A\xAC", + "\xAA\xE3" => "\xE8\x8A\xA5", + "\xAA\xE4" => "\xE8\x8A\xAF", + "\xAA\xE5" => "\xE8\x8A\xB8", + "\xAA\xE6" => "\xE8\x8A\xA3", + "\xAA\xE7" => "\xE8\x8A\xB0", + "\xAA\xE8" => "\xE8\x8A\xBE", + "\xAA\xE9" => "\xE8\x8A\xB7", + "\xAA\xEA" => "\xE8\x99\x8E", + "\xAA\xEB" => "\xE8\x99\xB1", + "\xAA\xEC" => "\xE5\x88\x9D", + "\xAA\xED" => "\xE8\xA1\xA8", + "\xAA\xEE" => "\xE8\xBB\x8B", + "\xAA\xEF" => "\xE8\xBF\x8E", + "\xAA\xF0" => "\xE8\xBF\x94", + "\xAA\xF1" => "\xE8\xBF\x91", + "\xAA\xF2" => "\xE9\x82\xB5", + "\xAA\xF3" => "\xE9\x82\xB8", + "\xAA\xF4" => "\xE9\x82\xB1", + "\xAA\xF5" => "\xE9\x82\xB6", + "\xAA\xF6" => "\xE9\x87\x87", + "\xAA\xF7" => "\xE9\x87\x91", + "\xAA\xF8" => "\xE9\x95\xB7", + "\xAA\xF9" => "\xE9\x96\x80", + "\xAA\xFA" => "\xE9\x98\x9C", + "\xAA\xFB" => "\xE9\x99\x80", + "\xAA\xFC" => "\xE9\x98\xBF", + "\xAA\xFD" => "\xE9\x98\xBB", + "\xAA\xFE" => "\xE9\x99\x84", + "\xAB\x40" => "\xE9\x99\x82", + "\xAB\x41" => "\xE9\x9A\xB9", + "\xAB\x42" => "\xE9\x9B\xA8", + "\xAB\x43" => "\xE9\x9D\x92", + "\xAB\x44" => "\xE9\x9D\x9E", + "\xAB\x45" => "\xE4\xBA\x9F", + "\xAB\x46" => "\xE4\xBA\xAD", + "\xAB\x47" => "\xE4\xBA\xAE", + "\xAB\x48" => "\xE4\xBF\xA1", + "\xAB\x49" => "\xE4\xBE\xB5", + "\xAB\x4A" => "\xE4\xBE\xAF", + "\xAB\x4B" => "\xE4\xBE\xBF", + "\xAB\x4C" => "\xE4\xBF\xA0", + "\xAB\x4D" => "\xE4\xBF\x91", + "\xAB\x4E" => "\xE4\xBF\x8F", + "\xAB\x4F" => "\xE4\xBF\x9D", + "\xAB\x50" => "\xE4\xBF\x83", + "\xAB\x51" => "\xE4\xBE\xB6", + "\xAB\x52" => "\xE4\xBF\x98", + "\xAB\x53" => "\xE4\xBF\x9F", + "\xAB\x54" => "\xE4\xBF\x8A", + "\xAB\x55" => "\xE4\xBF\x97", + "\xAB\x56" => "\xE4\xBE\xAE", + "\xAB\x57" => "\xE4\xBF\x90", + "\xAB\x58" => "\xE4\xBF\x84", + "\xAB\x59" => "\xE4\xBF\x82", + "\xAB\x5A" => "\xE4\xBF\x9A", + "\xAB\x5B" => "\xE4\xBF\x8E", + "\xAB\x5C" => "\xE4\xBF\x9E", + "\xAB\x5D" => "\xE4\xBE\xB7", + "\xAB\x5E" => "\xE5\x85\x97", + "\xAB\x5F" => "\xE5\x86\x92", + "\xAB\x60" => "\xE5\x86\x91", + "\xAB\x61" => "\xE5\x86\xA0", + "\xAB\x62" => "\xE5\x89\x8E", + "\xAB\x63" => "\xE5\x89\x83", + "\xAB\x64" => "\xE5\x89\x8A", + "\xAB\x65" => "\xE5\x89\x8D", + "\xAB\x66" => "\xE5\x89\x8C", + "\xAB\x67" => "\xE5\x89\x8B", + "\xAB\x68" => "\xE5\x89\x87", + "\xAB\x69" => "\xE5\x8B\x87", + "\xAB\x6A" => "\xE5\x8B\x89", + "\xAB\x6B" => "\xE5\x8B\x83", + "\xAB\x6C" => "\xE5\x8B\x81", + "\xAB\x6D" => "\xE5\x8C\x8D", + "\xAB\x6E" => "\xE5\x8D\x97", + "\xAB\x6F" => "\xE5\x8D\xBB", + "\xAB\x70" => "\xE5\x8E\x9A", + "\xAB\x71" => "\xE5\x8F\x9B", + "\xAB\x72" => "\xE5\x92\xAC", + "\xAB\x73" => "\xE5\x93\x80", + "\xAB\x74" => "\xE5\x92\xA8", + "\xAB\x75" => "\xE5\x93\x8E", + "\xAB\x76" => "\xE5\x93\x89", + "\xAB\x77" => "\xE5\x92\xB8", + "\xAB\x78" => "\xE5\x92\xA6", + "\xAB\x79" => "\xE5\x92\xB3", + "\xAB\x7A" => "\xE5\x93\x87", + "\xAB\x7B" => "\xE5\x93\x82", + "\xAB\x7C" => "\xE5\x92\xBD", + "\xAB\x7D" => "\xE5\x92\xAA", + "\xAB\x7E" => "\xE5\x93\x81", + "\xAB\xA1" => "\xE5\x93\x84", + "\xAB\xA2" => "\xE5\x93\x88", + "\xAB\xA3" => "\xE5\x92\xAF", + "\xAB\xA4" => "\xE5\x92\xAB", + "\xAB\xA5" => "\xE5\x92\xB1", + "\xAB\xA6" => "\xE5\x92\xBB", + "\xAB\xA7" => "\xE5\x92\xA9", + "\xAB\xA8" => "\xE5\x92\xA7", + "\xAB\xA9" => "\xE5\x92\xBF", + "\xAB\xAA" => "\xE5\x9B\xBF", + "\xAB\xAB" => "\xE5\x9E\x82", + "\xAB\xAC" => "\xE5\x9E\x8B", + "\xAB\xAD" => "\xE5\x9E\xA0", + "\xAB\xAE" => "\xE5\x9E\xA3", + "\xAB\xAF" => "\xE5\x9E\xA2", + "\xAB\xB0" => "\xE5\x9F\x8E", + "\xAB\xB1" => "\xE5\x9E\xAE", + "\xAB\xB2" => "\xE5\x9E\x93", + "\xAB\xB3" => "\xE5\xA5\x95", + "\xAB\xB4" => "\xE5\xA5\x91", + "\xAB\xB5" => "\xE5\xA5\x8F", + "\xAB\xB6" => "\xE5\xA5\x8E", + "\xAB\xB7" => "\xE5\xA5\x90", + "\xAB\xB8" => "\xE5\xA7\x9C", + "\xAB\xB9" => "\xE5\xA7\x98", + "\xAB\xBA" => "\xE5\xA7\xBF", + "\xAB\xBB" => "\xE5\xA7\xA3", + "\xAB\xBC" => "\xE5\xA7\xA8", + "\xAB\xBD" => "\xE5\xA8\x83", + "\xAB\xBE" => "\xE5\xA7\xA5", + "\xAB\xBF" => "\xE5\xA7\xAA", + "\xAB\xC0" => "\xE5\xA7\x9A", + "\xAB\xC1" => "\xE5\xA7\xA6", + "\xAB\xC2" => "\xE5\xA8\x81", + "\xAB\xC3" => "\xE5\xA7\xBB", + "\xAB\xC4" => "\xE5\xAD\xA9", + "\xAB\xC5" => "\xE5\xAE\xA3", + "\xAB\xC6" => "\xE5\xAE\xA6", + "\xAB\xC7" => "\xE5\xAE\xA4", + "\xAB\xC8" => "\xE5\xAE\xA2", + "\xAB\xC9" => "\xE5\xAE\xA5", + "\xAB\xCA" => "\xE5\xB0\x81", + "\xAB\xCB" => "\xE5\xB1\x8E", + "\xAB\xCC" => "\xE5\xB1\x8F", + "\xAB\xCD" => "\xE5\xB1\x8D", + "\xAB\xCE" => "\xE5\xB1\x8B", + "\xAB\xCF" => "\xE5\xB3\x99", + "\xAB\xD0" => "\xE5\xB3\x92", + "\xAB\xD1" => "\xE5\xB7\xB7", + "\xAB\xD2" => "\xE5\xB8\x9D", + "\xAB\xD3" => "\xE5\xB8\xA5", + "\xAB\xD4" => "\xE5\xB8\x9F", + "\xAB\xD5" => "\xE5\xB9\xBD", + "\xAB\xD6" => "\xE5\xBA\xA0", + "\xAB\xD7" => "\xE5\xBA\xA6", + "\xAB\xD8" => "\xE5\xBB\xBA", + "\xAB\xD9" => "\xE5\xBC\x88", + "\xAB\xDA" => "\xE5\xBC\xAD", + "\xAB\xDB" => "\xE5\xBD\xA5", + "\xAB\xDC" => "\xE5\xBE\x88", + "\xAB\xDD" => "\xE5\xBE\x85", + "\xAB\xDE" => "\xE5\xBE\x8A", + "\xAB\xDF" => "\xE5\xBE\x8B", + "\xAB\xE0" => "\xE5\xBE\x87", + "\xAB\xE1" => "\xE5\xBE\x8C", + "\xAB\xE2" => "\xE5\xBE\x89", + "\xAB\xE3" => "\xE6\x80\x92", + "\xAB\xE4" => "\xE6\x80\x9D", + "\xAB\xE5" => "\xE6\x80\xA0", + "\xAB\xE6" => "\xE6\x80\xA5", + "\xAB\xE7" => "\xE6\x80\x8E", + "\xAB\xE8" => "\xE6\x80\xA8", + "\xAB\xE9" => "\xE6\x81\x8D", + "\xAB\xEA" => "\xE6\x81\xB0", + "\xAB\xEB" => "\xE6\x81\xA8", + "\xAB\xEC" => "\xE6\x81\xA2", + "\xAB\xED" => "\xE6\x81\x86", + "\xAB\xEE" => "\xE6\x81\x83", + "\xAB\xEF" => "\xE6\x81\xAC", + "\xAB\xF0" => "\xE6\x81\xAB", + "\xAB\xF1" => "\xE6\x81\xAA", + "\xAB\xF2" => "\xE6\x81\xA4", + "\xAB\xF3" => "\xE6\x89\x81", + "\xAB\xF4" => "\xE6\x8B\x9C", + "\xAB\xF5" => "\xE6\x8C\x96", + "\xAB\xF6" => "\xE6\x8C\x89", + "\xAB\xF7" => "\xE6\x8B\xBC", + "\xAB\xF8" => "\xE6\x8B\xAD", + "\xAB\xF9" => "\xE6\x8C\x81", + "\xAB\xFA" => "\xE6\x8B\xAE", + "\xAB\xFB" => "\xE6\x8B\xBD", + "\xAB\xFC" => "\xE6\x8C\x87", + "\xAB\xFD" => "\xE6\x8B\xB1", + "\xAB\xFE" => "\xE6\x8B\xB7", + "\xAC\x40" => "\xE6\x8B\xAF", + "\xAC\x41" => "\xE6\x8B\xAC", + "\xAC\x42" => "\xE6\x8B\xBE", + "\xAC\x43" => "\xE6\x8B\xB4", + "\xAC\x44" => "\xE6\x8C\x91", + "\xAC\x45" => "\xE6\x8C\x82", + "\xAC\x46" => "\xE6\x94\xBF", + "\xAC\x47" => "\xE6\x95\x85", + "\xAC\x48" => "\xE6\x96\xAB", + "\xAC\x49" => "\xE6\x96\xBD", + "\xAC\x4A" => "\xE6\x97\xA2", + "\xAC\x4B" => "\xE6\x98\xA5", + "\xAC\x4C" => "\xE6\x98\xAD", + "\xAC\x4D" => "\xE6\x98\xA0", + "\xAC\x4E" => "\xE6\x98\xA7", + "\xAC\x4F" => "\xE6\x98\xAF", + "\xAC\x50" => "\xE6\x98\x9F", + "\xAC\x51" => "\xE6\x98\xA8", + "\xAC\x52" => "\xE6\x98\xB1", + "\xAC\x53" => "\xE6\x98\xA4", + "\xAC\x54" => "\xE6\x9B\xB7", + "\xAC\x55" => "\xE6\x9F\xBF", + "\xAC\x56" => "\xE6\x9F\x93", + "\xAC\x57" => "\xE6\x9F\xB1", + "\xAC\x58" => "\xE6\x9F\x94", + "\xAC\x59" => "\xE6\x9F\x90", + "\xAC\x5A" => "\xE6\x9F\xAC", + "\xAC\x5B" => "\xE6\x9E\xB6", + "\xAC\x5C" => "\xE6\x9E\xAF", + "\xAC\x5D" => "\xE6\x9F\xB5", + "\xAC\x5E" => "\xE6\x9F\xA9", + "\xAC\x5F" => "\xE6\x9F\xAF", + "\xAC\x60" => "\xE6\x9F\x84", + "\xAC\x61" => "\xE6\x9F\x91", + "\xAC\x62" => "\xE6\x9E\xB4", + "\xAC\x63" => "\xE6\x9F\x9A", + "\xAC\x64" => "\xE6\x9F\xA5", + "\xAC\x65" => "\xE6\x9E\xB8", + "\xAC\x66" => "\xE6\x9F\x8F", + "\xAC\x67" => "\xE6\x9F\x9E", + "\xAC\x68" => "\xE6\x9F\xB3", + "\xAC\x69" => "\xE6\x9E\xB0", + "\xAC\x6A" => "\xE6\x9F\x99", + "\xAC\x6B" => "\xE6\x9F\xA2", + "\xAC\x6C" => "\xE6\x9F\x9D", + "\xAC\x6D" => "\xE6\x9F\x92", + "\xAC\x6E" => "\xE6\xAD\xAA", + "\xAC\x6F" => "\xE6\xAE\x83", + "\xAC\x70" => "\xE6\xAE\x86", + "\xAC\x71" => "\xE6\xAE\xB5", + "\xAC\x72" => "\xE6\xAF\x92", + "\xAC\x73" => "\xE6\xAF\x97", + "\xAC\x74" => "\xE6\xB0\x9F", + "\xAC\x75" => "\xE6\xB3\x89", + "\xAC\x76" => "\xE6\xB4\x8B", + "\xAC\x77" => "\xE6\xB4\xB2", + "\xAC\x78" => "\xE6\xB4\xAA", + "\xAC\x79" => "\xE6\xB5\x81", + "\xAC\x7A" => "\xE6\xB4\xA5", + "\xAC\x7B" => "\xE6\xB4\x8C", + "\xAC\x7C" => "\xE6\xB4\xB1", + "\xAC\x7D" => "\xE6\xB4\x9E", + "\xAC\x7E" => "\xE6\xB4\x97", + "\xAC\xA1" => "\xE6\xB4\xBB", + "\xAC\xA2" => "\xE6\xB4\xBD", + "\xAC\xA3" => "\xE6\xB4\xBE", + "\xAC\xA4" => "\xE6\xB4\xB6", + "\xAC\xA5" => "\xE6\xB4\x9B", + "\xAC\xA6" => "\xE6\xB3\xB5", + "\xAC\xA7" => "\xE6\xB4\xB9", + "\xAC\xA8" => "\xE6\xB4\xA7", + "\xAC\xA9" => "\xE6\xB4\xB8", + "\xAC\xAA" => "\xE6\xB4\xA9", + "\xAC\xAB" => "\xE6\xB4\xAE", + "\xAC\xAC" => "\xE6\xB4\xB5", + "\xAC\xAD" => "\xE6\xB4\x8E", + "\xAC\xAE" => "\xE6\xB4\xAB", + "\xAC\xAF" => "\xE7\x82\xAB", + "\xAC\xB0" => "\xE7\x82\xBA", + "\xAC\xB1" => "\xE7\x82\xB3", + "\xAC\xB2" => "\xE7\x82\xAC", + "\xAC\xB3" => "\xE7\x82\xAF", + "\xAC\xB4" => "\xE7\x82\xAD", + "\xAC\xB5" => "\xE7\x82\xB8", + "\xAC\xB6" => "\xE7\x82\xAE", + "\xAC\xB7" => "\xE7\x82\xA4", + "\xAC\xB8" => "\xE7\x88\xB0", + "\xAC\xB9" => "\xE7\x89\xB2", + "\xAC\xBA" => "\xE7\x89\xAF", + "\xAC\xBB" => "\xE7\x89\xB4", + "\xAC\xBC" => "\xE7\x8B\xA9", + "\xAC\xBD" => "\xE7\x8B\xA0", + "\xAC\xBE" => "\xE7\x8B\xA1", + "\xAC\xBF" => "\xE7\x8E\xB7", + "\xAC\xC0" => "\xE7\x8F\x8A", + "\xAC\xC1" => "\xE7\x8E\xBB", + "\xAC\xC2" => "\xE7\x8E\xB2", + "\xAC\xC3" => "\xE7\x8F\x8D", + "\xAC\xC4" => "\xE7\x8F\x80", + "\xAC\xC5" => "\xE7\x8E\xB3", + "\xAC\xC6" => "\xE7\x94\x9A", + "\xAC\xC7" => "\xE7\x94\xAD", + "\xAC\xC8" => "\xE7\x95\x8F", + "\xAC\xC9" => "\xE7\x95\x8C", + "\xAC\xCA" => "\xE7\x95\x8E", + "\xAC\xCB" => "\xE7\x95\x8B", + "\xAC\xCC" => "\xE7\x96\xAB", + "\xAC\xCD" => "\xE7\x96\xA4", + "\xAC\xCE" => "\xE7\x96\xA5", + "\xAC\xCF" => "\xE7\x96\xA2", + "\xAC\xD0" => "\xE7\x96\xA3", + "\xAC\xD1" => "\xE7\x99\xB8", + "\xAC\xD2" => "\xE7\x9A\x86", + "\xAC\xD3" => "\xE7\x9A\x87", + "\xAC\xD4" => "\xE7\x9A\x88", + "\xAC\xD5" => "\xE7\x9B\x88", + "\xAC\xD6" => "\xE7\x9B\x86", + "\xAC\xD7" => "\xE7\x9B\x83", + "\xAC\xD8" => "\xE7\x9B\x85", + "\xAC\xD9" => "\xE7\x9C\x81", + "\xAC\xDA" => "\xE7\x9B\xB9", + "\xAC\xDB" => "\xE7\x9B\xB8", + "\xAC\xDC" => "\xE7\x9C\x89", + "\xAC\xDD" => "\xE7\x9C\x8B", + "\xAC\xDE" => "\xE7\x9B\xBE", + "\xAC\xDF" => "\xE7\x9B\xBC", + "\xAC\xE0" => "\xE7\x9C\x87", + "\xAC\xE1" => "\xE7\x9F\x9C", + "\xAC\xE2" => "\xE7\xA0\x82", + "\xAC\xE3" => "\xE7\xA0\x94", + "\xAC\xE4" => "\xE7\xA0\x8C", + "\xAC\xE5" => "\xE7\xA0\x8D", + "\xAC\xE6" => "\xE7\xA5\x86", + "\xAC\xE7" => "\xE7\xA5\x89", + "\xAC\xE8" => "\xE7\xA5\x88", + "\xAC\xE9" => "\xE7\xA5\x87", + "\xAC\xEA" => "\xE7\xA6\xB9", + "\xAC\xEB" => "\xE7\xA6\xBA", + "\xAC\xEC" => "\xE7\xA7\x91", + "\xAC\xED" => "\xE7\xA7\x92", + "\xAC\xEE" => "\xE7\xA7\x8B", + "\xAC\xEF" => "\xE7\xA9\xBF", + "\xAC\xF0" => "\xE7\xAA\x81", + "\xAC\xF1" => "\xE7\xAB\xBF", + "\xAC\xF2" => "\xE7\xAB\xBD", + "\xAC\xF3" => "\xE7\xB1\xBD", + "\xAC\xF4" => "\xE7\xB4\x82", + "\xAC\xF5" => "\xE7\xB4\x85", + "\xAC\xF6" => "\xE7\xB4\x80", + "\xAC\xF7" => "\xE7\xB4\x89", + "\xAC\xF8" => "\xE7\xB4\x87", + "\xAC\xF9" => "\xE7\xB4\x84", + "\xAC\xFA" => "\xE7\xB4\x86", + "\xAC\xFB" => "\xE7\xBC\xB8", + "\xAC\xFC" => "\xE7\xBE\x8E", + "\xAC\xFD" => "\xE7\xBE\xBF", + "\xAC\xFE" => "\xE8\x80\x84", + "\xAD\x40" => "\xE8\x80\x90", + "\xAD\x41" => "\xE8\x80\x8D", + "\xAD\x42" => "\xE8\x80\x91", + "\xAD\x43" => "\xE8\x80\xB6", + "\xAD\x44" => "\xE8\x83\x96", + "\xAD\x45" => "\xE8\x83\xA5", + "\xAD\x46" => "\xE8\x83\x9A", + "\xAD\x47" => "\xE8\x83\x83", + "\xAD\x48" => "\xE8\x83\x84", + "\xAD\x49" => "\xE8\x83\x8C", + "\xAD\x4A" => "\xE8\x83\xA1", + "\xAD\x4B" => "\xE8\x83\x9B", + "\xAD\x4C" => "\xE8\x83\x8E", + "\xAD\x4D" => "\xE8\x83\x9E", + "\xAD\x4E" => "\xE8\x83\xA4", + "\xAD\x4F" => "\xE8\x83\x9D", + "\xAD\x50" => "\xE8\x87\xB4", + "\xAD\x51" => "\xE8\x88\xA2", + "\xAD\x52" => "\xE8\x8B\xA7", + "\xAD\x53" => "\xE8\x8C\x83", + "\xAD\x54" => "\xE8\x8C\x85", + "\xAD\x55" => "\xE8\x8B\xA3", + "\xAD\x56" => "\xE8\x8B\x9B", + "\xAD\x57" => "\xE8\x8B\xA6", + "\xAD\x58" => "\xE8\x8C\x84", + "\xAD\x59" => "\xE8\x8B\xA5", + "\xAD\x5A" => "\xE8\x8C\x82", + "\xAD\x5B" => "\xE8\x8C\x89", + "\xAD\x5C" => "\xE8\x8B\x92", + "\xAD\x5D" => "\xE8\x8B\x97", + "\xAD\x5E" => "\xE8\x8B\xB1", + "\xAD\x5F" => "\xE8\x8C\x81", + "\xAD\x60" => "\xE8\x8B\x9C", + "\xAD\x61" => "\xE8\x8B\x94", + "\xAD\x62" => "\xE8\x8B\x91", + "\xAD\x63" => "\xE8\x8B\x9E", + "\xAD\x64" => "\xE8\x8B\x93", + "\xAD\x65" => "\xE8\x8B\x9F", + "\xAD\x66" => "\xE8\x8B\xAF", + "\xAD\x67" => "\xE8\x8C\x86", + "\xAD\x68" => "\xE8\x99\x90", + "\xAD\x69" => "\xE8\x99\xB9", + "\xAD\x6A" => "\xE8\x99\xBB", + "\xAD\x6B" => "\xE8\x99\xBA", + "\xAD\x6C" => "\xE8\xA1\x8D", + "\xAD\x6D" => "\xE8\xA1\xAB", + "\xAD\x6E" => "\xE8\xA6\x81", + "\xAD\x6F" => "\xE8\xA7\x94", + "\xAD\x70" => "\xE8\xA8\x88", + "\xAD\x71" => "\xE8\xA8\x82", + "\xAD\x72" => "\xE8\xA8\x83", + "\xAD\x73" => "\xE8\xB2\x9E", + "\xAD\x74" => "\xE8\xB2\xA0", + "\xAD\x75" => "\xE8\xB5\xB4", + "\xAD\x76" => "\xE8\xB5\xB3", + "\xAD\x77" => "\xE8\xB6\xB4", + "\xAD\x78" => "\xE8\xBB\x8D", + "\xAD\x79" => "\xE8\xBB\x8C", + "\xAD\x7A" => "\xE8\xBF\xB0", + "\xAD\x7B" => "\xE8\xBF\xA6", + "\xAD\x7C" => "\xE8\xBF\xA2", + "\xAD\x7D" => "\xE8\xBF\xAA", + "\xAD\x7E" => "\xE8\xBF\xA5", + "\xAD\xA1" => "\xE8\xBF\xAD", + "\xAD\xA2" => "\xE8\xBF\xAB", + "\xAD\xA3" => "\xE8\xBF\xA4", + "\xAD\xA4" => "\xE8\xBF\xA8", + "\xAD\xA5" => "\xE9\x83\x8A", + "\xAD\xA6" => "\xE9\x83\x8E", + "\xAD\xA7" => "\xE9\x83\x81", + "\xAD\xA8" => "\xE9\x83\x83", + "\xAD\xA9" => "\xE9\x85\x8B", + "\xAD\xAA" => "\xE9\x85\x8A", + "\xAD\xAB" => "\xE9\x87\x8D", + "\xAD\xAC" => "\xE9\x96\x82", + "\xAD\xAD" => "\xE9\x99\x90", + "\xAD\xAE" => "\xE9\x99\x8B", + "\xAD\xAF" => "\xE9\x99\x8C", + "\xAD\xB0" => "\xE9\x99\x8D", + "\xAD\xB1" => "\xE9\x9D\xA2", + "\xAD\xB2" => "\xE9\x9D\xA9", + "\xAD\xB3" => "\xE9\x9F\x8B", + "\xAD\xB4" => "\xE9\x9F\xAD", + "\xAD\xB5" => "\xE9\x9F\xB3", + "\xAD\xB6" => "\xE9\xA0\x81", + "\xAD\xB7" => "\xE9\xA2\xA8", + "\xAD\xB8" => "\xE9\xA3\x9B", + "\xAD\xB9" => "\xE9\xA3\x9F", + "\xAD\xBA" => "\xE9\xA6\x96", + "\xAD\xBB" => "\xE9\xA6\x99", + "\xAD\xBC" => "\xE4\xB9\x98", + "\xAD\xBD" => "\xE4\xBA\xB3", + "\xAD\xBE" => "\xE5\x80\x8C", + "\xAD\xBF" => "\xE5\x80\x8D", + "\xAD\xC0" => "\xE5\x80\xA3", + "\xAD\xC1" => "\xE4\xBF\xAF", + "\xAD\xC2" => "\xE5\x80\xA6", + "\xAD\xC3" => "\xE5\x80\xA5", + "\xAD\xC4" => "\xE4\xBF\xB8", + "\xAD\xC5" => "\xE5\x80\xA9", + "\xAD\xC6" => "\xE5\x80\x96", + "\xAD\xC7" => "\xE5\x80\x86", + "\xAD\xC8" => "\xE5\x80\xBC", + "\xAD\xC9" => "\xE5\x80\x9F", + "\xAD\xCA" => "\xE5\x80\x9A", + "\xAD\xCB" => "\xE5\x80\x92", + "\xAD\xCC" => "\xE5\x80\x91", + "\xAD\xCD" => "\xE4\xBF\xBA", + "\xAD\xCE" => "\xE5\x80\x80", + "\xAD\xCF" => "\xE5\x80\x94", + "\xAD\xD0" => "\xE5\x80\xA8", + "\xAD\xD1" => "\xE4\xBF\xB1", + "\xAD\xD2" => "\xE5\x80\xA1", + "\xAD\xD3" => "\xE5\x80\x8B", + "\xAD\xD4" => "\xE5\x80\x99", + "\xAD\xD5" => "\xE5\x80\x98", + "\xAD\xD6" => "\xE4\xBF\xB3", + "\xAD\xD7" => "\xE4\xBF\xAE", + "\xAD\xD8" => "\xE5\x80\xAD", + "\xAD\xD9" => "\xE5\x80\xAA", + "\xAD\xDA" => "\xE4\xBF\xBE", + "\xAD\xDB" => "\xE5\x80\xAB", + "\xAD\xDC" => "\xE5\x80\x89", + "\xAD\xDD" => "\xE5\x85\xBC", + "\xAD\xDE" => "\xE5\x86\xA4", + "\xAD\xDF" => "\xE5\x86\xA5", + "\xAD\xE0" => "\xE5\x86\xA2", + "\xAD\xE1" => "\xE5\x87\x8D", + "\xAD\xE2" => "\xE5\x87\x8C", + "\xAD\xE3" => "\xE5\x87\x86", + "\xAD\xE4" => "\xE5\x87\x8B", + "\xAD\xE5" => "\xE5\x89\x96", + "\xAD\xE6" => "\xE5\x89\x9C", + "\xAD\xE7" => "\xE5\x89\x94", + "\xAD\xE8" => "\xE5\x89\x9B", + "\xAD\xE9" => "\xE5\x89\x9D", + "\xAD\xEA" => "\xE5\x8C\xAA", + "\xAD\xEB" => "\xE5\x8D\xBF", + "\xAD\xEC" => "\xE5\x8E\x9F", + "\xAD\xED" => "\xE5\x8E\x9D", + "\xAD\xEE" => "\xE5\x8F\x9F", + "\xAD\xEF" => "\xE5\x93\xA8", + "\xAD\xF0" => "\xE5\x94\x90", + "\xAD\xF1" => "\xE5\x94\x81", + "\xAD\xF2" => "\xE5\x94\xB7", + "\xAD\xF3" => "\xE5\x93\xBC", + "\xAD\xF4" => "\xE5\x93\xA5", + "\xAD\xF5" => "\xE5\x93\xB2", + "\xAD\xF6" => "\xE5\x94\x86", + "\xAD\xF7" => "\xE5\x93\xBA", + "\xAD\xF8" => "\xE5\x94\x94", + "\xAD\xF9" => "\xE5\x93\xA9", + "\xAD\xFA" => "\xE5\x93\xAD", + "\xAD\xFB" => "\xE5\x93\xA1", + "\xAD\xFC" => "\xE5\x94\x89", + "\xAD\xFD" => "\xE5\x93\xAE", + "\xAD\xFE" => "\xE5\x93\xAA", + "\xAE\x40" => "\xE5\x93\xA6", + "\xAE\x41" => "\xE5\x94\xA7", + "\xAE\x42" => "\xE5\x94\x87", + "\xAE\x43" => "\xE5\x93\xBD", + "\xAE\x44" => "\xE5\x94\x8F", + "\xAE\x45" => "\xE5\x9C\x83", + "\xAE\x46" => "\xE5\x9C\x84", + "\xAE\x47" => "\xE5\x9F\x82", + "\xAE\x48" => "\xE5\x9F\x94", + "\xAE\x49" => "\xE5\x9F\x8B", + "\xAE\x4A" => "\xE5\x9F\x83", + "\xAE\x4B" => "\xE5\xA0\x89", + "\xAE\x4C" => "\xE5\xA4\x8F", + "\xAE\x4D" => "\xE5\xA5\x97", + "\xAE\x4E" => "\xE5\xA5\x98", + "\xAE\x4F" => "\xE5\xA5\x9A", + "\xAE\x50" => "\xE5\xA8\x91", + "\xAE\x51" => "\xE5\xA8\x98", + "\xAE\x52" => "\xE5\xA8\x9C", + "\xAE\x53" => "\xE5\xA8\x9F", + "\xAE\x54" => "\xE5\xA8\x9B", + "\xAE\x55" => "\xE5\xA8\x93", + "\xAE\x56" => "\xE5\xA7\xAC", + "\xAE\x57" => "\xE5\xA8\xA0", + "\xAE\x58" => "\xE5\xA8\xA3", + "\xAE\x59" => "\xE5\xA8\xA9", + "\xAE\x5A" => "\xE5\xA8\xA5", + "\xAE\x5B" => "\xE5\xA8\x8C", + "\xAE\x5C" => "\xE5\xA8\x89", + "\xAE\x5D" => "\xE5\xAD\xAB", + "\xAE\x5E" => "\xE5\xB1\x98", + "\xAE\x5F" => "\xE5\xAE\xB0", + "\xAE\x60" => "\xE5\xAE\xB3", + "\xAE\x61" => "\xE5\xAE\xB6", + "\xAE\x62" => "\xE5\xAE\xB4", + "\xAE\x63" => "\xE5\xAE\xAE", + "\xAE\x64" => "\xE5\xAE\xB5", + "\xAE\x65" => "\xE5\xAE\xB9", + "\xAE\x66" => "\xE5\xAE\xB8", + "\xAE\x67" => "\xE5\xB0\x84", + "\xAE\x68" => "\xE5\xB1\x91", + "\xAE\x69" => "\xE5\xB1\x95", + "\xAE\x6A" => "\xE5\xB1\x90", + "\xAE\x6B" => "\xE5\xB3\xAD", + "\xAE\x6C" => "\xE5\xB3\xBD", + "\xAE\x6D" => "\xE5\xB3\xBB", + "\xAE\x6E" => "\xE5\xB3\xAA", + "\xAE\x6F" => "\xE5\xB3\xA8", + "\xAE\x70" => "\xE5\xB3\xB0", + "\xAE\x71" => "\xE5\xB3\xB6", + "\xAE\x72" => "\xE5\xB4\x81", + "\xAE\x73" => "\xE5\xB3\xB4", + "\xAE\x74" => "\xE5\xB7\xAE", + "\xAE\x75" => "\xE5\xB8\xAD", + "\xAE\x76" => "\xE5\xB8\xAB", + "\xAE\x77" => "\xE5\xBA\xAB", + "\xAE\x78" => "\xE5\xBA\xAD", + "\xAE\x79" => "\xE5\xBA\xA7", + "\xAE\x7A" => "\xE5\xBC\xB1", + "\xAE\x7B" => "\xE5\xBE\x92", + "\xAE\x7C" => "\xE5\xBE\x91", + "\xAE\x7D" => "\xE5\xBE\x90", + "\xAE\x7E" => "\xE6\x81\x99", + "\xAE\xA1" => "\xE6\x81\xA3", + "\xAE\xA2" => "\xE6\x81\xA5", + "\xAE\xA3" => "\xE6\x81\x90", + "\xAE\xA4" => "\xE6\x81\x95", + "\xAE\xA5" => "\xE6\x81\xAD", + "\xAE\xA6" => "\xE6\x81\xA9", + "\xAE\xA7" => "\xE6\x81\xAF", + "\xAE\xA8" => "\xE6\x82\x84", + "\xAE\xA9" => "\xE6\x82\x9F", + "\xAE\xAA" => "\xE6\x82\x9A", + "\xAE\xAB" => "\xE6\x82\x8D", + "\xAE\xAC" => "\xE6\x82\x94", + "\xAE\xAD" => "\xE6\x82\x8C", + "\xAE\xAE" => "\xE6\x82\x85", + "\xAE\xAF" => "\xE6\x82\x96", + "\xAE\xB0" => "\xE6\x89\x87", + "\xAE\xB1" => "\xE6\x8B\xB3", + "\xAE\xB2" => "\xE6\x8C\x88", + "\xAE\xB3" => "\xE6\x8B\xBF", + "\xAE\xB4" => "\xE6\x8D\x8E", + "\xAE\xB5" => "\xE6\x8C\xBE", + "\xAE\xB6" => "\xE6\x8C\xAF", + "\xAE\xB7" => "\xE6\x8D\x95", + "\xAE\xB8" => "\xE6\x8D\x82", + "\xAE\xB9" => "\xE6\x8D\x86", + "\xAE\xBA" => "\xE6\x8D\x8F", + "\xAE\xBB" => "\xE6\x8D\x89", + "\xAE\xBC" => "\xE6\x8C\xBA", + "\xAE\xBD" => "\xE6\x8D\x90", + "\xAE\xBE" => "\xE6\x8C\xBD", + "\xAE\xBF" => "\xE6\x8C\xAA", + "\xAE\xC0" => "\xE6\x8C\xAB", + "\xAE\xC1" => "\xE6\x8C\xA8", + "\xAE\xC2" => "\xE6\x8D\x8D", + "\xAE\xC3" => "\xE6\x8D\x8C", + "\xAE\xC4" => "\xE6\x95\x88", + "\xAE\xC5" => "\xE6\x95\x89", + "\xAE\xC6" => "\xE6\x96\x99", + "\xAE\xC7" => "\xE6\x97\x81", + "\xAE\xC8" => "\xE6\x97\x85", + "\xAE\xC9" => "\xE6\x99\x82", + "\xAE\xCA" => "\xE6\x99\x89", + "\xAE\xCB" => "\xE6\x99\x8F", + "\xAE\xCC" => "\xE6\x99\x83", + "\xAE\xCD" => "\xE6\x99\x92", + "\xAE\xCE" => "\xE6\x99\x8C", + "\xAE\xCF" => "\xE6\x99\x85", + "\xAE\xD0" => "\xE6\x99\x81", + "\xAE\xD1" => "\xE6\x9B\xB8", + "\xAE\xD2" => "\xE6\x9C\x94", + "\xAE\xD3" => "\xE6\x9C\x95", + "\xAE\xD4" => "\xE6\x9C\x97", + "\xAE\xD5" => "\xE6\xA0\xA1", + "\xAE\xD6" => "\xE6\xA0\xB8", + "\xAE\xD7" => "\xE6\xA1\x88", + "\xAE\xD8" => "\xE6\xA1\x86", + "\xAE\xD9" => "\xE6\xA1\x93", + "\xAE\xDA" => "\xE6\xA0\xB9", + "\xAE\xDB" => "\xE6\xA1\x82", + "\xAE\xDC" => "\xE6\xA1\x94", + "\xAE\xDD" => "\xE6\xA0\xA9", + "\xAE\xDE" => "\xE6\xA2\xB3", + "\xAE\xDF" => "\xE6\xA0\x97", + "\xAE\xE0" => "\xE6\xA1\x8C", + "\xAE\xE1" => "\xE6\xA1\x91", + "\xAE\xE2" => "\xE6\xA0\xBD", + "\xAE\xE3" => "\xE6\x9F\xB4", + "\xAE\xE4" => "\xE6\xA1\x90", + "\xAE\xE5" => "\xE6\xA1\x80", + "\xAE\xE6" => "\xE6\xA0\xBC", + "\xAE\xE7" => "\xE6\xA1\x83", + "\xAE\xE8" => "\xE6\xA0\xAA", + "\xAE\xE9" => "\xE6\xA1\x85", + "\xAE\xEA" => "\xE6\xA0\x93", + "\xAE\xEB" => "\xE6\xA0\x98", + "\xAE\xEC" => "\xE6\xA1\x81", + "\xAE\xED" => "\xE6\xAE\x8A", + "\xAE\xEE" => "\xE6\xAE\x89", + "\xAE\xEF" => "\xE6\xAE\xB7", + "\xAE\xF0" => "\xE6\xB0\xA3", + "\xAE\xF1" => "\xE6\xB0\xA7", + "\xAE\xF2" => "\xE6\xB0\xA8", + "\xAE\xF3" => "\xE6\xB0\xA6", + "\xAE\xF4" => "\xE6\xB0\xA4", + "\xAE\xF5" => "\xE6\xB3\xB0", + "\xAE\xF6" => "\xE6\xB5\xAA", + "\xAE\xF7" => "\xE6\xB6\x95", + "\xAE\xF8" => "\xE6\xB6\x88", + "\xAE\xF9" => "\xE6\xB6\x87", + "\xAE\xFA" => "\xE6\xB5\xA6", + "\xAE\xFB" => "\xE6\xB5\xB8", + "\xAE\xFC" => "\xE6\xB5\xB7", + "\xAE\xFD" => "\xE6\xB5\x99", + "\xAE\xFE" => "\xE6\xB6\x93", + "\xAF\x40" => "\xE6\xB5\xAC", + "\xAF\x41" => "\xE6\xB6\x89", + "\xAF\x42" => "\xE6\xB5\xAE", + "\xAF\x43" => "\xE6\xB5\x9A", + "\xAF\x44" => "\xE6\xB5\xB4", + "\xAF\x45" => "\xE6\xB5\xA9", + "\xAF\x46" => "\xE6\xB6\x8C", + "\xAF\x47" => "\xE6\xB6\x8A", + "\xAF\x48" => "\xE6\xB5\xB9", + "\xAF\x49" => "\xE6\xB6\x85", + "\xAF\x4A" => "\xE6\xB5\xA5", + "\xAF\x4B" => "\xE6\xB6\x94", + "\xAF\x4C" => "\xE7\x83\x8A", + "\xAF\x4D" => "\xE7\x83\x98", + "\xAF\x4E" => "\xE7\x83\xA4", + "\xAF\x4F" => "\xE7\x83\x99", + "\xAF\x50" => "\xE7\x83\x88", + "\xAF\x51" => "\xE7\x83\x8F", + "\xAF\x52" => "\xE7\x88\xB9", + "\xAF\x53" => "\xE7\x89\xB9", + "\xAF\x54" => "\xE7\x8B\xBC", + "\xAF\x55" => "\xE7\x8B\xB9", + "\xAF\x56" => "\xE7\x8B\xBD", + "\xAF\x57" => "\xE7\x8B\xB8", + "\xAF\x58" => "\xE7\x8B\xB7", + "\xAF\x59" => "\xE7\x8E\x86", + "\xAF\x5A" => "\xE7\x8F\xAD", + "\xAF\x5B" => "\xE7\x90\x89", + "\xAF\x5C" => "\xE7\x8F\xAE", + "\xAF\x5D" => "\xE7\x8F\xA0", + "\xAF\x5E" => "\xE7\x8F\xAA", + "\xAF\x5F" => "\xE7\x8F\x9E", + "\xAF\x60" => "\xE7\x95\x94", + "\xAF\x61" => "\xE7\x95\x9D", + "\xAF\x62" => "\xE7\x95\x9C", + "\xAF\x63" => "\xE7\x95\x9A", + "\xAF\x64" => "\xE7\x95\x99", + "\xAF\x65" => "\xE7\x96\xBE", + "\xAF\x66" => "\xE7\x97\x85", + "\xAF\x67" => "\xE7\x97\x87", + "\xAF\x68" => "\xE7\x96\xB2", + "\xAF\x69" => "\xE7\x96\xB3", + "\xAF\x6A" => "\xE7\x96\xBD", + "\xAF\x6B" => "\xE7\x96\xBC", + "\xAF\x6C" => "\xE7\x96\xB9", + "\xAF\x6D" => "\xE7\x97\x82", + "\xAF\x6E" => "\xE7\x96\xB8", + "\xAF\x6F" => "\xE7\x9A\x8B", + "\xAF\x70" => "\xE7\x9A\xB0", + "\xAF\x71" => "\xE7\x9B\x8A", + "\xAF\x72" => "\xE7\x9B\x8D", + "\xAF\x73" => "\xE7\x9B\x8E", + "\xAF\x74" => "\xE7\x9C\xA9", + "\xAF\x75" => "\xE7\x9C\x9F", + "\xAF\x76" => "\xE7\x9C\xA0", + "\xAF\x77" => "\xE7\x9C\xA8", + "\xAF\x78" => "\xE7\x9F\xA9", + "\xAF\x79" => "\xE7\xA0\xB0", + "\xAF\x7A" => "\xE7\xA0\xA7", + "\xAF\x7B" => "\xE7\xA0\xB8", + "\xAF\x7C" => "\xE7\xA0\x9D", + "\xAF\x7D" => "\xE7\xA0\xB4", + "\xAF\x7E" => "\xE7\xA0\xB7", + "\xAF\xA1" => "\xE7\xA0\xA5", + "\xAF\xA2" => "\xE7\xA0\xAD", + "\xAF\xA3" => "\xE7\xA0\xA0", + "\xAF\xA4" => "\xE7\xA0\x9F", + "\xAF\xA5" => "\xE7\xA0\xB2", + "\xAF\xA6" => "\xE7\xA5\x95", + "\xAF\xA7" => "\xE7\xA5\x90", + "\xAF\xA8" => "\xE7\xA5\xA0", + "\xAF\xA9" => "\xE7\xA5\x9F", + "\xAF\xAA" => "\xE7\xA5\x96", + "\xAF\xAB" => "\xE7\xA5\x9E", + "\xAF\xAC" => "\xE7\xA5\x9D", + "\xAF\xAD" => "\xE7\xA5\x97", + "\xAF\xAE" => "\xE7\xA5\x9A", + "\xAF\xAF" => "\xE7\xA7\xA4", + "\xAF\xB0" => "\xE7\xA7\xA3", + "\xAF\xB1" => "\xE7\xA7\xA7", + "\xAF\xB2" => "\xE7\xA7\x9F", + "\xAF\xB3" => "\xE7\xA7\xA6", + "\xAF\xB4" => "\xE7\xA7\xA9", + "\xAF\xB5" => "\xE7\xA7\x98", + "\xAF\xB6" => "\xE7\xAA\x84", + "\xAF\xB7" => "\xE7\xAA\x88", + "\xAF\xB8" => "\xE7\xAB\x99", + "\xAF\xB9" => "\xE7\xAC\x86", + "\xAF\xBA" => "\xE7\xAC\x91", + "\xAF\xBB" => "\xE7\xB2\x89", + "\xAF\xBC" => "\xE7\xB4\xA1", + "\xAF\xBD" => "\xE7\xB4\x97", + "\xAF\xBE" => "\xE7\xB4\x8B", + "\xAF\xBF" => "\xE7\xB4\x8A", + "\xAF\xC0" => "\xE7\xB4\xA0", + "\xAF\xC1" => "\xE7\xB4\xA2", + "\xAF\xC2" => "\xE7\xB4\x94", + "\xAF\xC3" => "\xE7\xB4\x90", + "\xAF\xC4" => "\xE7\xB4\x95", + "\xAF\xC5" => "\xE7\xB4\x9A", + "\xAF\xC6" => "\xE7\xB4\x9C", + "\xAF\xC7" => "\xE7\xB4\x8D", + "\xAF\xC8" => "\xE7\xB4\x99", + "\xAF\xC9" => "\xE7\xB4\x9B", + "\xAF\xCA" => "\xE7\xBC\xBA", + "\xAF\xCB" => "\xE7\xBD\x9F", + "\xAF\xCC" => "\xE7\xBE\x94", + "\xAF\xCD" => "\xE7\xBF\x85", + "\xAF\xCE" => "\xE7\xBF\x81", + "\xAF\xCF" => "\xE8\x80\x86", + "\xAF\xD0" => "\xE8\x80\x98", + "\xAF\xD1" => "\xE8\x80\x95", + "\xAF\xD2" => "\xE8\x80\x99", + "\xAF\xD3" => "\xE8\x80\x97", + "\xAF\xD4" => "\xE8\x80\xBD", + "\xAF\xD5" => "\xE8\x80\xBF", + "\xAF\xD6" => "\xE8\x83\xB1", + "\xAF\xD7" => "\xE8\x84\x82", + "\xAF\xD8" => "\xE8\x83\xB0", + "\xAF\xD9" => "\xE8\x84\x85", + "\xAF\xDA" => "\xE8\x83\xAD", + "\xAF\xDB" => "\xE8\x83\xB4", + "\xAF\xDC" => "\xE8\x84\x86", + "\xAF\xDD" => "\xE8\x83\xB8", + "\xAF\xDE" => "\xE8\x83\xB3", + "\xAF\xDF" => "\xE8\x84\x88", + "\xAF\xE0" => "\xE8\x83\xBD", + "\xAF\xE1" => "\xE8\x84\x8A", + "\xAF\xE2" => "\xE8\x83\xBC", + "\xAF\xE3" => "\xE8\x83\xAF", + "\xAF\xE4" => "\xE8\x87\xAD", + "\xAF\xE5" => "\xE8\x87\xAC", + "\xAF\xE6" => "\xE8\x88\x80", + "\xAF\xE7" => "\xE8\x88\x90", + "\xAF\xE8" => "\xE8\x88\xAA", + "\xAF\xE9" => "\xE8\x88\xAB", + "\xAF\xEA" => "\xE8\x88\xA8", + "\xAF\xEB" => "\xE8\x88\xAC", + "\xAF\xEC" => "\xE8\x8A\xBB", + "\xAF\xED" => "\xE8\x8C\xAB", + "\xAF\xEE" => "\xE8\x8D\x92", + "\xAF\xEF" => "\xE8\x8D\x94", + "\xAF\xF0" => "\xE8\x8D\x8A", + "\xAF\xF1" => "\xE8\x8C\xB8", + "\xAF\xF2" => "\xE8\x8D\x90", + "\xAF\xF3" => "\xE8\x8D\x89", + "\xAF\xF4" => "\xE8\x8C\xB5", + "\xAF\xF5" => "\xE8\x8C\xB4", + "\xAF\xF6" => "\xE8\x8D\x8F", + "\xAF\xF7" => "\xE8\x8C\xB2", + "\xAF\xF8" => "\xE8\x8C\xB9", + "\xAF\xF9" => "\xE8\x8C\xB6", + "\xAF\xFA" => "\xE8\x8C\x97", + "\xAF\xFB" => "\xE8\x8D\x80", + "\xAF\xFC" => "\xE8\x8C\xB1", + "\xAF\xFD" => "\xE8\x8C\xA8", + "\xAF\xFE" => "\xE8\x8D\x83", + "\xB0\x40" => "\xE8\x99\x94", + "\xB0\x41" => "\xE8\x9A\x8A", + "\xB0\x42" => "\xE8\x9A\xAA", + "\xB0\x43" => "\xE8\x9A\x93", + "\xB0\x44" => "\xE8\x9A\xA4", + "\xB0\x45" => "\xE8\x9A\xA9", + "\xB0\x46" => "\xE8\x9A\x8C", + "\xB0\x47" => "\xE8\x9A\xA3", + "\xB0\x48" => "\xE8\x9A\x9C", + "\xB0\x49" => "\xE8\xA1\xB0", + "\xB0\x4A" => "\xE8\xA1\xB7", + "\xB0\x4B" => "\xE8\xA2\x81", + "\xB0\x4C" => "\xE8\xA2\x82", + "\xB0\x4D" => "\xE8\xA1\xBD", + "\xB0\x4E" => "\xE8\xA1\xB9", + "\xB0\x4F" => "\xE8\xA8\x98", + "\xB0\x50" => "\xE8\xA8\x90", + "\xB0\x51" => "\xE8\xA8\x8E", + "\xB0\x52" => "\xE8\xA8\x8C", + "\xB0\x53" => "\xE8\xA8\x95", + "\xB0\x54" => "\xE8\xA8\x8A", + "\xB0\x55" => "\xE8\xA8\x97", + "\xB0\x56" => "\xE8\xA8\x93", + "\xB0\x57" => "\xE8\xA8\x96", + "\xB0\x58" => "\xE8\xA8\x8F", + "\xB0\x59" => "\xE8\xA8\x91", + "\xB0\x5A" => "\xE8\xB1\x88", + "\xB0\x5B" => "\xE8\xB1\xBA", + "\xB0\x5C" => "\xE8\xB1\xB9", + "\xB0\x5D" => "\xE8\xB2\xA1", + "\xB0\x5E" => "\xE8\xB2\xA2", + "\xB0\x5F" => "\xE8\xB5\xB7", + "\xB0\x60" => "\xE8\xBA\xAC", + "\xB0\x61" => "\xE8\xBB\x92", + "\xB0\x62" => "\xE8\xBB\x94", + "\xB0\x63" => "\xE8\xBB\x8F", + "\xB0\x64" => "\xE8\xBE\xB1", + "\xB0\x65" => "\xE9\x80\x81", + "\xB0\x66" => "\xE9\x80\x86", + "\xB0\x67" => "\xE8\xBF\xB7", + "\xB0\x68" => "\xE9\x80\x80", + "\xB0\x69" => "\xE8\xBF\xBA", + "\xB0\x6A" => "\xE8\xBF\xB4", + "\xB0\x6B" => "\xE9\x80\x83", + "\xB0\x6C" => "\xE8\xBF\xBD", + "\xB0\x6D" => "\xE9\x80\x85", + "\xB0\x6E" => "\xE8\xBF\xB8", + "\xB0\x6F" => "\xE9\x82\x95", + "\xB0\x70" => "\xE9\x83\xA1", + "\xB0\x71" => "\xE9\x83\x9D", + "\xB0\x72" => "\xE9\x83\xA2", + "\xB0\x73" => "\xE9\x85\x92", + "\xB0\x74" => "\xE9\x85\x8D", + "\xB0\x75" => "\xE9\x85\x8C", + "\xB0\x76" => "\xE9\x87\x98", + "\xB0\x77" => "\xE9\x87\x9D", + "\xB0\x78" => "\xE9\x87\x97", + "\xB0\x79" => "\xE9\x87\x9C", + "\xB0\x7A" => "\xE9\x87\x99", + "\xB0\x7B" => "\xE9\x96\x83", + "\xB0\x7C" => "\xE9\x99\xA2", + "\xB0\x7D" => "\xE9\x99\xA3", + "\xB0\x7E" => "\xE9\x99\xA1", + "\xB0\xA1" => "\xE9\x99\x9B", + "\xB0\xA2" => "\xE9\x99\x9D", + "\xB0\xA3" => "\xE9\x99\xA4", + "\xB0\xA4" => "\xE9\x99\x98", + "\xB0\xA5" => "\xE9\x99\x9E", + "\xB0\xA6" => "\xE9\x9A\xBB", + "\xB0\xA7" => "\xE9\xA3\xA2", + "\xB0\xA8" => "\xE9\xA6\xAC", + "\xB0\xA9" => "\xE9\xAA\xA8", + "\xB0\xAA" => "\xE9\xAB\x98", + "\xB0\xAB" => "\xE9\xAC\xA5", + "\xB0\xAC" => "\xE9\xAC\xB2", + "\xB0\xAD" => "\xE9\xAC\xBC", + "\xB0\xAE" => "\xE4\xB9\xBE", + "\xB0\xAF" => "\xE5\x81\xBA", + "\xB0\xB0" => "\xE5\x81\xBD", + "\xB0\xB1" => "\xE5\x81\x9C", + "\xB0\xB2" => "\xE5\x81\x87", + "\xB0\xB3" => "\xE5\x81\x83", + "\xB0\xB4" => "\xE5\x81\x8C", + "\xB0\xB5" => "\xE5\x81\x9A", + "\xB0\xB6" => "\xE5\x81\x89", + "\xB0\xB7" => "\xE5\x81\xA5", + "\xB0\xB8" => "\xE5\x81\xB6", + "\xB0\xB9" => "\xE5\x81\x8E", + "\xB0\xBA" => "\xE5\x81\x95", + "\xB0\xBB" => "\xE5\x81\xB5", + "\xB0\xBC" => "\xE5\x81\xB4", + "\xB0\xBD" => "\xE5\x81\xB7", + "\xB0\xBE" => "\xE5\x81\x8F", + "\xB0\xBF" => "\xE5\x80\x8F", + "\xB0\xC0" => "\xE5\x81\xAF", + "\xB0\xC1" => "\xE5\x81\xAD", + "\xB0\xC2" => "\xE5\x85\x9C", + "\xB0\xC3" => "\xE5\x86\x95", + "\xB0\xC4" => "\xE5\x87\xB0", + "\xB0\xC5" => "\xE5\x89\xAA", + "\xB0\xC6" => "\xE5\x89\xAF", + "\xB0\xC7" => "\xE5\x8B\x92", + "\xB0\xC8" => "\xE5\x8B\x99", + "\xB0\xC9" => "\xE5\x8B\x98", + "\xB0\xCA" => "\xE5\x8B\x95", + "\xB0\xCB" => "\xE5\x8C\x90", + "\xB0\xCC" => "\xE5\x8C\x8F", + "\xB0\xCD" => "\xE5\x8C\x99", + "\xB0\xCE" => "\xE5\x8C\xBF", + "\xB0\xCF" => "\xE5\x8D\x80", + "\xB0\xD0" => "\xE5\x8C\xBE", + "\xB0\xD1" => "\xE5\x8F\x83", + "\xB0\xD2" => "\xE6\x9B\xBC", + "\xB0\xD3" => "\xE5\x95\x86", + "\xB0\xD4" => "\xE5\x95\xAA", + "\xB0\xD5" => "\xE5\x95\xA6", + "\xB0\xD6" => "\xE5\x95\x84", + "\xB0\xD7" => "\xE5\x95\x9E", + "\xB0\xD8" => "\xE5\x95\xA1", + "\xB0\xD9" => "\xE5\x95\x83", + "\xB0\xDA" => "\xE5\x95\x8A", + "\xB0\xDB" => "\xE5\x94\xB1", + "\xB0\xDC" => "\xE5\x95\x96", + "\xB0\xDD" => "\xE5\x95\x8F", + "\xB0\xDE" => "\xE5\x95\x95", + "\xB0\xDF" => "\xE5\x94\xAF", + "\xB0\xE0" => "\xE5\x95\xA4", + "\xB0\xE1" => "\xE5\x94\xB8", + "\xB0\xE2" => "\xE5\x94\xAE", + "\xB0\xE3" => "\xE5\x95\x9C", + "\xB0\xE4" => "\xE5\x94\xAC", + "\xB0\xE5" => "\xE5\x95\xA3", + "\xB0\xE6" => "\xE5\x94\xB3", + "\xB0\xE7" => "\xE5\x95\x81", + "\xB0\xE8" => "\xE5\x95\x97", + "\xB0\xE9" => "\xE5\x9C\x88", + "\xB0\xEA" => "\xE5\x9C\x8B", + "\xB0\xEB" => "\xE5\x9C\x89", + "\xB0\xEC" => "\xE5\x9F\x9F", + "\xB0\xED" => "\xE5\xA0\x85", + "\xB0\xEE" => "\xE5\xA0\x8A", + "\xB0\xEF" => "\xE5\xA0\x86", + "\xB0\xF0" => "\xE5\x9F\xA0", + "\xB0\xF1" => "\xE5\x9F\xA4", + "\xB0\xF2" => "\xE5\x9F\xBA", + "\xB0\xF3" => "\xE5\xA0\x82", + "\xB0\xF4" => "\xE5\xA0\xB5", + "\xB0\xF5" => "\xE5\x9F\xB7", + "\xB0\xF6" => "\xE5\x9F\xB9", + "\xB0\xF7" => "\xE5\xA4\xA0", + "\xB0\xF8" => "\xE5\xA5\xA2", + "\xB0\xF9" => "\xE5\xA8\xB6", + "\xB0\xFA" => "\xE5\xA9\x81", + "\xB0\xFB" => "\xE5\xA9\x89", + "\xB0\xFC" => "\xE5\xA9\xA6", + "\xB0\xFD" => "\xE5\xA9\xAA", + "\xB0\xFE" => "\xE5\xA9\x80", + "\xB1\x40" => "\xE5\xA8\xBC", + "\xB1\x41" => "\xE5\xA9\xA2", + "\xB1\x42" => "\xE5\xA9\x9A", + "\xB1\x43" => "\xE5\xA9\x86", + "\xB1\x44" => "\xE5\xA9\x8A", + "\xB1\x45" => "\xE5\xAD\xB0", + "\xB1\x46" => "\xE5\xAF\x87", + "\xB1\x47" => "\xE5\xAF\x85", + "\xB1\x48" => "\xE5\xAF\x84", + "\xB1\x49" => "\xE5\xAF\x82", + "\xB1\x4A" => "\xE5\xAE\xBF", + "\xB1\x4B" => "\xE5\xAF\x86", + "\xB1\x4C" => "\xE5\xB0\x89", + "\xB1\x4D" => "\xE5\xB0\x88", + "\xB1\x4E" => "\xE5\xB0\x87", + "\xB1\x4F" => "\xE5\xB1\xA0", + "\xB1\x50" => "\xE5\xB1\x9C", + "\xB1\x51" => "\xE5\xB1\x9D", + "\xB1\x52" => "\xE5\xB4\x87", + "\xB1\x53" => "\xE5\xB4\x86", + "\xB1\x54" => "\xE5\xB4\x8E", + "\xB1\x55" => "\xE5\xB4\x9B", + "\xB1\x56" => "\xE5\xB4\x96", + "\xB1\x57" => "\xE5\xB4\xA2", + "\xB1\x58" => "\xE5\xB4\x91", + "\xB1\x59" => "\xE5\xB4\xA9", + "\xB1\x5A" => "\xE5\xB4\x94", + "\xB1\x5B" => "\xE5\xB4\x99", + "\xB1\x5C" => "\xE5\xB4\xA4", + "\xB1\x5D" => "\xE5\xB4\xA7", + "\xB1\x5E" => "\xE5\xB4\x97", + "\xB1\x5F" => "\xE5\xB7\xA2", + "\xB1\x60" => "\xE5\xB8\xB8", + "\xB1\x61" => "\xE5\xB8\xB6", + "\xB1\x62" => "\xE5\xB8\xB3", + "\xB1\x63" => "\xE5\xB8\xB7", + "\xB1\x64" => "\xE5\xBA\xB7", + "\xB1\x65" => "\xE5\xBA\xB8", + "\xB1\x66" => "\xE5\xBA\xB6", + "\xB1\x67" => "\xE5\xBA\xB5", + "\xB1\x68" => "\xE5\xBA\xBE", + "\xB1\x69" => "\xE5\xBC\xB5", + "\xB1\x6A" => "\xE5\xBC\xB7", + "\xB1\x6B" => "\xE5\xBD\x97", + "\xB1\x6C" => "\xE5\xBD\xAC", + "\xB1\x6D" => "\xE5\xBD\xA9", + "\xB1\x6E" => "\xE5\xBD\xAB", + "\xB1\x6F" => "\xE5\xBE\x97", + "\xB1\x70" => "\xE5\xBE\x99", + "\xB1\x71" => "\xE5\xBE\x9E", + "\xB1\x72" => "\xE5\xBE\x98", + "\xB1\x73" => "\xE5\xBE\xA1", + "\xB1\x74" => "\xE5\xBE\xA0", + "\xB1\x75" => "\xE5\xBE\x9C", + "\xB1\x76" => "\xE6\x81\xBF", + "\xB1\x77" => "\xE6\x82\xA3", + "\xB1\x78" => "\xE6\x82\x89", + "\xB1\x79" => "\xE6\x82\xA0", + "\xB1\x7A" => "\xE6\x82\xA8", + "\xB1\x7B" => "\xE6\x83\x8B", + "\xB1\x7C" => "\xE6\x82\xB4", + "\xB1\x7D" => "\xE6\x83\xA6", + "\xB1\x7E" => "\xE6\x82\xBD", + "\xB1\xA1" => "\xE6\x83\x85", + "\xB1\xA2" => "\xE6\x82\xBB", + "\xB1\xA3" => "\xE6\x82\xB5", + "\xB1\xA4" => "\xE6\x83\x9C", + "\xB1\xA5" => "\xE6\x82\xBC", + "\xB1\xA6" => "\xE6\x83\x98", + "\xB1\xA7" => "\xE6\x83\x95", + "\xB1\xA8" => "\xE6\x83\x86", + "\xB1\xA9" => "\xE6\x83\x9F", + "\xB1\xAA" => "\xE6\x82\xB8", + "\xB1\xAB" => "\xE6\x83\x9A", + "\xB1\xAC" => "\xE6\x83\x87", + "\xB1\xAD" => "\xE6\x88\x9A", + "\xB1\xAE" => "\xE6\x88\x9B", + "\xB1\xAF" => "\xE6\x89\x88", + "\xB1\xB0" => "\xE6\x8E\xA0", + "\xB1\xB1" => "\xE6\x8E\xA7", + "\xB1\xB2" => "\xE6\x8D\xB2", + "\xB1\xB3" => "\xE6\x8E\x96", + "\xB1\xB4" => "\xE6\x8E\xA2", + "\xB1\xB5" => "\xE6\x8E\xA5", + "\xB1\xB6" => "\xE6\x8D\xB7", + "\xB1\xB7" => "\xE6\x8D\xA7", + "\xB1\xB8" => "\xE6\x8E\x98", + "\xB1\xB9" => "\xE6\x8E\xAA", + "\xB1\xBA" => "\xE6\x8D\xB1", + "\xB1\xBB" => "\xE6\x8E\xA9", + "\xB1\xBC" => "\xE6\x8E\x89", + "\xB1\xBD" => "\xE6\x8E\x83", + "\xB1\xBE" => "\xE6\x8E\x9B", + "\xB1\xBF" => "\xE6\x8D\xAB", + "\xB1\xC0" => "\xE6\x8E\xA8", + "\xB1\xC1" => "\xE6\x8E\x84", + "\xB1\xC2" => "\xE6\x8E\x88", + "\xB1\xC3" => "\xE6\x8E\x99", + "\xB1\xC4" => "\xE6\x8E\xA1", + "\xB1\xC5" => "\xE6\x8E\xAC", + "\xB1\xC6" => "\xE6\x8E\x92", + "\xB1\xC7" => "\xE6\x8E\x8F", + "\xB1\xC8" => "\xE6\x8E\x80", + "\xB1\xC9" => "\xE6\x8D\xBB", + "\xB1\xCA" => "\xE6\x8D\xA9", + "\xB1\xCB" => "\xE6\x8D\xA8", + "\xB1\xCC" => "\xE6\x8D\xBA", + "\xB1\xCD" => "\xE6\x95\x9D", + "\xB1\xCE" => "\xE6\x95\x96", + "\xB1\xCF" => "\xE6\x95\x91", + "\xB1\xD0" => "\xE6\x95\x99", + "\xB1\xD1" => "\xE6\x95\x97", + "\xB1\xD2" => "\xE5\x95\x9F", + "\xB1\xD3" => "\xE6\x95\x8F", + "\xB1\xD4" => "\xE6\x95\x98", + "\xB1\xD5" => "\xE6\x95\x95", + "\xB1\xD6" => "\xE6\x95\x94", + "\xB1\xD7" => "\xE6\x96\x9C", + "\xB1\xD8" => "\xE6\x96\x9B", + "\xB1\xD9" => "\xE6\x96\xAC", + "\xB1\xDA" => "\xE6\x97\x8F", + "\xB1\xDB" => "\xE6\x97\x8B", + "\xB1\xDC" => "\xE6\x97\x8C", + "\xB1\xDD" => "\xE6\x97\x8E", + "\xB1\xDE" => "\xE6\x99\x9D", + "\xB1\xDF" => "\xE6\x99\x9A", + "\xB1\xE0" => "\xE6\x99\xA4", + "\xB1\xE1" => "\xE6\x99\xA8", + "\xB1\xE2" => "\xE6\x99\xA6", + "\xB1\xE3" => "\xE6\x99\x9E", + "\xB1\xE4" => "\xE6\x9B\xB9", + "\xB1\xE5" => "\xE5\x8B\x97", + "\xB1\xE6" => "\xE6\x9C\x9B", + "\xB1\xE7" => "\xE6\xA2\x81", + "\xB1\xE8" => "\xE6\xA2\xAF", + "\xB1\xE9" => "\xE6\xA2\xA2", + "\xB1\xEA" => "\xE6\xA2\x93", + "\xB1\xEB" => "\xE6\xA2\xB5", + "\xB1\xEC" => "\xE6\xA1\xBF", + "\xB1\xED" => "\xE6\xA1\xB6", + "\xB1\xEE" => "\xE6\xA2\xB1", + "\xB1\xEF" => "\xE6\xA2\xA7", + "\xB1\xF0" => "\xE6\xA2\x97", + "\xB1\xF1" => "\xE6\xA2\xB0", + "\xB1\xF2" => "\xE6\xA2\x83", + "\xB1\xF3" => "\xE6\xA3\x84", + "\xB1\xF4" => "\xE6\xA2\xAD", + "\xB1\xF5" => "\xE6\xA2\x86", + "\xB1\xF6" => "\xE6\xA2\x85", + "\xB1\xF7" => "\xE6\xA2\x94", + "\xB1\xF8" => "\xE6\xA2\x9D", + "\xB1\xF9" => "\xE6\xA2\xA8", + "\xB1\xFA" => "\xE6\xA2\x9F", + "\xB1\xFB" => "\xE6\xA2\xA1", + "\xB1\xFC" => "\xE6\xA2\x82", + "\xB1\xFD" => "\xE6\xAC\xB2", + "\xB1\xFE" => "\xE6\xAE\xBA", + "\xB2\x40" => "\xE6\xAF\xAB", + "\xB2\x41" => "\xE6\xAF\xAC", + "\xB2\x42" => "\xE6\xB0\xAB", + "\xB2\x43" => "\xE6\xB6\x8E", + "\xB2\x44" => "\xE6\xB6\xBC", + "\xB2\x45" => "\xE6\xB7\xB3", + "\xB2\x46" => "\xE6\xB7\x99", + "\xB2\x47" => "\xE6\xB6\xB2", + "\xB2\x48" => "\xE6\xB7\xA1", + "\xB2\x49" => "\xE6\xB7\x8C", + "\xB2\x4A" => "\xE6\xB7\xA4", + "\xB2\x4B" => "\xE6\xB7\xBB", + "\xB2\x4C" => "\xE6\xB7\xBA", + "\xB2\x4D" => "\xE6\xB8\x85", + "\xB2\x4E" => "\xE6\xB7\x87", + "\xB2\x4F" => "\xE6\xB7\x8B", + "\xB2\x50" => "\xE6\xB6\xAF", + "\xB2\x51" => "\xE6\xB7\x91", + "\xB2\x52" => "\xE6\xB6\xAE", + "\xB2\x53" => "\xE6\xB7\x9E", + "\xB2\x54" => "\xE6\xB7\xB9", + "\xB2\x55" => "\xE6\xB6\xB8", + "\xB2\x56" => "\xE6\xB7\xB7", + "\xB2\x57" => "\xE6\xB7\xB5", + "\xB2\x58" => "\xE6\xB7\x85", + "\xB2\x59" => "\xE6\xB7\x92", + "\xB2\x5A" => "\xE6\xB8\x9A", + "\xB2\x5B" => "\xE6\xB6\xB5", + "\xB2\x5C" => "\xE6\xB7\x9A", + "\xB2\x5D" => "\xE6\xB7\xAB", + "\xB2\x5E" => "\xE6\xB7\x98", + "\xB2\x5F" => "\xE6\xB7\xAA", + "\xB2\x60" => "\xE6\xB7\xB1", + "\xB2\x61" => "\xE6\xB7\xAE", + "\xB2\x62" => "\xE6\xB7\xA8", + "\xB2\x63" => "\xE6\xB7\x86", + "\xB2\x64" => "\xE6\xB7\x84", + "\xB2\x65" => "\xE6\xB6\xAA", + "\xB2\x66" => "\xE6\xB7\xAC", + "\xB2\x67" => "\xE6\xB6\xBF", + "\xB2\x68" => "\xE6\xB7\xA6", + "\xB2\x69" => "\xE7\x83\xB9", + "\xB2\x6A" => "\xE7\x84\x89", + "\xB2\x6B" => "\xE7\x84\x8A", + "\xB2\x6C" => "\xE7\x83\xBD", + "\xB2\x6D" => "\xE7\x83\xAF", + "\xB2\x6E" => "\xE7\x88\xBD", + "\xB2\x6F" => "\xE7\x89\xBD", + "\xB2\x70" => "\xE7\x8A\x81", + "\xB2\x71" => "\xE7\x8C\x9C", + "\xB2\x72" => "\xE7\x8C\x9B", + "\xB2\x73" => "\xE7\x8C\x96", + "\xB2\x74" => "\xE7\x8C\x93", + "\xB2\x75" => "\xE7\x8C\x99", + "\xB2\x76" => "\xE7\x8E\x87", + "\xB2\x77" => "\xE7\x90\x85", + "\xB2\x78" => "\xE7\x90\x8A", + "\xB2\x79" => "\xE7\x90\x83", + "\xB2\x7A" => "\xE7\x90\x86", + "\xB2\x7B" => "\xE7\x8F\xBE", + "\xB2\x7C" => "\xE7\x90\x8D", + "\xB2\x7D" => "\xE7\x93\xA0", + "\xB2\x7E" => "\xE7\x93\xB6", + "\xB2\xA1" => "\xE7\x93\xB7", + "\xB2\xA2" => "\xE7\x94\x9C", + "\xB2\xA3" => "\xE7\x94\xA2", + "\xB2\xA4" => "\xE7\x95\xA5", + "\xB2\xA5" => "\xE7\x95\xA6", + "\xB2\xA6" => "\xE7\x95\xA2", + "\xB2\xA7" => "\xE7\x95\xB0", + "\xB2\xA8" => "\xE7\x96\x8F", + "\xB2\xA9" => "\xE7\x97\x94", + "\xB2\xAA" => "\xE7\x97\x95", + "\xB2\xAB" => "\xE7\x96\xB5", + "\xB2\xAC" => "\xE7\x97\x8A", + "\xB2\xAD" => "\xE7\x97\x8D", + "\xB2\xAE" => "\xE7\x9A\x8E", + "\xB2\xAF" => "\xE7\x9B\x94", + "\xB2\xB0" => "\xE7\x9B\x92", + "\xB2\xB1" => "\xE7\x9B\x9B", + "\xB2\xB2" => "\xE7\x9C\xB7", + "\xB2\xB3" => "\xE7\x9C\xBE", + "\xB2\xB4" => "\xE7\x9C\xBC", + "\xB2\xB5" => "\xE7\x9C\xB6", + "\xB2\xB6" => "\xE7\x9C\xB8", + "\xB2\xB7" => "\xE7\x9C\xBA", + "\xB2\xB8" => "\xE7\xA1\xAB", + "\xB2\xB9" => "\xE7\xA1\x83", + "\xB2\xBA" => "\xE7\xA1\x8E", + "\xB2\xBB" => "\xE7\xA5\xA5", + "\xB2\xBC" => "\xE7\xA5\xA8", + "\xB2\xBD" => "\xE7\xA5\xAD", + "\xB2\xBE" => "\xE7\xA7\xBB", + "\xB2\xBF" => "\xE7\xAA\x92", + "\xB2\xC0" => "\xE7\xAA\x95", + "\xB2\xC1" => "\xE7\xAC\xA0", + "\xB2\xC2" => "\xE7\xAC\xA8", + "\xB2\xC3" => "\xE7\xAC\x9B", + "\xB2\xC4" => "\xE7\xAC\xAC", + "\xB2\xC5" => "\xE7\xAC\xA6", + "\xB2\xC6" => "\xE7\xAC\x99", + "\xB2\xC7" => "\xE7\xAC\x9E", + "\xB2\xC8" => "\xE7\xAC\xAE", + "\xB2\xC9" => "\xE7\xB2\x92", + "\xB2\xCA" => "\xE7\xB2\x97", + "\xB2\xCB" => "\xE7\xB2\x95", + "\xB2\xCC" => "\xE7\xB5\x86", + "\xB2\xCD" => "\xE7\xB5\x83", + "\xB2\xCE" => "\xE7\xB5\xB1", + "\xB2\xCF" => "\xE7\xB4\xAE", + "\xB2\xD0" => "\xE7\xB4\xB9", + "\xB2\xD1" => "\xE7\xB4\xBC", + "\xB2\xD2" => "\xE7\xB5\x80", + "\xB2\xD3" => "\xE7\xB4\xB0", + "\xB2\xD4" => "\xE7\xB4\xB3", + "\xB2\xD5" => "\xE7\xB5\x84", + "\xB2\xD6" => "\xE7\xB4\xAF", + "\xB2\xD7" => "\xE7\xB5\x82", + "\xB2\xD8" => "\xE7\xB4\xB2", + "\xB2\xD9" => "\xE7\xB4\xB1", + "\xB2\xDA" => "\xE7\xBC\xBD", + "\xB2\xDB" => "\xE7\xBE\x9E", + "\xB2\xDC" => "\xE7\xBE\x9A", + "\xB2\xDD" => "\xE7\xBF\x8C", + "\xB2\xDE" => "\xE7\xBF\x8E", + "\xB2\xDF" => "\xE7\xBF\x92", + "\xB2\xE0" => "\xE8\x80\x9C", + "\xB2\xE1" => "\xE8\x81\x8A", + "\xB2\xE2" => "\xE8\x81\x86", + "\xB2\xE3" => "\xE8\x84\xAF", + "\xB2\xE4" => "\xE8\x84\x96", + "\xB2\xE5" => "\xE8\x84\xA3", + "\xB2\xE6" => "\xE8\x84\xAB", + "\xB2\xE7" => "\xE8\x84\xA9", + "\xB2\xE8" => "\xE8\x84\xB0", + "\xB2\xE9" => "\xE8\x84\xA4", + "\xB2\xEA" => "\xE8\x88\x82", + "\xB2\xEB" => "\xE8\x88\xB5", + "\xB2\xEC" => "\xE8\x88\xB7", + "\xB2\xED" => "\xE8\x88\xB6", + "\xB2\xEE" => "\xE8\x88\xB9", + "\xB2\xEF" => "\xE8\x8E\x8E", + "\xB2\xF0" => "\xE8\x8E\x9E", + "\xB2\xF1" => "\xE8\x8E\x98", + "\xB2\xF2" => "\xE8\x8D\xB8", + "\xB2\xF3" => "\xE8\x8E\xA2", + "\xB2\xF4" => "\xE8\x8E\x96", + "\xB2\xF5" => "\xE8\x8E\xBD", + "\xB2\xF6" => "\xE8\x8E\xAB", + "\xB2\xF7" => "\xE8\x8E\x92", + "\xB2\xF8" => "\xE8\x8E\x8A", + "\xB2\xF9" => "\xE8\x8E\x93", + "\xB2\xFA" => "\xE8\x8E\x89", + "\xB2\xFB" => "\xE8\x8E\xA0", + "\xB2\xFC" => "\xE8\x8D\xB7", + "\xB2\xFD" => "\xE8\x8D\xBB", + "\xB2\xFE" => "\xE8\x8D\xBC", + "\xB3\x40" => "\xE8\x8E\x86", + "\xB3\x41" => "\xE8\x8E\xA7", + "\xB3\x42" => "\xE8\x99\x95", + "\xB3\x43" => "\xE5\xBD\xAA", + "\xB3\x44" => "\xE8\x9B\x87", + "\xB3\x45" => "\xE8\x9B\x80", + "\xB3\x46" => "\xE8\x9A\xB6", + "\xB3\x47" => "\xE8\x9B\x84", + "\xB3\x48" => "\xE8\x9A\xB5", + "\xB3\x49" => "\xE8\x9B\x86", + "\xB3\x4A" => "\xE8\x9B\x8B", + "\xB3\x4B" => "\xE8\x9A\xB1", + "\xB3\x4C" => "\xE8\x9A\xAF", + "\xB3\x4D" => "\xE8\x9B\x89", + "\xB3\x4E" => "\xE8\xA1\x93", + "\xB3\x4F" => "\xE8\xA2\x9E", + "\xB3\x50" => "\xE8\xA2\x88", + "\xB3\x51" => "\xE8\xA2\xAB", + "\xB3\x52" => "\xE8\xA2\x92", + "\xB3\x53" => "\xE8\xA2\x96", + "\xB3\x54" => "\xE8\xA2\x8D", + "\xB3\x55" => "\xE8\xA2\x8B", + "\xB3\x56" => "\xE8\xA6\x93", + "\xB3\x57" => "\xE8\xA6\x8F", + "\xB3\x58" => "\xE8\xA8\xAA", + "\xB3\x59" => "\xE8\xA8\x9D", + "\xB3\x5A" => "\xE8\xA8\xA3", + "\xB3\x5B" => "\xE8\xA8\xA5", + "\xB3\x5C" => "\xE8\xA8\xB1", + "\xB3\x5D" => "\xE8\xA8\xAD", + "\xB3\x5E" => "\xE8\xA8\x9F", + "\xB3\x5F" => "\xE8\xA8\x9B", + "\xB3\x60" => "\xE8\xA8\xA2", + "\xB3\x61" => "\xE8\xB1\x89", + "\xB3\x62" => "\xE8\xB1\x9A", + "\xB3\x63" => "\xE8\xB2\xA9", + "\xB3\x64" => "\xE8\xB2\xAC", + "\xB3\x65" => "\xE8\xB2\xAB", + "\xB3\x66" => "\xE8\xB2\xA8", + "\xB3\x67" => "\xE8\xB2\xAA", + "\xB3\x68" => "\xE8\xB2\xA7", + "\xB3\x69" => "\xE8\xB5\xA7", + "\xB3\x6A" => "\xE8\xB5\xA6", + "\xB3\x6B" => "\xE8\xB6\xBE", + "\xB3\x6C" => "\xE8\xB6\xBA", + "\xB3\x6D" => "\xE8\xBB\x9B", + "\xB3\x6E" => "\xE8\xBB\x9F", + "\xB3\x6F" => "\xE9\x80\x99", + "\xB3\x70" => "\xE9\x80\x8D", + "\xB3\x71" => "\xE9\x80\x9A", + "\xB3\x72" => "\xE9\x80\x97", + "\xB3\x73" => "\xE9\x80\xA3", + "\xB3\x74" => "\xE9\x80\x9F", + "\xB3\x75" => "\xE9\x80\x9D", + "\xB3\x76" => "\xE9\x80\x90", + "\xB3\x77" => "\xE9\x80\x95", + "\xB3\x78" => "\xE9\x80\x9E", + "\xB3\x79" => "\xE9\x80\xA0", + "\xB3\x7A" => "\xE9\x80\x8F", + "\xB3\x7B" => "\xE9\x80\xA2", + "\xB3\x7C" => "\xE9\x80\x96", + "\xB3\x7D" => "\xE9\x80\x9B", + "\xB3\x7E" => "\xE9\x80\x94", + "\xB3\xA1" => "\xE9\x83\xA8", + "\xB3\xA2" => "\xE9\x83\xAD", + "\xB3\xA3" => "\xE9\x83\xBD", + "\xB3\xA4" => "\xE9\x85\x97", + "\xB3\xA5" => "\xE9\x87\x8E", + "\xB3\xA6" => "\xE9\x87\xB5", + "\xB3\xA7" => "\xE9\x87\xA6", + "\xB3\xA8" => "\xE9\x87\xA3", + "\xB3\xA9" => "\xE9\x87\xA7", + "\xB3\xAA" => "\xE9\x87\xAD", + "\xB3\xAB" => "\xE9\x87\xA9", + "\xB3\xAC" => "\xE9\x96\x89", + "\xB3\xAD" => "\xE9\x99\xAA", + "\xB3\xAE" => "\xE9\x99\xB5", + "\xB3\xAF" => "\xE9\x99\xB3", + "\xB3\xB0" => "\xE9\x99\xB8", + "\xB3\xB1" => "\xE9\x99\xB0", + "\xB3\xB2" => "\xE9\x99\xB4", + "\xB3\xB3" => "\xE9\x99\xB6", + "\xB3\xB4" => "\xE9\x99\xB7", + "\xB3\xB5" => "\xE9\x99\xAC", + "\xB3\xB6" => "\xE9\x9B\x80", + "\xB3\xB7" => "\xE9\x9B\xAA", + "\xB3\xB8" => "\xE9\x9B\xA9", + "\xB3\xB9" => "\xE7\xAB\xA0", + "\xB3\xBA" => "\xE7\xAB\x9F", + "\xB3\xBB" => "\xE9\xA0\x82", + "\xB3\xBC" => "\xE9\xA0\x83", + "\xB3\xBD" => "\xE9\xAD\x9A", + "\xB3\xBE" => "\xE9\xB3\xA5", + "\xB3\xBF" => "\xE9\xB9\xB5", + "\xB3\xC0" => "\xE9\xB9\xBF", + "\xB3\xC1" => "\xE9\xBA\xA5", + "\xB3\xC2" => "\xE9\xBA\xBB", + "\xB3\xC3" => "\xE5\x82\xA2", + "\xB3\xC4" => "\xE5\x82\x8D", + "\xB3\xC5" => "\xE5\x82\x85", + "\xB3\xC6" => "\xE5\x82\x99", + "\xB3\xC7" => "\xE5\x82\x91", + "\xB3\xC8" => "\xE5\x82\x80", + "\xB3\xC9" => "\xE5\x82\x96", + "\xB3\xCA" => "\xE5\x82\x98", + "\xB3\xCB" => "\xE5\x82\x9A", + "\xB3\xCC" => "\xE6\x9C\x80", + "\xB3\xCD" => "\xE5\x87\xB1", + "\xB3\xCE" => "\xE5\x89\xB2", + "\xB3\xCF" => "\xE5\x89\xB4", + "\xB3\xD0" => "\xE5\x89\xB5", + "\xB3\xD1" => "\xE5\x89\xA9", + "\xB3\xD2" => "\xE5\x8B\x9E", + "\xB3\xD3" => "\xE5\x8B\x9D", + "\xB3\xD4" => "\xE5\x8B\x9B", + "\xB3\xD5" => "\xE5\x8D\x9A", + "\xB3\xD6" => "\xE5\x8E\xA5", + "\xB3\xD7" => "\xE5\x95\xBB", + "\xB3\xD8" => "\xE5\x96\x80", + "\xB3\xD9" => "\xE5\x96\xA7", + "\xB3\xDA" => "\xE5\x95\xBC", + "\xB3\xDB" => "\xE5\x96\x8A", + "\xB3\xDC" => "\xE5\x96\x9D", + "\xB3\xDD" => "\xE5\x96\x98", + "\xB3\xDE" => "\xE5\x96\x82", + "\xB3\xDF" => "\xE5\x96\x9C", + "\xB3\xE0" => "\xE5\x96\xAA", + "\xB3\xE1" => "\xE5\x96\x94", + "\xB3\xE2" => "\xE5\x96\x87", + "\xB3\xE3" => "\xE5\x96\x8B", + "\xB3\xE4" => "\xE5\x96\x83", + "\xB3\xE5" => "\xE5\x96\xB3", + "\xB3\xE6" => "\xE5\x96\xAE", + "\xB3\xE7" => "\xE5\x96\x9F", + "\xB3\xE8" => "\xE5\x94\xBE", + "\xB3\xE9" => "\xE5\x96\xB2", + "\xB3\xEA" => "\xE5\x96\x9A", + "\xB3\xEB" => "\xE5\x96\xBB", + "\xB3\xEC" => "\xE5\x96\xAC", + "\xB3\xED" => "\xE5\x96\xB1", + "\xB3\xEE" => "\xE5\x95\xBE", + "\xB3\xEF" => "\xE5\x96\x89", + "\xB3\xF0" => "\xE5\x96\xAB", + "\xB3\xF1" => "\xE5\x96\x99", + "\xB3\xF2" => "\xE5\x9C\x8D", + "\xB3\xF3" => "\xE5\xA0\xAF", + "\xB3\xF4" => "\xE5\xA0\xAA", + "\xB3\xF5" => "\xE5\xA0\xB4", + "\xB3\xF6" => "\xE5\xA0\xA4", + "\xB3\xF7" => "\xE5\xA0\xB0", + "\xB3\xF8" => "\xE5\xA0\xB1", + "\xB3\xF9" => "\xE5\xA0\xA1", + "\xB3\xFA" => "\xE5\xA0\x9D", + "\xB3\xFB" => "\xE5\xA0\xA0", + "\xB3\xFC" => "\xE5\xA3\xB9", + "\xB3\xFD" => "\xE5\xA3\xBA", + "\xB3\xFE" => "\xE5\xA5\xA0", + "\xB4\x40" => "\xE5\xA9\xB7", + "\xB4\x41" => "\xE5\xAA\x9A", + "\xB4\x42" => "\xE5\xA9\xBF", + "\xB4\x43" => "\xE5\xAA\x92", + "\xB4\x44" => "\xE5\xAA\x9B", + "\xB4\x45" => "\xE5\xAA\xA7", + "\xB4\x46" => "\xE5\xAD\xB3", + "\xB4\x47" => "\xE5\xAD\xB1", + "\xB4\x48" => "\xE5\xAF\x92", + "\xB4\x49" => "\xE5\xAF\x8C", + "\xB4\x4A" => "\xE5\xAF\x93", + "\xB4\x4B" => "\xE5\xAF\x90", + "\xB4\x4C" => "\xE5\xB0\x8A", + "\xB4\x4D" => "\xE5\xB0\x8B", + "\xB4\x4E" => "\xE5\xB0\xB1", + "\xB4\x4F" => "\xE5\xB5\x8C", + "\xB4\x50" => "\xE5\xB5\x90", + "\xB4\x51" => "\xE5\xB4\xB4", + "\xB4\x52" => "\xE5\xB5\x87", + "\xB4\x53" => "\xE5\xB7\xBD", + "\xB4\x54" => "\xE5\xB9\x85", + "\xB4\x55" => "\xE5\xB8\xBD", + "\xB4\x56" => "\xE5\xB9\x80", + "\xB4\x57" => "\xE5\xB9\x83", + "\xB4\x58" => "\xE5\xB9\xBE", + "\xB4\x59" => "\xE5\xBB\x8A", + "\xB4\x5A" => "\xE5\xBB\x81", + "\xB4\x5B" => "\xE5\xBB\x82", + "\xB4\x5C" => "\xE5\xBB\x84", + "\xB4\x5D" => "\xE5\xBC\xBC", + "\xB4\x5E" => "\xE5\xBD\xAD", + "\xB4\x5F" => "\xE5\xBE\xA9", + "\xB4\x60" => "\xE5\xBE\xAA", + "\xB4\x61" => "\xE5\xBE\xA8", + "\xB4\x62" => "\xE6\x83\x91", + "\xB4\x63" => "\xE6\x83\xA1", + "\xB4\x64" => "\xE6\x82\xB2", + "\xB4\x65" => "\xE6\x82\xB6", + "\xB4\x66" => "\xE6\x83\xA0", + "\xB4\x67" => "\xE6\x84\x9C", + "\xB4\x68" => "\xE6\x84\xA3", + "\xB4\x69" => "\xE6\x83\xBA", + "\xB4\x6A" => "\xE6\x84\x95", + "\xB4\x6B" => "\xE6\x83\xB0", + "\xB4\x6C" => "\xE6\x83\xBB", + "\xB4\x6D" => "\xE6\x83\xB4", + "\xB4\x6E" => "\xE6\x85\xA8", + "\xB4\x6F" => "\xE6\x83\xB1", + "\xB4\x70" => "\xE6\x84\x8E", + "\xB4\x71" => "\xE6\x83\xB6", + "\xB4\x72" => "\xE6\x84\x89", + "\xB4\x73" => "\xE6\x84\x80", + "\xB4\x74" => "\xE6\x84\x92", + "\xB4\x75" => "\xE6\x88\x9F", + "\xB4\x76" => "\xE6\x89\x89", + "\xB4\x77" => "\xE6\x8E\xA3", + "\xB4\x78" => "\xE6\x8E\x8C", + "\xB4\x79" => "\xE6\x8F\x8F", + "\xB4\x7A" => "\xE6\x8F\x80", + "\xB4\x7B" => "\xE6\x8F\xA9", + "\xB4\x7C" => "\xE6\x8F\x89", + "\xB4\x7D" => "\xE6\x8F\x86", + "\xB4\x7E" => "\xE6\x8F\x8D", + "\xB4\xA1" => "\xE6\x8F\x92", + "\xB4\xA2" => "\xE6\x8F\xA3", + "\xB4\xA3" => "\xE6\x8F\x90", + "\xB4\xA4" => "\xE6\x8F\xA1", + "\xB4\xA5" => "\xE6\x8F\x96", + "\xB4\xA6" => "\xE6\x8F\xAD", + "\xB4\xA7" => "\xE6\x8F\xAE", + "\xB4\xA8" => "\xE6\x8D\xB6", + "\xB4\xA9" => "\xE6\x8F\xB4", + "\xB4\xAA" => "\xE6\x8F\xAA", + "\xB4\xAB" => "\xE6\x8F\x9B", + "\xB4\xAC" => "\xE6\x91\x92", + "\xB4\xAD" => "\xE6\x8F\x9A", + "\xB4\xAE" => "\xE6\x8F\xB9", + "\xB4\xAF" => "\xE6\x95\x9E", + "\xB4\xB0" => "\xE6\x95\xA6", + "\xB4\xB1" => "\xE6\x95\xA2", + "\xB4\xB2" => "\xE6\x95\xA3", + "\xB4\xB3" => "\xE6\x96\x91", + "\xB4\xB4" => "\xE6\x96\x90", + "\xB4\xB5" => "\xE6\x96\xAF", + "\xB4\xB6" => "\xE6\x99\xAE", + "\xB4\xB7" => "\xE6\x99\xB0", + "\xB4\xB8" => "\xE6\x99\xB4", + "\xB4\xB9" => "\xE6\x99\xB6", + "\xB4\xBA" => "\xE6\x99\xAF", + "\xB4\xBB" => "\xE6\x9A\x91", + "\xB4\xBC" => "\xE6\x99\xBA", + "\xB4\xBD" => "\xE6\x99\xBE", + "\xB4\xBE" => "\xE6\x99\xB7", + "\xB4\xBF" => "\xE6\x9B\xBE", + "\xB4\xC0" => "\xE6\x9B\xBF", + "\xB4\xC1" => "\xE6\x9C\x9F", + "\xB4\xC2" => "\xE6\x9C\x9D", + "\xB4\xC3" => "\xE6\xA3\xBA", + "\xB4\xC4" => "\xE6\xA3\x95", + "\xB4\xC5" => "\xE6\xA3\xA0", + "\xB4\xC6" => "\xE6\xA3\x98", + "\xB4\xC7" => "\xE6\xA3\x97", + "\xB4\xC8" => "\xE6\xA4\x85", + "\xB4\xC9" => "\xE6\xA3\x9F", + "\xB4\xCA" => "\xE6\xA3\xB5", + "\xB4\xCB" => "\xE6\xA3\xAE", + "\xB4\xCC" => "\xE6\xA3\xA7", + "\xB4\xCD" => "\xE6\xA3\xB9", + "\xB4\xCE" => "\xE6\xA3\x92", + "\xB4\xCF" => "\xE6\xA3\xB2", + "\xB4\xD0" => "\xE6\xA3\xA3", + "\xB4\xD1" => "\xE6\xA3\x8B", + "\xB4\xD2" => "\xE6\xA3\x8D", + "\xB4\xD3" => "\xE6\xA4\x8D", + "\xB4\xD4" => "\xE6\xA4\x92", + "\xB4\xD5" => "\xE6\xA4\x8E", + "\xB4\xD6" => "\xE6\xA3\x89", + "\xB4\xD7" => "\xE6\xA3\x9A", + "\xB4\xD8" => "\xE6\xA5\xAE", + "\xB4\xD9" => "\xE6\xA3\xBB", + "\xB4\xDA" => "\xE6\xAC\xBE", + "\xB4\xDB" => "\xE6\xAC\xBA", + "\xB4\xDC" => "\xE6\xAC\xBD", + "\xB4\xDD" => "\xE6\xAE\x98", + "\xB4\xDE" => "\xE6\xAE\x96", + "\xB4\xDF" => "\xE6\xAE\xBC", + "\xB4\xE0" => "\xE6\xAF\xAF", + "\xB4\xE1" => "\xE6\xB0\xAE", + "\xB4\xE2" => "\xE6\xB0\xAF", + "\xB4\xE3" => "\xE6\xB0\xAC", + "\xB4\xE4" => "\xE6\xB8\xAF", + "\xB4\xE5" => "\xE6\xB8\xB8", + "\xB4\xE6" => "\xE6\xB9\x94", + "\xB4\xE7" => "\xE6\xB8\xA1", + "\xB4\xE8" => "\xE6\xB8\xB2", + "\xB4\xE9" => "\xE6\xB9\xA7", + "\xB4\xEA" => "\xE6\xB9\x8A", + "\xB4\xEB" => "\xE6\xB8\xA0", + "\xB4\xEC" => "\xE6\xB8\xA5", + "\xB4\xED" => "\xE6\xB8\xA3", + "\xB4\xEE" => "\xE6\xB8\x9B", + "\xB4\xEF" => "\xE6\xB9\x9B", + "\xB4\xF0" => "\xE6\xB9\x98", + "\xB4\xF1" => "\xE6\xB8\xA4", + "\xB4\xF2" => "\xE6\xB9\x96", + "\xB4\xF3" => "\xE6\xB9\xAE", + "\xB4\xF4" => "\xE6\xB8\xAD", + "\xB4\xF5" => "\xE6\xB8\xA6", + "\xB4\xF6" => "\xE6\xB9\xAF", + "\xB4\xF7" => "\xE6\xB8\xB4", + "\xB4\xF8" => "\xE6\xB9\x8D", + "\xB4\xF9" => "\xE6\xB8\xBA", + "\xB4\xFA" => "\xE6\xB8\xAC", + "\xB4\xFB" => "\xE6\xB9\x83", + "\xB4\xFC" => "\xE6\xB8\x9D", + "\xB4\xFD" => "\xE6\xB8\xBE", + "\xB4\xFE" => "\xE6\xBB\x8B", + "\xB5\x40" => "\xE6\xBA\x89", + "\xB5\x41" => "\xE6\xB8\x99", + "\xB5\x42" => "\xE6\xB9\x8E", + "\xB5\x43" => "\xE6\xB9\xA3", + "\xB5\x44" => "\xE6\xB9\x84", + "\xB5\x45" => "\xE6\xB9\xB2", + "\xB5\x46" => "\xE6\xB9\xA9", + "\xB5\x47" => "\xE6\xB9\x9F", + "\xB5\x48" => "\xE7\x84\x99", + "\xB5\x49" => "\xE7\x84\x9A", + "\xB5\x4A" => "\xE7\x84\xA6", + "\xB5\x4B" => "\xE7\x84\xB0", + "\xB5\x4C" => "\xE7\x84\xA1", + "\xB5\x4D" => "\xE7\x84\xB6", + "\xB5\x4E" => "\xE7\x85\xAE", + "\xB5\x4F" => "\xE7\x84\x9C", + "\xB5\x50" => "\xE7\x89\x8C", + "\xB5\x51" => "\xE7\x8A\x84", + "\xB5\x52" => "\xE7\x8A\x80", + "\xB5\x53" => "\xE7\x8C\xB6", + "\xB5\x54" => "\xE7\x8C\xA5", + "\xB5\x55" => "\xE7\x8C\xB4", + "\xB5\x56" => "\xE7\x8C\xA9", + "\xB5\x57" => "\xE7\x90\xBA", + "\xB5\x58" => "\xE7\x90\xAA", + "\xB5\x59" => "\xE7\x90\xB3", + "\xB5\x5A" => "\xE7\x90\xA2", + "\xB5\x5B" => "\xE7\x90\xA5", + "\xB5\x5C" => "\xE7\x90\xB5", + "\xB5\x5D" => "\xE7\x90\xB6", + "\xB5\x5E" => "\xE7\x90\xB4", + "\xB5\x5F" => "\xE7\x90\xAF", + "\xB5\x60" => "\xE7\x90\x9B", + "\xB5\x61" => "\xE7\x90\xA6", + "\xB5\x62" => "\xE7\x90\xA8", + "\xB5\x63" => "\xE7\x94\xA5", + "\xB5\x64" => "\xE7\x94\xA6", + "\xB5\x65" => "\xE7\x95\xAB", + "\xB5\x66" => "\xE7\x95\xAA", + "\xB5\x67" => "\xE7\x97\xA2", + "\xB5\x68" => "\xE7\x97\x9B", + "\xB5\x69" => "\xE7\x97\xA3", + "\xB5\x6A" => "\xE7\x97\x99", + "\xB5\x6B" => "\xE7\x97\x98", + "\xB5\x6C" => "\xE7\x97\x9E", + "\xB5\x6D" => "\xE7\x97\xA0", + "\xB5\x6E" => "\xE7\x99\xBB", + "\xB5\x6F" => "\xE7\x99\xBC", + "\xB5\x70" => "\xE7\x9A\x96", + "\xB5\x71" => "\xE7\x9A\x93", + "\xB5\x72" => "\xE7\x9A\xB4", + "\xB5\x73" => "\xE7\x9B\x9C", + "\xB5\x74" => "\xE7\x9D\x8F", + "\xB5\x75" => "\xE7\x9F\xAD", + "\xB5\x76" => "\xE7\xA1\x9D", + "\xB5\x77" => "\xE7\xA1\xAC", + "\xB5\x78" => "\xE7\xA1\xAF", + "\xB5\x79" => "\xE7\xA8\x8D", + "\xB5\x7A" => "\xE7\xA8\x88", + "\xB5\x7B" => "\xE7\xA8\x8B", + "\xB5\x7C" => "\xE7\xA8\x85", + "\xB5\x7D" => "\xE7\xA8\x80", + "\xB5\x7E" => "\xE7\xAA\x98", + "\xB5\xA1" => "\xE7\xAA\x97", + "\xB5\xA2" => "\xE7\xAA\x96", + "\xB5\xA3" => "\xE7\xAB\xA5", + "\xB5\xA4" => "\xE7\xAB\xA3", + "\xB5\xA5" => "\xE7\xAD\x89", + "\xB5\xA6" => "\xE7\xAD\x96", + "\xB5\xA7" => "\xE7\xAD\x86", + "\xB5\xA8" => "\xE7\xAD\x90", + "\xB5\xA9" => "\xE7\xAD\x92", + "\xB5\xAA" => "\xE7\xAD\x94", + "\xB5\xAB" => "\xE7\xAD\x8D", + "\xB5\xAC" => "\xE7\xAD\x8B", + "\xB5\xAD" => "\xE7\xAD\x8F", + "\xB5\xAE" => "\xE7\xAD\x91", + "\xB5\xAF" => "\xE7\xB2\x9F", + "\xB5\xB0" => "\xE7\xB2\xA5", + "\xB5\xB1" => "\xE7\xB5\x9E", + "\xB5\xB2" => "\xE7\xB5\x90", + "\xB5\xB3" => "\xE7\xB5\xA8", + "\xB5\xB4" => "\xE7\xB5\x95", + "\xB5\xB5" => "\xE7\xB4\xAB", + "\xB5\xB6" => "\xE7\xB5\xAE", + "\xB5\xB7" => "\xE7\xB5\xB2", + "\xB5\xB8" => "\xE7\xB5\xA1", + "\xB5\xB9" => "\xE7\xB5\xA6", + "\xB5\xBA" => "\xE7\xB5\xA2", + "\xB5\xBB" => "\xE7\xB5\xB0", + "\xB5\xBC" => "\xE7\xB5\xB3", + "\xB5\xBD" => "\xE5\x96\x84", + "\xB5\xBE" => "\xE7\xBF\x94", + "\xB5\xBF" => "\xE7\xBF\x95", + "\xB5\xC0" => "\xE8\x80\x8B", + "\xB5\xC1" => "\xE8\x81\x92", + "\xB5\xC2" => "\xE8\x82\x85", + "\xB5\xC3" => "\xE8\x85\x95", + "\xB5\xC4" => "\xE8\x85\x94", + "\xB5\xC5" => "\xE8\x85\x8B", + "\xB5\xC6" => "\xE8\x85\x91", + "\xB5\xC7" => "\xE8\x85\x8E", + "\xB5\xC8" => "\xE8\x84\xB9", + "\xB5\xC9" => "\xE8\x85\x86", + "\xB5\xCA" => "\xE8\x84\xBE", + "\xB5\xCB" => "\xE8\x85\x8C", + "\xB5\xCC" => "\xE8\x85\x93", + "\xB5\xCD" => "\xE8\x85\xB4", + "\xB5\xCE" => "\xE8\x88\x92", + "\xB5\xCF" => "\xE8\x88\x9C", + "\xB5\xD0" => "\xE8\x8F\xA9", + "\xB5\xD1" => "\xE8\x90\x83", + "\xB5\xD2" => "\xE8\x8F\xB8", + "\xB5\xD3" => "\xE8\x90\x8D", + "\xB5\xD4" => "\xE8\x8F\xA0", + "\xB5\xD5" => "\xE8\x8F\x85", + "\xB5\xD6" => "\xE8\x90\x8B", + "\xB5\xD7" => "\xE8\x8F\x81", + "\xB5\xD8" => "\xE8\x8F\xAF", + "\xB5\xD9" => "\xE8\x8F\xB1", + "\xB5\xDA" => "\xE8\x8F\xB4", + "\xB5\xDB" => "\xE8\x91\x97", + "\xB5\xDC" => "\xE8\x90\x8A", + "\xB5\xDD" => "\xE8\x8F\xB0", + "\xB5\xDE" => "\xE8\x90\x8C", + "\xB5\xDF" => "\xE8\x8F\x8C", + "\xB5\xE0" => "\xE8\x8F\xBD", + "\xB5\xE1" => "\xE8\x8F\xB2", + "\xB5\xE2" => "\xE8\x8F\x8A", + "\xB5\xE3" => "\xE8\x90\xB8", + "\xB5\xE4" => "\xE8\x90\x8E", + "\xB5\xE5" => "\xE8\x90\x84", + "\xB5\xE6" => "\xE8\x8F\x9C", + "\xB5\xE7" => "\xE8\x90\x87", + "\xB5\xE8" => "\xE8\x8F\x94", + "\xB5\xE9" => "\xE8\x8F\x9F", + "\xB5\xEA" => "\xE8\x99\x9B", + "\xB5\xEB" => "\xE8\x9B\x9F", + "\xB5\xEC" => "\xE8\x9B\x99", + "\xB5\xED" => "\xE8\x9B\xAD", + "\xB5\xEE" => "\xE8\x9B\x94", + "\xB5\xEF" => "\xE8\x9B\x9B", + "\xB5\xF0" => "\xE8\x9B\xA4", + "\xB5\xF1" => "\xE8\x9B\x90", + "\xB5\xF2" => "\xE8\x9B\x9E", + "\xB5\xF3" => "\xE8\xA1\x97", + "\xB5\xF4" => "\xE8\xA3\x81", + "\xB5\xF5" => "\xE8\xA3\x82", + "\xB5\xF6" => "\xE8\xA2\xB1", + "\xB5\xF7" => "\xE8\xA6\x83", + "\xB5\xF8" => "\xE8\xA6\x96", + "\xB5\xF9" => "\xE8\xA8\xBB", + "\xB5\xFA" => "\xE8\xA9\xA0", + "\xB5\xFB" => "\xE8\xA9\x95", + "\xB5\xFC" => "\xE8\xA9\x9E", + "\xB5\xFD" => "\xE8\xA8\xBC", + "\xB5\xFE" => "\xE8\xA9\x81", + "\xB6\x40" => "\xE8\xA9\x94", + "\xB6\x41" => "\xE8\xA9\x9B", + "\xB6\x42" => "\xE8\xA9\x90", + "\xB6\x43" => "\xE8\xA9\x86", + "\xB6\x44" => "\xE8\xA8\xB4", + "\xB6\x45" => "\xE8\xA8\xBA", + "\xB6\x46" => "\xE8\xA8\xB6", + "\xB6\x47" => "\xE8\xA9\x96", + "\xB6\x48" => "\xE8\xB1\xA1", + "\xB6\x49" => "\xE8\xB2\x82", + "\xB6\x4A" => "\xE8\xB2\xAF", + "\xB6\x4B" => "\xE8\xB2\xBC", + "\xB6\x4C" => "\xE8\xB2\xB3", + "\xB6\x4D" => "\xE8\xB2\xBD", + "\xB6\x4E" => "\xE8\xB3\x81", + "\xB6\x4F" => "\xE8\xB2\xBB", + "\xB6\x50" => "\xE8\xB3\x80", + "\xB6\x51" => "\xE8\xB2\xB4", + "\xB6\x52" => "\xE8\xB2\xB7", + "\xB6\x53" => "\xE8\xB2\xB6", + "\xB6\x54" => "\xE8\xB2\xBF", + "\xB6\x55" => "\xE8\xB2\xB8", + "\xB6\x56" => "\xE8\xB6\x8A", + "\xB6\x57" => "\xE8\xB6\x85", + "\xB6\x58" => "\xE8\xB6\x81", + "\xB6\x59" => "\xE8\xB7\x8E", + "\xB6\x5A" => "\xE8\xB7\x9D", + "\xB6\x5B" => "\xE8\xB7\x8B", + "\xB6\x5C" => "\xE8\xB7\x9A", + "\xB6\x5D" => "\xE8\xB7\x91", + "\xB6\x5E" => "\xE8\xB7\x8C", + "\xB6\x5F" => "\xE8\xB7\x9B", + "\xB6\x60" => "\xE8\xB7\x86", + "\xB6\x61" => "\xE8\xBB\xBB", + "\xB6\x62" => "\xE8\xBB\xB8", + "\xB6\x63" => "\xE8\xBB\xBC", + "\xB6\x64" => "\xE8\xBE\x9C", + "\xB6\x65" => "\xE9\x80\xAE", + "\xB6\x66" => "\xE9\x80\xB5", + "\xB6\x67" => "\xE9\x80\xB1", + "\xB6\x68" => "\xE9\x80\xB8", + "\xB6\x69" => "\xE9\x80\xB2", + "\xB6\x6A" => "\xE9\x80\xB6", + "\xB6\x6B" => "\xE9\x84\x82", + "\xB6\x6C" => "\xE9\x83\xB5", + "\xB6\x6D" => "\xE9\x84\x89", + "\xB6\x6E" => "\xE9\x83\xBE", + "\xB6\x6F" => "\xE9\x85\xA3", + "\xB6\x70" => "\xE9\x85\xA5", + "\xB6\x71" => "\xE9\x87\x8F", + "\xB6\x72" => "\xE9\x88\x94", + "\xB6\x73" => "\xE9\x88\x95", + "\xB6\x74" => "\xE9\x88\xA3", + "\xB6\x75" => "\xE9\x88\x89", + "\xB6\x76" => "\xE9\x88\x9E", + "\xB6\x77" => "\xE9\x88\x8D", + "\xB6\x78" => "\xE9\x88\x90", + "\xB6\x79" => "\xE9\x88\x87", + "\xB6\x7A" => "\xE9\x88\x91", + "\xB6\x7B" => "\xE9\x96\x94", + "\xB6\x7C" => "\xE9\x96\x8F", + "\xB6\x7D" => "\xE9\x96\x8B", + "\xB6\x7E" => "\xE9\x96\x91", + "\xB6\xA1" => "\xE9\x96\x93", + "\xB6\xA2" => "\xE9\x96\x92", + "\xB6\xA3" => "\xE9\x96\x8E", + "\xB6\xA4" => "\xE9\x9A\x8A", + "\xB6\xA5" => "\xE9\x9A\x8E", + "\xB6\xA6" => "\xE9\x9A\x8B", + "\xB6\xA7" => "\xE9\x99\xBD", + "\xB6\xA8" => "\xE9\x9A\x85", + "\xB6\xA9" => "\xE9\x9A\x86", + "\xB6\xAA" => "\xE9\x9A\x8D", + "\xB6\xAB" => "\xE9\x99\xB2", + "\xB6\xAC" => "\xE9\x9A\x84", + "\xB6\xAD" => "\xE9\x9B\x81", + "\xB6\xAE" => "\xE9\x9B\x85", + "\xB6\xAF" => "\xE9\x9B\x84", + "\xB6\xB0" => "\xE9\x9B\x86", + "\xB6\xB1" => "\xE9\x9B\x87", + "\xB6\xB2" => "\xE9\x9B\xAF", + "\xB6\xB3" => "\xE9\x9B\xB2", + "\xB6\xB4" => "\xE9\x9F\x8C", + "\xB6\xB5" => "\xE9\xA0\x85", + "\xB6\xB6" => "\xE9\xA0\x86", + "\xB6\xB7" => "\xE9\xA0\x88", + "\xB6\xB8" => "\xE9\xA3\xA7", + "\xB6\xB9" => "\xE9\xA3\xAA", + "\xB6\xBA" => "\xE9\xA3\xAF", + "\xB6\xBB" => "\xE9\xA3\xA9", + "\xB6\xBC" => "\xE9\xA3\xB2", + "\xB6\xBD" => "\xE9\xA3\xAD", + "\xB6\xBE" => "\xE9\xA6\xAE", + "\xB6\xBF" => "\xE9\xA6\xAD", + "\xB6\xC0" => "\xE9\xBB\x83", + "\xB6\xC1" => "\xE9\xBB\x8D", + "\xB6\xC2" => "\xE9\xBB\x91", + "\xB6\xC3" => "\xE4\xBA\x82", + "\xB6\xC4" => "\xE5\x82\xAD", + "\xB6\xC5" => "\xE5\x82\xB5", + "\xB6\xC6" => "\xE5\x82\xB2", + "\xB6\xC7" => "\xE5\x82\xB3", + "\xB6\xC8" => "\xE5\x83\x85", + "\xB6\xC9" => "\xE5\x82\xBE", + "\xB6\xCA" => "\xE5\x82\xAC", + "\xB6\xCB" => "\xE5\x82\xB7", + "\xB6\xCC" => "\xE5\x82\xBB", + "\xB6\xCD" => "\xE5\x82\xAF", + "\xB6\xCE" => "\xE5\x83\x87", + "\xB6\xCF" => "\xE5\x89\xBF", + "\xB6\xD0" => "\xE5\x89\xB7", + "\xB6\xD1" => "\xE5\x89\xBD", + "\xB6\xD2" => "\xE5\x8B\x9F", + "\xB6\xD3" => "\xE5\x8B\xA6", + "\xB6\xD4" => "\xE5\x8B\xA4", + "\xB6\xD5" => "\xE5\x8B\xA2", + "\xB6\xD6" => "\xE5\x8B\xA3", + "\xB6\xD7" => "\xE5\x8C\xAF", + "\xB6\xD8" => "\xE5\x97\x9F", + "\xB6\xD9" => "\xE5\x97\xA8", + "\xB6\xDA" => "\xE5\x97\x93", + "\xB6\xDB" => "\xE5\x97\xA6", + "\xB6\xDC" => "\xE5\x97\x8E", + "\xB6\xDD" => "\xE5\x97\x9C", + "\xB6\xDE" => "\xE5\x97\x87", + "\xB6\xDF" => "\xE5\x97\x91", + "\xB6\xE0" => "\xE5\x97\xA3", + "\xB6\xE1" => "\xE5\x97\xA4", + "\xB6\xE2" => "\xE5\x97\xAF", + "\xB6\xE3" => "\xE5\x97\x9A", + "\xB6\xE4" => "\xE5\x97\xA1", + "\xB6\xE5" => "\xE5\x97\x85", + "\xB6\xE6" => "\xE5\x97\x86", + "\xB6\xE7" => "\xE5\x97\xA5", + "\xB6\xE8" => "\xE5\x97\x89", + "\xB6\xE9" => "\xE5\x9C\x92", + "\xB6\xEA" => "\xE5\x9C\x93", + "\xB6\xEB" => "\xE5\xA1\x9E", + "\xB6\xEC" => "\xE5\xA1\x91", + "\xB6\xED" => "\xE5\xA1\x98", + "\xB6\xEE" => "\xE5\xA1\x97", + "\xB6\xEF" => "\xE5\xA1\x9A", + "\xB6\xF0" => "\xE5\xA1\x94", + "\xB6\xF1" => "\xE5\xA1\xAB", + "\xB6\xF2" => "\xE5\xA1\x8C", + "\xB6\xF3" => "\xE5\xA1\xAD", + "\xB6\xF4" => "\xE5\xA1\x8A", + "\xB6\xF5" => "\xE5\xA1\xA2", + "\xB6\xF6" => "\xE5\xA1\x92", + "\xB6\xF7" => "\xE5\xA1\x8B", + "\xB6\xF8" => "\xE5\xA5\xA7", + "\xB6\xF9" => "\xE5\xAB\x81", + "\xB6\xFA" => "\xE5\xAB\x89", + "\xB6\xFB" => "\xE5\xAB\x8C", + "\xB6\xFC" => "\xE5\xAA\xBE", + "\xB6\xFD" => "\xE5\xAA\xBD", + "\xB6\xFE" => "\xE5\xAA\xBC", + "\xB7\x40" => "\xE5\xAA\xB3", + "\xB7\x41" => "\xE5\xAB\x82", + "\xB7\x42" => "\xE5\xAA\xB2", + "\xB7\x43" => "\xE5\xB5\xA9", + "\xB7\x44" => "\xE5\xB5\xAF", + "\xB7\x45" => "\xE5\xB9\x8C", + "\xB7\x46" => "\xE5\xB9\xB9", + "\xB7\x47" => "\xE5\xBB\x89", + "\xB7\x48" => "\xE5\xBB\x88", + "\xB7\x49" => "\xE5\xBC\x92", + "\xB7\x4A" => "\xE5\xBD\x99", + "\xB7\x4B" => "\xE5\xBE\xAC", + "\xB7\x4C" => "\xE5\xBE\xAE", + "\xB7\x4D" => "\xE6\x84\x9A", + "\xB7\x4E" => "\xE6\x84\x8F", + "\xB7\x4F" => "\xE6\x85\x88", + "\xB7\x50" => "\xE6\x84\x9F", + "\xB7\x51" => "\xE6\x83\xB3", + "\xB7\x52" => "\xE6\x84\x9B", + "\xB7\x53" => "\xE6\x83\xB9", + "\xB7\x54" => "\xE6\x84\x81", + "\xB7\x55" => "\xE6\x84\x88", + "\xB7\x56" => "\xE6\x85\x8E", + "\xB7\x57" => "\xE6\x85\x8C", + "\xB7\x58" => "\xE6\x85\x84", + "\xB7\x59" => "\xE6\x85\x8D", + "\xB7\x5A" => "\xE6\x84\xBE", + "\xB7\x5B" => "\xE6\x84\xB4", + "\xB7\x5C" => "\xE6\x84\xA7", + "\xB7\x5D" => "\xE6\x84\x8D", + "\xB7\x5E" => "\xE6\x84\x86", + "\xB7\x5F" => "\xE6\x84\xB7", + "\xB7\x60" => "\xE6\x88\xA1", + "\xB7\x61" => "\xE6\x88\xA2", + "\xB7\x62" => "\xE6\x90\x93", + "\xB7\x63" => "\xE6\x90\xBE", + "\xB7\x64" => "\xE6\x90\x9E", + "\xB7\x65" => "\xE6\x90\xAA", + "\xB7\x66" => "\xE6\x90\xAD", + "\xB7\x67" => "\xE6\x90\xBD", + "\xB7\x68" => "\xE6\x90\xAC", + "\xB7\x69" => "\xE6\x90\x8F", + "\xB7\x6A" => "\xE6\x90\x9C", + "\xB7\x6B" => "\xE6\x90\x94", + "\xB7\x6C" => "\xE6\x90\x8D", + "\xB7\x6D" => "\xE6\x90\xB6", + "\xB7\x6E" => "\xE6\x90\x96", + "\xB7\x6F" => "\xE6\x90\x97", + "\xB7\x70" => "\xE6\x90\x86", + "\xB7\x71" => "\xE6\x95\xAC", + "\xB7\x72" => "\xE6\x96\x9F", + "\xB7\x73" => "\xE6\x96\xB0", + "\xB7\x74" => "\xE6\x9A\x97", + "\xB7\x75" => "\xE6\x9A\x89", + "\xB7\x76" => "\xE6\x9A\x87", + "\xB7\x77" => "\xE6\x9A\x88", + "\xB7\x78" => "\xE6\x9A\x96", + "\xB7\x79" => "\xE6\x9A\x84", + "\xB7\x7A" => "\xE6\x9A\x98", + "\xB7\x7B" => "\xE6\x9A\x8D", + "\xB7\x7C" => "\xE6\x9C\x83", + "\xB7\x7D" => "\xE6\xA6\x94", + "\xB7\x7E" => "\xE6\xA5\xAD", + "\xB7\xA1" => "\xE6\xA5\x9A", + "\xB7\xA2" => "\xE6\xA5\xB7", + "\xB7\xA3" => "\xE6\xA5\xA0", + "\xB7\xA4" => "\xE6\xA5\x94", + "\xB7\xA5" => "\xE6\xA5\xB5", + "\xB7\xA6" => "\xE6\xA4\xB0", + "\xB7\xA7" => "\xE6\xA6\x82", + "\xB7\xA8" => "\xE6\xA5\x8A", + "\xB7\xA9" => "\xE6\xA5\xA8", + "\xB7\xAA" => "\xE6\xA5\xAB", + "\xB7\xAB" => "\xE6\xA5\x9E", + "\xB7\xAC" => "\xE6\xA5\x93", + "\xB7\xAD" => "\xE6\xA5\xB9", + "\xB7\xAE" => "\xE6\xA6\x86", + "\xB7\xAF" => "\xE6\xA5\x9D", + "\xB7\xB0" => "\xE6\xA5\xA3", + "\xB7\xB1" => "\xE6\xA5\x9B", + "\xB7\xB2" => "\xE6\xAD\x87", + "\xB7\xB3" => "\xE6\xAD\xB2", + "\xB7\xB4" => "\xE6\xAF\x80", + "\xB7\xB5" => "\xE6\xAE\xBF", + "\xB7\xB6" => "\xE6\xAF\x93", + "\xB7\xB7" => "\xE6\xAF\xBD", + "\xB7\xB8" => "\xE6\xBA\xA2", + "\xB7\xB9" => "\xE6\xBA\xAF", + "\xB7\xBA" => "\xE6\xBB\x93", + "\xB7\xBB" => "\xE6\xBA\xB6", + "\xB7\xBC" => "\xE6\xBB\x82", + "\xB7\xBD" => "\xE6\xBA\x90", + "\xB7\xBE" => "\xE6\xBA\x9D", + "\xB7\xBF" => "\xE6\xBB\x87", + "\xB7\xC0" => "\xE6\xBB\x85", + "\xB7\xC1" => "\xE6\xBA\xA5", + "\xB7\xC2" => "\xE6\xBA\x98", + "\xB7\xC3" => "\xE6\xBA\xBC", + "\xB7\xC4" => "\xE6\xBA\xBA", + "\xB7\xC5" => "\xE6\xBA\xAB", + "\xB7\xC6" => "\xE6\xBB\x91", + "\xB7\xC7" => "\xE6\xBA\x96", + "\xB7\xC8" => "\xE6\xBA\x9C", + "\xB7\xC9" => "\xE6\xBB\x84", + "\xB7\xCA" => "\xE6\xBB\x94", + "\xB7\xCB" => "\xE6\xBA\xAA", + "\xB7\xCC" => "\xE6\xBA\xA7", + "\xB7\xCD" => "\xE6\xBA\xB4", + "\xB7\xCE" => "\xE7\x85\x8E", + "\xB7\xCF" => "\xE7\x85\x99", + "\xB7\xD0" => "\xE7\x85\xA9", + "\xB7\xD1" => "\xE7\x85\xA4", + "\xB7\xD2" => "\xE7\x85\x89", + "\xB7\xD3" => "\xE7\x85\xA7", + "\xB7\xD4" => "\xE7\x85\x9C", + "\xB7\xD5" => "\xE7\x85\xAC", + "\xB7\xD6" => "\xE7\x85\xA6", + "\xB7\xD7" => "\xE7\x85\x8C", + "\xB7\xD8" => "\xE7\x85\xA5", + "\xB7\xD9" => "\xE7\x85\x9E", + "\xB7\xDA" => "\xE7\x85\x86", + "\xB7\xDB" => "\xE7\x85\xA8", + "\xB7\xDC" => "\xE7\x85\x96", + "\xB7\xDD" => "\xE7\x88\xBA", + "\xB7\xDE" => "\xE7\x89\x92", + "\xB7\xDF" => "\xE7\x8C\xB7", + "\xB7\xE0" => "\xE7\x8D\x85", + "\xB7\xE1" => "\xE7\x8C\xBF", + "\xB7\xE2" => "\xE7\x8C\xBE", + "\xB7\xE3" => "\xE7\x91\xAF", + "\xB7\xE4" => "\xE7\x91\x9A", + "\xB7\xE5" => "\xE7\x91\x95", + "\xB7\xE6" => "\xE7\x91\x9F", + "\xB7\xE7" => "\xE7\x91\x9E", + "\xB7\xE8" => "\xE7\x91\x81", + "\xB7\xE9" => "\xE7\x90\xBF", + "\xB7\xEA" => "\xE7\x91\x99", + "\xB7\xEB" => "\xE7\x91\x9B", + "\xB7\xEC" => "\xE7\x91\x9C", + "\xB7\xED" => "\xE7\x95\xB6", + "\xB7\xEE" => "\xE7\x95\xB8", + "\xB7\xEF" => "\xE7\x98\x80", + "\xB7\xF0" => "\xE7\x97\xB0", + "\xB7\xF1" => "\xE7\x98\x81", + "\xB7\xF2" => "\xE7\x97\xB2", + "\xB7\xF3" => "\xE7\x97\xB1", + "\xB7\xF4" => "\xE7\x97\xBA", + "\xB7\xF5" => "\xE7\x97\xBF", + "\xB7\xF6" => "\xE7\x97\xB4", + "\xB7\xF7" => "\xE7\x97\xB3", + "\xB7\xF8" => "\xE7\x9B\x9E", + "\xB7\xF9" => "\xE7\x9B\x9F", + "\xB7\xFA" => "\xE7\x9D\x9B", + "\xB7\xFB" => "\xE7\x9D\xAB", + "\xB7\xFC" => "\xE7\x9D\xA6", + "\xB7\xFD" => "\xE7\x9D\x9E", + "\xB7\xFE" => "\xE7\x9D\xA3", + "\xB8\x40" => "\xE7\x9D\xB9", + "\xB8\x41" => "\xE7\x9D\xAA", + "\xB8\x42" => "\xE7\x9D\xAC", + "\xB8\x43" => "\xE7\x9D\x9C", + "\xB8\x44" => "\xE7\x9D\xA5", + "\xB8\x45" => "\xE7\x9D\xA8", + "\xB8\x46" => "\xE7\x9D\xA2", + "\xB8\x47" => "\xE7\x9F\xAE", + "\xB8\x48" => "\xE7\xA2\x8E", + "\xB8\x49" => "\xE7\xA2\xB0", + "\xB8\x4A" => "\xE7\xA2\x97", + "\xB8\x4B" => "\xE7\xA2\x98", + "\xB8\x4C" => "\xE7\xA2\x8C", + "\xB8\x4D" => "\xE7\xA2\x89", + "\xB8\x4E" => "\xE7\xA1\xBC", + "\xB8\x4F" => "\xE7\xA2\x91", + "\xB8\x50" => "\xE7\xA2\x93", + "\xB8\x51" => "\xE7\xA1\xBF", + "\xB8\x52" => "\xE7\xA5\xBA", + "\xB8\x53" => "\xE7\xA5\xBF", + "\xB8\x54" => "\xE7\xA6\x81", + "\xB8\x55" => "\xE8\x90\xAC", + "\xB8\x56" => "\xE7\xA6\xBD", + "\xB8\x57" => "\xE7\xA8\x9C", + "\xB8\x58" => "\xE7\xA8\x9A", + "\xB8\x59" => "\xE7\xA8\xA0", + "\xB8\x5A" => "\xE7\xA8\x94", + "\xB8\x5B" => "\xE7\xA8\x9F", + "\xB8\x5C" => "\xE7\xA8\x9E", + "\xB8\x5D" => "\xE7\xAA\x9F", + "\xB8\x5E" => "\xE7\xAA\xA0", + "\xB8\x5F" => "\xE7\xAD\xB7", + "\xB8\x60" => "\xE7\xAF\x80", + "\xB8\x61" => "\xE7\xAD\xA0", + "\xB8\x62" => "\xE7\xAD\xAE", + "\xB8\x63" => "\xE7\xAD\xA7", + "\xB8\x64" => "\xE7\xB2\xB1", + "\xB8\x65" => "\xE7\xB2\xB3", + "\xB8\x66" => "\xE7\xB2\xB5", + "\xB8\x67" => "\xE7\xB6\x93", + "\xB8\x68" => "\xE7\xB5\xB9", + "\xB8\x69" => "\xE7\xB6\x91", + "\xB8\x6A" => "\xE7\xB6\x81", + "\xB8\x6B" => "\xE7\xB6\x8F", + "\xB8\x6C" => "\xE7\xB5\x9B", + "\xB8\x6D" => "\xE7\xBD\xAE", + "\xB8\x6E" => "\xE7\xBD\xA9", + "\xB8\x6F" => "\xE7\xBD\xAA", + "\xB8\x70" => "\xE7\xBD\xB2", + "\xB8\x71" => "\xE7\xBE\xA9", + "\xB8\x72" => "\xE7\xBE\xA8", + "\xB8\x73" => "\xE7\xBE\xA4", + "\xB8\x74" => "\xE8\x81\x96", + "\xB8\x75" => "\xE8\x81\x98", + "\xB8\x76" => "\xE8\x82\x86", + "\xB8\x77" => "\xE8\x82\x84", + "\xB8\x78" => "\xE8\x85\xB1", + "\xB8\x79" => "\xE8\x85\xB0", + "\xB8\x7A" => "\xE8\x85\xB8", + "\xB8\x7B" => "\xE8\x85\xA5", + "\xB8\x7C" => "\xE8\x85\xAE", + "\xB8\x7D" => "\xE8\x85\xB3", + "\xB8\x7E" => "\xE8\x85\xAB", + "\xB8\xA1" => "\xE8\x85\xB9", + "\xB8\xA2" => "\xE8\x85\xBA", + "\xB8\xA3" => "\xE8\x85\xA6", + "\xB8\xA4" => "\xE8\x88\x85", + "\xB8\xA5" => "\xE8\x89\x87", + "\xB8\xA6" => "\xE8\x92\x82", + "\xB8\xA7" => "\xE8\x91\xB7", + "\xB8\xA8" => "\xE8\x90\xBD", + "\xB8\xA9" => "\xE8\x90\xB1", + "\xB8\xAA" => "\xE8\x91\xB5", + "\xB8\xAB" => "\xE8\x91\xA6", + "\xB8\xAC" => "\xE8\x91\xAB", + "\xB8\xAD" => "\xE8\x91\x89", + "\xB8\xAE" => "\xE8\x91\xAC", + "\xB8\xAF" => "\xE8\x91\x9B", + "\xB8\xB0" => "\xE8\x90\xBC", + "\xB8\xB1" => "\xE8\x90\xB5", + "\xB8\xB2" => "\xE8\x91\xA1", + "\xB8\xB3" => "\xE8\x91\xA3", + "\xB8\xB4" => "\xE8\x91\xA9", + "\xB8\xB5" => "\xE8\x91\xAD", + "\xB8\xB6" => "\xE8\x91\x86", + "\xB8\xB7" => "\xE8\x99\x9E", + "\xB8\xB8" => "\xE8\x99\x9C", + "\xB8\xB9" => "\xE8\x99\x9F", + "\xB8\xBA" => "\xE8\x9B\xB9", + "\xB8\xBB" => "\xE8\x9C\x93", + "\xB8\xBC" => "\xE8\x9C\x88", + "\xB8\xBD" => "\xE8\x9C\x87", + "\xB8\xBE" => "\xE8\x9C\x80", + "\xB8\xBF" => "\xE8\x9B\xBE", + "\xB8\xC0" => "\xE8\x9B\xBB", + "\xB8\xC1" => "\xE8\x9C\x82", + "\xB8\xC2" => "\xE8\x9C\x83", + "\xB8\xC3" => "\xE8\x9C\x86", + "\xB8\xC4" => "\xE8\x9C\x8A", + "\xB8\xC5" => "\xE8\xA1\x99", + "\xB8\xC6" => "\xE8\xA3\x9F", + "\xB8\xC7" => "\xE8\xA3\x94", + "\xB8\xC8" => "\xE8\xA3\x99", + "\xB8\xC9" => "\xE8\xA3\x9C", + "\xB8\xCA" => "\xE8\xA3\x98", + "\xB8\xCB" => "\xE8\xA3\x9D", + "\xB8\xCC" => "\xE8\xA3\xA1", + "\xB8\xCD" => "\xE8\xA3\x8A", + "\xB8\xCE" => "\xE8\xA3\x95", + "\xB8\xCF" => "\xE8\xA3\x92", + "\xB8\xD0" => "\xE8\xA6\x9C", + "\xB8\xD1" => "\xE8\xA7\xA3", + "\xB8\xD2" => "\xE8\xA9\xAB", + "\xB8\xD3" => "\xE8\xA9\xB2", + "\xB8\xD4" => "\xE8\xA9\xB3", + "\xB8\xD5" => "\xE8\xA9\xA6", + "\xB8\xD6" => "\xE8\xA9\xA9", + "\xB8\xD7" => "\xE8\xA9\xB0", + "\xB8\xD8" => "\xE8\xAA\x87", + "\xB8\xD9" => "\xE8\xA9\xBC", + "\xB8\xDA" => "\xE8\xA9\xA3", + "\xB8\xDB" => "\xE8\xAA\xA0", + "\xB8\xDC" => "\xE8\xA9\xB1", + "\xB8\xDD" => "\xE8\xAA\x85", + "\xB8\xDE" => "\xE8\xA9\xAD", + "\xB8\xDF" => "\xE8\xA9\xA2", + "\xB8\xE0" => "\xE8\xA9\xAE", + "\xB8\xE1" => "\xE8\xA9\xAC", + "\xB8\xE2" => "\xE8\xA9\xB9", + "\xB8\xE3" => "\xE8\xA9\xBB", + "\xB8\xE4" => "\xE8\xA8\xBE", + "\xB8\xE5" => "\xE8\xA9\xA8", + "\xB8\xE6" => "\xE8\xB1\xA2", + "\xB8\xE7" => "\xE8\xB2\x8A", + "\xB8\xE8" => "\xE8\xB2\x89", + "\xB8\xE9" => "\xE8\xB3\x8A", + "\xB8\xEA" => "\xE8\xB3\x87", + "\xB8\xEB" => "\xE8\xB3\x88", + "\xB8\xEC" => "\xE8\xB3\x84", + "\xB8\xED" => "\xE8\xB2\xB2", + "\xB8\xEE" => "\xE8\xB3\x83", + "\xB8\xEF" => "\xE8\xB3\x82", + "\xB8\xF0" => "\xE8\xB3\x85", + "\xB8\xF1" => "\xE8\xB7\xA1", + "\xB8\xF2" => "\xE8\xB7\x9F", + "\xB8\xF3" => "\xE8\xB7\xA8", + "\xB8\xF4" => "\xE8\xB7\xAF", + "\xB8\xF5" => "\xE8\xB7\xB3", + "\xB8\xF6" => "\xE8\xB7\xBA", + "\xB8\xF7" => "\xE8\xB7\xAA", + "\xB8\xF8" => "\xE8\xB7\xA4", + "\xB8\xF9" => "\xE8\xB7\xA6", + "\xB8\xFA" => "\xE8\xBA\xB2", + "\xB8\xFB" => "\xE8\xBC\x83", + "\xB8\xFC" => "\xE8\xBC\x89", + "\xB8\xFD" => "\xE8\xBB\xBE", + "\xB8\xFE" => "\xE8\xBC\x8A", + "\xB9\x40" => "\xE8\xBE\x9F", + "\xB9\x41" => "\xE8\xBE\xB2", + "\xB9\x42" => "\xE9\x81\x8B", + "\xB9\x43" => "\xE9\x81\x8A", + "\xB9\x44" => "\xE9\x81\x93", + "\xB9\x45" => "\xE9\x81\x82", + "\xB9\x46" => "\xE9\x81\x94", + "\xB9\x47" => "\xE9\x80\xBC", + "\xB9\x48" => "\xE9\x81\x95", + "\xB9\x49" => "\xE9\x81\x90", + "\xB9\x4A" => "\xE9\x81\x87", + "\xB9\x4B" => "\xE9\x81\x8F", + "\xB9\x4C" => "\xE9\x81\x8E", + "\xB9\x4D" => "\xE9\x81\x8D", + "\xB9\x4E" => "\xE9\x81\x91", + "\xB9\x4F" => "\xE9\x80\xBE", + "\xB9\x50" => "\xE9\x81\x81", + "\xB9\x51" => "\xE9\x84\x92", + "\xB9\x52" => "\xE9\x84\x97", + "\xB9\x53" => "\xE9\x85\xAC", + "\xB9\x54" => "\xE9\x85\xAA", + "\xB9\x55" => "\xE9\x85\xA9", + "\xB9\x56" => "\xE9\x87\x89", + "\xB9\x57" => "\xE9\x88\xB7", + "\xB9\x58" => "\xE9\x89\x97", + "\xB9\x59" => "\xE9\x88\xB8", + "\xB9\x5A" => "\xE9\x88\xBD", + "\xB9\x5B" => "\xE9\x89\x80", + "\xB9\x5C" => "\xE9\x88\xBE", + "\xB9\x5D" => "\xE9\x89\x9B", + "\xB9\x5E" => "\xE9\x89\x8B", + "\xB9\x5F" => "\xE9\x89\xA4", + "\xB9\x60" => "\xE9\x89\x91", + "\xB9\x61" => "\xE9\x88\xB4", + "\xB9\x62" => "\xE9\x89\x89", + "\xB9\x63" => "\xE9\x89\x8D", + "\xB9\x64" => "\xE9\x89\x85", + "\xB9\x65" => "\xE9\x88\xB9", + "\xB9\x66" => "\xE9\x88\xBF", + "\xB9\x67" => "\xE9\x89\x9A", + "\xB9\x68" => "\xE9\x96\x98", + "\xB9\x69" => "\xE9\x9A\x98", + "\xB9\x6A" => "\xE9\x9A\x94", + "\xB9\x6B" => "\xE9\x9A\x95", + "\xB9\x6C" => "\xE9\x9B\x8D", + "\xB9\x6D" => "\xE9\x9B\x8B", + "\xB9\x6E" => "\xE9\x9B\x89", + "\xB9\x6F" => "\xE9\x9B\x8A", + "\xB9\x70" => "\xE9\x9B\xB7", + "\xB9\x71" => "\xE9\x9B\xBB", + "\xB9\x72" => "\xE9\x9B\xB9", + "\xB9\x73" => "\xE9\x9B\xB6", + "\xB9\x74" => "\xE9\x9D\x96", + "\xB9\x75" => "\xE9\x9D\xB4", + "\xB9\x76" => "\xE9\x9D\xB6", + "\xB9\x77" => "\xE9\xA0\x90", + "\xB9\x78" => "\xE9\xA0\x91", + "\xB9\x79" => "\xE9\xA0\x93", + "\xB9\x7A" => "\xE9\xA0\x8A", + "\xB9\x7B" => "\xE9\xA0\x92", + "\xB9\x7C" => "\xE9\xA0\x8C", + "\xB9\x7D" => "\xE9\xA3\xBC", + "\xB9\x7E" => "\xE9\xA3\xB4", + "\xB9\xA1" => "\xE9\xA3\xBD", + "\xB9\xA2" => "\xE9\xA3\xBE", + "\xB9\xA3" => "\xE9\xA6\xB3", + "\xB9\xA4" => "\xE9\xA6\xB1", + "\xB9\xA5" => "\xE9\xA6\xB4", + "\xB9\xA6" => "\xE9\xAB\xA1", + "\xB9\xA7" => "\xE9\xB3\xA9", + "\xB9\xA8" => "\xE9\xBA\x82", + "\xB9\xA9" => "\xE9\xBC\x8E", + "\xB9\xAA" => "\xE9\xBC\x93", + "\xB9\xAB" => "\xE9\xBC\xA0", + "\xB9\xAC" => "\xE5\x83\xA7", + "\xB9\xAD" => "\xE5\x83\xAE", + "\xB9\xAE" => "\xE5\x83\xA5", + "\xB9\xAF" => "\xE5\x83\x96", + "\xB9\xB0" => "\xE5\x83\xAD", + "\xB9\xB1" => "\xE5\x83\x9A", + "\xB9\xB2" => "\xE5\x83\x95", + "\xB9\xB3" => "\xE5\x83\x8F", + "\xB9\xB4" => "\xE5\x83\x91", + "\xB9\xB5" => "\xE5\x83\xB1", + "\xB9\xB6" => "\xE5\x83\x8E", + "\xB9\xB7" => "\xE5\x83\xA9", + "\xB9\xB8" => "\xE5\x85\xA2", + "\xB9\xB9" => "\xE5\x87\xB3", + "\xB9\xBA" => "\xE5\x8A\x83", + "\xB9\xBB" => "\xE5\x8A\x82", + "\xB9\xBC" => "\xE5\x8C\xB1", + "\xB9\xBD" => "\xE5\x8E\xAD", + "\xB9\xBE" => "\xE5\x97\xBE", + "\xB9\xBF" => "\xE5\x98\x80", + "\xB9\xC0" => "\xE5\x98\x9B", + "\xB9\xC1" => "\xE5\x98\x97", + "\xB9\xC2" => "\xE5\x97\xBD", + "\xB9\xC3" => "\xE5\x98\x94", + "\xB9\xC4" => "\xE5\x98\x86", + "\xB9\xC5" => "\xE5\x98\x89", + "\xB9\xC6" => "\xE5\x98\x8D", + "\xB9\xC7" => "\xE5\x98\x8E", + "\xB9\xC8" => "\xE5\x97\xB7", + "\xB9\xC9" => "\xE5\x98\x96", + "\xB9\xCA" => "\xE5\x98\x9F", + "\xB9\xCB" => "\xE5\x98\x88", + "\xB9\xCC" => "\xE5\x98\x90", + "\xB9\xCD" => "\xE5\x97\xB6", + "\xB9\xCE" => "\xE5\x9C\x98", + "\xB9\xCF" => "\xE5\x9C\x96", + "\xB9\xD0" => "\xE5\xA1\xB5", + "\xB9\xD1" => "\xE5\xA1\xBE", + "\xB9\xD2" => "\xE5\xA2\x83", + "\xB9\xD3" => "\xE5\xA2\x93", + "\xB9\xD4" => "\xE5\xA2\x8A", + "\xB9\xD5" => "\xE5\xA1\xB9", + "\xB9\xD6" => "\xE5\xA2\x85", + "\xB9\xD7" => "\xE5\xA1\xBD", + "\xB9\xD8" => "\xE5\xA3\xBD", + "\xB9\xD9" => "\xE5\xA4\xA5", + "\xB9\xDA" => "\xE5\xA4\xA2", + "\xB9\xDB" => "\xE5\xA4\xA4", + "\xB9\xDC" => "\xE5\xA5\xAA", + "\xB9\xDD" => "\xE5\xA5\xA9", + "\xB9\xDE" => "\xE5\xAB\xA1", + "\xB9\xDF" => "\xE5\xAB\xA6", + "\xB9\xE0" => "\xE5\xAB\xA9", + "\xB9\xE1" => "\xE5\xAB\x97", + "\xB9\xE2" => "\xE5\xAB\x96", + "\xB9\xE3" => "\xE5\xAB\x98", + "\xB9\xE4" => "\xE5\xAB\xA3", + "\xB9\xE5" => "\xE5\xAD\xB5", + "\xB9\xE6" => "\xE5\xAF\x9E", + "\xB9\xE7" => "\xE5\xAF\xA7", + "\xB9\xE8" => "\xE5\xAF\xA1", + "\xB9\xE9" => "\xE5\xAF\xA5", + "\xB9\xEA" => "\xE5\xAF\xA6", + "\xB9\xEB" => "\xE5\xAF\xA8", + "\xB9\xEC" => "\xE5\xAF\xA2", + "\xB9\xED" => "\xE5\xAF\xA4", + "\xB9\xEE" => "\xE5\xAF\x9F", + "\xB9\xEF" => "\xE5\xB0\x8D", + "\xB9\xF0" => "\xE5\xB1\xA2", + "\xB9\xF1" => "\xE5\xB6\x84", + "\xB9\xF2" => "\xE5\xB6\x87", + "\xB9\xF3" => "\xE5\xB9\x9B", + "\xB9\xF4" => "\xE5\xB9\xA3", + "\xB9\xF5" => "\xE5\xB9\x95", + "\xB9\xF6" => "\xE5\xB9\x97", + "\xB9\xF7" => "\xE5\xB9\x94", + "\xB9\xF8" => "\xE5\xBB\x93", + "\xB9\xF9" => "\xE5\xBB\x96", + "\xB9\xFA" => "\xE5\xBC\x8A", + "\xB9\xFB" => "\xE5\xBD\x86", + "\xB9\xFC" => "\xE5\xBD\xB0", + "\xB9\xFD" => "\xE5\xBE\xB9", + "\xB9\xFE" => "\xE6\x85\x87", + "\xBA\x40" => "\xE6\x84\xBF", + "\xBA\x41" => "\xE6\x85\x8B", + "\xBA\x42" => "\xE6\x85\xB7", + "\xBA\x43" => "\xE6\x85\xA2", + "\xBA\x44" => "\xE6\x85\xA3", + "\xBA\x45" => "\xE6\x85\x9F", + "\xBA\x46" => "\xE6\x85\x9A", + "\xBA\x47" => "\xE6\x85\x98", + "\xBA\x48" => "\xE6\x85\xB5", + "\xBA\x49" => "\xE6\x88\xAA", + "\xBA\x4A" => "\xE6\x92\x87", + "\xBA\x4B" => "\xE6\x91\x98", + "\xBA\x4C" => "\xE6\x91\x94", + "\xBA\x4D" => "\xE6\x92\xA4", + "\xBA\x4E" => "\xE6\x91\xB8", + "\xBA\x4F" => "\xE6\x91\x9F", + "\xBA\x50" => "\xE6\x91\xBA", + "\xBA\x51" => "\xE6\x91\x91", + "\xBA\x52" => "\xE6\x91\xA7", + "\xBA\x53" => "\xE6\x90\xB4", + "\xBA\x54" => "\xE6\x91\xAD", + "\xBA\x55" => "\xE6\x91\xBB", + "\xBA\x56" => "\xE6\x95\xB2", + "\xBA\x57" => "\xE6\x96\xA1", + "\xBA\x58" => "\xE6\x97\x97", + "\xBA\x59" => "\xE6\x97\x96", + "\xBA\x5A" => "\xE6\x9A\xA2", + "\xBA\x5B" => "\xE6\x9A\xA8", + "\xBA\x5C" => "\xE6\x9A\x9D", + "\xBA\x5D" => "\xE6\xA6\x9C", + "\xBA\x5E" => "\xE6\xA6\xA8", + "\xBA\x5F" => "\xE6\xA6\x95", + "\xBA\x60" => "\xE6\xA7\x81", + "\xBA\x61" => "\xE6\xA6\xAE", + "\xBA\x62" => "\xE6\xA7\x93", + "\xBA\x63" => "\xE6\xA7\x8B", + "\xBA\x64" => "\xE6\xA6\x9B", + "\xBA\x65" => "\xE6\xA6\xB7", + "\xBA\x66" => "\xE6\xA6\xBB", + "\xBA\x67" => "\xE6\xA6\xAB", + "\xBA\x68" => "\xE6\xA6\xB4", + "\xBA\x69" => "\xE6\xA7\x90", + "\xBA\x6A" => "\xE6\xA7\x8D", + "\xBA\x6B" => "\xE6\xA6\xAD", + "\xBA\x6C" => "\xE6\xA7\x8C", + "\xBA\x6D" => "\xE6\xA6\xA6", + "\xBA\x6E" => "\xE6\xA7\x83", + "\xBA\x6F" => "\xE6\xA6\xA3", + "\xBA\x70" => "\xE6\xAD\x89", + "\xBA\x71" => "\xE6\xAD\x8C", + "\xBA\x72" => "\xE6\xB0\xB3", + "\xBA\x73" => "\xE6\xBC\xB3", + "\xBA\x74" => "\xE6\xBC\x94", + "\xBA\x75" => "\xE6\xBB\xBE", + "\xBA\x76" => "\xE6\xBC\x93", + "\xBA\x77" => "\xE6\xBB\xB4", + "\xBA\x78" => "\xE6\xBC\xA9", + "\xBA\x79" => "\xE6\xBC\xBE", + "\xBA\x7A" => "\xE6\xBC\xA0", + "\xBA\x7B" => "\xE6\xBC\xAC", + "\xBA\x7C" => "\xE6\xBC\x8F", + "\xBA\x7D" => "\xE6\xBC\x82", + "\xBA\x7E" => "\xE6\xBC\xA2", + "\xBA\xA1" => "\xE6\xBB\xBF", + "\xBA\xA2" => "\xE6\xBB\xAF", + "\xBA\xA3" => "\xE6\xBC\x86", + "\xBA\xA4" => "\xE6\xBC\xB1", + "\xBA\xA5" => "\xE6\xBC\xB8", + "\xBA\xA6" => "\xE6\xBC\xB2", + "\xBA\xA7" => "\xE6\xBC\xA3", + "\xBA\xA8" => "\xE6\xBC\x95", + "\xBA\xA9" => "\xE6\xBC\xAB", + "\xBA\xAA" => "\xE6\xBC\xAF", + "\xBA\xAB" => "\xE6\xBE\x88", + "\xBA\xAC" => "\xE6\xBC\xAA", + "\xBA\xAD" => "\xE6\xBB\xAC", + "\xBA\xAE" => "\xE6\xBC\x81", + "\xBA\xAF" => "\xE6\xBB\xB2", + "\xBA\xB0" => "\xE6\xBB\x8C", + "\xBA\xB1" => "\xE6\xBB\xB7", + "\xBA\xB2" => "\xE7\x86\x94", + "\xBA\xB3" => "\xE7\x86\x99", + "\xBA\xB4" => "\xE7\x85\xBD", + "\xBA\xB5" => "\xE7\x86\x8A", + "\xBA\xB6" => "\xE7\x86\x84", + "\xBA\xB7" => "\xE7\x86\x92", + "\xBA\xB8" => "\xE7\x88\xBE", + "\xBA\xB9" => "\xE7\x8A\x92", + "\xBA\xBA" => "\xE7\x8A\x96", + "\xBA\xBB" => "\xE7\x8D\x84", + "\xBA\xBC" => "\xE7\x8D\x90", + "\xBA\xBD" => "\xE7\x91\xA4", + "\xBA\xBE" => "\xE7\x91\xA3", + "\xBA\xBF" => "\xE7\x91\xAA", + "\xBA\xC0" => "\xE7\x91\xB0", + "\xBA\xC1" => "\xE7\x91\xAD", + "\xBA\xC2" => "\xE7\x94\x84", + "\xBA\xC3" => "\xE7\x96\x91", + "\xBA\xC4" => "\xE7\x98\xA7", + "\xBA\xC5" => "\xE7\x98\x8D", + "\xBA\xC6" => "\xE7\x98\x8B", + "\xBA\xC7" => "\xE7\x98\x89", + "\xBA\xC8" => "\xE7\x98\x93", + "\xBA\xC9" => "\xE7\x9B\xA1", + "\xBA\xCA" => "\xE7\x9B\xA3", + "\xBA\xCB" => "\xE7\x9E\x84", + "\xBA\xCC" => "\xE7\x9D\xBD", + "\xBA\xCD" => "\xE7\x9D\xBF", + "\xBA\xCE" => "\xE7\x9D\xA1", + "\xBA\xCF" => "\xE7\xA3\x81", + "\xBA\xD0" => "\xE7\xA2\x9F", + "\xBA\xD1" => "\xE7\xA2\xA7", + "\xBA\xD2" => "\xE7\xA2\xB3", + "\xBA\xD3" => "\xE7\xA2\xA9", + "\xBA\xD4" => "\xE7\xA2\xA3", + "\xBA\xD5" => "\xE7\xA6\x8E", + "\xBA\xD6" => "\xE7\xA6\x8F", + "\xBA\xD7" => "\xE7\xA6\x8D", + "\xBA\xD8" => "\xE7\xA8\xAE", + "\xBA\xD9" => "\xE7\xA8\xB1", + "\xBA\xDA" => "\xE7\xAA\xAA", + "\xBA\xDB" => "\xE7\xAA\xA9", + "\xBA\xDC" => "\xE7\xAB\xAD", + "\xBA\xDD" => "\xE7\xAB\xAF", + "\xBA\xDE" => "\xE7\xAE\xA1", + "\xBA\xDF" => "\xE7\xAE\x95", + "\xBA\xE0" => "\xE7\xAE\x8B", + "\xBA\xE1" => "\xE7\xAD\xB5", + "\xBA\xE2" => "\xE7\xAE\x97", + "\xBA\xE3" => "\xE7\xAE\x9D", + "\xBA\xE4" => "\xE7\xAE\x94", + "\xBA\xE5" => "\xE7\xAE\x8F", + "\xBA\xE6" => "\xE7\xAE\xB8", + "\xBA\xE7" => "\xE7\xAE\x87", + "\xBA\xE8" => "\xE7\xAE\x84", + "\xBA\xE9" => "\xE7\xB2\xB9", + "\xBA\xEA" => "\xE7\xB2\xBD", + "\xBA\xEB" => "\xE7\xB2\xBE", + "\xBA\xEC" => "\xE7\xB6\xBB", + "\xBA\xED" => "\xE7\xB6\xB0", + "\xBA\xEE" => "\xE7\xB6\x9C", + "\xBA\xEF" => "\xE7\xB6\xBD", + "\xBA\xF0" => "\xE7\xB6\xBE", + "\xBA\xF1" => "\xE7\xB6\xA0", + "\xBA\xF2" => "\xE7\xB7\x8A", + "\xBA\xF3" => "\xE7\xB6\xB4", + "\xBA\xF4" => "\xE7\xB6\xB2", + "\xBA\xF5" => "\xE7\xB6\xB1", + "\xBA\xF6" => "\xE7\xB6\xBA", + "\xBA\xF7" => "\xE7\xB6\xA2", + "\xBA\xF8" => "\xE7\xB6\xBF", + "\xBA\xF9" => "\xE7\xB6\xB5", + "\xBA\xFA" => "\xE7\xB6\xB8", + "\xBA\xFB" => "\xE7\xB6\xAD", + "\xBA\xFC" => "\xE7\xB7\x92", + "\xBA\xFD" => "\xE7\xB7\x87", + "\xBA\xFE" => "\xE7\xB6\xAC", + "\xBB\x40" => "\xE7\xBD\xB0", + "\xBB\x41" => "\xE7\xBF\xA0", + "\xBB\x42" => "\xE7\xBF\xA1", + "\xBB\x43" => "\xE7\xBF\x9F", + "\xBB\x44" => "\xE8\x81\x9E", + "\xBB\x45" => "\xE8\x81\x9A", + "\xBB\x46" => "\xE8\x82\x87", + "\xBB\x47" => "\xE8\x85\x90", + "\xBB\x48" => "\xE8\x86\x80", + "\xBB\x49" => "\xE8\x86\x8F", + "\xBB\x4A" => "\xE8\x86\x88", + "\xBB\x4B" => "\xE8\x86\x8A", + "\xBB\x4C" => "\xE8\x85\xBF", + "\xBB\x4D" => "\xE8\x86\x82", + "\xBB\x4E" => "\xE8\x87\xA7", + "\xBB\x4F" => "\xE8\x87\xBA", + "\xBB\x50" => "\xE8\x88\x87", + "\xBB\x51" => "\xE8\x88\x94", + "\xBB\x52" => "\xE8\x88\x9E", + "\xBB\x53" => "\xE8\x89\x8B", + "\xBB\x54" => "\xE8\x93\x89", + "\xBB\x55" => "\xE8\x92\xBF", + "\xBB\x56" => "\xE8\x93\x86", + "\xBB\x57" => "\xE8\x93\x84", + "\xBB\x58" => "\xE8\x92\x99", + "\xBB\x59" => "\xE8\x92\x9E", + "\xBB\x5A" => "\xE8\x92\xB2", + "\xBB\x5B" => "\xE8\x92\x9C", + "\xBB\x5C" => "\xE8\x93\x8B", + "\xBB\x5D" => "\xE8\x92\xB8", + "\xBB\x5E" => "\xE8\x93\x80", + "\xBB\x5F" => "\xE8\x93\x93", + "\xBB\x60" => "\xE8\x92\x90", + "\xBB\x61" => "\xE8\x92\xBC", + "\xBB\x62" => "\xE8\x93\x91", + "\xBB\x63" => "\xE8\x93\x8A", + "\xBB\x64" => "\xE8\x9C\xBF", + "\xBB\x65" => "\xE8\x9C\x9C", + "\xBB\x66" => "\xE8\x9C\xBB", + "\xBB\x67" => "\xE8\x9C\xA2", + "\xBB\x68" => "\xE8\x9C\xA5", + "\xBB\x69" => "\xE8\x9C\xB4", + "\xBB\x6A" => "\xE8\x9C\x98", + "\xBB\x6B" => "\xE8\x9D\x95", + "\xBB\x6C" => "\xE8\x9C\xB7", + "\xBB\x6D" => "\xE8\x9C\xA9", + "\xBB\x6E" => "\xE8\xA3\xB3", + "\xBB\x6F" => "\xE8\xA4\x82", + "\xBB\x70" => "\xE8\xA3\xB4", + "\xBB\x71" => "\xE8\xA3\xB9", + "\xBB\x72" => "\xE8\xA3\xB8", + "\xBB\x73" => "\xE8\xA3\xBD", + "\xBB\x74" => "\xE8\xA3\xA8", + "\xBB\x75" => "\xE8\xA4\x9A", + "\xBB\x76" => "\xE8\xA3\xAF", + "\xBB\x77" => "\xE8\xAA\xA6", + "\xBB\x78" => "\xE8\xAA\x8C", + "\xBB\x79" => "\xE8\xAA\x9E", + "\xBB\x7A" => "\xE8\xAA\xA3", + "\xBB\x7B" => "\xE8\xAA\x8D", + "\xBB\x7C" => "\xE8\xAA\xA1", + "\xBB\x7D" => "\xE8\xAA\x93", + "\xBB\x7E" => "\xE8\xAA\xA4", + "\xBB\xA1" => "\xE8\xAA\xAA", + "\xBB\xA2" => "\xE8\xAA\xA5", + "\xBB\xA3" => "\xE8\xAA\xA8", + "\xBB\xA4" => "\xE8\xAA\x98", + "\xBB\xA5" => "\xE8\xAA\x91", + "\xBB\xA6" => "\xE8\xAA\x9A", + "\xBB\xA7" => "\xE8\xAA\xA7", + "\xBB\xA8" => "\xE8\xB1\xAA", + "\xBB\xA9" => "\xE8\xB2\x8D", + "\xBB\xAA" => "\xE8\xB2\x8C", + "\xBB\xAB" => "\xE8\xB3\x93", + "\xBB\xAC" => "\xE8\xB3\x91", + "\xBB\xAD" => "\xE8\xB3\x92", + "\xBB\xAE" => "\xE8\xB5\xAB", + "\xBB\xAF" => "\xE8\xB6\x99", + "\xBB\xB0" => "\xE8\xB6\x95", + "\xBB\xB1" => "\xE8\xB7\xBC", + "\xBB\xB2" => "\xE8\xBC\x94", + "\xBB\xB3" => "\xE8\xBC\x92", + "\xBB\xB4" => "\xE8\xBC\x95", + "\xBB\xB5" => "\xE8\xBC\x93", + "\xBB\xB6" => "\xE8\xBE\xA3", + "\xBB\xB7" => "\xE9\x81\xA0", + "\xBB\xB8" => "\xE9\x81\x98", + "\xBB\xB9" => "\xE9\x81\x9C", + "\xBB\xBA" => "\xE9\x81\xA3", + "\xBB\xBB" => "\xE9\x81\x99", + "\xBB\xBC" => "\xE9\x81\x9E", + "\xBB\xBD" => "\xE9\x81\xA2", + "\xBB\xBE" => "\xE9\x81\x9D", + "\xBB\xBF" => "\xE9\x81\x9B", + "\xBB\xC0" => "\xE9\x84\x99", + "\xBB\xC1" => "\xE9\x84\x98", + "\xBB\xC2" => "\xE9\x84\x9E", + "\xBB\xC3" => "\xE9\x85\xB5", + "\xBB\xC4" => "\xE9\x85\xB8", + "\xBB\xC5" => "\xE9\x85\xB7", + "\xBB\xC6" => "\xE9\x85\xB4", + "\xBB\xC7" => "\xE9\x89\xB8", + "\xBB\xC8" => "\xE9\x8A\x80", + "\xBB\xC9" => "\xE9\x8A\x85", + "\xBB\xCA" => "\xE9\x8A\x98", + "\xBB\xCB" => "\xE9\x8A\x96", + "\xBB\xCC" => "\xE9\x89\xBB", + "\xBB\xCD" => "\xE9\x8A\x93", + "\xBB\xCE" => "\xE9\x8A\x9C", + "\xBB\xCF" => "\xE9\x8A\xA8", + "\xBB\xD0" => "\xE9\x89\xBC", + "\xBB\xD1" => "\xE9\x8A\x91", + "\xBB\xD2" => "\xE9\x96\xA1", + "\xBB\xD3" => "\xE9\x96\xA8", + "\xBB\xD4" => "\xE9\x96\xA9", + "\xBB\xD5" => "\xE9\x96\xA3", + "\xBB\xD6" => "\xE9\x96\xA5", + "\xBB\xD7" => "\xE9\x96\xA4", + "\xBB\xD8" => "\xE9\x9A\x99", + "\xBB\xD9" => "\xE9\x9A\x9C", + "\xBB\xDA" => "\xE9\x9A\x9B", + "\xBB\xDB" => "\xE9\x9B\x8C", + "\xBB\xDC" => "\xE9\x9B\x92", + "\xBB\xDD" => "\xE9\x9C\x80", + "\xBB\xDE" => "\xE9\x9D\xBC", + "\xBB\xDF" => "\xE9\x9E\x85", + "\xBB\xE0" => "\xE9\x9F\xB6", + "\xBB\xE1" => "\xE9\xA0\x97", + "\xBB\xE2" => "\xE9\xA0\x98", + "\xBB\xE3" => "\xE9\xA2\xAF", + "\xBB\xE4" => "\xE9\xA2\xB1", + "\xBB\xE5" => "\xE9\xA4\x83", + "\xBB\xE6" => "\xE9\xA4\x85", + "\xBB\xE7" => "\xE9\xA4\x8C", + "\xBB\xE8" => "\xE9\xA4\x89", + "\xBB\xE9" => "\xE9\xA7\x81", + "\xBB\xEA" => "\xE9\xAA\xAF", + "\xBB\xEB" => "\xE9\xAA\xB0", + "\xBB\xEC" => "\xE9\xAB\xA6", + "\xBB\xED" => "\xE9\xAD\x81", + "\xBB\xEE" => "\xE9\xAD\x82", + "\xBB\xEF" => "\xE9\xB3\xB4", + "\xBB\xF0" => "\xE9\xB3\xB6", + "\xBB\xF1" => "\xE9\xB3\xB3", + "\xBB\xF2" => "\xE9\xBA\xBC", + "\xBB\xF3" => "\xE9\xBC\xBB", + "\xBB\xF4" => "\xE9\xBD\x8A", + "\xBB\xF5" => "\xE5\x84\x84", + "\xBB\xF6" => "\xE5\x84\x80", + "\xBB\xF7" => "\xE5\x83\xBB", + "\xBB\xF8" => "\xE5\x83\xB5", + "\xBB\xF9" => "\xE5\x83\xB9", + "\xBB\xFA" => "\xE5\x84\x82", + "\xBB\xFB" => "\xE5\x84\x88", + "\xBB\xFC" => "\xE5\x84\x89", + "\xBB\xFD" => "\xE5\x84\x85", + "\xBB\xFE" => "\xE5\x87\x9C", + "\xBC\x40" => "\xE5\x8A\x87", + "\xBC\x41" => "\xE5\x8A\x88", + "\xBC\x42" => "\xE5\x8A\x89", + "\xBC\x43" => "\xE5\x8A\x8D", + "\xBC\x44" => "\xE5\x8A\x8A", + "\xBC\x45" => "\xE5\x8B\xB0", + "\xBC\x46" => "\xE5\x8E\xB2", + "\xBC\x47" => "\xE5\x98\xAE", + "\xBC\x48" => "\xE5\x98\xBB", + "\xBC\x49" => "\xE5\x98\xB9", + "\xBC\x4A" => "\xE5\x98\xB2", + "\xBC\x4B" => "\xE5\x98\xBF", + "\xBC\x4C" => "\xE5\x98\xB4", + "\xBC\x4D" => "\xE5\x98\xA9", + "\xBC\x4E" => "\xE5\x99\x93", + "\xBC\x4F" => "\xE5\x99\x8E", + "\xBC\x50" => "\xE5\x99\x97", + "\xBC\x51" => "\xE5\x99\xB4", + "\xBC\x52" => "\xE5\x98\xB6", + "\xBC\x53" => "\xE5\x98\xAF", + "\xBC\x54" => "\xE5\x98\xB0", + "\xBC\x55" => "\xE5\xA2\x80", + "\xBC\x56" => "\xE5\xA2\x9F", + "\xBC\x57" => "\xE5\xA2\x9E", + "\xBC\x58" => "\xE5\xA2\xB3", + "\xBC\x59" => "\xE5\xA2\x9C", + "\xBC\x5A" => "\xE5\xA2\xAE", + "\xBC\x5B" => "\xE5\xA2\xA9", + "\xBC\x5C" => "\xE5\xA2\xA6", + "\xBC\x5D" => "\xE5\xA5\xAD", + "\xBC\x5E" => "\xE5\xAC\x89", + "\xBC\x5F" => "\xE5\xAB\xBB", + "\xBC\x60" => "\xE5\xAC\x8B", + "\xBC\x61" => "\xE5\xAB\xB5", + "\xBC\x62" => "\xE5\xAC\x8C", + "\xBC\x63" => "\xE5\xAC\x88", + "\xBC\x64" => "\xE5\xAF\xAE", + "\xBC\x65" => "\xE5\xAF\xAC", + "\xBC\x66" => "\xE5\xAF\xA9", + "\xBC\x67" => "\xE5\xAF\xAB", + "\xBC\x68" => "\xE5\xB1\xA4", + "\xBC\x69" => "\xE5\xB1\xA5", + "\xBC\x6A" => "\xE5\xB6\x9D", + "\xBC\x6B" => "\xE5\xB6\x94", + "\xBC\x6C" => "\xE5\xB9\xA2", + "\xBC\x6D" => "\xE5\xB9\x9F", + "\xBC\x6E" => "\xE5\xB9\xA1", + "\xBC\x6F" => "\xE5\xBB\xA2", + "\xBC\x70" => "\xE5\xBB\x9A", + "\xBC\x71" => "\xE5\xBB\x9F", + "\xBC\x72" => "\xE5\xBB\x9D", + "\xBC\x73" => "\xE5\xBB\xA3", + "\xBC\x74" => "\xE5\xBB\xA0", + "\xBC\x75" => "\xE5\xBD\x88", + "\xBC\x76" => "\xE5\xBD\xB1", + "\xBC\x77" => "\xE5\xBE\xB7", + "\xBC\x78" => "\xE5\xBE\xB5", + "\xBC\x79" => "\xE6\x85\xB6", + "\xBC\x7A" => "\xE6\x85\xA7", + "\xBC\x7B" => "\xE6\x85\xAE", + "\xBC\x7C" => "\xE6\x85\x9D", + "\xBC\x7D" => "\xE6\x85\x95", + "\xBC\x7E" => "\xE6\x86\x82", + "\xBC\xA1" => "\xE6\x85\xBC", + "\xBC\xA2" => "\xE6\x85\xB0", + "\xBC\xA3" => "\xE6\x85\xAB", + "\xBC\xA4" => "\xE6\x85\xBE", + "\xBC\xA5" => "\xE6\x86\xA7", + "\xBC\xA6" => "\xE6\x86\x90", + "\xBC\xA7" => "\xE6\x86\xAB", + "\xBC\xA8" => "\xE6\x86\x8E", + "\xBC\xA9" => "\xE6\x86\xAC", + "\xBC\xAA" => "\xE6\x86\x9A", + "\xBC\xAB" => "\xE6\x86\xA4", + "\xBC\xAC" => "\xE6\x86\x94", + "\xBC\xAD" => "\xE6\x86\xAE", + "\xBC\xAE" => "\xE6\x88\xAE", + "\xBC\xAF" => "\xE6\x91\xA9", + "\xBC\xB0" => "\xE6\x91\xAF", + "\xBC\xB1" => "\xE6\x91\xB9", + "\xBC\xB2" => "\xE6\x92\x9E", + "\xBC\xB3" => "\xE6\x92\xB2", + "\xBC\xB4" => "\xE6\x92\x88", + "\xBC\xB5" => "\xE6\x92\x90", + "\xBC\xB6" => "\xE6\x92\xB0", + "\xBC\xB7" => "\xE6\x92\xA5", + "\xBC\xB8" => "\xE6\x92\x93", + "\xBC\xB9" => "\xE6\x92\x95", + "\xBC\xBA" => "\xE6\x92\xA9", + "\xBC\xBB" => "\xE6\x92\x92", + "\xBC\xBC" => "\xE6\x92\xAE", + "\xBC\xBD" => "\xE6\x92\xAD", + "\xBC\xBE" => "\xE6\x92\xAB", + "\xBC\xBF" => "\xE6\x92\x9A", + "\xBC\xC0" => "\xE6\x92\xAC", + "\xBC\xC1" => "\xE6\x92\x99", + "\xBC\xC2" => "\xE6\x92\xA2", + "\xBC\xC3" => "\xE6\x92\xB3", + "\xBC\xC4" => "\xE6\x95\xB5", + "\xBC\xC5" => "\xE6\x95\xB7", + "\xBC\xC6" => "\xE6\x95\xB8", + "\xBC\xC7" => "\xE6\x9A\xAE", + "\xBC\xC8" => "\xE6\x9A\xAB", + "\xBC\xC9" => "\xE6\x9A\xB4", + "\xBC\xCA" => "\xE6\x9A\xB1", + "\xBC\xCB" => "\xE6\xA8\xA3", + "\xBC\xCC" => "\xE6\xA8\x9F", + "\xBC\xCD" => "\xE6\xA7\xA8", + "\xBC\xCE" => "\xE6\xA8\x81", + "\xBC\xCF" => "\xE6\xA8\x9E", + "\xBC\xD0" => "\xE6\xA8\x99", + "\xBC\xD1" => "\xE6\xA7\xBD", + "\xBC\xD2" => "\xE6\xA8\xA1", + "\xBC\xD3" => "\xE6\xA8\x93", + "\xBC\xD4" => "\xE6\xA8\x8A", + "\xBC\xD5" => "\xE6\xA7\xB3", + "\xBC\xD6" => "\xE6\xA8\x82", + "\xBC\xD7" => "\xE6\xA8\x85", + "\xBC\xD8" => "\xE6\xA7\xAD", + "\xBC\xD9" => "\xE6\xA8\x91", + "\xBC\xDA" => "\xE6\xAD\x90", + "\xBC\xDB" => "\xE6\xAD\x8E", + "\xBC\xDC" => "\xE6\xAE\xA4", + "\xBC\xDD" => "\xE6\xAF\x85", + "\xBC\xDE" => "\xE6\xAF\x86", + "\xBC\xDF" => "\xE6\xBC\xBF", + "\xBC\xE0" => "\xE6\xBD\xBC", + "\xBC\xE1" => "\xE6\xBE\x84", + "\xBC\xE2" => "\xE6\xBD\x91", + "\xBC\xE3" => "\xE6\xBD\xA6", + "\xBC\xE4" => "\xE6\xBD\x94", + "\xBC\xE5" => "\xE6\xBE\x86", + "\xBC\xE6" => "\xE6\xBD\xAD", + "\xBC\xE7" => "\xE6\xBD\x9B", + "\xBC\xE8" => "\xE6\xBD\xB8", + "\xBC\xE9" => "\xE6\xBD\xAE", + "\xBC\xEA" => "\xE6\xBE\x8E", + "\xBC\xEB" => "\xE6\xBD\xBA", + "\xBC\xEC" => "\xE6\xBD\xB0", + "\xBC\xED" => "\xE6\xBD\xA4", + "\xBC\xEE" => "\xE6\xBE\x97", + "\xBC\xEF" => "\xE6\xBD\x98", + "\xBC\xF0" => "\xE6\xBB\x95", + "\xBC\xF1" => "\xE6\xBD\xAF", + "\xBC\xF2" => "\xE6\xBD\xA0", + "\xBC\xF3" => "\xE6\xBD\x9F", + "\xBC\xF4" => "\xE7\x86\x9F", + "\xBC\xF5" => "\xE7\x86\xAC", + "\xBC\xF6" => "\xE7\x86\xB1", + "\xBC\xF7" => "\xE7\x86\xA8", + "\xBC\xF8" => "\xE7\x89\x96", + "\xBC\xF9" => "\xE7\x8A\x9B", + "\xBC\xFA" => "\xE7\x8D\x8E", + "\xBC\xFB" => "\xE7\x8D\x97", + "\xBC\xFC" => "\xE7\x91\xA9", + "\xBC\xFD" => "\xE7\x92\x8B", + "\xBC\xFE" => "\xE7\x92\x83", + "\xBD\x40" => "\xE7\x91\xBE", + "\xBD\x41" => "\xE7\x92\x80", + "\xBD\x42" => "\xE7\x95\xBF", + "\xBD\x43" => "\xE7\x98\xA0", + "\xBD\x44" => "\xE7\x98\xA9", + "\xBD\x45" => "\xE7\x98\x9F", + "\xBD\x46" => "\xE7\x98\xA4", + "\xBD\x47" => "\xE7\x98\xA6", + "\xBD\x48" => "\xE7\x98\xA1", + "\xBD\x49" => "\xE7\x98\xA2", + "\xBD\x4A" => "\xE7\x9A\x9A", + "\xBD\x4B" => "\xE7\x9A\xBA", + "\xBD\x4C" => "\xE7\x9B\xA4", + "\xBD\x4D" => "\xE7\x9E\x8E", + "\xBD\x4E" => "\xE7\x9E\x87", + "\xBD\x4F" => "\xE7\x9E\x8C", + "\xBD\x50" => "\xE7\x9E\x91", + "\xBD\x51" => "\xE7\x9E\x8B", + "\xBD\x52" => "\xE7\xA3\x8B", + "\xBD\x53" => "\xE7\xA3\x85", + "\xBD\x54" => "\xE7\xA2\xBA", + "\xBD\x55" => "\xE7\xA3\x8A", + "\xBD\x56" => "\xE7\xA2\xBE", + "\xBD\x57" => "\xE7\xA3\x95", + "\xBD\x58" => "\xE7\xA2\xBC", + "\xBD\x59" => "\xE7\xA3\x90", + "\xBD\x5A" => "\xE7\xA8\xBF", + "\xBD\x5B" => "\xE7\xA8\xBC", + "\xBD\x5C" => "\xE7\xA9\x80", + "\xBD\x5D" => "\xE7\xA8\xBD", + "\xBD\x5E" => "\xE7\xA8\xB7", + "\xBD\x5F" => "\xE7\xA8\xBB", + "\xBD\x60" => "\xE7\xAA\xAF", + "\xBD\x61" => "\xE7\xAA\xAE", + "\xBD\x62" => "\xE7\xAE\xAD", + "\xBD\x63" => "\xE7\xAE\xB1", + "\xBD\x64" => "\xE7\xAF\x84", + "\xBD\x65" => "\xE7\xAE\xB4", + "\xBD\x66" => "\xE7\xAF\x86", + "\xBD\x67" => "\xE7\xAF\x87", + "\xBD\x68" => "\xE7\xAF\x81", + "\xBD\x69" => "\xE7\xAE\xA0", + "\xBD\x6A" => "\xE7\xAF\x8C", + "\xBD\x6B" => "\xE7\xB3\x8A", + "\xBD\x6C" => "\xE7\xB7\xA0", + "\xBD\x6D" => "\xE7\xB7\xB4", + "\xBD\x6E" => "\xE7\xB7\xAF", + "\xBD\x6F" => "\xE7\xB7\xBB", + "\xBD\x70" => "\xE7\xB7\x98", + "\xBD\x71" => "\xE7\xB7\xAC", + "\xBD\x72" => "\xE7\xB7\x9D", + "\xBD\x73" => "\xE7\xB7\xA8", + "\xBD\x74" => "\xE7\xB7\xA3", + "\xBD\x75" => "\xE7\xB7\x9A", + "\xBD\x76" => "\xE7\xB7\x9E", + "\xBD\x77" => "\xE7\xB7\xA9", + "\xBD\x78" => "\xE7\xB6\x9E", + "\xBD\x79" => "\xE7\xB7\x99", + "\xBD\x7A" => "\xE7\xB7\xB2", + "\xBD\x7B" => "\xE7\xB7\xB9", + "\xBD\x7C" => "\xE7\xBD\xB5", + "\xBD\x7D" => "\xE7\xBD\xB7", + "\xBD\x7E" => "\xE7\xBE\xAF", + "\xBD\xA1" => "\xE7\xBF\xA9", + "\xBD\xA2" => "\xE8\x80\xA6", + "\xBD\xA3" => "\xE8\x86\x9B", + "\xBD\xA4" => "\xE8\x86\x9C", + "\xBD\xA5" => "\xE8\x86\x9D", + "\xBD\xA6" => "\xE8\x86\xA0", + "\xBD\xA7" => "\xE8\x86\x9A", + "\xBD\xA8" => "\xE8\x86\x98", + "\xBD\xA9" => "\xE8\x94\x97", + "\xBD\xAA" => "\xE8\x94\xBD", + "\xBD\xAB" => "\xE8\x94\x9A", + "\xBD\xAC" => "\xE8\x93\xAE", + "\xBD\xAD" => "\xE8\x94\xAC", + "\xBD\xAE" => "\xE8\x94\xAD", + "\xBD\xAF" => "\xE8\x94\x93", + "\xBD\xB0" => "\xE8\x94\x91", + "\xBD\xB1" => "\xE8\x94\xA3", + "\xBD\xB2" => "\xE8\x94\xA1", + "\xBD\xB3" => "\xE8\x94\x94", + "\xBD\xB4" => "\xE8\x93\xAC", + "\xBD\xB5" => "\xE8\x94\xA5", + "\xBD\xB6" => "\xE8\x93\xBF", + "\xBD\xB7" => "\xE8\x94\x86", + "\xBD\xB8" => "\xE8\x9E\x82", + "\xBD\xB9" => "\xE8\x9D\xB4", + "\xBD\xBA" => "\xE8\x9D\xB6", + "\xBD\xBB" => "\xE8\x9D\xA0", + "\xBD\xBC" => "\xE8\x9D\xA6", + "\xBD\xBD" => "\xE8\x9D\xB8", + "\xBD\xBE" => "\xE8\x9D\xA8", + "\xBD\xBF" => "\xE8\x9D\x99", + "\xBD\xC0" => "\xE8\x9D\x97", + "\xBD\xC1" => "\xE8\x9D\x8C", + "\xBD\xC2" => "\xE8\x9D\x93", + "\xBD\xC3" => "\xE8\xA1\x9B", + "\xBD\xC4" => "\xE8\xA1\x9D", + "\xBD\xC5" => "\xE8\xA4\x90", + "\xBD\xC6" => "\xE8\xA4\x87", + "\xBD\xC7" => "\xE8\xA4\x92", + "\xBD\xC8" => "\xE8\xA4\x93", + "\xBD\xC9" => "\xE8\xA4\x95", + "\xBD\xCA" => "\xE8\xA4\x8A", + "\xBD\xCB" => "\xE8\xAA\xBC", + "\xBD\xCC" => "\xE8\xAB\x92", + "\xBD\xCD" => "\xE8\xAB\x87", + "\xBD\xCE" => "\xE8\xAB\x84", + "\xBD\xCF" => "\xE8\xAA\x95", + "\xBD\xD0" => "\xE8\xAB\x8B", + "\xBD\xD1" => "\xE8\xAB\xB8", + "\xBD\xD2" => "\xE8\xAA\xB2", + "\xBD\xD3" => "\xE8\xAB\x89", + "\xBD\xD4" => "\xE8\xAB\x82", + "\xBD\xD5" => "\xE8\xAA\xBF", + "\xBD\xD6" => "\xE8\xAA\xB0", + "\xBD\xD7" => "\xE8\xAB\x96", + "\xBD\xD8" => "\xE8\xAB\x8D", + "\xBD\xD9" => "\xE8\xAA\xB6", + "\xBD\xDA" => "\xE8\xAA\xB9", + "\xBD\xDB" => "\xE8\xAB\x9B", + "\xBD\xDC" => "\xE8\xB1\x8C", + "\xBD\xDD" => "\xE8\xB1\x8E", + "\xBD\xDE" => "\xE8\xB1\xAC", + "\xBD\xDF" => "\xE8\xB3\xA0", + "\xBD\xE0" => "\xE8\xB3\x9E", + "\xBD\xE1" => "\xE8\xB3\xA6", + "\xBD\xE2" => "\xE8\xB3\xA4", + "\xBD\xE3" => "\xE8\xB3\xAC", + "\xBD\xE4" => "\xE8\xB3\xAD", + "\xBD\xE5" => "\xE8\xB3\xA2", + "\xBD\xE6" => "\xE8\xB3\xA3", + "\xBD\xE7" => "\xE8\xB3\x9C", + "\xBD\xE8" => "\xE8\xB3\xAA", + "\xBD\xE9" => "\xE8\xB3\xA1", + "\xBD\xEA" => "\xE8\xB5\xAD", + "\xBD\xEB" => "\xE8\xB6\x9F", + "\xBD\xEC" => "\xE8\xB6\xA3", + "\xBD\xED" => "\xE8\xB8\xAB", + "\xBD\xEE" => "\xE8\xB8\x90", + "\xBD\xEF" => "\xE8\xB8\x9D", + "\xBD\xF0" => "\xE8\xB8\xA2", + "\xBD\xF1" => "\xE8\xB8\x8F", + "\xBD\xF2" => "\xE8\xB8\xA9", + "\xBD\xF3" => "\xE8\xB8\x9F", + "\xBD\xF4" => "\xE8\xB8\xA1", + "\xBD\xF5" => "\xE8\xB8\x9E", + "\xBD\xF6" => "\xE8\xBA\xBA", + "\xBD\xF7" => "\xE8\xBC\x9D", + "\xBD\xF8" => "\xE8\xBC\x9B", + "\xBD\xF9" => "\xE8\xBC\x9F", + "\xBD\xFA" => "\xE8\xBC\xA9", + "\xBD\xFB" => "\xE8\xBC\xA6", + "\xBD\xFC" => "\xE8\xBC\xAA", + "\xBD\xFD" => "\xE8\xBC\x9C", + "\xBD\xFE" => "\xE8\xBC\x9E", + "\xBE\x40" => "\xE8\xBC\xA5", + "\xBE\x41" => "\xE9\x81\xA9", + "\xBE\x42" => "\xE9\x81\xAE", + "\xBE\x43" => "\xE9\x81\xA8", + "\xBE\x44" => "\xE9\x81\xAD", + "\xBE\x45" => "\xE9\x81\xB7", + "\xBE\x46" => "\xE9\x84\xB0", + "\xBE\x47" => "\xE9\x84\xAD", + "\xBE\x48" => "\xE9\x84\xA7", + "\xBE\x49" => "\xE9\x84\xB1", + "\xBE\x4A" => "\xE9\x86\x87", + "\xBE\x4B" => "\xE9\x86\x89", + "\xBE\x4C" => "\xE9\x86\x8B", + "\xBE\x4D" => "\xE9\x86\x83", + "\xBE\x4E" => "\xE9\x8B\x85", + "\xBE\x4F" => "\xE9\x8A\xBB", + "\xBE\x50" => "\xE9\x8A\xB7", + "\xBE\x51" => "\xE9\x8B\xAA", + "\xBE\x52" => "\xE9\x8A\xAC", + "\xBE\x53" => "\xE9\x8B\xA4", + "\xBE\x54" => "\xE9\x8B\x81", + "\xBE\x55" => "\xE9\x8A\xB3", + "\xBE\x56" => "\xE9\x8A\xBC", + "\xBE\x57" => "\xE9\x8B\x92", + "\xBE\x58" => "\xE9\x8B\x87", + "\xBE\x59" => "\xE9\x8B\xB0", + "\xBE\x5A" => "\xE9\x8A\xB2", + "\xBE\x5B" => "\xE9\x96\xAD", + "\xBE\x5C" => "\xE9\x96\xB1", + "\xBE\x5D" => "\xE9\x9C\x84", + "\xBE\x5E" => "\xE9\x9C\x86", + "\xBE\x5F" => "\xE9\x9C\x87", + "\xBE\x60" => "\xE9\x9C\x89", + "\xBE\x61" => "\xE9\x9D\xA0", + "\xBE\x62" => "\xE9\x9E\x8D", + "\xBE\x63" => "\xE9\x9E\x8B", + "\xBE\x64" => "\xE9\x9E\x8F", + "\xBE\x65" => "\xE9\xA0\xA1", + "\xBE\x66" => "\xE9\xA0\xAB", + "\xBE\x67" => "\xE9\xA0\x9C", + "\xBE\x68" => "\xE9\xA2\xB3", + "\xBE\x69" => "\xE9\xA4\x8A", + "\xBE\x6A" => "\xE9\xA4\x93", + "\xBE\x6B" => "\xE9\xA4\x92", + "\xBE\x6C" => "\xE9\xA4\x98", + "\xBE\x6D" => "\xE9\xA7\x9D", + "\xBE\x6E" => "\xE9\xA7\x90", + "\xBE\x6F" => "\xE9\xA7\x9F", + "\xBE\x70" => "\xE9\xA7\x9B", + "\xBE\x71" => "\xE9\xA7\x91", + "\xBE\x72" => "\xE9\xA7\x95", + "\xBE\x73" => "\xE9\xA7\x92", + "\xBE\x74" => "\xE9\xA7\x99", + "\xBE\x75" => "\xE9\xAA\xB7", + "\xBE\x76" => "\xE9\xAB\xAE", + "\xBE\x77" => "\xE9\xAB\xAF", + "\xBE\x78" => "\xE9\xAC\xA7", + "\xBE\x79" => "\xE9\xAD\x85", + "\xBE\x7A" => "\xE9\xAD\x84", + "\xBE\x7B" => "\xE9\xAD\xB7", + "\xBE\x7C" => "\xE9\xAD\xAF", + "\xBE\x7D" => "\xE9\xB4\x86", + "\xBE\x7E" => "\xE9\xB4\x89", + "\xBE\xA1" => "\xE9\xB4\x83", + "\xBE\xA2" => "\xE9\xBA\xA9", + "\xBE\xA3" => "\xE9\xBA\xBE", + "\xBE\xA4" => "\xE9\xBB\x8E", + "\xBE\xA5" => "\xE5\xA2\xA8", + "\xBE\xA6" => "\xE9\xBD\x92", + "\xBE\xA7" => "\xE5\x84\x92", + "\xBE\xA8" => "\xE5\x84\x98", + "\xBE\xA9" => "\xE5\x84\x94", + "\xBE\xAA" => "\xE5\x84\x90", + "\xBE\xAB" => "\xE5\x84\x95", + "\xBE\xAC" => "\xE5\x86\x80", + "\xBE\xAD" => "\xE5\x86\xAA", + "\xBE\xAE" => "\xE5\x87\x9D", + "\xBE\xAF" => "\xE5\x8A\x91", + "\xBE\xB0" => "\xE5\x8A\x93", + "\xBE\xB1" => "\xE5\x8B\xB3", + "\xBE\xB2" => "\xE5\x99\x99", + "\xBE\xB3" => "\xE5\x99\xAB", + "\xBE\xB4" => "\xE5\x99\xB9", + "\xBE\xB5" => "\xE5\x99\xA9", + "\xBE\xB6" => "\xE5\x99\xA4", + "\xBE\xB7" => "\xE5\x99\xB8", + "\xBE\xB8" => "\xE5\x99\xAA", + "\xBE\xB9" => "\xE5\x99\xA8", + "\xBE\xBA" => "\xE5\x99\xA5", + "\xBE\xBB" => "\xE5\x99\xB1", + "\xBE\xBC" => "\xE5\x99\xAF", + "\xBE\xBD" => "\xE5\x99\xAC", + "\xBE\xBE" => "\xE5\x99\xA2", + "\xBE\xBF" => "\xE5\x99\xB6", + "\xBE\xC0" => "\xE5\xA3\x81", + "\xBE\xC1" => "\xE5\xA2\xBE", + "\xBE\xC2" => "\xE5\xA3\x87", + "\xBE\xC3" => "\xE5\xA3\x85", + "\xBE\xC4" => "\xE5\xA5\xAE", + "\xBE\xC5" => "\xE5\xAC\x9D", + "\xBE\xC6" => "\xE5\xAC\xB4", + "\xBE\xC7" => "\xE5\xAD\xB8", + "\xBE\xC8" => "\xE5\xAF\xB0", + "\xBE\xC9" => "\xE5\xB0\x8E", + "\xBE\xCA" => "\xE5\xBD\x8A", + "\xBE\xCB" => "\xE6\x86\xB2", + "\xBE\xCC" => "\xE6\x86\x91", + "\xBE\xCD" => "\xE6\x86\xA9", + "\xBE\xCE" => "\xE6\x86\x8A", + "\xBE\xCF" => "\xE6\x87\x8D", + "\xBE\xD0" => "\xE6\x86\xB6", + "\xBE\xD1" => "\xE6\x86\xBE", + "\xBE\xD2" => "\xE6\x87\x8A", + "\xBE\xD3" => "\xE6\x87\x88", + "\xBE\xD4" => "\xE6\x88\xB0", + "\xBE\xD5" => "\xE6\x93\x85", + "\xBE\xD6" => "\xE6\x93\x81", + "\xBE\xD7" => "\xE6\x93\x8B", + "\xBE\xD8" => "\xE6\x92\xBB", + "\xBE\xD9" => "\xE6\x92\xBC", + "\xBE\xDA" => "\xE6\x93\x9A", + "\xBE\xDB" => "\xE6\x93\x84", + "\xBE\xDC" => "\xE6\x93\x87", + "\xBE\xDD" => "\xE6\x93\x82", + "\xBE\xDE" => "\xE6\x93\x8D", + "\xBE\xDF" => "\xE6\x92\xBF", + "\xBE\xE0" => "\xE6\x93\x92", + "\xBE\xE1" => "\xE6\x93\x94", + "\xBE\xE2" => "\xE6\x92\xBE", + "\xBE\xE3" => "\xE6\x95\xB4", + "\xBE\xE4" => "\xE6\x9B\x86", + "\xBE\xE5" => "\xE6\x9B\x89", + "\xBE\xE6" => "\xE6\x9A\xB9", + "\xBE\xE7" => "\xE6\x9B\x84", + "\xBE\xE8" => "\xE6\x9B\x87", + "\xBE\xE9" => "\xE6\x9A\xB8", + "\xBE\xEA" => "\xE6\xA8\xBD", + "\xBE\xEB" => "\xE6\xA8\xB8", + "\xBE\xEC" => "\xE6\xA8\xBA", + "\xBE\xED" => "\xE6\xA9\x99", + "\xBE\xEE" => "\xE6\xA9\xAB", + "\xBE\xEF" => "\xE6\xA9\x98", + "\xBE\xF0" => "\xE6\xA8\xB9", + "\xBE\xF1" => "\xE6\xA9\x84", + "\xBE\xF2" => "\xE6\xA9\xA2", + "\xBE\xF3" => "\xE6\xA9\xA1", + "\xBE\xF4" => "\xE6\xA9\x8B", + "\xBE\xF5" => "\xE6\xA9\x87", + "\xBE\xF6" => "\xE6\xA8\xB5", + "\xBE\xF7" => "\xE6\xA9\x9F", + "\xBE\xF8" => "\xE6\xA9\x88", + "\xBE\xF9" => "\xE6\xAD\x99", + "\xBE\xFA" => "\xE6\xAD\xB7", + "\xBE\xFB" => "\xE6\xB0\x85", + "\xBE\xFC" => "\xE6\xBF\x82", + "\xBE\xFD" => "\xE6\xBE\xB1", + "\xBE\xFE" => "\xE6\xBE\xA1", + "\xBF\x40" => "\xE6\xBF\x83", + "\xBF\x41" => "\xE6\xBE\xA4", + "\xBF\x42" => "\xE6\xBF\x81", + "\xBF\x43" => "\xE6\xBE\xA7", + "\xBF\x44" => "\xE6\xBE\xB3", + "\xBF\x45" => "\xE6\xBF\x80", + "\xBF\x46" => "\xE6\xBE\xB9", + "\xBF\x47" => "\xE6\xBE\xB6", + "\xBF\x48" => "\xE6\xBE\xA6", + "\xBF\x49" => "\xE6\xBE\xA0", + "\xBF\x4A" => "\xE6\xBE\xB4", + "\xBF\x4B" => "\xE7\x86\xBE", + "\xBF\x4C" => "\xE7\x87\x89", + "\xBF\x4D" => "\xE7\x87\x90", + "\xBF\x4E" => "\xE7\x87\x92", + "\xBF\x4F" => "\xE7\x87\x88", + "\xBF\x50" => "\xE7\x87\x95", + "\xBF\x51" => "\xE7\x86\xB9", + "\xBF\x52" => "\xE7\x87\x8E", + "\xBF\x53" => "\xE7\x87\x99", + "\xBF\x54" => "\xE7\x87\x9C", + "\xBF\x55" => "\xE7\x87\x83", + "\xBF\x56" => "\xE7\x87\x84", + "\xBF\x57" => "\xE7\x8D\xA8", + "\xBF\x58" => "\xE7\x92\x9C", + "\xBF\x59" => "\xE7\x92\xA3", + "\xBF\x5A" => "\xE7\x92\x98", + "\xBF\x5B" => "\xE7\x92\x9F", + "\xBF\x5C" => "\xE7\x92\x9E", + "\xBF\x5D" => "\xE7\x93\xA2", + "\xBF\x5E" => "\xE7\x94\x8C", + "\xBF\x5F" => "\xE7\x94\x8D", + "\xBF\x60" => "\xE7\x98\xB4", + "\xBF\x61" => "\xE7\x98\xB8", + "\xBF\x62" => "\xE7\x98\xBA", + "\xBF\x63" => "\xE7\x9B\xA7", + "\xBF\x64" => "\xE7\x9B\xA5", + "\xBF\x65" => "\xE7\x9E\xA0", + "\xBF\x66" => "\xE7\x9E\x9E", + "\xBF\x67" => "\xE7\x9E\x9F", + "\xBF\x68" => "\xE7\x9E\xA5", + "\xBF\x69" => "\xE7\xA3\xA8", + "\xBF\x6A" => "\xE7\xA3\x9A", + "\xBF\x6B" => "\xE7\xA3\xAC", + "\xBF\x6C" => "\xE7\xA3\xA7", + "\xBF\x6D" => "\xE7\xA6\xA6", + "\xBF\x6E" => "\xE7\xA9\x8D", + "\xBF\x6F" => "\xE7\xA9\x8E", + "\xBF\x70" => "\xE7\xA9\x86", + "\xBF\x71" => "\xE7\xA9\x8C", + "\xBF\x72" => "\xE7\xA9\x8B", + "\xBF\x73" => "\xE7\xAA\xBA", + "\xBF\x74" => "\xE7\xAF\x99", + "\xBF\x75" => "\xE7\xB0\x91", + "\xBF\x76" => "\xE7\xAF\x89", + "\xBF\x77" => "\xE7\xAF\xA4", + "\xBF\x78" => "\xE7\xAF\x9B", + "\xBF\x79" => "\xE7\xAF\xA1", + "\xBF\x7A" => "\xE7\xAF\xA9", + "\xBF\x7B" => "\xE7\xAF\xA6", + "\xBF\x7C" => "\xE7\xB3\x95", + "\xBF\x7D" => "\xE7\xB3\x96", + "\xBF\x7E" => "\xE7\xB8\x8A", + "\xBF\xA1" => "\xE7\xB8\x91", + "\xBF\xA2" => "\xE7\xB8\x88", + "\xBF\xA3" => "\xE7\xB8\x9B", + "\xBF\xA4" => "\xE7\xB8\xA3", + "\xBF\xA5" => "\xE7\xB8\x9E", + "\xBF\xA6" => "\xE7\xB8\x9D", + "\xBF\xA7" => "\xE7\xB8\x89", + "\xBF\xA8" => "\xE7\xB8\x90", + "\xBF\xA9" => "\xE7\xBD\xB9", + "\xBF\xAA" => "\xE7\xBE\xB2", + "\xBF\xAB" => "\xE7\xBF\xB0", + "\xBF\xAC" => "\xE7\xBF\xB1", + "\xBF\xAD" => "\xE7\xBF\xAE", + "\xBF\xAE" => "\xE8\x80\xA8", + "\xBF\xAF" => "\xE8\x86\xB3", + "\xBF\xB0" => "\xE8\x86\xA9", + "\xBF\xB1" => "\xE8\x86\xA8", + "\xBF\xB2" => "\xE8\x87\xBB", + "\xBF\xB3" => "\xE8\x88\x88", + "\xBF\xB4" => "\xE8\x89\x98", + "\xBF\xB5" => "\xE8\x89\x99", + "\xBF\xB6" => "\xE8\x95\x8A", + "\xBF\xB7" => "\xE8\x95\x99", + "\xBF\xB8" => "\xE8\x95\x88", + "\xBF\xB9" => "\xE8\x95\xA8", + "\xBF\xBA" => "\xE8\x95\xA9", + "\xBF\xBB" => "\xE8\x95\x83", + "\xBF\xBC" => "\xE8\x95\x89", + "\xBF\xBD" => "\xE8\x95\xAD", + "\xBF\xBE" => "\xE8\x95\xAA", + "\xBF\xBF" => "\xE8\x95\x9E", + "\xBF\xC0" => "\xE8\x9E\x83", + "\xBF\xC1" => "\xE8\x9E\x9F", + "\xBF\xC2" => "\xE8\x9E\x9E", + "\xBF\xC3" => "\xE8\x9E\xA2", + "\xBF\xC4" => "\xE8\x9E\x8D", + "\xBF\xC5" => "\xE8\xA1\xA1", + "\xBF\xC6" => "\xE8\xA4\xAA", + "\xBF\xC7" => "\xE8\xA4\xB2", + "\xBF\xC8" => "\xE8\xA4\xA5", + "\xBF\xC9" => "\xE8\xA4\xAB", + "\xBF\xCA" => "\xE8\xA4\xA1", + "\xBF\xCB" => "\xE8\xA6\xAA", + "\xBF\xCC" => "\xE8\xA6\xA6", + "\xBF\xCD" => "\xE8\xAB\xA6", + "\xBF\xCE" => "\xE8\xAB\xBA", + "\xBF\xCF" => "\xE8\xAB\xAB", + "\xBF\xD0" => "\xE8\xAB\xB1", + "\xBF\xD1" => "\xE8\xAC\x80", + "\xBF\xD2" => "\xE8\xAB\x9C", + "\xBF\xD3" => "\xE8\xAB\xA7", + "\xBF\xD4" => "\xE8\xAB\xAE", + "\xBF\xD5" => "\xE8\xAB\xBE", + "\xBF\xD6" => "\xE8\xAC\x81", + "\xBF\xD7" => "\xE8\xAC\x82", + "\xBF\xD8" => "\xE8\xAB\xB7", + "\xBF\xD9" => "\xE8\xAB\xAD", + "\xBF\xDA" => "\xE8\xAB\xB3", + "\xBF\xDB" => "\xE8\xAB\xB6", + "\xBF\xDC" => "\xE8\xAB\xBC", + "\xBF\xDD" => "\xE8\xB1\xAB", + "\xBF\xDE" => "\xE8\xB1\xAD", + "\xBF\xDF" => "\xE8\xB2\x93", + "\xBF\xE0" => "\xE8\xB3\xB4", + "\xBF\xE1" => "\xE8\xB9\x84", + "\xBF\xE2" => "\xE8\xB8\xB1", + "\xBF\xE3" => "\xE8\xB8\xB4", + "\xBF\xE4" => "\xE8\xB9\x82", + "\xBF\xE5" => "\xE8\xB8\xB9", + "\xBF\xE6" => "\xE8\xB8\xB5", + "\xBF\xE7" => "\xE8\xBC\xBB", + "\xBF\xE8" => "\xE8\xBC\xAF", + "\xBF\xE9" => "\xE8\xBC\xB8", + "\xBF\xEA" => "\xE8\xBC\xB3", + "\xBF\xEB" => "\xE8\xBE\xA8", + "\xBF\xEC" => "\xE8\xBE\xA6", + "\xBF\xED" => "\xE9\x81\xB5", + "\xBF\xEE" => "\xE9\x81\xB4", + "\xBF\xEF" => "\xE9\x81\xB8", + "\xBF\xF0" => "\xE9\x81\xB2", + "\xBF\xF1" => "\xE9\x81\xBC", + "\xBF\xF2" => "\xE9\x81\xBA", + "\xBF\xF3" => "\xE9\x84\xB4", + "\xBF\xF4" => "\xE9\x86\x92", + "\xBF\xF5" => "\xE9\x8C\xA0", + "\xBF\xF6" => "\xE9\x8C\xB6", + "\xBF\xF7" => "\xE9\x8B\xB8", + "\xBF\xF8" => "\xE9\x8C\xB3", + "\xBF\xF9" => "\xE9\x8C\xAF", + "\xBF\xFA" => "\xE9\x8C\xA2", + "\xBF\xFB" => "\xE9\x8B\xBC", + "\xBF\xFC" => "\xE9\x8C\xAB", + "\xBF\xFD" => "\xE9\x8C\x84", + "\xBF\xFE" => "\xE9\x8C\x9A", + "\xC0\x40" => "\xE9\x8C\x90", + "\xC0\x41" => "\xE9\x8C\xA6", + "\xC0\x42" => "\xE9\x8C\xA1", + "\xC0\x43" => "\xE9\x8C\x95", + "\xC0\x44" => "\xE9\x8C\xAE", + "\xC0\x45" => "\xE9\x8C\x99", + "\xC0\x46" => "\xE9\x96\xBB", + "\xC0\x47" => "\xE9\x9A\xA7", + "\xC0\x48" => "\xE9\x9A\xA8", + "\xC0\x49" => "\xE9\x9A\xAA", + "\xC0\x4A" => "\xE9\x9B\x95", + "\xC0\x4B" => "\xE9\x9C\x8E", + "\xC0\x4C" => "\xE9\x9C\x91", + "\xC0\x4D" => "\xE9\x9C\x96", + "\xC0\x4E" => "\xE9\x9C\x8D", + "\xC0\x4F" => "\xE9\x9C\x93", + "\xC0\x50" => "\xE9\x9C\x8F", + "\xC0\x51" => "\xE9\x9D\x9B", + "\xC0\x52" => "\xE9\x9D\x9C", + "\xC0\x53" => "\xE9\x9D\xA6", + "\xC0\x54" => "\xE9\x9E\x98", + "\xC0\x55" => "\xE9\xA0\xB0", + "\xC0\x56" => "\xE9\xA0\xB8", + "\xC0\x57" => "\xE9\xA0\xBB", + "\xC0\x58" => "\xE9\xA0\xB7", + "\xC0\x59" => "\xE9\xA0\xAD", + "\xC0\x5A" => "\xE9\xA0\xB9", + "\xC0\x5B" => "\xE9\xA0\xA4", + "\xC0\x5C" => "\xE9\xA4\x90", + "\xC0\x5D" => "\xE9\xA4\xA8", + "\xC0\x5E" => "\xE9\xA4\x9E", + "\xC0\x5F" => "\xE9\xA4\x9B", + "\xC0\x60" => "\xE9\xA4\xA1", + "\xC0\x61" => "\xE9\xA4\x9A", + "\xC0\x62" => "\xE9\xA7\xAD", + "\xC0\x63" => "\xE9\xA7\xA2", + "\xC0\x64" => "\xE9\xA7\xB1", + "\xC0\x65" => "\xE9\xAA\xB8", + "\xC0\x66" => "\xE9\xAA\xBC", + "\xC0\x67" => "\xE9\xAB\xBB", + "\xC0\x68" => "\xE9\xAB\xAD", + "\xC0\x69" => "\xE9\xAC\xA8", + "\xC0\x6A" => "\xE9\xAE\x91", + "\xC0\x6B" => "\xE9\xB4\x95", + "\xC0\x6C" => "\xE9\xB4\xA3", + "\xC0\x6D" => "\xE9\xB4\xA6", + "\xC0\x6E" => "\xE9\xB4\xA8", + "\xC0\x6F" => "\xE9\xB4\x92", + "\xC0\x70" => "\xE9\xB4\x9B", + "\xC0\x71" => "\xE9\xBB\x98", + "\xC0\x72" => "\xE9\xBB\x94", + "\xC0\x73" => "\xE9\xBE\x8D", + "\xC0\x74" => "\xE9\xBE\x9C", + "\xC0\x75" => "\xE5\x84\xAA", + "\xC0\x76" => "\xE5\x84\x9F", + "\xC0\x77" => "\xE5\x84\xA1", + "\xC0\x78" => "\xE5\x84\xB2", + "\xC0\x79" => "\xE5\x8B\xB5", + "\xC0\x7A" => "\xE5\x9A\x8E", + "\xC0\x7B" => "\xE5\x9A\x80", + "\xC0\x7C" => "\xE5\x9A\x90", + "\xC0\x7D" => "\xE5\x9A\x85", + "\xC0\x7E" => "\xE5\x9A\x87", + "\xC0\xA1" => "\xE5\x9A\x8F", + "\xC0\xA2" => "\xE5\xA3\x95", + "\xC0\xA3" => "\xE5\xA3\x93", + "\xC0\xA4" => "\xE5\xA3\x91", + "\xC0\xA5" => "\xE5\xA3\x8E", + "\xC0\xA6" => "\xE5\xAC\xB0", + "\xC0\xA7" => "\xE5\xAC\xAA", + "\xC0\xA8" => "\xE5\xAC\xA4", + "\xC0\xA9" => "\xE5\xAD\xBA", + "\xC0\xAA" => "\xE5\xB0\xB7", + "\xC0\xAB" => "\xE5\xB1\xA8", + "\xC0\xAC" => "\xE5\xB6\xBC", + "\xC0\xAD" => "\xE5\xB6\xBA", + "\xC0\xAE" => "\xE5\xB6\xBD", + "\xC0\xAF" => "\xE5\xB6\xB8", + "\xC0\xB0" => "\xE5\xB9\xAB", + "\xC0\xB1" => "\xE5\xBD\x8C", + "\xC0\xB2" => "\xE5\xBE\xBD", + "\xC0\xB3" => "\xE6\x87\x89", + "\xC0\xB4" => "\xE6\x87\x82", + "\xC0\xB5" => "\xE6\x87\x87", + "\xC0\xB6" => "\xE6\x87\xA6", + "\xC0\xB7" => "\xE6\x87\x8B", + "\xC0\xB8" => "\xE6\x88\xB2", + "\xC0\xB9" => "\xE6\x88\xB4", + "\xC0\xBA" => "\xE6\x93\x8E", + "\xC0\xBB" => "\xE6\x93\x8A", + "\xC0\xBC" => "\xE6\x93\x98", + "\xC0\xBD" => "\xE6\x93\xA0", + "\xC0\xBE" => "\xE6\x93\xB0", + "\xC0\xBF" => "\xE6\x93\xA6", + "\xC0\xC0" => "\xE6\x93\xAC", + "\xC0\xC1" => "\xE6\x93\xB1", + "\xC0\xC2" => "\xE6\x93\xA2", + "\xC0\xC3" => "\xE6\x93\xAD", + "\xC0\xC4" => "\xE6\x96\x82", + "\xC0\xC5" => "\xE6\x96\x83", + "\xC0\xC6" => "\xE6\x9B\x99", + "\xC0\xC7" => "\xE6\x9B\x96", + "\xC0\xC8" => "\xE6\xAA\x80", + "\xC0\xC9" => "\xE6\xAA\x94", + "\xC0\xCA" => "\xE6\xAA\x84", + "\xC0\xCB" => "\xE6\xAA\xA2", + "\xC0\xCC" => "\xE6\xAA\x9C", + "\xC0\xCD" => "\xE6\xAB\x9B", + "\xC0\xCE" => "\xE6\xAA\xA3", + "\xC0\xCF" => "\xE6\xA9\xBE", + "\xC0\xD0" => "\xE6\xAA\x97", + "\xC0\xD1" => "\xE6\xAA\x90", + "\xC0\xD2" => "\xE6\xAA\xA0", + "\xC0\xD3" => "\xE6\xAD\x9C", + "\xC0\xD4" => "\xE6\xAE\xAE", + "\xC0\xD5" => "\xE6\xAF\x9A", + "\xC0\xD6" => "\xE6\xB0\x88", + "\xC0\xD7" => "\xE6\xBF\x98", + "\xC0\xD8" => "\xE6\xBF\xB1", + "\xC0\xD9" => "\xE6\xBF\x9F", + "\xC0\xDA" => "\xE6\xBF\xA0", + "\xC0\xDB" => "\xE6\xBF\x9B", + "\xC0\xDC" => "\xE6\xBF\xA4", + "\xC0\xDD" => "\xE6\xBF\xAB", + "\xC0\xDE" => "\xE6\xBF\xAF", + "\xC0\xDF" => "\xE6\xBE\x80", + "\xC0\xE0" => "\xE6\xBF\xAC", + "\xC0\xE1" => "\xE6\xBF\xA1", + "\xC0\xE2" => "\xE6\xBF\xA9", + "\xC0\xE3" => "\xE6\xBF\x95", + "\xC0\xE4" => "\xE6\xBF\xAE", + "\xC0\xE5" => "\xE6\xBF\xB0", + "\xC0\xE6" => "\xE7\x87\xA7", + "\xC0\xE7" => "\xE7\x87\x9F", + "\xC0\xE8" => "\xE7\x87\xAE", + "\xC0\xE9" => "\xE7\x87\xA6", + "\xC0\xEA" => "\xE7\x87\xA5", + "\xC0\xEB" => "\xE7\x87\xAD", + "\xC0\xEC" => "\xE7\x87\xAC", + "\xC0\xED" => "\xE7\x87\xB4", + "\xC0\xEE" => "\xE7\x87\xA0", + "\xC0\xEF" => "\xE7\x88\xB5", + "\xC0\xF0" => "\xE7\x89\x86", + "\xC0\xF1" => "\xE7\x8D\xB0", + "\xC0\xF2" => "\xE7\x8D\xB2", + "\xC0\xF3" => "\xE7\x92\xA9", + "\xC0\xF4" => "\xE7\x92\xB0", + "\xC0\xF5" => "\xE7\x92\xA6", + "\xC0\xF6" => "\xE7\x92\xA8", + "\xC0\xF7" => "\xE7\x99\x86", + "\xC0\xF8" => "\xE7\x99\x82", + "\xC0\xF9" => "\xE7\x99\x8C", + "\xC0\xFA" => "\xE7\x9B\xAA", + "\xC0\xFB" => "\xE7\x9E\xB3", + "\xC0\xFC" => "\xE7\x9E\xAA", + "\xC0\xFD" => "\xE7\x9E\xB0", + "\xC0\xFE" => "\xE7\x9E\xAC", + "\xC1\x40" => "\xE7\x9E\xA7", + "\xC1\x41" => "\xE7\x9E\xAD", + "\xC1\x42" => "\xE7\x9F\xAF", + "\xC1\x43" => "\xE7\xA3\xB7", + "\xC1\x44" => "\xE7\xA3\xBA", + "\xC1\x45" => "\xE7\xA3\xB4", + "\xC1\x46" => "\xE7\xA3\xAF", + "\xC1\x47" => "\xE7\xA4\x81", + "\xC1\x48" => "\xE7\xA6\xA7", + "\xC1\x49" => "\xE7\xA6\xAA", + "\xC1\x4A" => "\xE7\xA9\x97", + "\xC1\x4B" => "\xE7\xAA\xBF", + "\xC1\x4C" => "\xE7\xB0\x87", + "\xC1\x4D" => "\xE7\xB0\x8D", + "\xC1\x4E" => "\xE7\xAF\xBE", + "\xC1\x4F" => "\xE7\xAF\xB7", + "\xC1\x50" => "\xE7\xB0\x8C", + "\xC1\x51" => "\xE7\xAF\xA0", + "\xC1\x52" => "\xE7\xB3\xA0", + "\xC1\x53" => "\xE7\xB3\x9C", + "\xC1\x54" => "\xE7\xB3\x9E", + "\xC1\x55" => "\xE7\xB3\xA2", + "\xC1\x56" => "\xE7\xB3\x9F", + "\xC1\x57" => "\xE7\xB3\x99", + "\xC1\x58" => "\xE7\xB3\x9D", + "\xC1\x59" => "\xE7\xB8\xAE", + "\xC1\x5A" => "\xE7\xB8\xBE", + "\xC1\x5B" => "\xE7\xB9\x86", + "\xC1\x5C" => "\xE7\xB8\xB7", + "\xC1\x5D" => "\xE7\xB8\xB2", + "\xC1\x5E" => "\xE7\xB9\x83", + "\xC1\x5F" => "\xE7\xB8\xAB", + "\xC1\x60" => "\xE7\xB8\xBD", + "\xC1\x61" => "\xE7\xB8\xB1", + "\xC1\x62" => "\xE7\xB9\x85", + "\xC1\x63" => "\xE7\xB9\x81", + "\xC1\x64" => "\xE7\xB8\xB4", + "\xC1\x65" => "\xE7\xB8\xB9", + "\xC1\x66" => "\xE7\xB9\x88", + "\xC1\x67" => "\xE7\xB8\xB5", + "\xC1\x68" => "\xE7\xB8\xBF", + "\xC1\x69" => "\xE7\xB8\xAF", + "\xC1\x6A" => "\xE7\xBD\x84", + "\xC1\x6B" => "\xE7\xBF\xB3", + "\xC1\x6C" => "\xE7\xBF\xBC", + "\xC1\x6D" => "\xE8\x81\xB1", + "\xC1\x6E" => "\xE8\x81\xB2", + "\xC1\x6F" => "\xE8\x81\xB0", + "\xC1\x70" => "\xE8\x81\xAF", + "\xC1\x71" => "\xE8\x81\xB3", + "\xC1\x72" => "\xE8\x87\x86", + "\xC1\x73" => "\xE8\x87\x83", + "\xC1\x74" => "\xE8\x86\xBA", + "\xC1\x75" => "\xE8\x87\x82", + "\xC1\x76" => "\xE8\x87\x80", + "\xC1\x77" => "\xE8\x86\xBF", + "\xC1\x78" => "\xE8\x86\xBD", + "\xC1\x79" => "\xE8\x87\x89", + "\xC1\x7A" => "\xE8\x86\xBE", + "\xC1\x7B" => "\xE8\x87\xA8", + "\xC1\x7C" => "\xE8\x88\x89", + "\xC1\x7D" => "\xE8\x89\xB1", + "\xC1\x7E" => "\xE8\x96\xAA", + "\xC1\xA1" => "\xE8\x96\x84", + "\xC1\xA2" => "\xE8\x95\xBE", + "\xC1\xA3" => "\xE8\x96\x9C", + "\xC1\xA4" => "\xE8\x96\x91", + "\xC1\xA5" => "\xE8\x96\x94", + "\xC1\xA6" => "\xE8\x96\xAF", + "\xC1\xA7" => "\xE8\x96\x9B", + "\xC1\xA8" => "\xE8\x96\x87", + "\xC1\xA9" => "\xE8\x96\xA8", + "\xC1\xAA" => "\xE8\x96\x8A", + "\xC1\xAB" => "\xE8\x99\xA7", + "\xC1\xAC" => "\xE8\x9F\x80", + "\xC1\xAD" => "\xE8\x9F\x91", + "\xC1\xAE" => "\xE8\x9E\xB3", + "\xC1\xAF" => "\xE8\x9F\x92", + "\xC1\xB0" => "\xE8\x9F\x86", + "\xC1\xB1" => "\xE8\x9E\xAB", + "\xC1\xB2" => "\xE8\x9E\xBB", + "\xC1\xB3" => "\xE8\x9E\xBA", + "\xC1\xB4" => "\xE8\x9F\x88", + "\xC1\xB5" => "\xE8\x9F\x8B", + "\xC1\xB6" => "\xE8\xA4\xBB", + "\xC1\xB7" => "\xE8\xA4\xB6", + "\xC1\xB8" => "\xE8\xA5\x84", + "\xC1\xB9" => "\xE8\xA4\xB8", + "\xC1\xBA" => "\xE8\xA4\xBD", + "\xC1\xBB" => "\xE8\xA6\xAC", + "\xC1\xBC" => "\xE8\xAC\x8E", + "\xC1\xBD" => "\xE8\xAC\x97", + "\xC1\xBE" => "\xE8\xAC\x99", + "\xC1\xBF" => "\xE8\xAC\x9B", + "\xC1\xC0" => "\xE8\xAC\x8A", + "\xC1\xC1" => "\xE8\xAC\xA0", + "\xC1\xC2" => "\xE8\xAC\x9D", + "\xC1\xC3" => "\xE8\xAC\x84", + "\xC1\xC4" => "\xE8\xAC\x90", + "\xC1\xC5" => "\xE8\xB1\x81", + "\xC1\xC6" => "\xE8\xB0\xBF", + "\xC1\xC7" => "\xE8\xB1\xB3", + "\xC1\xC8" => "\xE8\xB3\xBA", + "\xC1\xC9" => "\xE8\xB3\xBD", + "\xC1\xCA" => "\xE8\xB3\xBC", + "\xC1\xCB" => "\xE8\xB3\xB8", + "\xC1\xCC" => "\xE8\xB3\xBB", + "\xC1\xCD" => "\xE8\xB6\xA8", + "\xC1\xCE" => "\xE8\xB9\x89", + "\xC1\xCF" => "\xE8\xB9\x8B", + "\xC1\xD0" => "\xE8\xB9\x88", + "\xC1\xD1" => "\xE8\xB9\x8A", + "\xC1\xD2" => "\xE8\xBD\x84", + "\xC1\xD3" => "\xE8\xBC\xBE", + "\xC1\xD4" => "\xE8\xBD\x82", + "\xC1\xD5" => "\xE8\xBD\x85", + "\xC1\xD6" => "\xE8\xBC\xBF", + "\xC1\xD7" => "\xE9\x81\xBF", + "\xC1\xD8" => "\xE9\x81\xBD", + "\xC1\xD9" => "\xE9\x82\x84", + "\xC1\xDA" => "\xE9\x82\x81", + "\xC1\xDB" => "\xE9\x82\x82", + "\xC1\xDC" => "\xE9\x82\x80", + "\xC1\xDD" => "\xE9\x84\xB9", + "\xC1\xDE" => "\xE9\x86\xA3", + "\xC1\xDF" => "\xE9\x86\x9E", + "\xC1\xE0" => "\xE9\x86\x9C", + "\xC1\xE1" => "\xE9\x8D\x8D", + "\xC1\xE2" => "\xE9\x8E\x82", + "\xC1\xE3" => "\xE9\x8C\xA8", + "\xC1\xE4" => "\xE9\x8D\xB5", + "\xC1\xE5" => "\xE9\x8D\x8A", + "\xC1\xE6" => "\xE9\x8D\xA5", + "\xC1\xE7" => "\xE9\x8D\x8B", + "\xC1\xE8" => "\xE9\x8C\x98", + "\xC1\xE9" => "\xE9\x8D\xBE", + "\xC1\xEA" => "\xE9\x8D\xAC", + "\xC1\xEB" => "\xE9\x8D\x9B", + "\xC1\xEC" => "\xE9\x8D\xB0", + "\xC1\xED" => "\xE9\x8D\x9A", + "\xC1\xEE" => "\xE9\x8D\x94", + "\xC1\xEF" => "\xE9\x97\x8A", + "\xC1\xF0" => "\xE9\x97\x8B", + "\xC1\xF1" => "\xE9\x97\x8C", + "\xC1\xF2" => "\xE9\x97\x88", + "\xC1\xF3" => "\xE9\x97\x86", + "\xC1\xF4" => "\xE9\x9A\xB1", + "\xC1\xF5" => "\xE9\x9A\xB8", + "\xC1\xF6" => "\xE9\x9B\x96", + "\xC1\xF7" => "\xE9\x9C\x9C", + "\xC1\xF8" => "\xE9\x9C\x9E", + "\xC1\xF9" => "\xE9\x9E\xA0", + "\xC1\xFA" => "\xE9\x9F\x93", + "\xC1\xFB" => "\xE9\xA1\x86", + "\xC1\xFC" => "\xE9\xA2\xB6", + "\xC1\xFD" => "\xE9\xA4\xB5", + "\xC1\xFE" => "\xE9\xA8\x81", + "\xC2\x40" => "\xE9\xA7\xBF", + "\xC2\x41" => "\xE9\xAE\xAE", + "\xC2\x42" => "\xE9\xAE\xAB", + "\xC2\x43" => "\xE9\xAE\xAA", + "\xC2\x44" => "\xE9\xAE\xAD", + "\xC2\x45" => "\xE9\xB4\xBB", + "\xC2\x46" => "\xE9\xB4\xBF", + "\xC2\x47" => "\xE9\xBA\x8B", + "\xC2\x48" => "\xE9\xBB\x8F", + "\xC2\x49" => "\xE9\xBB\x9E", + "\xC2\x4A" => "\xE9\xBB\x9C", + "\xC2\x4B" => "\xE9\xBB\x9D", + "\xC2\x4C" => "\xE9\xBB\x9B", + "\xC2\x4D" => "\xE9\xBC\xBE", + "\xC2\x4E" => "\xE9\xBD\x8B", + "\xC2\x4F" => "\xE5\x8F\xA2", + "\xC2\x50" => "\xE5\x9A\x95", + "\xC2\x51" => "\xE5\x9A\xAE", + "\xC2\x52" => "\xE5\xA3\x99", + "\xC2\x53" => "\xE5\xA3\x98", + "\xC2\x54" => "\xE5\xAC\xB8", + "\xC2\x55" => "\xE5\xBD\x9D", + "\xC2\x56" => "\xE6\x87\xA3", + "\xC2\x57" => "\xE6\x88\xB3", + "\xC2\x58" => "\xE6\x93\xB4", + "\xC2\x59" => "\xE6\x93\xB2", + "\xC2\x5A" => "\xE6\x93\xBE", + "\xC2\x5B" => "\xE6\x94\x86", + "\xC2\x5C" => "\xE6\x93\xBA", + "\xC2\x5D" => "\xE6\x93\xBB", + "\xC2\x5E" => "\xE6\x93\xB7", + "\xC2\x5F" => "\xE6\x96\xB7", + "\xC2\x60" => "\xE6\x9B\x9C", + "\xC2\x61" => "\xE6\x9C\xA6", + "\xC2\x62" => "\xE6\xAA\xB3", + "\xC2\x63" => "\xE6\xAA\xAC", + "\xC2\x64" => "\xE6\xAB\x83", + "\xC2\x65" => "\xE6\xAA\xBB", + "\xC2\x66" => "\xE6\xAA\xB8", + "\xC2\x67" => "\xE6\xAB\x82", + "\xC2\x68" => "\xE6\xAA\xAE", + "\xC2\x69" => "\xE6\xAA\xAF", + "\xC2\x6A" => "\xE6\xAD\x9F", + "\xC2\x6B" => "\xE6\xAD\xB8", + "\xC2\x6C" => "\xE6\xAE\xAF", + "\xC2\x6D" => "\xE7\x80\x89", + "\xC2\x6E" => "\xE7\x80\x8B", + "\xC2\x6F" => "\xE6\xBF\xBE", + "\xC2\x70" => "\xE7\x80\x86", + "\xC2\x71" => "\xE6\xBF\xBA", + "\xC2\x72" => "\xE7\x80\x91", + "\xC2\x73" => "\xE7\x80\x8F", + "\xC2\x74" => "\xE7\x87\xBB", + "\xC2\x75" => "\xE7\x87\xBC", + "\xC2\x76" => "\xE7\x87\xBE", + "\xC2\x77" => "\xE7\x87\xB8", + "\xC2\x78" => "\xE7\x8D\xB7", + "\xC2\x79" => "\xE7\x8D\xB5", + "\xC2\x7A" => "\xE7\x92\xA7", + "\xC2\x7B" => "\xE7\x92\xBF", + "\xC2\x7C" => "\xE7\x94\x95", + "\xC2\x7D" => "\xE7\x99\x96", + "\xC2\x7E" => "\xE7\x99\x98", + "\xC2\xA1" => "\xE7\x99\x92", + "\xC2\xA2" => "\xE7\x9E\xBD", + "\xC2\xA3" => "\xE7\x9E\xBF", + "\xC2\xA4" => "\xE7\x9E\xBB", + "\xC2\xA5" => "\xE7\x9E\xBC", + "\xC2\xA6" => "\xE7\xA4\x8E", + "\xC2\xA7" => "\xE7\xA6\xAE", + "\xC2\xA8" => "\xE7\xA9\xA1", + "\xC2\xA9" => "\xE7\xA9\xA2", + "\xC2\xAA" => "\xE7\xA9\xA0", + "\xC2\xAB" => "\xE7\xAB\x84", + "\xC2\xAC" => "\xE7\xAB\x85", + "\xC2\xAD" => "\xE7\xB0\xAB", + "\xC2\xAE" => "\xE7\xB0\xA7", + "\xC2\xAF" => "\xE7\xB0\xAA", + "\xC2\xB0" => "\xE7\xB0\x9E", + "\xC2\xB1" => "\xE7\xB0\xA3", + "\xC2\xB2" => "\xE7\xB0\xA1", + "\xC2\xB3" => "\xE7\xB3\xA7", + "\xC2\xB4" => "\xE7\xB9\x94", + "\xC2\xB5" => "\xE7\xB9\x95", + "\xC2\xB6" => "\xE7\xB9\x9E", + "\xC2\xB7" => "\xE7\xB9\x9A", + "\xC2\xB8" => "\xE7\xB9\xA1", + "\xC2\xB9" => "\xE7\xB9\x92", + "\xC2\xBA" => "\xE7\xB9\x99", + "\xC2\xBB" => "\xE7\xBD\x88", + "\xC2\xBC" => "\xE7\xBF\xB9", + "\xC2\xBD" => "\xE7\xBF\xBB", + "\xC2\xBE" => "\xE8\x81\xB7", + "\xC2\xBF" => "\xE8\x81\xB6", + "\xC2\xC0" => "\xE8\x87\x8D", + "\xC2\xC1" => "\xE8\x87\x8F", + "\xC2\xC2" => "\xE8\x88\x8A", + "\xC2\xC3" => "\xE8\x97\x8F", + "\xC2\xC4" => "\xE8\x96\xA9", + "\xC2\xC5" => "\xE8\x97\x8D", + "\xC2\xC6" => "\xE8\x97\x90", + "\xC2\xC7" => "\xE8\x97\x89", + "\xC2\xC8" => "\xE8\x96\xB0", + "\xC2\xC9" => "\xE8\x96\xBA", + "\xC2\xCA" => "\xE8\x96\xB9", + "\xC2\xCB" => "\xE8\x96\xA6", + "\xC2\xCC" => "\xE8\x9F\xAF", + "\xC2\xCD" => "\xE8\x9F\xAC", + "\xC2\xCE" => "\xE8\x9F\xB2", + "\xC2\xCF" => "\xE8\x9F\xA0", + "\xC2\xD0" => "\xE8\xA6\x86", + "\xC2\xD1" => "\xE8\xA6\xB2", + "\xC2\xD2" => "\xE8\xA7\xB4", + "\xC2\xD3" => "\xE8\xAC\xA8", + "\xC2\xD4" => "\xE8\xAC\xB9", + "\xC2\xD5" => "\xE8\xAC\xAC", + "\xC2\xD6" => "\xE8\xAC\xAB", + "\xC2\xD7" => "\xE8\xB1\x90", + "\xC2\xD8" => "\xE8\xB4\x85", + "\xC2\xD9" => "\xE8\xB9\x99", + "\xC2\xDA" => "\xE8\xB9\xA3", + "\xC2\xDB" => "\xE8\xB9\xA6", + "\xC2\xDC" => "\xE8\xB9\xA4", + "\xC2\xDD" => "\xE8\xB9\x9F", + "\xC2\xDE" => "\xE8\xB9\x95", + "\xC2\xDF" => "\xE8\xBB\x80", + "\xC2\xE0" => "\xE8\xBD\x89", + "\xC2\xE1" => "\xE8\xBD\x8D", + "\xC2\xE2" => "\xE9\x82\x87", + "\xC2\xE3" => "\xE9\x82\x83", + "\xC2\xE4" => "\xE9\x82\x88", + "\xC2\xE5" => "\xE9\x86\xAB", + "\xC2\xE6" => "\xE9\x86\xAC", + "\xC2\xE7" => "\xE9\x87\x90", + "\xC2\xE8" => "\xE9\x8E\x94", + "\xC2\xE9" => "\xE9\x8E\x8A", + "\xC2\xEA" => "\xE9\x8E\x96", + "\xC2\xEB" => "\xE9\x8E\xA2", + "\xC2\xEC" => "\xE9\x8E\xB3", + "\xC2\xED" => "\xE9\x8E\xAE", + "\xC2\xEE" => "\xE9\x8E\xAC", + "\xC2\xEF" => "\xE9\x8E\xB0", + "\xC2\xF0" => "\xE9\x8E\x98", + "\xC2\xF1" => "\xE9\x8E\x9A", + "\xC2\xF2" => "\xE9\x8E\x97", + "\xC2\xF3" => "\xE9\x97\x94", + "\xC2\xF4" => "\xE9\x97\x96", + "\xC2\xF5" => "\xE9\x97\x90", + "\xC2\xF6" => "\xE9\x97\x95", + "\xC2\xF7" => "\xE9\x9B\xA2", + "\xC2\xF8" => "\xE9\x9B\x9C", + "\xC2\xF9" => "\xE9\x9B\x99", + "\xC2\xFA" => "\xE9\x9B\x9B", + "\xC2\xFB" => "\xE9\x9B\x9E", + "\xC2\xFC" => "\xE9\x9C\xA4", + "\xC2\xFD" => "\xE9\x9E\xA3", + "\xC2\xFE" => "\xE9\x9E\xA6", + "\xC3\x40" => "\xE9\x9E\xAD", + "\xC3\x41" => "\xE9\x9F\xB9", + "\xC3\x42" => "\xE9\xA1\x8D", + "\xC3\x43" => "\xE9\xA1\x8F", + "\xC3\x44" => "\xE9\xA1\x8C", + "\xC3\x45" => "\xE9\xA1\x8E", + "\xC3\x46" => "\xE9\xA1\x93", + "\xC3\x47" => "\xE9\xA2\xBA", + "\xC3\x48" => "\xE9\xA4\xBE", + "\xC3\x49" => "\xE9\xA4\xBF", + "\xC3\x4A" => "\xE9\xA4\xBD", + "\xC3\x4B" => "\xE9\xA4\xAE", + "\xC3\x4C" => "\xE9\xA6\xA5", + "\xC3\x4D" => "\xE9\xA8\x8E", + "\xC3\x4E" => "\xE9\xAB\x81", + "\xC3\x4F" => "\xE9\xAC\x83", + "\xC3\x50" => "\xE9\xAC\x86", + "\xC3\x51" => "\xE9\xAD\x8F", + "\xC3\x52" => "\xE9\xAD\x8E", + "\xC3\x53" => "\xE9\xAD\x8D", + "\xC3\x54" => "\xE9\xAF\x8A", + "\xC3\x55" => "\xE9\xAF\x89", + "\xC3\x56" => "\xE9\xAF\xBD", + "\xC3\x57" => "\xE9\xAF\x88", + "\xC3\x58" => "\xE9\xAF\x80", + "\xC3\x59" => "\xE9\xB5\x91", + "\xC3\x5A" => "\xE9\xB5\x9D", + "\xC3\x5B" => "\xE9\xB5\xA0", + "\xC3\x5C" => "\xE9\xBB\xA0", + "\xC3\x5D" => "\xE9\xBC\x95", + "\xC3\x5E" => "\xE9\xBC\xAC", + "\xC3\x5F" => "\xE5\x84\xB3", + "\xC3\x60" => "\xE5\x9A\xA5", + "\xC3\x61" => "\xE5\xA3\x9E", + "\xC3\x62" => "\xE5\xA3\x9F", + "\xC3\x63" => "\xE5\xA3\xA2", + "\xC3\x64" => "\xE5\xAF\xB5", + "\xC3\x65" => "\xE9\xBE\x90", + "\xC3\x66" => "\xE5\xBB\xAC", + "\xC3\x67" => "\xE6\x87\xB2", + "\xC3\x68" => "\xE6\x87\xB7", + "\xC3\x69" => "\xE6\x87\xB6", + "\xC3\x6A" => "\xE6\x87\xB5", + "\xC3\x6B" => "\xE6\x94\x80", + "\xC3\x6C" => "\xE6\x94\x8F", + "\xC3\x6D" => "\xE6\x9B\xA0", + "\xC3\x6E" => "\xE6\x9B\x9D", + "\xC3\x6F" => "\xE6\xAB\xA5", + "\xC3\x70" => "\xE6\xAB\x9D", + "\xC3\x71" => "\xE6\xAB\x9A", + "\xC3\x72" => "\xE6\xAB\x93", + "\xC3\x73" => "\xE7\x80\x9B", + "\xC3\x74" => "\xE7\x80\x9F", + "\xC3\x75" => "\xE7\x80\xA8", + "\xC3\x76" => "\xE7\x80\x9A", + "\xC3\x77" => "\xE7\x80\x9D", + "\xC3\x78" => "\xE7\x80\x95", + "\xC3\x79" => "\xE7\x80\x98", + "\xC3\x7A" => "\xE7\x88\x86", + "\xC3\x7B" => "\xE7\x88\x8D", + "\xC3\x7C" => "\xE7\x89\x98", + "\xC3\x7D" => "\xE7\x8A\xA2", + "\xC3\x7E" => "\xE7\x8D\xB8", + "\xC3\xA1" => "\xE7\x8D\xBA", + "\xC3\xA2" => "\xE7\x92\xBD", + "\xC3\xA3" => "\xE7\x93\x8A", + "\xC3\xA4" => "\xE7\x93\xA3", + "\xC3\xA5" => "\xE7\x96\x87", + "\xC3\xA6" => "\xE7\x96\x86", + "\xC3\xA7" => "\xE7\x99\x9F", + "\xC3\xA8" => "\xE7\x99\xA1", + "\xC3\xA9" => "\xE7\x9F\x87", + "\xC3\xAA" => "\xE7\xA4\x99", + "\xC3\xAB" => "\xE7\xA6\xB1", + "\xC3\xAC" => "\xE7\xA9\xAB", + "\xC3\xAD" => "\xE7\xA9\xA9", + "\xC3\xAE" => "\xE7\xB0\xBE", + "\xC3\xAF" => "\xE7\xB0\xBF", + "\xC3\xB0" => "\xE7\xB0\xB8", + "\xC3\xB1" => "\xE7\xB0\xBD", + "\xC3\xB2" => "\xE7\xB0\xB7", + "\xC3\xB3" => "\xE7\xB1\x80", + "\xC3\xB4" => "\xE7\xB9\xAB", + "\xC3\xB5" => "\xE7\xB9\xAD", + "\xC3\xB6" => "\xE7\xB9\xB9", + "\xC3\xB7" => "\xE7\xB9\xA9", + "\xC3\xB8" => "\xE7\xB9\xAA", + "\xC3\xB9" => "\xE7\xBE\x85", + "\xC3\xBA" => "\xE7\xB9\xB3", + "\xC3\xBB" => "\xE7\xBE\xB6", + "\xC3\xBC" => "\xE7\xBE\xB9", + "\xC3\xBD" => "\xE7\xBE\xB8", + "\xC3\xBE" => "\xE8\x87\x98", + "\xC3\xBF" => "\xE8\x97\xA9", + "\xC3\xC0" => "\xE8\x97\x9D", + "\xC3\xC1" => "\xE8\x97\xAA", + "\xC3\xC2" => "\xE8\x97\x95", + "\xC3\xC3" => "\xE8\x97\xA4", + "\xC3\xC4" => "\xE8\x97\xA5", + "\xC3\xC5" => "\xE8\x97\xB7", + "\xC3\xC6" => "\xE8\x9F\xBB", + "\xC3\xC7" => "\xE8\xA0\x85", + "\xC3\xC8" => "\xE8\xA0\x8D", + "\xC3\xC9" => "\xE8\x9F\xB9", + "\xC3\xCA" => "\xE8\x9F\xBE", + "\xC3\xCB" => "\xE8\xA5\xA0", + "\xC3\xCC" => "\xE8\xA5\x9F", + "\xC3\xCD" => "\xE8\xA5\x96", + "\xC3\xCE" => "\xE8\xA5\x9E", + "\xC3\xCF" => "\xE8\xAD\x81", + "\xC3\xD0" => "\xE8\xAD\x9C", + "\xC3\xD1" => "\xE8\xAD\x98", + "\xC3\xD2" => "\xE8\xAD\x89", + "\xC3\xD3" => "\xE8\xAD\x9A", + "\xC3\xD4" => "\xE8\xAD\x8E", + "\xC3\xD5" => "\xE8\xAD\x8F", + "\xC3\xD6" => "\xE8\xAD\x86", + "\xC3\xD7" => "\xE8\xAD\x99", + "\xC3\xD8" => "\xE8\xB4\x88", + "\xC3\xD9" => "\xE8\xB4\x8A", + "\xC3\xDA" => "\xE8\xB9\xBC", + "\xC3\xDB" => "\xE8\xB9\xB2", + "\xC3\xDC" => "\xE8\xBA\x87", + "\xC3\xDD" => "\xE8\xB9\xB6", + "\xC3\xDE" => "\xE8\xB9\xAC", + "\xC3\xDF" => "\xE8\xB9\xBA", + "\xC3\xE0" => "\xE8\xB9\xB4", + "\xC3\xE1" => "\xE8\xBD\x94", + "\xC3\xE2" => "\xE8\xBD\x8E", + "\xC3\xE3" => "\xE8\xBE\xAD", + "\xC3\xE4" => "\xE9\x82\x8A", + "\xC3\xE5" => "\xE9\x82\x8B", + "\xC3\xE6" => "\xE9\x86\xB1", + "\xC3\xE7" => "\xE9\x86\xAE", + "\xC3\xE8" => "\xE9\x8F\xA1", + "\xC3\xE9" => "\xE9\x8F\x91", + "\xC3\xEA" => "\xE9\x8F\x9F", + "\xC3\xEB" => "\xE9\x8F\x83", + "\xC3\xEC" => "\xE9\x8F\x88", + "\xC3\xED" => "\xE9\x8F\x9C", + "\xC3\xEE" => "\xE9\x8F\x9D", + "\xC3\xEF" => "\xE9\x8F\x96", + "\xC3\xF0" => "\xE9\x8F\xA2", + "\xC3\xF1" => "\xE9\x8F\x8D", + "\xC3\xF2" => "\xE9\x8F\x98", + "\xC3\xF3" => "\xE9\x8F\xA4", + "\xC3\xF4" => "\xE9\x8F\x97", + "\xC3\xF5" => "\xE9\x8F\xA8", + "\xC3\xF6" => "\xE9\x97\x9C", + "\xC3\xF7" => "\xE9\x9A\xB4", + "\xC3\xF8" => "\xE9\x9B\xA3", + "\xC3\xF9" => "\xE9\x9C\xAA", + "\xC3\xFA" => "\xE9\x9C\xA7", + "\xC3\xFB" => "\xE9\x9D\xA1", + "\xC3\xFC" => "\xE9\x9F\x9C", + "\xC3\xFD" => "\xE9\x9F\xBB", + "\xC3\xFE" => "\xE9\xA1\x9E", + "\xC4\x40" => "\xE9\xA1\x98", + "\xC4\x41" => "\xE9\xA1\x9B", + "\xC4\x42" => "\xE9\xA2\xBC", + "\xC4\x43" => "\xE9\xA5\x85", + "\xC4\x44" => "\xE9\xA5\x89", + "\xC4\x45" => "\xE9\xA8\x96", + "\xC4\x46" => "\xE9\xA8\x99", + "\xC4\x47" => "\xE9\xAC\x8D", + "\xC4\x48" => "\xE9\xAF\xA8", + "\xC4\x49" => "\xE9\xAF\xA7", + "\xC4\x4A" => "\xE9\xAF\x96", + "\xC4\x4B" => "\xE9\xAF\x9B", + "\xC4\x4C" => "\xE9\xB6\x89", + "\xC4\x4D" => "\xE9\xB5\xA1", + "\xC4\x4E" => "\xE9\xB5\xB2", + "\xC4\x4F" => "\xE9\xB5\xAA", + "\xC4\x50" => "\xE9\xB5\xAC", + "\xC4\x51" => "\xE9\xBA\x92", + "\xC4\x52" => "\xE9\xBA\x97", + "\xC4\x53" => "\xE9\xBA\x93", + "\xC4\x54" => "\xE9\xBA\xB4", + "\xC4\x55" => "\xE5\x8B\xB8", + "\xC4\x56" => "\xE5\x9A\xA8", + "\xC4\x57" => "\xE5\x9A\xB7", + "\xC4\x58" => "\xE5\x9A\xB6", + "\xC4\x59" => "\xE5\x9A\xB4", + "\xC4\x5A" => "\xE5\x9A\xBC", + "\xC4\x5B" => "\xE5\xA3\xA4", + "\xC4\x5C" => "\xE5\xAD\x80", + "\xC4\x5D" => "\xE5\xAD\x83", + "\xC4\x5E" => "\xE5\xAD\xBD", + "\xC4\x5F" => "\xE5\xAF\xB6", + "\xC4\x60" => "\xE5\xB7\x89", + "\xC4\x61" => "\xE6\x87\xB8", + "\xC4\x62" => "\xE6\x87\xBA", + "\xC4\x63" => "\xE6\x94\x98", + "\xC4\x64" => "\xE6\x94\x94", + "\xC4\x65" => "\xE6\x94\x99", + "\xC4\x66" => "\xE6\x9B\xA6", + "\xC4\x67" => "\xE6\x9C\xA7", + "\xC4\x68" => "\xE6\xAB\xAC", + "\xC4\x69" => "\xE7\x80\xBE", + "\xC4\x6A" => "\xE7\x80\xB0", + "\xC4\x6B" => "\xE7\x80\xB2", + "\xC4\x6C" => "\xE7\x88\x90", + "\xC4\x6D" => "\xE7\x8D\xBB", + "\xC4\x6E" => "\xE7\x93\x8F", + "\xC4\x6F" => "\xE7\x99\xA2", + "\xC4\x70" => "\xE7\x99\xA5", + "\xC4\x71" => "\xE7\xA4\xA6", + "\xC4\x72" => "\xE7\xA4\xAA", + "\xC4\x73" => "\xE7\xA4\xAC", + "\xC4\x74" => "\xE7\xA4\xAB", + "\xC4\x75" => "\xE7\xAB\x87", + "\xC4\x76" => "\xE7\xAB\xB6", + "\xC4\x77" => "\xE7\xB1\x8C", + "\xC4\x78" => "\xE7\xB1\x83", + "\xC4\x79" => "\xE7\xB1\x8D", + "\xC4\x7A" => "\xE7\xB3\xAF", + "\xC4\x7B" => "\xE7\xB3\xB0", + "\xC4\x7C" => "\xE8\xBE\xAE", + "\xC4\x7D" => "\xE7\xB9\xBD", + "\xC4\x7E" => "\xE7\xB9\xBC", + "\xC4\xA1" => "\xE7\xBA\x82", + "\xC4\xA2" => "\xE7\xBD\x8C", + "\xC4\xA3" => "\xE8\x80\x80", + "\xC4\xA4" => "\xE8\x87\x9A", + "\xC4\xA5" => "\xE8\x89\xA6", + "\xC4\xA6" => "\xE8\x97\xBB", + "\xC4\xA7" => "\xE8\x97\xB9", + "\xC4\xA8" => "\xE8\x98\x91", + "\xC4\xA9" => "\xE8\x97\xBA", + "\xC4\xAA" => "\xE8\x98\x86", + "\xC4\xAB" => "\xE8\x98\x8B", + "\xC4\xAC" => "\xE8\x98\x87", + "\xC4\xAD" => "\xE8\x98\x8A", + "\xC4\xAE" => "\xE8\xA0\x94", + "\xC4\xAF" => "\xE8\xA0\x95", + "\xC4\xB0" => "\xE8\xA5\xA4", + "\xC4\xB1" => "\xE8\xA6\xBA", + "\xC4\xB2" => "\xE8\xA7\xB8", + "\xC4\xB3" => "\xE8\xAD\xB0", + "\xC4\xB4" => "\xE8\xAD\xAC", + "\xC4\xB5" => "\xE8\xAD\xA6", + "\xC4\xB6" => "\xE8\xAD\xAF", + "\xC4\xB7" => "\xE8\xAD\x9F", + "\xC4\xB8" => "\xE8\xAD\xAB", + "\xC4\xB9" => "\xE8\xB4\x8F", + "\xC4\xBA" => "\xE8\xB4\x8D", + "\xC4\xBB" => "\xE8\xBA\x89", + "\xC4\xBC" => "\xE8\xBA\x81", + "\xC4\xBD" => "\xE8\xBA\x85", + "\xC4\xBE" => "\xE8\xBA\x82", + "\xC4\xBF" => "\xE9\x86\xB4", + "\xC4\xC0" => "\xE9\x87\x8B", + "\xC4\xC1" => "\xE9\x90\x98", + "\xC4\xC2" => "\xE9\x90\x83", + "\xC4\xC3" => "\xE9\x8F\xBD", + "\xC4\xC4" => "\xE9\x97\xA1", + "\xC4\xC5" => "\xE9\x9C\xB0", + "\xC4\xC6" => "\xE9\xA3\x84", + "\xC4\xC7" => "\xE9\xA5\x92", + "\xC4\xC8" => "\xE9\xA5\x91", + "\xC4\xC9" => "\xE9\xA6\xA8", + "\xC4\xCA" => "\xE9\xA8\xAB", + "\xC4\xCB" => "\xE9\xA8\xB0", + "\xC4\xCC" => "\xE9\xA8\xB7", + "\xC4\xCD" => "\xE9\xA8\xB5", + "\xC4\xCE" => "\xE9\xB0\x93", + "\xC4\xCF" => "\xE9\xB0\x8D", + "\xC4\xD0" => "\xE9\xB9\xB9", + "\xC4\xD1" => "\xE9\xBA\xB5", + "\xC4\xD2" => "\xE9\xBB\xA8", + "\xC4\xD3" => "\xE9\xBC\xAF", + "\xC4\xD4" => "\xE9\xBD\x9F", + "\xC4\xD5" => "\xE9\xBD\xA3", + "\xC4\xD6" => "\xE9\xBD\xA1", + "\xC4\xD7" => "\xE5\x84\xB7", + "\xC4\xD8" => "\xE5\x84\xB8", + "\xC4\xD9" => "\xE5\x9B\x81", + "\xC4\xDA" => "\xE5\x9B\x80", + "\xC4\xDB" => "\xE5\x9B\x82", + "\xC4\xDC" => "\xE5\xA4\x94", + "\xC4\xDD" => "\xE5\xB1\xAC", + "\xC4\xDE" => "\xE5\xB7\x8D", + "\xC4\xDF" => "\xE6\x87\xBC", + "\xC4\xE0" => "\xE6\x87\xBE", + "\xC4\xE1" => "\xE6\x94\x9D", + "\xC4\xE2" => "\xE6\x94\x9C", + "\xC4\xE3" => "\xE6\x96\x95", + "\xC4\xE4" => "\xE6\x9B\xA9", + "\xC4\xE5" => "\xE6\xAB\xBB", + "\xC4\xE6" => "\xE6\xAC\x84", + "\xC4\xE7" => "\xE6\xAB\xBA", + "\xC4\xE8" => "\xE6\xAE\xB2", + "\xC4\xE9" => "\xE7\x81\x8C", + "\xC4\xEA" => "\xE7\x88\x9B", + "\xC4\xEB" => "\xE7\x8A\xA7", + "\xC4\xEC" => "\xE7\x93\x96", + "\xC4\xED" => "\xE7\x93\x94", + "\xC4\xEE" => "\xE7\x99\xA9", + "\xC4\xEF" => "\xE7\x9F\x93", + "\xC4\xF0" => "\xE7\xB1\x90", + "\xC4\xF1" => "\xE7\xBA\x8F", + "\xC4\xF2" => "\xE7\xBA\x8C", + "\xC4\xF3" => "\xE7\xBE\xBC", + "\xC4\xF4" => "\xE8\x98\x97", + "\xC4\xF5" => "\xE8\x98\xAD", + "\xC4\xF6" => "\xE8\x98\x9A", + "\xC4\xF7" => "\xE8\xA0\xA3", + "\xC4\xF8" => "\xE8\xA0\xA2", + "\xC4\xF9" => "\xE8\xA0\xA1", + "\xC4\xFA" => "\xE8\xA0\x9F", + "\xC4\xFB" => "\xE8\xA5\xAA", + "\xC4\xFC" => "\xE8\xA5\xAC", + "\xC4\xFD" => "\xE8\xA6\xBD", + "\xC4\xFE" => "\xE8\xAD\xB4", + "\xC5\x40" => "\xE8\xAD\xB7", + "\xC5\x41" => "\xE8\xAD\xBD", + "\xC5\x42" => "\xE8\xB4\x93", + "\xC5\x43" => "\xE8\xBA\x8A", + "\xC5\x44" => "\xE8\xBA\x8D", + "\xC5\x45" => "\xE8\xBA\x8B", + "\xC5\x46" => "\xE8\xBD\x9F", + "\xC5\x47" => "\xE8\xBE\xAF", + "\xC5\x48" => "\xE9\x86\xBA", + "\xC5\x49" => "\xE9\x90\xAE", + "\xC5\x4A" => "\xE9\x90\xB3", + "\xC5\x4B" => "\xE9\x90\xB5", + "\xC5\x4C" => "\xE9\x90\xBA", + "\xC5\x4D" => "\xE9\x90\xB8", + "\xC5\x4E" => "\xE9\x90\xB2", + "\xC5\x4F" => "\xE9\x90\xAB", + "\xC5\x50" => "\xE9\x97\xA2", + "\xC5\x51" => "\xE9\x9C\xB8", + "\xC5\x52" => "\xE9\x9C\xB9", + "\xC5\x53" => "\xE9\x9C\xB2", + "\xC5\x54" => "\xE9\x9F\xBF", + "\xC5\x55" => "\xE9\xA1\xA7", + "\xC5\x56" => "\xE9\xA1\xA5", + "\xC5\x57" => "\xE9\xA5\x97", + "\xC5\x58" => "\xE9\xA9\x85", + "\xC5\x59" => "\xE9\xA9\x83", + "\xC5\x5A" => "\xE9\xA9\x80", + "\xC5\x5B" => "\xE9\xA8\xBE", + "\xC5\x5C" => "\xE9\xAB\x8F", + "\xC5\x5D" => "\xE9\xAD\x94", + "\xC5\x5E" => "\xE9\xAD\x91", + "\xC5\x5F" => "\xE9\xB0\xAD", + "\xC5\x60" => "\xE9\xB0\xA5", + "\xC5\x61" => "\xE9\xB6\xAF", + "\xC5\x62" => "\xE9\xB6\xB4", + "\xC5\x63" => "\xE9\xB7\x82", + "\xC5\x64" => "\xE9\xB6\xB8", + "\xC5\x65" => "\xE9\xBA\x9D", + "\xC5\x66" => "\xE9\xBB\xAF", + "\xC5\x67" => "\xE9\xBC\x99", + "\xC5\x68" => "\xE9\xBD\x9C", + "\xC5\x69" => "\xE9\xBD\xA6", + "\xC5\x6A" => "\xE9\xBD\xA7", + "\xC5\x6B" => "\xE5\x84\xBC", + "\xC5\x6C" => "\xE5\x84\xBB", + "\xC5\x6D" => "\xE5\x9B\x88", + "\xC5\x6E" => "\xE5\x9B\x8A", + "\xC5\x6F" => "\xE5\x9B\x89", + "\xC5\x70" => "\xE5\xAD\xBF", + "\xC5\x71" => "\xE5\xB7\x94", + "\xC5\x72" => "\xE5\xB7\x92", + "\xC5\x73" => "\xE5\xBD\x8E", + "\xC5\x74" => "\xE6\x87\xBF", + "\xC5\x75" => "\xE6\x94\xA4", + "\xC5\x76" => "\xE6\xAC\x8A", + "\xC5\x77" => "\xE6\xAD\xA1", + "\xC5\x78" => "\xE7\x81\x91", + "\xC5\x79" => "\xE7\x81\x98", + "\xC5\x7A" => "\xE7\x8E\x80", + "\xC5\x7B" => "\xE7\x93\xA4", + "\xC5\x7C" => "\xE7\x96\x8A", + "\xC5\x7D" => "\xE7\x99\xAE", + "\xC5\x7E" => "\xE7\x99\xAC", + "\xC5\xA1" => "\xE7\xA6\xB3", + "\xC5\xA2" => "\xE7\xB1\xA0", + "\xC5\xA3" => "\xE7\xB1\x9F", + "\xC5\xA4" => "\xE8\x81\xBE", + "\xC5\xA5" => "\xE8\x81\xBD", + "\xC5\xA6" => "\xE8\x87\x9F", + "\xC5\xA7" => "\xE8\xA5\xB2", + "\xC5\xA8" => "\xE8\xA5\xAF", + "\xC5\xA9" => "\xE8\xA7\xBC", + "\xC5\xAA" => "\xE8\xAE\x80", + "\xC5\xAB" => "\xE8\xB4\x96", + "\xC5\xAC" => "\xE8\xB4\x97", + "\xC5\xAD" => "\xE8\xBA\x91", + "\xC5\xAE" => "\xE8\xBA\x93", + "\xC5\xAF" => "\xE8\xBD\xA1", + "\xC5\xB0" => "\xE9\x85\x88", + "\xC5\xB1" => "\xE9\x91\x84", + "\xC5\xB2" => "\xE9\x91\x91", + "\xC5\xB3" => "\xE9\x91\x92", + "\xC5\xB4" => "\xE9\x9C\xBD", + "\xC5\xB5" => "\xE9\x9C\xBE", + "\xC5\xB6" => "\xE9\x9F\x83", + "\xC5\xB7" => "\xE9\x9F\x81", + "\xC5\xB8" => "\xE9\xA1\xAB", + "\xC5\xB9" => "\xE9\xA5\x95", + "\xC5\xBA" => "\xE9\xA9\x95", + "\xC5\xBB" => "\xE9\xA9\x8D", + "\xC5\xBC" => "\xE9\xAB\x92", + "\xC5\xBD" => "\xE9\xAC\x9A", + "\xC5\xBE" => "\xE9\xB1\x89", + "\xC5\xBF" => "\xE9\xB0\xB1", + "\xC5\xC0" => "\xE9\xB0\xBE", + "\xC5\xC1" => "\xE9\xB0\xBB", + "\xC5\xC2" => "\xE9\xB7\x93", + "\xC5\xC3" => "\xE9\xB7\x97", + "\xC5\xC4" => "\xE9\xBC\xB4", + "\xC5\xC5" => "\xE9\xBD\xAC", + "\xC5\xC6" => "\xE9\xBD\xAA", + "\xC5\xC7" => "\xE9\xBE\x94", + "\xC5\xC8" => "\xE5\x9B\x8C", + "\xC5\xC9" => "\xE5\xB7\x96", + "\xC5\xCA" => "\xE6\x88\x80", + "\xC5\xCB" => "\xE6\x94\xA3", + "\xC5\xCC" => "\xE6\x94\xAB", + "\xC5\xCD" => "\xE6\x94\xAA", + "\xC5\xCE" => "\xE6\x9B\xAC", + "\xC5\xCF" => "\xE6\xAC\x90", + "\xC5\xD0" => "\xE7\x93\x9A", + "\xC5\xD1" => "\xE7\xAB\x8A", + "\xC5\xD2" => "\xE7\xB1\xA4", + "\xC5\xD3" => "\xE7\xB1\xA3", + "\xC5\xD4" => "\xE7\xB1\xA5", + "\xC5\xD5" => "\xE7\xBA\x93", + "\xC5\xD6" => "\xE7\xBA\x96", + "\xC5\xD7" => "\xE7\xBA\x94", + "\xC5\xD8" => "\xE8\x87\xA2", + "\xC5\xD9" => "\xE8\x98\xB8", + "\xC5\xDA" => "\xE8\x98\xBF", + "\xC5\xDB" => "\xE8\xA0\xB1", + "\xC5\xDC" => "\xE8\xAE\x8A", + "\xC5\xDD" => "\xE9\x82\x90", + "\xC5\xDE" => "\xE9\x82\x8F", + "\xC5\xDF" => "\xE9\x91\xA3", + "\xC5\xE0" => "\xE9\x91\xA0", + "\xC5\xE1" => "\xE9\x91\xA4", + "\xC5\xE2" => "\xE9\x9D\xA8", + "\xC5\xE3" => "\xE9\xA1\xAF", + "\xC5\xE4" => "\xE9\xA5\x9C", + "\xC5\xE5" => "\xE9\xA9\x9A", + "\xC5\xE6" => "\xE9\xA9\x9B", + "\xC5\xE7" => "\xE9\xA9\x97", + "\xC5\xE8" => "\xE9\xAB\x93", + "\xC5\xE9" => "\xE9\xAB\x94", + "\xC5\xEA" => "\xE9\xAB\x91", + "\xC5\xEB" => "\xE9\xB1\x94", + "\xC5\xEC" => "\xE9\xB1\x97", + "\xC5\xED" => "\xE9\xB1\x96", + "\xC5\xEE" => "\xE9\xB7\xA5", + "\xC5\xEF" => "\xE9\xBA\x9F", + "\xC5\xF0" => "\xE9\xBB\xB4", + "\xC5\xF1" => "\xE5\x9B\x91", + "\xC5\xF2" => "\xE5\xA3\xA9", + "\xC5\xF3" => "\xE6\x94\xAC", + "\xC5\xF4" => "\xE7\x81\x9E", + "\xC5\xF5" => "\xE7\x99\xB1", + "\xC5\xF6" => "\xE7\x99\xB2", + "\xC5\xF7" => "\xE7\x9F\x97", + "\xC5\xF8" => "\xE7\xBD\x90", + "\xC5\xF9" => "\xE7\xBE\x88", + "\xC5\xFA" => "\xE8\xA0\xB6", + "\xC5\xFB" => "\xE8\xA0\xB9", + "\xC5\xFC" => "\xE8\xA1\xA2", + "\xC5\xFD" => "\xE8\xAE\x93", + "\xC5\xFE" => "\xE8\xAE\x92", + "\xC6\x40" => "\xE8\xAE\x96", + "\xC6\x41" => "\xE8\x89\xB7", + "\xC6\x42" => "\xE8\xB4\x9B", + "\xC6\x43" => "\xE9\x87\x80", + "\xC6\x44" => "\xE9\x91\xAA", + "\xC6\x45" => "\xE9\x9D\x82", + "\xC6\x46" => "\xE9\x9D\x88", + "\xC6\x47" => "\xE9\x9D\x84", + "\xC6\x48" => "\xE9\x9F\x86", + "\xC6\x49" => "\xE9\xA1\xB0", + "\xC6\x4A" => "\xE9\xA9\x9F", + "\xC6\x4B" => "\xE9\xAC\xA2", + "\xC6\x4C" => "\xE9\xAD\x98", + "\xC6\x4D" => "\xE9\xB1\x9F", + "\xC6\x4E" => "\xE9\xB7\xB9", + "\xC6\x4F" => "\xE9\xB7\xBA", + "\xC6\x50" => "\xE9\xB9\xBC", + "\xC6\x51" => "\xE9\xB9\xBD", + "\xC6\x52" => "\xE9\xBC\x87", + "\xC6\x53" => "\xE9\xBD\xB7", + "\xC6\x54" => "\xE9\xBD\xB2", + "\xC6\x55" => "\xE5\xBB\xB3", + "\xC6\x56" => "\xE6\xAC\x96", + "\xC6\x57" => "\xE7\x81\xA3", + "\xC6\x58" => "\xE7\xB1\xAC", + "\xC6\x59" => "\xE7\xB1\xAE", + "\xC6\x5A" => "\xE8\xA0\xBB", + "\xC6\x5B" => "\xE8\xA7\x80", + "\xC6\x5C" => "\xE8\xBA\xA1", + "\xC6\x5D" => "\xE9\x87\x81", + "\xC6\x5E" => "\xE9\x91\xB2", + "\xC6\x5F" => "\xE9\x91\xB0", + "\xC6\x60" => "\xE9\xA1\xB1", + "\xC6\x61" => "\xE9\xA5\x9E", + "\xC6\x62" => "\xE9\xAB\x96", + "\xC6\x63" => "\xE9\xAC\xA3", + "\xC6\x64" => "\xE9\xBB\x8C", + "\xC6\x65" => "\xE7\x81\xA4", + "\xC6\x66" => "\xE7\x9F\x9A", + "\xC6\x67" => "\xE8\xAE\x9A", + "\xC6\x68" => "\xE9\x91\xB7", + "\xC6\x69" => "\xE9\x9F\x89", + "\xC6\x6A" => "\xE9\xA9\xA2", + "\xC6\x6B" => "\xE9\xA9\xA5", + "\xC6\x6C" => "\xE7\xBA\x9C", + "\xC6\x6D" => "\xE8\xAE\x9C", + "\xC6\x6E" => "\xE8\xBA\xAA", + "\xC6\x6F" => "\xE9\x87\x85", + "\xC6\x70" => "\xE9\x91\xBD", + "\xC6\x71" => "\xE9\x91\xBE", + "\xC6\x72" => "\xE9\x91\xBC", + "\xC6\x73" => "\xE9\xB1\xB7", + "\xC6\x74" => "\xE9\xB1\xB8", + "\xC6\x75" => "\xE9\xBB\xB7", + "\xC6\x76" => "\xE8\xB1\x94", + "\xC6\x77" => "\xE9\x91\xBF", + "\xC6\x78" => "\xE9\xB8\x9A", + "\xC6\x79" => "\xE7\x88\xA8", + "\xC6\x7A" => "\xE9\xA9\xAA", + "\xC6\x7B" => "\xE9\xAC\xB1", + "\xC6\x7C" => "\xE9\xB8\x9B", + "\xC6\x7D" => "\xE9\xB8\x9E", + "\xC6\x7E" => "\xE7\xB1\xB2", + "\xC6\xA1" => "\xE3\x83\xBE", + "\xC6\xA2" => "\xE3\x82\x9D", + "\xC6\xA3" => "\xE3\x82\x9E", + "\xC6\xA4" => "\xE3\x80\x85", + "\xC6\xA5" => "\xE3\x81\x81", + "\xC6\xA6" => "\xE3\x81\x82", + "\xC6\xA7" => "\xE3\x81\x83", + "\xC6\xA8" => "\xE3\x81\x84", + "\xC6\xA9" => "\xE3\x81\x85", + "\xC6\xAA" => "\xE3\x81\x86", + "\xC6\xAB" => "\xE3\x81\x87", + "\xC6\xAC" => "\xE3\x81\x88", + "\xC6\xAD" => "\xE3\x81\x89", + "\xC6\xAE" => "\xE3\x81\x8A", + "\xC6\xAF" => "\xE3\x81\x8B", + "\xC6\xB0" => "\xE3\x81\x8C", + "\xC6\xB1" => "\xE3\x81\x8D", + "\xC6\xB2" => "\xE3\x81\x8E", + "\xC6\xB3" => "\xE3\x81\x8F", + "\xC6\xB4" => "\xE3\x81\x90", + "\xC6\xB5" => "\xE3\x81\x91", + "\xC6\xB6" => "\xE3\x81\x92", + "\xC6\xB7" => "\xE3\x81\x93", + "\xC6\xB8" => "\xE3\x81\x94", + "\xC6\xB9" => "\xE3\x81\x95", + "\xC6\xBA" => "\xE3\x81\x96", + "\xC6\xBB" => "\xE3\x81\x97", + "\xC6\xBC" => "\xE3\x81\x98", + "\xC6\xBD" => "\xE3\x81\x99", + "\xC6\xBE" => "\xE3\x81\x9A", + "\xC6\xBF" => "\xE3\x81\x9B", + "\xC6\xC0" => "\xE3\x81\x9C", + "\xC6\xC1" => "\xE3\x81\x9D", + "\xC6\xC2" => "\xE3\x81\x9E", + "\xC6\xC3" => "\xE3\x81\x9F", + "\xC6\xC4" => "\xE3\x81\xA0", + "\xC6\xC5" => "\xE3\x81\xA1", + "\xC6\xC6" => "\xE3\x81\xA2", + "\xC6\xC7" => "\xE3\x81\xA3", + "\xC6\xC8" => "\xE3\x81\xA4", + "\xC6\xC9" => "\xE3\x81\xA5", + "\xC6\xCA" => "\xE3\x81\xA6", + "\xC6\xCB" => "\xE3\x81\xA7", + "\xC6\xCC" => "\xE3\x81\xA8", + "\xC6\xCD" => "\xE3\x81\xA9", + "\xC6\xCE" => "\xE3\x81\xAA", + "\xC6\xCF" => "\xE3\x81\xAB", + "\xC6\xD0" => "\xE3\x81\xAC", + "\xC6\xD1" => "\xE3\x81\xAD", + "\xC6\xD2" => "\xE3\x81\xAE", + "\xC6\xD3" => "\xE3\x81\xAF", + "\xC6\xD4" => "\xE3\x81\xB0", + "\xC6\xD5" => "\xE3\x81\xB1", + "\xC6\xD6" => "\xE3\x81\xB2", + "\xC6\xD7" => "\xE3\x81\xB3", + "\xC6\xD8" => "\xE3\x81\xB4", + "\xC6\xD9" => "\xE3\x81\xB5", + "\xC6\xDA" => "\xE3\x81\xB6", + "\xC6\xDB" => "\xE3\x81\xB7", + "\xC6\xDC" => "\xE3\x81\xB8", + "\xC6\xDD" => "\xE3\x81\xB9", + "\xC6\xDE" => "\xE3\x81\xBA", + "\xC6\xDF" => "\xE3\x81\xBB", + "\xC6\xE0" => "\xE3\x81\xBC", + "\xC6\xE1" => "\xE3\x81\xBD", + "\xC6\xE2" => "\xE3\x81\xBE", + "\xC6\xE3" => "\xE3\x81\xBF", + "\xC6\xE4" => "\xE3\x82\x80", + "\xC6\xE5" => "\xE3\x82\x81", + "\xC6\xE6" => "\xE3\x82\x82", + "\xC6\xE7" => "\xE3\x82\x83", + "\xC6\xE8" => "\xE3\x82\x84", + "\xC6\xE9" => "\xE3\x82\x85", + "\xC6\xEA" => "\xE3\x82\x86", + "\xC6\xEB" => "\xE3\x82\x87", + "\xC6\xEC" => "\xE3\x82\x88", + "\xC6\xED" => "\xE3\x82\x89", + "\xC6\xEE" => "\xE3\x82\x8A", + "\xC6\xEF" => "\xE3\x82\x8B", + "\xC6\xF0" => "\xE3\x82\x8C", + "\xC6\xF1" => "\xE3\x82\x8D", + "\xC6\xF2" => "\xE3\x82\x8E", + "\xC6\xF3" => "\xE3\x82\x8F", + "\xC6\xF4" => "\xE3\x82\x90", + "\xC6\xF5" => "\xE3\x82\x91", + "\xC6\xF6" => "\xE3\x82\x92", + "\xC6\xF7" => "\xE3\x82\x93", + "\xC6\xF8" => "\xE3\x82\xA1", + "\xC6\xF9" => "\xE3\x82\xA2", + "\xC6\xFA" => "\xE3\x82\xA3", + "\xC6\xFB" => "\xE3\x82\xA4", + "\xC6\xFC" => "\xE3\x82\xA5", + "\xC6\xFD" => "\xE3\x82\xA6", + "\xC6\xFE" => "\xE3\x82\xA7", + "\xC7\x40" => "\xE3\x82\xA8", + "\xC7\x41" => "\xE3\x82\xA9", + "\xC7\x42" => "\xE3\x82\xAA", + "\xC7\x43" => "\xE3\x82\xAB", + "\xC7\x44" => "\xE3\x82\xAC", + "\xC7\x45" => "\xE3\x82\xAD", + "\xC7\x46" => "\xE3\x82\xAE", + "\xC7\x47" => "\xE3\x82\xAF", + "\xC7\x48" => "\xE3\x82\xB0", + "\xC7\x49" => "\xE3\x82\xB1", + "\xC7\x4A" => "\xE3\x82\xB2", + "\xC7\x4B" => "\xE3\x82\xB3", + "\xC7\x4C" => "\xE3\x82\xB4", + "\xC7\x4D" => "\xE3\x82\xB5", + "\xC7\x4E" => "\xE3\x82\xB6", + "\xC7\x4F" => "\xE3\x82\xB7", + "\xC7\x50" => "\xE3\x82\xB8", + "\xC7\x51" => "\xE3\x82\xB9", + "\xC7\x52" => "\xE3\x82\xBA", + "\xC7\x53" => "\xE3\x82\xBB", + "\xC7\x54" => "\xE3\x82\xBC", + "\xC7\x55" => "\xE3\x82\xBD", + "\xC7\x56" => "\xE3\x82\xBE", + "\xC7\x57" => "\xE3\x82\xBF", + "\xC7\x58" => "\xE3\x83\x80", + "\xC7\x59" => "\xE3\x83\x81", + "\xC7\x5A" => "\xE3\x83\x82", + "\xC7\x5B" => "\xE3\x83\x83", + "\xC7\x5C" => "\xE3\x83\x84", + "\xC7\x5D" => "\xE3\x83\x85", + "\xC7\x5E" => "\xE3\x83\x86", + "\xC7\x5F" => "\xE3\x83\x87", + "\xC7\x60" => "\xE3\x83\x88", + "\xC7\x61" => "\xE3\x83\x89", + "\xC7\x62" => "\xE3\x83\x8A", + "\xC7\x63" => "\xE3\x83\x8B", + "\xC7\x64" => "\xE3\x83\x8C", + "\xC7\x65" => "\xE3\x83\x8D", + "\xC7\x66" => "\xE3\x83\x8E", + "\xC7\x67" => "\xE3\x83\x8F", + "\xC7\x68" => "\xE3\x83\x90", + "\xC7\x69" => "\xE3\x83\x91", + "\xC7\x6A" => "\xE3\x83\x92", + "\xC7\x6B" => "\xE3\x83\x93", + "\xC7\x6C" => "\xE3\x83\x94", + "\xC7\x6D" => "\xE3\x83\x95", + "\xC7\x6E" => "\xE3\x83\x96", + "\xC7\x6F" => "\xE3\x83\x97", + "\xC7\x70" => "\xE3\x83\x98", + "\xC7\x71" => "\xE3\x83\x99", + "\xC7\x72" => "\xE3\x83\x9A", + "\xC7\x73" => "\xE3\x83\x9B", + "\xC7\x74" => "\xE3\x83\x9C", + "\xC7\x75" => "\xE3\x83\x9D", + "\xC7\x76" => "\xE3\x83\x9E", + "\xC7\x77" => "\xE3\x83\x9F", + "\xC7\x78" => "\xE3\x83\xA0", + "\xC7\x79" => "\xE3\x83\xA1", + "\xC7\x7A" => "\xE3\x83\xA2", + "\xC7\x7B" => "\xE3\x83\xA3", + "\xC7\x7C" => "\xE3\x83\xA4", + "\xC7\x7D" => "\xE3\x83\xA5", + "\xC7\x7E" => "\xE3\x83\xA6", + "\xC7\xA1" => "\xE3\x83\xA7", + "\xC7\xA2" => "\xE3\x83\xA8", + "\xC7\xA3" => "\xE3\x83\xA9", + "\xC7\xA4" => "\xE3\x83\xAA", + "\xC7\xA5" => "\xE3\x83\xAB", + "\xC7\xA6" => "\xE3\x83\xAC", + "\xC7\xA7" => "\xE3\x83\xAD", + "\xC7\xA8" => "\xE3\x83\xAE", + "\xC7\xA9" => "\xE3\x83\xAF", + "\xC7\xAA" => "\xE3\x83\xB0", + "\xC7\xAB" => "\xE3\x83\xB1", + "\xC7\xAC" => "\xE3\x83\xB2", + "\xC7\xAD" => "\xE3\x83\xB3", + "\xC7\xAE" => "\xE3\x83\xB4", + "\xC7\xAF" => "\xE3\x83\xB5", + "\xC7\xB0" => "\xE3\x83\xB6", + "\xC7\xB1" => "\xD0\x94", + "\xC7\xB2" => "\xD0\x95", + "\xC7\xB3" => "\xD0\x81", + "\xC7\xB4" => "\xD0\x96", + "\xC7\xB5" => "\xD0\x97", + "\xC7\xB6" => "\xD0\x98", + "\xC7\xB7" => "\xD0\x99", + "\xC7\xB8" => "\xD0\x9A", + "\xC7\xB9" => "\xD0\x9B", + "\xC7\xBA" => "\xD0\x9C", + "\xC7\xBB" => "\xD0\xA3", + "\xC7\xBC" => "\xD0\xA4", + "\xC7\xBD" => "\xD0\xA5", + "\xC7\xBE" => "\xD0\xA6", + "\xC7\xBF" => "\xD0\xA7", + "\xC7\xC0" => "\xD0\xA8", + "\xC7\xC1" => "\xD0\xA9", + "\xC7\xC2" => "\xD0\xAA", + "\xC7\xC3" => "\xD0\xAB", + "\xC7\xC4" => "\xD0\xAC", + "\xC7\xC5" => "\xD0\xAD", + "\xC7\xC6" => "\xD0\xAE", + "\xC7\xC7" => "\xD0\xAF", + "\xC7\xC8" => "\xD0\xB0", + "\xC7\xC9" => "\xD0\xB1", + "\xC7\xCA" => "\xD0\xB2", + "\xC7\xCB" => "\xD0\xB3", + "\xC7\xCC" => "\xD0\xB4", + "\xC7\xCD" => "\xD0\xB5", + "\xC7\xCE" => "\xD1\x91", + "\xC7\xCF" => "\xD0\xB6", + "\xC7\xD0" => "\xD0\xB7", + "\xC7\xD1" => "\xD0\xB8", + "\xC7\xD2" => "\xD0\xB9", + "\xC7\xD3" => "\xD0\xBA", + "\xC7\xD4" => "\xD0\xBB", + "\xC7\xD5" => "\xD0\xBC", + "\xC7\xD6" => "\xD0\xBD", + "\xC7\xD7" => "\xD0\xBE", + "\xC7\xD8" => "\xD0\xBF", + "\xC7\xD9" => "\xD1\x80", + "\xC7\xDA" => "\xD1\x81", + "\xC7\xDB" => "\xD1\x82", + "\xC7\xDC" => "\xD1\x83", + "\xC7\xDD" => "\xD1\x84", + "\xC7\xDE" => "\xD1\x85", + "\xC7\xDF" => "\xD1\x86", + "\xC7\xE0" => "\xD1\x87", + "\xC7\xE1" => "\xD1\x88", + "\xC7\xE2" => "\xD1\x89", + "\xC7\xE3" => "\xD1\x8A", + "\xC7\xE4" => "\xD1\x8B", + "\xC7\xE5" => "\xD1\x8C", + "\xC7\xE6" => "\xD1\x8D", + "\xC7\xE7" => "\xD1\x8E", + "\xC7\xE8" => "\xD1\x8F", + "\xC7\xE9" => "\xE2\x91\xA0", + "\xC7\xEA" => "\xE2\x91\xA1", + "\xC7\xEB" => "\xE2\x91\xA2", + "\xC7\xEC" => "\xE2\x91\xA3", + "\xC7\xED" => "\xE2\x91\xA4", + "\xC7\xEE" => "\xE2\x91\xA5", + "\xC7\xEF" => "\xE2\x91\xA6", + "\xC7\xF0" => "\xE2\x91\xA7", + "\xC7\xF1" => "\xE2\x91\xA8", + "\xC7\xF2" => "\xE2\x91\xA9", + "\xC7\xF3" => "\xE2\x91\xB4", + "\xC7\xF4" => "\xE2\x91\xB5", + "\xC7\xF5" => "\xE2\x91\xB6", + "\xC7\xF6" => "\xE2\x91\xB7", + "\xC7\xF7" => "\xE2\x91\xB8", + "\xC7\xF8" => "\xE2\x91\xB9", + "\xC7\xF9" => "\xE2\x91\xBA", + "\xC7\xFA" => "\xE2\x91\xBB", + "\xC7\xFB" => "\xE2\x91\xBC", + "\xC7\xFC" => "\xE2\x91\xBD", + "\xC9\x40" => "\xE4\xB9\x82", + "\xC9\x41" => "\xE4\xB9\x9C", + "\xC9\x42" => "\xE5\x87\xB5", + "\xC9\x43" => "\xE5\x8C\x9A", + "\xC9\x44" => "\xE5\x8E\x82", + "\xC9\x45" => "\xE4\xB8\x87", + "\xC9\x46" => "\xE4\xB8\x8C", + "\xC9\x47" => "\xE4\xB9\x87", + "\xC9\x48" => "\xE4\xBA\x8D", + "\xC9\x49" => "\xE5\x9B\x97", + "\xC9\x4A" => "\xEF\xA8\x8C", + "\xC9\x4B" => "\xE5\xB1\xAE", + "\xC9\x4C" => "\xE5\xBD\xB3", + "\xC9\x4D" => "\xE4\xB8\x8F", + "\xC9\x4E" => "\xE5\x86\x87", + "\xC9\x4F" => "\xE4\xB8\x8E", + "\xC9\x50" => "\xE4\xB8\xAE", + "\xC9\x51" => "\xE4\xBA\x93", + "\xC9\x52" => "\xE4\xBB\x82", + "\xC9\x53" => "\xE4\xBB\x89", + "\xC9\x54" => "\xE4\xBB\x88", + "\xC9\x55" => "\xE5\x86\x98", + "\xC9\x56" => "\xE5\x8B\xBC", + "\xC9\x57" => "\xE5\x8D\xAC", + "\xC9\x58" => "\xE5\x8E\xB9", + "\xC9\x59" => "\xE5\x9C\xA0", + "\xC9\x5A" => "\xE5\xA4\x83", + "\xC9\x5B" => "\xE5\xA4\xAC", + "\xC9\x5C" => "\xE5\xB0\x90", + "\xC9\x5D" => "\xE5\xB7\xBF", + "\xC9\x5E" => "\xE6\x97\xA1", + "\xC9\x5F" => "\xE6\xAE\xB3", + "\xC9\x60" => "\xE6\xAF\x8C", + "\xC9\x61" => "\xE6\xB0\x94", + "\xC9\x62" => "\xE7\x88\xBF", + "\xC9\x63" => "\xE4\xB8\xB1", + "\xC9\x64" => "\xE4\xB8\xBC", + "\xC9\x65" => "\xE4\xBB\xA8", + "\xC9\x66" => "\xE4\xBB\x9C", + "\xC9\x67" => "\xE4\xBB\xA9", + "\xC9\x68" => "\xE4\xBB\xA1", + "\xC9\x69" => "\xE4\xBB\x9D", + "\xC9\x6A" => "\xE4\xBB\x9A", + "\xC9\x6B" => "\xE5\x88\x8C", + "\xC9\x6C" => "\xE5\x8C\x9C", + "\xC9\x6D" => "\xE5\x8D\x8C", + "\xC9\x6E" => "\xE5\x9C\xA2", + "\xC9\x6F" => "\xE5\x9C\xA3", + "\xC9\x70" => "\xE5\xA4\x97", + "\xC9\x71" => "\xE5\xA4\xAF", + "\xC9\x72" => "\xE5\xAE\x81", + "\xC9\x73" => "\xE5\xAE\x84", + "\xC9\x74" => "\xE5\xB0\x92", + "\xC9\x75" => "\xE5\xB0\xBB", + "\xC9\x76" => "\xE5\xB1\xB4", + "\xC9\x77" => "\xE5\xB1\xB3", + "\xC9\x78" => "\xE5\xB8\x84", + "\xC9\x79" => "\xE5\xBA\x80", + "\xC9\x7A" => "\xE5\xBA\x82", + "\xC9\x7B" => "\xE5\xBF\x89", + "\xC9\x7C" => "\xE6\x88\x89", + "\xC9\x7D" => "\xE6\x89\x90", + "\xC9\x7E" => "\xE6\xB0\x95", + "\xC9\xA1" => "\xE6\xB0\xB6", + "\xC9\xA2" => "\xE6\xB1\x83", + "\xC9\xA3" => "\xE6\xB0\xBF", + "\xC9\xA4" => "\xE6\xB0\xBB", + "\xC9\xA5" => "\xE7\x8A\xAE", + "\xC9\xA6" => "\xE7\x8A\xB0", + "\xC9\xA7" => "\xE7\x8E\x8A", + "\xC9\xA8" => "\xE7\xA6\xB8", + "\xC9\xA9" => "\xE8\x82\x8A", + "\xC9\xAA" => "\xE9\x98\x9E", + "\xC9\xAB" => "\xE4\xBC\x8E", + "\xC9\xAC" => "\xE4\xBC\x98", + "\xC9\xAD" => "\xE4\xBC\xAC", + "\xC9\xAE" => "\xE4\xBB\xB5", + "\xC9\xAF" => "\xE4\xBC\x94", + "\xC9\xB0" => "\xE4\xBB\xB1", + "\xC9\xB1" => "\xE4\xBC\x80", + "\xC9\xB2" => "\xE4\xBB\xB7", + "\xC9\xB3" => "\xE4\xBC\x88", + "\xC9\xB4" => "\xE4\xBC\x9D", + "\xC9\xB5" => "\xE4\xBC\x82", + "\xC9\xB6" => "\xE4\xBC\x85", + "\xC9\xB7" => "\xE4\xBC\xA2", + "\xC9\xB8" => "\xE4\xBC\x93", + "\xC9\xB9" => "\xE4\xBC\x84", + "\xC9\xBA" => "\xE4\xBB\xB4", + "\xC9\xBB" => "\xE4\xBC\x92", + "\xC9\xBC" => "\xE5\x86\xB1", + "\xC9\xBD" => "\xE5\x88\x93", + "\xC9\xBE" => "\xE5\x88\x89", + "\xC9\xBF" => "\xE5\x88\x90", + "\xC9\xC0" => "\xE5\x8A\xA6", + "\xC9\xC1" => "\xE5\x8C\xA2", + "\xC9\xC2" => "\xE5\x8C\x9F", + "\xC9\xC3" => "\xE5\x8D\x8D", + "\xC9\xC4" => "\xE5\x8E\x8A", + "\xC9\xC5" => "\xE5\x90\x87", + "\xC9\xC6" => "\xE5\x9B\xA1", + "\xC9\xC7" => "\xE5\x9B\x9F", + "\xC9\xC8" => "\xE5\x9C\xAE", + "\xC9\xC9" => "\xE5\x9C\xAA", + "\xC9\xCA" => "\xE5\x9C\xB4", + "\xC9\xCB" => "\xE5\xA4\xBC", + "\xC9\xCC" => "\xE5\xA6\x80", + "\xC9\xCD" => "\xE5\xA5\xBC", + "\xC9\xCE" => "\xE5\xA6\x85", + "\xC9\xCF" => "\xE5\xA5\xBB", + "\xC9\xD0" => "\xE5\xA5\xBE", + "\xC9\xD1" => "\xE5\xA5\xB7", + "\xC9\xD2" => "\xE5\xA5\xBF", + "\xC9\xD3" => "\xE5\xAD\x96", + "\xC9\xD4" => "\xE5\xB0\x95", + "\xC9\xD5" => "\xE5\xB0\xA5", + "\xC9\xD6" => "\xE5\xB1\xBC", + "\xC9\xD7" => "\xE5\xB1\xBA", + "\xC9\xD8" => "\xE5\xB1\xBB", + "\xC9\xD9" => "\xE5\xB1\xBE", + "\xC9\xDA" => "\xE5\xB7\x9F", + "\xC9\xDB" => "\xE5\xB9\xB5", + "\xC9\xDC" => "\xE5\xBA\x84", + "\xC9\xDD" => "\xE5\xBC\x82", + "\xC9\xDE" => "\xE5\xBC\x9A", + "\xC9\xDF" => "\xE5\xBD\xB4", + "\xC9\xE0" => "\xE5\xBF\x95", + "\xC9\xE1" => "\xE5\xBF\x94", + "\xC9\xE2" => "\xE5\xBF\x8F", + "\xC9\xE3" => "\xE6\x89\x9C", + "\xC9\xE4" => "\xE6\x89\x9E", + "\xC9\xE5" => "\xE6\x89\xA4", + "\xC9\xE6" => "\xE6\x89\xA1", + "\xC9\xE7" => "\xE6\x89\xA6", + "\xC9\xE8" => "\xE6\x89\xA2", + "\xC9\xE9" => "\xE6\x89\x99", + "\xC9\xEA" => "\xE6\x89\xA0", + "\xC9\xEB" => "\xE6\x89\x9A", + "\xC9\xEC" => "\xE6\x89\xA5", + "\xC9\xED" => "\xE6\x97\xAF", + "\xC9\xEE" => "\xE6\x97\xAE", + "\xC9\xEF" => "\xE6\x9C\xBE", + "\xC9\xF0" => "\xE6\x9C\xB9", + "\xC9\xF1" => "\xE6\x9C\xB8", + "\xC9\xF2" => "\xE6\x9C\xBB", + "\xC9\xF3" => "\xE6\x9C\xBA", + "\xC9\xF4" => "\xE6\x9C\xBF", + "\xC9\xF5" => "\xE6\x9C\xBC", + "\xC9\xF6" => "\xE6\x9C\xB3", + "\xC9\xF7" => "\xE6\xB0\x98", + "\xC9\xF8" => "\xE6\xB1\x86", + "\xC9\xF9" => "\xE6\xB1\x92", + "\xC9\xFA" => "\xE6\xB1\x9C", + "\xC9\xFB" => "\xE6\xB1\x8F", + "\xC9\xFC" => "\xE6\xB1\x8A", + "\xC9\xFD" => "\xE6\xB1\x94", + "\xC9\xFE" => "\xE6\xB1\x8B", + "\xCA\x40" => "\xE6\xB1\x8C", + "\xCA\x41" => "\xE7\x81\xB1", + "\xCA\x42" => "\xE7\x89\x9E", + "\xCA\x43" => "\xE7\x8A\xB4", + "\xCA\x44" => "\xE7\x8A\xB5", + "\xCA\x45" => "\xE7\x8E\x8E", + "\xCA\x46" => "\xE7\x94\xAA", + "\xCA\x47" => "\xE7\x99\xBF", + "\xCA\x48" => "\xE7\xA9\xB5", + "\xCA\x49" => "\xE7\xBD\x91", + "\xCA\x4A" => "\xE8\x89\xB8", + "\xCA\x4B" => "\xE8\x89\xBC", + "\xCA\x4C" => "\xE8\x8A\x80", + "\xCA\x4D" => "\xE8\x89\xBD", + "\xCA\x4E" => "\xE8\x89\xBF", + "\xCA\x4F" => "\xE8\x99\x8D", + "\xCA\x50" => "\xE8\xA5\xBE", + "\xCA\x51" => "\xE9\x82\x99", + "\xCA\x52" => "\xE9\x82\x97", + "\xCA\x53" => "\xE9\x82\x98", + "\xCA\x54" => "\xE9\x82\x9B", + "\xCA\x55" => "\xE9\x82\x94", + "\xCA\x56" => "\xE9\x98\xA2", + "\xCA\x57" => "\xE9\x98\xA4", + "\xCA\x58" => "\xE9\x98\xA0", + "\xCA\x59" => "\xE9\x98\xA3", + "\xCA\x5A" => "\xE4\xBD\x96", + "\xCA\x5B" => "\xE4\xBC\xBB", + "\xCA\x5C" => "\xE4\xBD\xA2", + "\xCA\x5D" => "\xE4\xBD\x89", + "\xCA\x5E" => "\xE4\xBD\x93", + "\xCA\x5F" => "\xE4\xBD\xA4", + "\xCA\x60" => "\xE4\xBC\xBE", + "\xCA\x61" => "\xE4\xBD\xA7", + "\xCA\x62" => "\xE4\xBD\x92", + "\xCA\x63" => "\xE4\xBD\x9F", + "\xCA\x64" => "\xE4\xBD\x81", + "\xCA\x65" => "\xE4\xBD\x98", + "\xCA\x66" => "\xE4\xBC\xAD", + "\xCA\x67" => "\xE4\xBC\xB3", + "\xCA\x68" => "\xE4\xBC\xBF", + "\xCA\x69" => "\xE4\xBD\xA1", + "\xCA\x6A" => "\xE5\x86\x8F", + "\xCA\x6B" => "\xE5\x86\xB9", + "\xCA\x6C" => "\xE5\x88\x9C", + "\xCA\x6D" => "\xE5\x88\x9E", + "\xCA\x6E" => "\xE5\x88\xA1", + "\xCA\x6F" => "\xE5\x8A\xAD", + "\xCA\x70" => "\xE5\x8A\xAE", + "\xCA\x71" => "\xE5\x8C\x89", + "\xCA\x72" => "\xE5\x8D\xA3", + "\xCA\x73" => "\xE5\x8D\xB2", + "\xCA\x74" => "\xE5\x8E\x8E", + "\xCA\x75" => "\xE5\x8E\x8F", + "\xCA\x76" => "\xE5\x90\xB0", + "\xCA\x77" => "\xE5\x90\xB7", + "\xCA\x78" => "\xE5\x90\xAA", + "\xCA\x79" => "\xE5\x91\x94", + "\xCA\x7A" => "\xE5\x91\x85", + "\xCA\x7B" => "\xE5\x90\x99", + "\xCA\x7C" => "\xE5\x90\x9C", + "\xCA\x7D" => "\xE5\x90\xA5", + "\xCA\x7E" => "\xE5\x90\x98", + "\xCA\xA1" => "\xE5\x90\xBD", + "\xCA\xA2" => "\xE5\x91\x8F", + "\xCA\xA3" => "\xE5\x91\x81", + "\xCA\xA4" => "\xE5\x90\xA8", + "\xCA\xA5" => "\xE5\x90\xA4", + "\xCA\xA6" => "\xE5\x91\x87", + "\xCA\xA7" => "\xE5\x9B\xAE", + "\xCA\xA8" => "\xE5\x9B\xA7", + "\xCA\xA9" => "\xE5\x9B\xA5", + "\xCA\xAA" => "\xE5\x9D\x81", + "\xCA\xAB" => "\xE5\x9D\x85", + "\xCA\xAC" => "\xE5\x9D\x8C", + "\xCA\xAD" => "\xE5\x9D\x89", + "\xCA\xAE" => "\xE5\x9D\x8B", + "\xCA\xAF" => "\xE5\x9D\x92", + "\xCA\xB0" => "\xE5\xA4\x86", + "\xCA\xB1" => "\xE5\xA5\x80", + "\xCA\xB2" => "\xE5\xA6\xA6", + "\xCA\xB3" => "\xE5\xA6\x98", + "\xCA\xB4" => "\xE5\xA6\xA0", + "\xCA\xB5" => "\xE5\xA6\x97", + "\xCA\xB6" => "\xE5\xA6\x8E", + "\xCA\xB7" => "\xE5\xA6\xA2", + "\xCA\xB8" => "\xE5\xA6\x90", + "\xCA\xB9" => "\xE5\xA6\x8F", + "\xCA\xBA" => "\xE5\xA6\xA7", + "\xCA\xBB" => "\xE5\xA6\xA1", + "\xCA\xBC" => "\xE5\xAE\x8E", + "\xCA\xBD" => "\xE5\xAE\x92", + "\xCA\xBE" => "\xE5\xB0\xA8", + "\xCA\xBF" => "\xE5\xB0\xAA", + "\xCA\xC0" => "\xE5\xB2\x8D", + "\xCA\xC1" => "\xE5\xB2\x8F", + "\xCA\xC2" => "\xE5\xB2\x88", + "\xCA\xC3" => "\xE5\xB2\x8B", + "\xCA\xC4" => "\xE5\xB2\x89", + "\xCA\xC5" => "\xE5\xB2\x92", + "\xCA\xC6" => "\xE5\xB2\x8A", + "\xCA\xC7" => "\xE5\xB2\x86", + "\xCA\xC8" => "\xE5\xB2\x93", + "\xCA\xC9" => "\xE5\xB2\x95", + "\xCA\xCA" => "\xE5\xB7\xA0", + "\xCA\xCB" => "\xE5\xB8\x8A", + "\xCA\xCC" => "\xE5\xB8\x8E", + "\xCA\xCD" => "\xE5\xBA\x8B", + "\xCA\xCE" => "\xE5\xBA\x89", + "\xCA\xCF" => "\xE5\xBA\x8C", + "\xCA\xD0" => "\xE5\xBA\x88", + "\xCA\xD1" => "\xE5\xBA\x8D", + "\xCA\xD2" => "\xE5\xBC\x85", + "\xCA\xD3" => "\xE5\xBC\x9D", + "\xCA\xD4" => "\xE5\xBD\xB8", + "\xCA\xD5" => "\xE5\xBD\xB6", + "\xCA\xD6" => "\xE5\xBF\x92", + "\xCA\xD7" => "\xE5\xBF\x91", + "\xCA\xD8" => "\xE5\xBF\x90", + "\xCA\xD9" => "\xE5\xBF\xAD", + "\xCA\xDA" => "\xE5\xBF\xA8", + "\xCA\xDB" => "\xE5\xBF\xAE", + "\xCA\xDC" => "\xE5\xBF\xB3", + "\xCA\xDD" => "\xE5\xBF\xA1", + "\xCA\xDE" => "\xE5\xBF\xA4", + "\xCA\xDF" => "\xE5\xBF\xA3", + "\xCA\xE0" => "\xE5\xBF\xBA", + "\xCA\xE1" => "\xE5\xBF\xAF", + "\xCA\xE2" => "\xE5\xBF\xB7", + "\xCA\xE3" => "\xE5\xBF\xBB", + "\xCA\xE4" => "\xE6\x80\x80", + "\xCA\xE5" => "\xE5\xBF\xB4", + "\xCA\xE6" => "\xE6\x88\xBA", + "\xCA\xE7" => "\xE6\x8A\x83", + "\xCA\xE8" => "\xE6\x8A\x8C", + "\xCA\xE9" => "\xE6\x8A\x8E", + "\xCA\xEA" => "\xE6\x8A\x8F", + "\xCA\xEB" => "\xE6\x8A\x94", + "\xCA\xEC" => "\xE6\x8A\x87", + "\xCA\xED" => "\xE6\x89\xB1", + "\xCA\xEE" => "\xE6\x89\xBB", + "\xCA\xEF" => "\xE6\x89\xBA", + "\xCA\xF0" => "\xE6\x89\xB0", + "\xCA\xF1" => "\xE6\x8A\x81", + "\xCA\xF2" => "\xE6\x8A\x88", + "\xCA\xF3" => "\xE6\x89\xB7", + "\xCA\xF4" => "\xE6\x89\xBD", + "\xCA\xF5" => "\xE6\x89\xB2", + "\xCA\xF6" => "\xE6\x89\xB4", + "\xCA\xF7" => "\xE6\x94\xB7", + "\xCA\xF8" => "\xE6\x97\xB0", + "\xCA\xF9" => "\xE6\x97\xB4", + "\xCA\xFA" => "\xE6\x97\xB3", + "\xCA\xFB" => "\xE6\x97\xB2", + "\xCA\xFC" => "\xE6\x97\xB5", + "\xCA\xFD" => "\xE6\x9D\x85", + "\xCA\xFE" => "\xE6\x9D\x87", + "\xCB\x40" => "\xE6\x9D\x99", + "\xCB\x41" => "\xE6\x9D\x95", + "\xCB\x42" => "\xE6\x9D\x8C", + "\xCB\x43" => "\xE6\x9D\x88", + "\xCB\x44" => "\xE6\x9D\x9D", + "\xCB\x45" => "\xE6\x9D\x8D", + "\xCB\x46" => "\xE6\x9D\x9A", + "\xCB\x47" => "\xE6\x9D\x8B", + "\xCB\x48" => "\xE6\xAF\x90", + "\xCB\x49" => "\xE6\xB0\x99", + "\xCB\x4A" => "\xE6\xB0\x9A", + "\xCB\x4B" => "\xE6\xB1\xB8", + "\xCB\x4C" => "\xE6\xB1\xA7", + "\xCB\x4D" => "\xE6\xB1\xAB", + "\xCB\x4E" => "\xE6\xB2\x84", + "\xCB\x4F" => "\xE6\xB2\x8B", + "\xCB\x50" => "\xE6\xB2\x8F", + "\xCB\x51" => "\xE6\xB1\xB1", + "\xCB\x52" => "\xE6\xB1\xAF", + "\xCB\x53" => "\xE6\xB1\xA9", + "\xCB\x54" => "\xE6\xB2\x9A", + "\xCB\x55" => "\xE6\xB1\xAD", + "\xCB\x56" => "\xE6\xB2\x87", + "\xCB\x57" => "\xE6\xB2\x95", + "\xCB\x58" => "\xE6\xB2\x9C", + "\xCB\x59" => "\xE6\xB1\xA6", + "\xCB\x5A" => "\xE6\xB1\xB3", + "\xCB\x5B" => "\xE6\xB1\xA5", + "\xCB\x5C" => "\xE6\xB1\xBB", + "\xCB\x5D" => "\xE6\xB2\x8E", + "\xCB\x5E" => "\xE7\x81\xB4", + "\xCB\x5F" => "\xE7\x81\xBA", + "\xCB\x60" => "\xE7\x89\xA3", + "\xCB\x61" => "\xE7\x8A\xBF", + "\xCB\x62" => "\xE7\x8A\xBD", + "\xCB\x63" => "\xE7\x8B\x83", + "\xCB\x64" => "\xE7\x8B\x86", + "\xCB\x65" => "\xE7\x8B\x81", + "\xCB\x66" => "\xE7\x8A\xBA", + "\xCB\x67" => "\xE7\x8B\x85", + "\xCB\x68" => "\xE7\x8E\x95", + "\xCB\x69" => "\xE7\x8E\x97", + "\xCB\x6A" => "\xE7\x8E\x93", + "\xCB\x6B" => "\xE7\x8E\x94", + "\xCB\x6C" => "\xE7\x8E\x92", + "\xCB\x6D" => "\xE7\x94\xBA", + "\xCB\x6E" => "\xE7\x94\xB9", + "\xCB\x6F" => "\xE7\x96\x94", + "\xCB\x70" => "\xE7\x96\x95", + "\xCB\x71" => "\xE7\x9A\x81", + "\xCB\x72" => "\xE7\xA4\xBD", + "\xCB\x73" => "\xE8\x80\xB4", + "\xCB\x74" => "\xE8\x82\x95", + "\xCB\x75" => "\xE8\x82\x99", + "\xCB\x76" => "\xE8\x82\x90", + "\xCB\x77" => "\xE8\x82\x92", + "\xCB\x78" => "\xE8\x82\x9C", + "\xCB\x79" => "\xE8\x8A\x90", + "\xCB\x7A" => "\xE8\x8A\x8F", + "\xCB\x7B" => "\xE8\x8A\x85", + "\xCB\x7C" => "\xE8\x8A\x8E", + "\xCB\x7D" => "\xE8\x8A\x91", + "\xCB\x7E" => "\xE8\x8A\x93", + "\xCB\xA1" => "\xE8\x8A\x8A", + "\xCB\xA2" => "\xE8\x8A\x83", + "\xCB\xA3" => "\xE8\x8A\x84", + "\xCB\xA4" => "\xE8\xB1\xB8", + "\xCB\xA5" => "\xE8\xBF\x89", + "\xCB\xA6" => "\xE8\xBE\xBF", + "\xCB\xA7" => "\xE9\x82\x9F", + "\xCB\xA8" => "\xE9\x82\xA1", + "\xCB\xA9" => "\xE9\x82\xA5", + "\xCB\xAA" => "\xE9\x82\x9E", + "\xCB\xAB" => "\xE9\x82\xA7", + "\xCB\xAC" => "\xE9\x82\xA0", + "\xCB\xAD" => "\xE9\x98\xB0", + "\xCB\xAE" => "\xE9\x98\xA8", + "\xCB\xAF" => "\xE9\x98\xAF", + "\xCB\xB0" => "\xE9\x98\xAD", + "\xCB\xB1" => "\xE4\xB8\xB3", + "\xCB\xB2" => "\xE4\xBE\x98", + "\xCB\xB3" => "\xE4\xBD\xBC", + "\xCB\xB4" => "\xE4\xBE\x85", + "\xCB\xB5" => "\xE4\xBD\xBD", + "\xCB\xB6" => "\xE4\xBE\x80", + "\xCB\xB7" => "\xE4\xBE\x87", + "\xCB\xB8" => "\xE4\xBD\xB6", + "\xCB\xB9" => "\xE4\xBD\xB4", + "\xCB\xBA" => "\xE4\xBE\x89", + "\xCB\xBB" => "\xE4\xBE\x84", + "\xCB\xBC" => "\xE4\xBD\xB7", + "\xCB\xBD" => "\xE4\xBD\x8C", + "\xCB\xBE" => "\xE4\xBE\x97", + "\xCB\xBF" => "\xE4\xBD\xAA", + "\xCB\xC0" => "\xE4\xBE\x9A", + "\xCB\xC1" => "\xE4\xBD\xB9", + "\xCB\xC2" => "\xE4\xBE\x81", + "\xCB\xC3" => "\xE4\xBD\xB8", + "\xCB\xC4" => "\xE4\xBE\x90", + "\xCB\xC5" => "\xE4\xBE\x9C", + "\xCB\xC6" => "\xE4\xBE\x94", + "\xCB\xC7" => "\xE4\xBE\x9E", + "\xCB\xC8" => "\xE4\xBE\x92", + "\xCB\xC9" => "\xE4\xBE\x82", + "\xCB\xCA" => "\xE4\xBE\x95", + "\xCB\xCB" => "\xE4\xBD\xAB", + "\xCB\xCC" => "\xE4\xBD\xAE", + "\xCB\xCD" => "\xE5\x86\x9E", + "\xCB\xCE" => "\xE5\x86\xBC", + "\xCB\xCF" => "\xE5\x86\xBE", + "\xCB\xD0" => "\xE5\x88\xB5", + "\xCB\xD1" => "\xE5\x88\xB2", + "\xCB\xD2" => "\xE5\x88\xB3", + "\xCB\xD3" => "\xE5\x89\x86", + "\xCB\xD4" => "\xE5\x88\xB1", + "\xCB\xD5" => "\xE5\x8A\xBC", + "\xCB\xD6" => "\xE5\x8C\x8A", + "\xCB\xD7" => "\xE5\x8C\x8B", + "\xCB\xD8" => "\xE5\x8C\xBC", + "\xCB\xD9" => "\xE5\x8E\x92", + "\xCB\xDA" => "\xE5\x8E\x94", + "\xCB\xDB" => "\xE5\x92\x87", + "\xCB\xDC" => "\xE5\x91\xBF", + "\xCB\xDD" => "\xE5\x92\x81", + "\xCB\xDE" => "\xE5\x92\x91", + "\xCB\xDF" => "\xE5\x92\x82", + "\xCB\xE0" => "\xE5\x92\x88", + "\xCB\xE1" => "\xE5\x91\xAB", + "\xCB\xE2" => "\xE5\x91\xBA", + "\xCB\xE3" => "\xE5\x91\xBE", + "\xCB\xE4" => "\xE5\x91\xA5", + "\xCB\xE5" => "\xE5\x91\xAC", + "\xCB\xE6" => "\xE5\x91\xB4", + "\xCB\xE7" => "\xE5\x91\xA6", + "\xCB\xE8" => "\xE5\x92\x8D", + "\xCB\xE9" => "\xE5\x91\xAF", + "\xCB\xEA" => "\xE5\x91\xA1", + "\xCB\xEB" => "\xE5\x91\xA0", + "\xCB\xEC" => "\xE5\x92\x98", + "\xCB\xED" => "\xE5\x91\xA3", + "\xCB\xEE" => "\xE5\x91\xA7", + "\xCB\xEF" => "\xE5\x91\xA4", + "\xCB\xF0" => "\xE5\x9B\xB7", + "\xCB\xF1" => "\xE5\x9B\xB9", + "\xCB\xF2" => "\xE5\x9D\xAF", + "\xCB\xF3" => "\xE5\x9D\xB2", + "\xCB\xF4" => "\xE5\x9D\xAD", + "\xCB\xF5" => "\xE5\x9D\xAB", + "\xCB\xF6" => "\xE5\x9D\xB1", + "\xCB\xF7" => "\xE5\x9D\xB0", + "\xCB\xF8" => "\xE5\x9D\xB6", + "\xCB\xF9" => "\xE5\x9E\x80", + "\xCB\xFA" => "\xE5\x9D\xB5", + "\xCB\xFB" => "\xE5\x9D\xBB", + "\xCB\xFC" => "\xE5\x9D\xB3", + "\xCB\xFD" => "\xE5\x9D\xB4", + "\xCB\xFE" => "\xE5\x9D\xA2", + "\xCC\x40" => "\xE5\x9D\xA8", + "\xCC\x41" => "\xE5\x9D\xBD", + "\xCC\x42" => "\xE5\xA4\x8C", + "\xCC\x43" => "\xE5\xA5\x85", + "\xCC\x44" => "\xE5\xA6\xB5", + "\xCC\x45" => "\xE5\xA6\xBA", + "\xCC\x46" => "\xE5\xA7\x8F", + "\xCC\x47" => "\xE5\xA7\x8E", + "\xCC\x48" => "\xE5\xA6\xB2", + "\xCC\x49" => "\xE5\xA7\x8C", + "\xCC\x4A" => "\xE5\xA7\x81", + "\xCC\x4B" => "\xE5\xA6\xB6", + "\xCC\x4C" => "\xE5\xA6\xBC", + "\xCC\x4D" => "\xE5\xA7\x83", + "\xCC\x4E" => "\xE5\xA7\x96", + "\xCC\x4F" => "\xE5\xA6\xB1", + "\xCC\x50" => "\xE5\xA6\xBD", + "\xCC\x51" => "\xE5\xA7\x80", + "\xCC\x52" => "\xE5\xA7\x88", + "\xCC\x53" => "\xE5\xA6\xB4", + "\xCC\x54" => "\xE5\xA7\x87", + "\xCC\x55" => "\xE5\xAD\xA2", + "\xCC\x56" => "\xE5\xAD\xA5", + "\xCC\x57" => "\xE5\xAE\x93", + "\xCC\x58" => "\xE5\xAE\x95", + "\xCC\x59" => "\xE5\xB1\x84", + "\xCC\x5A" => "\xE5\xB1\x87", + "\xCC\x5B" => "\xE5\xB2\xAE", + "\xCC\x5C" => "\xE5\xB2\xA4", + "\xCC\x5D" => "\xE5\xB2\xA0", + "\xCC\x5E" => "\xE5\xB2\xB5", + "\xCC\x5F" => "\xE5\xB2\xAF", + "\xCC\x60" => "\xE5\xB2\xA8", + "\xCC\x61" => "\xE5\xB2\xAC", + "\xCC\x62" => "\xE5\xB2\x9F", + "\xCC\x63" => "\xE5\xB2\xA3", + "\xCC\x64" => "\xE5\xB2\xAD", + "\xCC\x65" => "\xE5\xB2\xA2", + "\xCC\x66" => "\xE5\xB2\xAA", + "\xCC\x67" => "\xE5\xB2\xA7", + "\xCC\x68" => "\xE5\xB2\x9D", + "\xCC\x69" => "\xE5\xB2\xA5", + "\xCC\x6A" => "\xE5\xB2\xB6", + "\xCC\x6B" => "\xE5\xB2\xB0", + "\xCC\x6C" => "\xE5\xB2\xA6", + "\xCC\x6D" => "\xE5\xB8\x97", + "\xCC\x6E" => "\xE5\xB8\x94", + "\xCC\x6F" => "\xE5\xB8\x99", + "\xCC\x70" => "\xE5\xBC\xA8", + "\xCC\x71" => "\xE5\xBC\xA2", + "\xCC\x72" => "\xE5\xBC\xA3", + "\xCC\x73" => "\xE5\xBC\xA4", + "\xCC\x74" => "\xE5\xBD\x94", + "\xCC\x75" => "\xE5\xBE\x82", + "\xCC\x76" => "\xE5\xBD\xBE", + "\xCC\x77" => "\xE5\xBD\xBD", + "\xCC\x78" => "\xE5\xBF\x9E", + "\xCC\x79" => "\xE5\xBF\xA5", + "\xCC\x7A" => "\xE6\x80\xAD", + "\xCC\x7B" => "\xE6\x80\xA6", + "\xCC\x7C" => "\xE6\x80\x99", + "\xCC\x7D" => "\xE6\x80\xB2", + "\xCC\x7E" => "\xE6\x80\x8B", + "\xCC\xA1" => "\xE6\x80\xB4", + "\xCC\xA2" => "\xE6\x80\x8A", + "\xCC\xA3" => "\xE6\x80\x97", + "\xCC\xA4" => "\xE6\x80\xB3", + "\xCC\xA5" => "\xE6\x80\x9A", + "\xCC\xA6" => "\xE6\x80\x9E", + "\xCC\xA7" => "\xE6\x80\xAC", + "\xCC\xA8" => "\xE6\x80\xA2", + "\xCC\xA9" => "\xE6\x80\x8D", + "\xCC\xAA" => "\xE6\x80\x90", + "\xCC\xAB" => "\xE6\x80\xAE", + "\xCC\xAC" => "\xE6\x80\x93", + "\xCC\xAD" => "\xE6\x80\x91", + "\xCC\xAE" => "\xE6\x80\x8C", + "\xCC\xAF" => "\xE6\x80\x89", + "\xCC\xB0" => "\xE6\x80\x9C", + "\xCC\xB1" => "\xE6\x88\x94", + "\xCC\xB2" => "\xE6\x88\xBD", + "\xCC\xB3" => "\xE6\x8A\xAD", + "\xCC\xB4" => "\xE6\x8A\xB4", + "\xCC\xB5" => "\xE6\x8B\x91", + "\xCC\xB6" => "\xE6\x8A\xBE", + "\xCC\xB7" => "\xE6\x8A\xAA", + "\xCC\xB8" => "\xE6\x8A\xB6", + "\xCC\xB9" => "\xE6\x8B\x8A", + "\xCC\xBA" => "\xE6\x8A\xAE", + "\xCC\xBB" => "\xE6\x8A\xB3", + "\xCC\xBC" => "\xE6\x8A\xAF", + "\xCC\xBD" => "\xE6\x8A\xBB", + "\xCC\xBE" => "\xE6\x8A\xA9", + "\xCC\xBF" => "\xE6\x8A\xB0", + "\xCC\xC0" => "\xE6\x8A\xB8", + "\xCC\xC1" => "\xE6\x94\xBD", + "\xCC\xC2" => "\xE6\x96\xA8", + "\xCC\xC3" => "\xE6\x96\xBB", + "\xCC\xC4" => "\xE6\x98\x89", + "\xCC\xC5" => "\xE6\x97\xBC", + "\xCC\xC6" => "\xE6\x98\x84", + "\xCC\xC7" => "\xE6\x98\x92", + "\xCC\xC8" => "\xE6\x98\x88", + "\xCC\xC9" => "\xE6\x97\xBB", + "\xCC\xCA" => "\xE6\x98\x83", + "\xCC\xCB" => "\xE6\x98\x8B", + "\xCC\xCC" => "\xE6\x98\x8D", + "\xCC\xCD" => "\xE6\x98\x85", + "\xCC\xCE" => "\xE6\x97\xBD", + "\xCC\xCF" => "\xE6\x98\x91", + "\xCC\xD0" => "\xE6\x98\x90", + "\xCC\xD1" => "\xE6\x9B\xB6", + "\xCC\xD2" => "\xE6\x9C\x8A", + "\xCC\xD3" => "\xE6\x9E\x85", + "\xCC\xD4" => "\xE6\x9D\xAC", + "\xCC\xD5" => "\xE6\x9E\x8E", + "\xCC\xD6" => "\xE6\x9E\x92", + "\xCC\xD7" => "\xE6\x9D\xB6", + "\xCC\xD8" => "\xE6\x9D\xBB", + "\xCC\xD9" => "\xE6\x9E\x98", + "\xCC\xDA" => "\xE6\x9E\x86", + "\xCC\xDB" => "\xE6\x9E\x84", + "\xCC\xDC" => "\xE6\x9D\xB4", + "\xCC\xDD" => "\xE6\x9E\x8D", + "\xCC\xDE" => "\xE6\x9E\x8C", + "\xCC\xDF" => "\xE6\x9D\xBA", + "\xCC\xE0" => "\xE6\x9E\x9F", + "\xCC\xE1" => "\xE6\x9E\x91", + "\xCC\xE2" => "\xE6\x9E\x99", + "\xCC\xE3" => "\xE6\x9E\x83", + "\xCC\xE4" => "\xE6\x9D\xBD", + "\xCC\xE5" => "\xE6\x9E\x81", + "\xCC\xE6" => "\xE6\x9D\xB8", + "\xCC\xE7" => "\xE6\x9D\xB9", + "\xCC\xE8" => "\xE6\x9E\x94", + "\xCC\xE9" => "\xE6\xAC\xA5", + "\xCC\xEA" => "\xE6\xAE\x80", + "\xCC\xEB" => "\xE6\xAD\xBE", + "\xCC\xEC" => "\xE6\xAF\x9E", + "\xCC\xED" => "\xE6\xB0\x9D", + "\xCC\xEE" => "\xE6\xB2\x93", + "\xCC\xEF" => "\xE6\xB3\xAC", + "\xCC\xF0" => "\xE6\xB3\xAB", + "\xCC\xF1" => "\xE6\xB3\xAE", + "\xCC\xF2" => "\xE6\xB3\x99", + "\xCC\xF3" => "\xE6\xB2\xB6", + "\xCC\xF4" => "\xE6\xB3\x94", + "\xCC\xF5" => "\xE6\xB2\xAD", + "\xCC\xF6" => "\xE6\xB3\xA7", + "\xCC\xF7" => "\xE6\xB2\xB7", + "\xCC\xF8" => "\xE6\xB3\x90", + "\xCC\xF9" => "\xE6\xB3\x82", + "\xCC\xFA" => "\xE6\xB2\xBA", + "\xCC\xFB" => "\xE6\xB3\x83", + "\xCC\xFC" => "\xE6\xB3\x86", + "\xCC\xFD" => "\xE6\xB3\xAD", + "\xCC\xFE" => "\xE6\xB3\xB2", + "\xCD\x40" => "\xE6\xB3\x92", + "\xCD\x41" => "\xE6\xB3\x9D", + "\xCD\x42" => "\xE6\xB2\xB4", + "\xCD\x43" => "\xE6\xB2\x8A", + "\xCD\x44" => "\xE6\xB2\x9D", + "\xCD\x45" => "\xE6\xB2\x80", + "\xCD\x46" => "\xE6\xB3\x9E", + "\xCD\x47" => "\xE6\xB3\x80", + "\xCD\x48" => "\xE6\xB4\xB0", + "\xCD\x49" => "\xE6\xB3\x8D", + "\xCD\x4A" => "\xE6\xB3\x87", + "\xCD\x4B" => "\xE6\xB2\xB0", + "\xCD\x4C" => "\xE6\xB3\xB9", + "\xCD\x4D" => "\xE6\xB3\x8F", + "\xCD\x4E" => "\xE6\xB3\xA9", + "\xCD\x4F" => "\xE6\xB3\x91", + "\xCD\x50" => "\xE7\x82\x94", + "\xCD\x51" => "\xE7\x82\x98", + "\xCD\x52" => "\xE7\x82\x85", + "\xCD\x53" => "\xE7\x82\x93", + "\xCD\x54" => "\xE7\x82\x86", + "\xCD\x55" => "\xE7\x82\x84", + "\xCD\x56" => "\xE7\x82\x91", + "\xCD\x57" => "\xE7\x82\x96", + "\xCD\x58" => "\xE7\x82\x82", + "\xCD\x59" => "\xE7\x82\x9A", + "\xCD\x5A" => "\xE7\x82\x83", + "\xCD\x5B" => "\xE7\x89\xAA", + "\xCD\x5C" => "\xE7\x8B\x96", + "\xCD\x5D" => "\xE7\x8B\x8B", + "\xCD\x5E" => "\xE7\x8B\x98", + "\xCD\x5F" => "\xE7\x8B\x89", + "\xCD\x60" => "\xE7\x8B\x9C", + "\xCD\x61" => "\xE7\x8B\x92", + "\xCD\x62" => "\xE7\x8B\x94", + "\xCD\x63" => "\xE7\x8B\x9A", + "\xCD\x64" => "\xE7\x8B\x8C", + "\xCD\x65" => "\xE7\x8B\x91", + "\xCD\x66" => "\xE7\x8E\xA4", + "\xCD\x67" => "\xE7\x8E\xA1", + "\xCD\x68" => "\xE7\x8E\xAD", + "\xCD\x69" => "\xE7\x8E\xA6", + "\xCD\x6A" => "\xE7\x8E\xA2", + "\xCD\x6B" => "\xE7\x8E\xA0", + "\xCD\x6C" => "\xE7\x8E\xAC", + "\xCD\x6D" => "\xE7\x8E\x9D", + "\xCD\x6E" => "\xE7\x93\x9D", + "\xCD\x6F" => "\xE7\x93\xA8", + "\xCD\x70" => "\xE7\x94\xBF", + "\xCD\x71" => "\xE7\x95\x80", + "\xCD\x72" => "\xE7\x94\xBE", + "\xCD\x73" => "\xE7\x96\x8C", + "\xCD\x74" => "\xE7\x96\x98", + "\xCD\x75" => "\xE7\x9A\xAF", + "\xCD\x76" => "\xE7\x9B\xB3", + "\xCD\x77" => "\xE7\x9B\xB1", + "\xCD\x78" => "\xE7\x9B\xB0", + "\xCD\x79" => "\xE7\x9B\xB5", + "\xCD\x7A" => "\xE7\x9F\xB8", + "\xCD\x7B" => "\xE7\x9F\xBC", + "\xCD\x7C" => "\xE7\x9F\xB9", + "\xCD\x7D" => "\xE7\x9F\xBB", + "\xCD\x7E" => "\xE7\x9F\xBA", + "\xCD\xA1" => "\xE7\x9F\xB7", + "\xCD\xA2" => "\xE7\xA5\x82", + "\xCD\xA3" => "\xE7\xA4\xBF", + "\xCD\xA4" => "\xE7\xA7\x85", + "\xCD\xA5" => "\xE7\xA9\xB8", + "\xCD\xA6" => "\xE7\xA9\xBB", + "\xCD\xA7" => "\xE7\xAB\xBB", + "\xCD\xA8" => "\xE7\xB1\xB5", + "\xCD\xA9" => "\xE7\xB3\xBD", + "\xCD\xAA" => "\xE8\x80\xB5", + "\xCD\xAB" => "\xE8\x82\x8F", + "\xCD\xAC" => "\xE8\x82\xAE", + "\xCD\xAD" => "\xE8\x82\xA3", + "\xCD\xAE" => "\xE8\x82\xB8", + "\xCD\xAF" => "\xE8\x82\xB5", + "\xCD\xB0" => "\xE8\x82\xAD", + "\xCD\xB1" => "\xE8\x88\xA0", + "\xCD\xB2" => "\xE8\x8A\xA0", + "\xCD\xB3" => "\xE8\x8B\x80", + "\xCD\xB4" => "\xE8\x8A\xAB", + "\xCD\xB5" => "\xE8\x8A\x9A", + "\xCD\xB6" => "\xE8\x8A\x98", + "\xCD\xB7" => "\xE8\x8A\x9B", + "\xCD\xB8" => "\xE8\x8A\xB5", + "\xCD\xB9" => "\xE8\x8A\xA7", + "\xCD\xBA" => "\xE8\x8A\xAE", + "\xCD\xBB" => "\xE8\x8A\xBC", + "\xCD\xBC" => "\xE8\x8A\x9E", + "\xCD\xBD" => "\xE8\x8A\xBA", + "\xCD\xBE" => "\xE8\x8A\xB4", + "\xCD\xBF" => "\xE8\x8A\xA8", + "\xCD\xC0" => "\xE8\x8A\xA1", + "\xCD\xC1" => "\xE8\x8A\xA9", + "\xCD\xC2" => "\xE8\x8B\x82", + "\xCD\xC3" => "\xE8\x8A\xA4", + "\xCD\xC4" => "\xE8\x8B\x83", + "\xCD\xC5" => "\xE8\x8A\xB6", + "\xCD\xC6" => "\xE8\x8A\xA2", + "\xCD\xC7" => "\xE8\x99\xB0", + "\xCD\xC8" => "\xE8\x99\xAF", + "\xCD\xC9" => "\xE8\x99\xAD", + "\xCD\xCA" => "\xE8\x99\xAE", + "\xCD\xCB" => "\xE8\xB1\x96", + "\xCD\xCC" => "\xE8\xBF\x92", + "\xCD\xCD" => "\xE8\xBF\x8B", + "\xCD\xCE" => "\xE8\xBF\x93", + "\xCD\xCF" => "\xE8\xBF\x8D", + "\xCD\xD0" => "\xE8\xBF\x96", + "\xCD\xD1" => "\xE8\xBF\x95", + "\xCD\xD2" => "\xE8\xBF\x97", + "\xCD\xD3" => "\xE9\x82\xB2", + "\xCD\xD4" => "\xE9\x82\xB4", + "\xCD\xD5" => "\xE9\x82\xAF", + "\xCD\xD6" => "\xE9\x82\xB3", + "\xCD\xD7" => "\xE9\x82\xB0", + "\xCD\xD8" => "\xE9\x98\xB9", + "\xCD\xD9" => "\xE9\x98\xBD", + "\xCD\xDA" => "\xE9\x98\xBC", + "\xCD\xDB" => "\xE9\x98\xBA", + "\xCD\xDC" => "\xE9\x99\x83", + "\xCD\xDD" => "\xE4\xBF\x8D", + "\xCD\xDE" => "\xE4\xBF\x85", + "\xCD\xDF" => "\xE4\xBF\x93", + "\xCD\xE0" => "\xE4\xBE\xB2", + "\xCD\xE1" => "\xE4\xBF\x89", + "\xCD\xE2" => "\xE4\xBF\x8B", + "\xCD\xE3" => "\xE4\xBF\x81", + "\xCD\xE4" => "\xE4\xBF\x94", + "\xCD\xE5" => "\xE4\xBF\x9C", + "\xCD\xE6" => "\xE4\xBF\x99", + "\xCD\xE7" => "\xE4\xBE\xBB", + "\xCD\xE8" => "\xE4\xBE\xB3", + "\xCD\xE9" => "\xE4\xBF\x9B", + "\xCD\xEA" => "\xE4\xBF\x87", + "\xCD\xEB" => "\xE4\xBF\x96", + "\xCD\xEC" => "\xE4\xBE\xBA", + "\xCD\xED" => "\xE4\xBF\x80", + "\xCD\xEE" => "\xE4\xBE\xB9", + "\xCD\xEF" => "\xE4\xBF\xAC", + "\xCD\xF0" => "\xE5\x89\x84", + "\xCD\xF1" => "\xE5\x89\x89", + "\xCD\xF2" => "\xE5\x8B\x80", + "\xCD\xF3" => "\xE5\x8B\x82", + "\xCD\xF4" => "\xE5\x8C\xBD", + "\xCD\xF5" => "\xE5\x8D\xBC", + "\xCD\xF6" => "\xE5\x8E\x97", + "\xCD\xF7" => "\xE5\x8E\x96", + "\xCD\xF8" => "\xE5\x8E\x99", + "\xCD\xF9" => "\xE5\x8E\x98", + "\xCD\xFA" => "\xE5\x92\xBA", + "\xCD\xFB" => "\xE5\x92\xA1", + "\xCD\xFC" => "\xE5\x92\xAD", + "\xCD\xFD" => "\xE5\x92\xA5", + "\xCD\xFE" => "\xE5\x93\x8F", + "\xCE\x40" => "\xE5\x93\x83", + "\xCE\x41" => "\xE8\x8C\x8D", + "\xCE\x42" => "\xE5\x92\xB7", + "\xCE\x43" => "\xE5\x92\xAE", + "\xCE\x44" => "\xE5\x93\x96", + "\xCE\x45" => "\xE5\x92\xB6", + "\xCE\x46" => "\xE5\x93\x85", + "\xCE\x47" => "\xE5\x93\x86", + "\xCE\x48" => "\xE5\x92\xA0", + "\xCE\x49" => "\xE5\x91\xB0", + "\xCE\x4A" => "\xE5\x92\xBC", + "\xCE\x4B" => "\xE5\x92\xA2", + "\xCE\x4C" => "\xE5\x92\xBE", + "\xCE\x4D" => "\xE5\x91\xB2", + "\xCE\x4E" => "\xE5\x93\x9E", + "\xCE\x4F" => "\xE5\x92\xB0", + "\xCE\x50" => "\xE5\x9E\xB5", + "\xCE\x51" => "\xE5\x9E\x9E", + "\xCE\x52" => "\xE5\x9E\x9F", + "\xCE\x53" => "\xE5\x9E\xA4", + "\xCE\x54" => "\xE5\x9E\x8C", + "\xCE\x55" => "\xE5\x9E\x97", + "\xCE\x56" => "\xE5\x9E\x9D", + "\xCE\x57" => "\xE5\x9E\x9B", + "\xCE\x58" => "\xE5\x9E\x94", + "\xCE\x59" => "\xE5\x9E\x98", + "\xCE\x5A" => "\xE5\x9E\x8F", + "\xCE\x5B" => "\xE5\x9E\x99", + "\xCE\x5C" => "\xE5\x9E\xA5", + "\xCE\x5D" => "\xE5\x9E\x9A", + "\xCE\x5E" => "\xE5\x9E\x95", + "\xCE\x5F" => "\xE5\xA3\xB4", + "\xCE\x60" => "\xE5\xA4\x8D", + "\xCE\x61" => "\xE5\xA5\x93", + "\xCE\x62" => "\xE5\xA7\xA1", + "\xCE\x63" => "\xE5\xA7\x9E", + "\xCE\x64" => "\xE5\xA7\xAE", + "\xCE\x65" => "\xE5\xA8\x80", + "\xCE\x66" => "\xE5\xA7\xB1", + "\xCE\x67" => "\xE5\xA7\x9D", + "\xCE\x68" => "\xE5\xA7\xBA", + "\xCE\x69" => "\xE5\xA7\xBD", + "\xCE\x6A" => "\xE5\xA7\xBC", + "\xCE\x6B" => "\xE5\xA7\xB6", + "\xCE\x6C" => "\xE5\xA7\xA4", + "\xCE\x6D" => "\xE5\xA7\xB2", + "\xCE\x6E" => "\xE5\xA7\xB7", + "\xCE\x6F" => "\xE5\xA7\x9B", + "\xCE\x70" => "\xE5\xA7\xA9", + "\xCE\x71" => "\xE5\xA7\xB3", + "\xCE\x72" => "\xE5\xA7\xB5", + "\xCE\x73" => "\xE5\xA7\xA0", + "\xCE\x74" => "\xE5\xA7\xBE", + "\xCE\x75" => "\xE5\xA7\xB4", + "\xCE\x76" => "\xE5\xA7\xAD", + "\xCE\x77" => "\xE5\xAE\xA8", + "\xCE\x78" => "\xE5\xB1\x8C", + "\xCE\x79" => "\xE5\xB3\x90", + "\xCE\x7A" => "\xE5\xB3\x98", + "\xCE\x7B" => "\xE5\xB3\x8C", + "\xCE\x7C" => "\xE5\xB3\x97", + "\xCE\x7D" => "\xE5\xB3\x8B", + "\xCE\x7E" => "\xE5\xB3\x9B", + "\xCE\xA1" => "\xE5\xB3\x9E", + "\xCE\xA2" => "\xE5\xB3\x9A", + "\xCE\xA3" => "\xE5\xB3\x89", + "\xCE\xA4" => "\xE5\xB3\x87", + "\xCE\xA5" => "\xE5\xB3\x8A", + "\xCE\xA6" => "\xE5\xB3\x96", + "\xCE\xA7" => "\xE5\xB3\x93", + "\xCE\xA8" => "\xE5\xB3\x94", + "\xCE\xA9" => "\xE5\xB3\x8F", + "\xCE\xAA" => "\xE5\xB3\x88", + "\xCE\xAB" => "\xE5\xB3\x86", + "\xCE\xAC" => "\xE5\xB3\x8E", + "\xCE\xAD" => "\xE5\xB3\x9F", + "\xCE\xAE" => "\xE5\xB3\xB8", + "\xCE\xAF" => "\xE5\xB7\xB9", + "\xCE\xB0" => "\xE5\xB8\xA1", + "\xCE\xB1" => "\xE5\xB8\xA2", + "\xCE\xB2" => "\xE5\xB8\xA3", + "\xCE\xB3" => "\xE5\xB8\xA0", + "\xCE\xB4" => "\xE5\xB8\xA4", + "\xCE\xB5" => "\xE5\xBA\xB0", + "\xCE\xB6" => "\xE5\xBA\xA4", + "\xCE\xB7" => "\xE5\xBA\xA2", + "\xCE\xB8" => "\xE5\xBA\x9B", + "\xCE\xB9" => "\xE5\xBA\xA3", + "\xCE\xBA" => "\xE5\xBA\xA5", + "\xCE\xBB" => "\xE5\xBC\x87", + "\xCE\xBC" => "\xE5\xBC\xAE", + "\xCE\xBD" => "\xE5\xBD\x96", + "\xCE\xBE" => "\xE5\xBE\x86", + "\xCE\xBF" => "\xE6\x80\xB7", + "\xCE\xC0" => "\xE6\x80\xB9", + "\xCE\xC1" => "\xE6\x81\x94", + "\xCE\xC2" => "\xE6\x81\xB2", + "\xCE\xC3" => "\xE6\x81\x9E", + "\xCE\xC4" => "\xE6\x81\x85", + "\xCE\xC5" => "\xE6\x81\x93", + "\xCE\xC6" => "\xE6\x81\x87", + "\xCE\xC7" => "\xE6\x81\x89", + "\xCE\xC8" => "\xE6\x81\x9B", + "\xCE\xC9" => "\xE6\x81\x8C", + "\xCE\xCA" => "\xE6\x81\x80", + "\xCE\xCB" => "\xE6\x81\x82", + "\xCE\xCC" => "\xE6\x81\x9F", + "\xCE\xCD" => "\xE6\x80\xA4", + "\xCE\xCE" => "\xE6\x81\x84", + "\xCE\xCF" => "\xE6\x81\x98", + "\xCE\xD0" => "\xE6\x81\xA6", + "\xCE\xD1" => "\xE6\x81\xAE", + "\xCE\xD2" => "\xE6\x89\x82", + "\xCE\xD3" => "\xE6\x89\x83", + "\xCE\xD4" => "\xE6\x8B\x8F", + "\xCE\xD5" => "\xE6\x8C\x8D", + "\xCE\xD6" => "\xE6\x8C\x8B", + "\xCE\xD7" => "\xE6\x8B\xB5", + "\xCE\xD8" => "\xE6\x8C\x8E", + "\xCE\xD9" => "\xE6\x8C\x83", + "\xCE\xDA" => "\xE6\x8B\xAB", + "\xCE\xDB" => "\xE6\x8B\xB9", + "\xCE\xDC" => "\xE6\x8C\x8F", + "\xCE\xDD" => "\xE6\x8C\x8C", + "\xCE\xDE" => "\xE6\x8B\xB8", + "\xCE\xDF" => "\xE6\x8B\xB6", + "\xCE\xE0" => "\xE6\x8C\x80", + "\xCE\xE1" => "\xE6\x8C\x93", + "\xCE\xE2" => "\xE6\x8C\x94", + "\xCE\xE3" => "\xE6\x8B\xBA", + "\xCE\xE4" => "\xE6\x8C\x95", + "\xCE\xE5" => "\xE6\x8B\xBB", + "\xCE\xE6" => "\xE6\x8B\xB0", + "\xCE\xE7" => "\xE6\x95\x81", + "\xCE\xE8" => "\xE6\x95\x83", + "\xCE\xE9" => "\xE6\x96\xAA", + "\xCE\xEA" => "\xE6\x96\xBF", + "\xCE\xEB" => "\xE6\x98\xB6", + "\xCE\xEC" => "\xE6\x98\xA1", + "\xCE\xED" => "\xE6\x98\xB2", + "\xCE\xEE" => "\xE6\x98\xB5", + "\xCE\xEF" => "\xE6\x98\x9C", + "\xCE\xF0" => "\xE6\x98\xA6", + "\xCE\xF1" => "\xE6\x98\xA2", + "\xCE\xF2" => "\xE6\x98\xB3", + "\xCE\xF3" => "\xE6\x98\xAB", + "\xCE\xF4" => "\xE6\x98\xBA", + "\xCE\xF5" => "\xE6\x98\x9D", + "\xCE\xF6" => "\xE6\x98\xB4", + "\xCE\xF7" => "\xE6\x98\xB9", + "\xCE\xF8" => "\xE6\x98\xAE", + "\xCE\xF9" => "\xE6\x9C\x8F", + "\xCE\xFA" => "\xE6\x9C\x90", + "\xCE\xFB" => "\xE6\x9F\x81", + "\xCE\xFC" => "\xE6\x9F\xB2", + "\xCE\xFD" => "\xE6\x9F\x88", + "\xCE\xFE" => "\xE6\x9E\xBA", + "\xCF\x40" => "\xE6\x9F\x9C", + "\xCF\x41" => "\xE6\x9E\xBB", + "\xCF\x42" => "\xE6\x9F\xB8", + "\xCF\x43" => "\xE6\x9F\x98", + "\xCF\x44" => "\xE6\x9F\x80", + "\xCF\x45" => "\xE6\x9E\xB7", + "\xCF\x46" => "\xE6\x9F\x85", + "\xCF\x47" => "\xE6\x9F\xAB", + "\xCF\x48" => "\xE6\x9F\xA4", + "\xCF\x49" => "\xE6\x9F\x9F", + "\xCF\x4A" => "\xE6\x9E\xB5", + "\xCF\x4B" => "\xE6\x9F\x8D", + "\xCF\x4C" => "\xE6\x9E\xB3", + "\xCF\x4D" => "\xE6\x9F\xB7", + "\xCF\x4E" => "\xE6\x9F\xB6", + "\xCF\x4F" => "\xE6\x9F\xAE", + "\xCF\x50" => "\xE6\x9F\xA3", + "\xCF\x51" => "\xE6\x9F\x82", + "\xCF\x52" => "\xE6\x9E\xB9", + "\xCF\x53" => "\xE6\x9F\x8E", + "\xCF\x54" => "\xE6\x9F\xA7", + "\xCF\x55" => "\xE6\x9F\xB0", + "\xCF\x56" => "\xE6\x9E\xB2", + "\xCF\x57" => "\xE6\x9F\xBC", + "\xCF\x58" => "\xE6\x9F\x86", + "\xCF\x59" => "\xE6\x9F\xAD", + "\xCF\x5A" => "\xE6\x9F\x8C", + "\xCF\x5B" => "\xE6\x9E\xAE", + "\xCF\x5C" => "\xE6\x9F\xA6", + "\xCF\x5D" => "\xE6\x9F\x9B", + "\xCF\x5E" => "\xE6\x9F\xBA", + "\xCF\x5F" => "\xE6\x9F\x89", + "\xCF\x60" => "\xE6\x9F\x8A", + "\xCF\x61" => "\xE6\x9F\x83", + "\xCF\x62" => "\xE6\x9F\xAA", + "\xCF\x63" => "\xE6\x9F\x8B", + "\xCF\x64" => "\xE6\xAC\xA8", + "\xCF\x65" => "\xE6\xAE\x82", + "\xCF\x66" => "\xE6\xAE\x84", + "\xCF\x67" => "\xE6\xAE\xB6", + "\xCF\x68" => "\xE6\xAF\x96", + "\xCF\x69" => "\xE6\xAF\x98", + "\xCF\x6A" => "\xE6\xAF\xA0", + "\xCF\x6B" => "\xE6\xB0\xA0", + "\xCF\x6C" => "\xE6\xB0\xA1", + "\xCF\x6D" => "\xE6\xB4\xA8", + "\xCF\x6E" => "\xE6\xB4\xB4", + "\xCF\x6F" => "\xE6\xB4\xAD", + "\xCF\x70" => "\xE6\xB4\x9F", + "\xCF\x71" => "\xE6\xB4\xBC", + "\xCF\x72" => "\xE6\xB4\xBF", + "\xCF\x73" => "\xE6\xB4\x92", + "\xCF\x74" => "\xE6\xB4\x8A", + "\xCF\x75" => "\xE6\xB3\x9A", + "\xCF\x76" => "\xE6\xB4\xB3", + "\xCF\x77" => "\xE6\xB4\x84", + "\xCF\x78" => "\xE6\xB4\x99", + "\xCF\x79" => "\xE6\xB4\xBA", + "\xCF\x7A" => "\xE6\xB4\x9A", + "\xCF\x7B" => "\xE6\xB4\x91", + "\xCF\x7C" => "\xE6\xB4\x80", + "\xCF\x7D" => "\xE6\xB4\x9D", + "\xCF\x7E" => "\xE6\xB5\x82", + "\xCF\xA1" => "\xE6\xB4\x81", + "\xCF\xA2" => "\xE6\xB4\x98", + "\xCF\xA3" => "\xE6\xB4\xB7", + "\xCF\xA4" => "\xE6\xB4\x83", + "\xCF\xA5" => "\xE6\xB4\x8F", + "\xCF\xA6" => "\xE6\xB5\x80", + "\xCF\xA7" => "\xE6\xB4\x87", + "\xCF\xA8" => "\xE6\xB4\xA0", + "\xCF\xA9" => "\xE6\xB4\xAC", + "\xCF\xAA" => "\xE6\xB4\x88", + "\xCF\xAB" => "\xE6\xB4\xA2", + "\xCF\xAC" => "\xE6\xB4\x89", + "\xCF\xAD" => "\xE6\xB4\x90", + "\xCF\xAE" => "\xE7\x82\xB7", + "\xCF\xAF" => "\xE7\x82\x9F", + "\xCF\xB0" => "\xE7\x82\xBE", + "\xCF\xB1" => "\xE7\x82\xB1", + "\xCF\xB2" => "\xE7\x82\xB0", + "\xCF\xB3" => "\xE7\x82\xA1", + "\xCF\xB4" => "\xE7\x82\xB4", + "\xCF\xB5" => "\xE7\x82\xB5", + "\xCF\xB6" => "\xE7\x82\xA9", + "\xCF\xB7" => "\xE7\x89\x81", + "\xCF\xB8" => "\xE7\x89\x89", + "\xCF\xB9" => "\xE7\x89\x8A", + "\xCF\xBA" => "\xE7\x89\xAC", + "\xCF\xBB" => "\xE7\x89\xB0", + "\xCF\xBC" => "\xE7\x89\xB3", + "\xCF\xBD" => "\xE7\x89\xAE", + "\xCF\xBE" => "\xE7\x8B\x8A", + "\xCF\xBF" => "\xE7\x8B\xA4", + "\xCF\xC0" => "\xE7\x8B\xA8", + "\xCF\xC1" => "\xE7\x8B\xAB", + "\xCF\xC2" => "\xE7\x8B\x9F", + "\xCF\xC3" => "\xE7\x8B\xAA", + "\xCF\xC4" => "\xE7\x8B\xA6", + "\xCF\xC5" => "\xE7\x8B\xA3", + "\xCF\xC6" => "\xE7\x8E\x85", + "\xCF\xC7" => "\xE7\x8F\x8C", + "\xCF\xC8" => "\xE7\x8F\x82", + "\xCF\xC9" => "\xE7\x8F\x88", + "\xCF\xCA" => "\xE7\x8F\x85", + "\xCF\xCB" => "\xE7\x8E\xB9", + "\xCF\xCC" => "\xE7\x8E\xB6", + "\xCF\xCD" => "\xE7\x8E\xB5", + "\xCF\xCE" => "\xE7\x8E\xB4", + "\xCF\xCF" => "\xE7\x8F\xAB", + "\xCF\xD0" => "\xE7\x8E\xBF", + "\xCF\xD1" => "\xE7\x8F\x87", + "\xCF\xD2" => "\xE7\x8E\xBE", + "\xCF\xD3" => "\xE7\x8F\x83", + "\xCF\xD4" => "\xE7\x8F\x86", + "\xCF\xD5" => "\xE7\x8E\xB8", + "\xCF\xD6" => "\xE7\x8F\x8B", + "\xCF\xD7" => "\xE7\x93\xAC", + "\xCF\xD8" => "\xE7\x93\xAE", + "\xCF\xD9" => "\xE7\x94\xAE", + "\xCF\xDA" => "\xE7\x95\x87", + "\xCF\xDB" => "\xE7\x95\x88", + "\xCF\xDC" => "\xE7\x96\xA7", + "\xCF\xDD" => "\xE7\x96\xAA", + "\xCF\xDE" => "\xE7\x99\xB9", + "\xCF\xDF" => "\xE7\x9B\x84", + "\xCF\xE0" => "\xE7\x9C\x88", + "\xCF\xE1" => "\xE7\x9C\x83", + "\xCF\xE2" => "\xE7\x9C\x84", + "\xCF\xE3" => "\xE7\x9C\x85", + "\xCF\xE4" => "\xE7\x9C\x8A", + "\xCF\xE5" => "\xE7\x9B\xB7", + "\xCF\xE6" => "\xE7\x9B\xBB", + "\xCF\xE7" => "\xE7\x9B\xBA", + "\xCF\xE8" => "\xE7\x9F\xA7", + "\xCF\xE9" => "\xE7\x9F\xA8", + "\xCF\xEA" => "\xE7\xA0\x86", + "\xCF\xEB" => "\xE7\xA0\x91", + "\xCF\xEC" => "\xE7\xA0\x92", + "\xCF\xED" => "\xE7\xA0\x85", + "\xCF\xEE" => "\xE7\xA0\x90", + "\xCF\xEF" => "\xE7\xA0\x8F", + "\xCF\xF0" => "\xE7\xA0\x8E", + "\xCF\xF1" => "\xE7\xA0\x89", + "\xCF\xF2" => "\xE7\xA0\x83", + "\xCF\xF3" => "\xE7\xA0\x93", + "\xCF\xF4" => "\xE7\xA5\x8A", + "\xCF\xF5" => "\xE7\xA5\x8C", + "\xCF\xF6" => "\xE7\xA5\x8B", + "\xCF\xF7" => "\xE7\xA5\x85", + "\xCF\xF8" => "\xE7\xA5\x84", + "\xCF\xF9" => "\xE7\xA7\x95", + "\xCF\xFA" => "\xE7\xA7\x8D", + "\xCF\xFB" => "\xE7\xA7\x8F", + "\xCF\xFC" => "\xE7\xA7\x96", + "\xCF\xFD" => "\xE7\xA7\x8E", + "\xCF\xFE" => "\xE7\xAA\x80", + "\xD0\x40" => "\xE7\xA9\xBE", + "\xD0\x41" => "\xE7\xAB\x91", + "\xD0\x42" => "\xE7\xAC\x80", + "\xD0\x43" => "\xE7\xAC\x81", + "\xD0\x44" => "\xE7\xB1\xBA", + "\xD0\x45" => "\xE7\xB1\xB8", + "\xD0\x46" => "\xE7\xB1\xB9", + "\xD0\x47" => "\xE7\xB1\xBF", + "\xD0\x48" => "\xE7\xB2\x80", + "\xD0\x49" => "\xE7\xB2\x81", + "\xD0\x4A" => "\xE7\xB4\x83", + "\xD0\x4B" => "\xE7\xB4\x88", + "\xD0\x4C" => "\xE7\xB4\x81", + "\xD0\x4D" => "\xE7\xBD\x98", + "\xD0\x4E" => "\xE7\xBE\x91", + "\xD0\x4F" => "\xE7\xBE\x8D", + "\xD0\x50" => "\xE7\xBE\xBE", + "\xD0\x51" => "\xE8\x80\x87", + "\xD0\x52" => "\xE8\x80\x8E", + "\xD0\x53" => "\xE8\x80\x8F", + "\xD0\x54" => "\xE8\x80\x94", + "\xD0\x55" => "\xE8\x80\xB7", + "\xD0\x56" => "\xE8\x83\x98", + "\xD0\x57" => "\xE8\x83\x87", + "\xD0\x58" => "\xE8\x83\xA0", + "\xD0\x59" => "\xE8\x83\x91", + "\xD0\x5A" => "\xE8\x83\x88", + "\xD0\x5B" => "\xE8\x83\x82", + "\xD0\x5C" => "\xE8\x83\x90", + "\xD0\x5D" => "\xE8\x83\x85", + "\xD0\x5E" => "\xE8\x83\xA3", + "\xD0\x5F" => "\xE8\x83\x99", + "\xD0\x60" => "\xE8\x83\x9C", + "\xD0\x61" => "\xE8\x83\x8A", + "\xD0\x62" => "\xE8\x83\x95", + "\xD0\x63" => "\xE8\x83\x89", + "\xD0\x64" => "\xE8\x83\x8F", + "\xD0\x65" => "\xE8\x83\x97", + "\xD0\x66" => "\xE8\x83\xA6", + "\xD0\x67" => "\xE8\x83\x8D", + "\xD0\x68" => "\xE8\x87\xBF", + "\xD0\x69" => "\xE8\x88\xA1", + "\xD0\x6A" => "\xE8\x8A\x94", + "\xD0\x6B" => "\xE8\x8B\x99", + "\xD0\x6C" => "\xE8\x8B\xBE", + "\xD0\x6D" => "\xE8\x8B\xB9", + "\xD0\x6E" => "\xE8\x8C\x87", + "\xD0\x6F" => "\xE8\x8B\xA8", + "\xD0\x70" => "\xE8\x8C\x80", + "\xD0\x71" => "\xE8\x8B\x95", + "\xD0\x72" => "\xE8\x8C\xBA", + "\xD0\x73" => "\xE8\x8B\xAB", + "\xD0\x74" => "\xE8\x8B\x96", + "\xD0\x75" => "\xE8\x8B\xB4", + "\xD0\x76" => "\xE8\x8B\xAC", + "\xD0\x77" => "\xE8\x8B\xA1", + "\xD0\x78" => "\xE8\x8B\xB2", + "\xD0\x79" => "\xE8\x8B\xB5", + "\xD0\x7A" => "\xE8\x8C\x8C", + "\xD0\x7B" => "\xE8\x8B\xBB", + "\xD0\x7C" => "\xE8\x8B\xB6", + "\xD0\x7D" => "\xE8\x8B\xB0", + "\xD0\x7E" => "\xE8\x8B\xAA", + "\xD0\xA1" => "\xE8\x8B\xA4", + "\xD0\xA2" => "\xE8\x8B\xA0", + "\xD0\xA3" => "\xE8\x8B\xBA", + "\xD0\xA4" => "\xE8\x8B\xB3", + "\xD0\xA5" => "\xE8\x8B\xAD", + "\xD0\xA6" => "\xE8\x99\xB7", + "\xD0\xA7" => "\xE8\x99\xB4", + "\xD0\xA8" => "\xE8\x99\xBC", + "\xD0\xA9" => "\xE8\x99\xB3", + "\xD0\xAA" => "\xE8\xA1\x81", + "\xD0\xAB" => "\xE8\xA1\x8E", + "\xD0\xAC" => "\xE8\xA1\xA7", + "\xD0\xAD" => "\xE8\xA1\xAA", + "\xD0\xAE" => "\xE8\xA1\xA9", + "\xD0\xAF" => "\xE8\xA7\x93", + "\xD0\xB0" => "\xE8\xA8\x84", + "\xD0\xB1" => "\xE8\xA8\x87", + "\xD0\xB2" => "\xE8\xB5\xB2", + "\xD0\xB3" => "\xE8\xBF\xA3", + "\xD0\xB4" => "\xE8\xBF\xA1", + "\xD0\xB5" => "\xE8\xBF\xAE", + "\xD0\xB6" => "\xE8\xBF\xA0", + "\xD0\xB7" => "\xE9\x83\xB1", + "\xD0\xB8" => "\xE9\x82\xBD", + "\xD0\xB9" => "\xE9\x82\xBF", + "\xD0\xBA" => "\xE9\x83\x95", + "\xD0\xBB" => "\xE9\x83\x85", + "\xD0\xBC" => "\xE9\x82\xBE", + "\xD0\xBD" => "\xE9\x83\x87", + "\xD0\xBE" => "\xE9\x83\x8B", + "\xD0\xBF" => "\xE9\x83\x88", + "\xD0\xC0" => "\xE9\x87\x94", + "\xD0\xC1" => "\xE9\x87\x93", + "\xD0\xC2" => "\xE9\x99\x94", + "\xD0\xC3" => "\xE9\x99\x8F", + "\xD0\xC4" => "\xE9\x99\x91", + "\xD0\xC5" => "\xE9\x99\x93", + "\xD0\xC6" => "\xE9\x99\x8A", + "\xD0\xC7" => "\xE9\x99\x8E", + "\xD0\xC8" => "\xE5\x80\x9E", + "\xD0\xC9" => "\xE5\x80\x85", + "\xD0\xCA" => "\xE5\x80\x87", + "\xD0\xCB" => "\xE5\x80\x93", + "\xD0\xCC" => "\xE5\x80\xA2", + "\xD0\xCD" => "\xE5\x80\xB0", + "\xD0\xCE" => "\xE5\x80\x9B", + "\xD0\xCF" => "\xE4\xBF\xB5", + "\xD0\xD0" => "\xE4\xBF\xB4", + "\xD0\xD1" => "\xE5\x80\xB3", + "\xD0\xD2" => "\xE5\x80\xB7", + "\xD0\xD3" => "\xE5\x80\xAC", + "\xD0\xD4" => "\xE4\xBF\xB6", + "\xD0\xD5" => "\xE4\xBF\xB7", + "\xD0\xD6" => "\xE5\x80\x97", + "\xD0\xD7" => "\xE5\x80\x9C", + "\xD0\xD8" => "\xE5\x80\xA0", + "\xD0\xD9" => "\xE5\x80\xA7", + "\xD0\xDA" => "\xE5\x80\xB5", + "\xD0\xDB" => "\xE5\x80\xAF", + "\xD0\xDC" => "\xE5\x80\xB1", + "\xD0\xDD" => "\xE5\x80\x8E", + "\xD0\xDE" => "\xE5\x85\x9A", + "\xD0\xDF" => "\xE5\x86\x94", + "\xD0\xE0" => "\xE5\x86\x93", + "\xD0\xE1" => "\xE5\x87\x8A", + "\xD0\xE2" => "\xE5\x87\x84", + "\xD0\xE3" => "\xE5\x87\x85", + "\xD0\xE4" => "\xE5\x87\x88", + "\xD0\xE5" => "\xE5\x87\x8E", + "\xD0\xE6" => "\xE5\x89\xA1", + "\xD0\xE7" => "\xE5\x89\x9A", + "\xD0\xE8" => "\xE5\x89\x92", + "\xD0\xE9" => "\xE5\x89\x9E", + "\xD0\xEA" => "\xE5\x89\x9F", + "\xD0\xEB" => "\xE5\x89\x95", + "\xD0\xEC" => "\xE5\x89\xA2", + "\xD0\xED" => "\xE5\x8B\x8D", + "\xD0\xEE" => "\xE5\x8C\x8E", + "\xD0\xEF" => "\xE5\x8E\x9E", + "\xD0\xF0" => "\xE5\x94\xA6", + "\xD0\xF1" => "\xE5\x93\xA2", + "\xD0\xF2" => "\xE5\x94\x97", + "\xD0\xF3" => "\xE5\x94\x92", + "\xD0\xF4" => "\xE5\x93\xA7", + "\xD0\xF5" => "\xE5\x93\xB3", + "\xD0\xF6" => "\xE5\x93\xA4", + "\xD0\xF7" => "\xE5\x94\x9A", + "\xD0\xF8" => "\xE5\x93\xBF", + "\xD0\xF9" => "\xE5\x94\x84", + "\xD0\xFA" => "\xE5\x94\x88", + "\xD0\xFB" => "\xE5\x93\xAB", + "\xD0\xFC" => "\xE5\x94\x91", + "\xD0\xFD" => "\xE5\x94\x85", + "\xD0\xFE" => "\xE5\x93\xB1", + "\xD1\x40" => "\xE5\x94\x8A", + "\xD1\x41" => "\xE5\x93\xBB", + "\xD1\x42" => "\xE5\x93\xB7", + "\xD1\x43" => "\xE5\x93\xB8", + "\xD1\x44" => "\xE5\x93\xA0", + "\xD1\x45" => "\xE5\x94\x8E", + "\xD1\x46" => "\xE5\x94\x83", + "\xD1\x47" => "\xE5\x94\x8B", + "\xD1\x48" => "\xE5\x9C\x81", + "\xD1\x49" => "\xE5\x9C\x82", + "\xD1\x4A" => "\xE5\x9F\x8C", + "\xD1\x4B" => "\xE5\xA0\xB2", + "\xD1\x4C" => "\xE5\x9F\x95", + "\xD1\x4D" => "\xE5\x9F\x92", + "\xD1\x4E" => "\xE5\x9E\xBA", + "\xD1\x4F" => "\xE5\x9F\x86", + "\xD1\x50" => "\xE5\x9E\xBD", + "\xD1\x51" => "\xE5\x9E\xBC", + "\xD1\x52" => "\xE5\x9E\xB8", + "\xD1\x53" => "\xE5\x9E\xB6", + "\xD1\x54" => "\xE5\x9E\xBF", + "\xD1\x55" => "\xE5\x9F\x87", + "\xD1\x56" => "\xE5\x9F\x90", + "\xD1\x57" => "\xE5\x9E\xB9", + "\xD1\x58" => "\xE5\x9F\x81", + "\xD1\x59" => "\xE5\xA4\x8E", + "\xD1\x5A" => "\xE5\xA5\x8A", + "\xD1\x5B" => "\xE5\xA8\x99", + "\xD1\x5C" => "\xE5\xA8\x96", + "\xD1\x5D" => "\xE5\xA8\xAD", + "\xD1\x5E" => "\xE5\xA8\xAE", + "\xD1\x5F" => "\xE5\xA8\x95", + "\xD1\x60" => "\xE5\xA8\x8F", + "\xD1\x61" => "\xE5\xA8\x97", + "\xD1\x62" => "\xE5\xA8\x8A", + "\xD1\x63" => "\xE5\xA8\x9E", + "\xD1\x64" => "\xE5\xA8\xB3", + "\xD1\x65" => "\xE5\xAD\xAC", + "\xD1\x66" => "\xE5\xAE\xA7", + "\xD1\x67" => "\xE5\xAE\xAD", + "\xD1\x68" => "\xE5\xAE\xAC", + "\xD1\x69" => "\xE5\xB0\x83", + "\xD1\x6A" => "\xE5\xB1\x96", + "\xD1\x6B" => "\xE5\xB1\x94", + "\xD1\x6C" => "\xE5\xB3\xAC", + "\xD1\x6D" => "\xE5\xB3\xBF", + "\xD1\x6E" => "\xE5\xB3\xAE", + "\xD1\x6F" => "\xE5\xB3\xB1", + "\xD1\x70" => "\xE5\xB3\xB7", + "\xD1\x71" => "\xE5\xB4\x80", + "\xD1\x72" => "\xE5\xB3\xB9", + "\xD1\x73" => "\xE5\xB8\xA9", + "\xD1\x74" => "\xE5\xB8\xA8", + "\xD1\x75" => "\xE5\xBA\xA8", + "\xD1\x76" => "\xE5\xBA\xAE", + "\xD1\x77" => "\xE5\xBA\xAA", + "\xD1\x78" => "\xE5\xBA\xAC", + "\xD1\x79" => "\xE5\xBC\xB3", + "\xD1\x7A" => "\xE5\xBC\xB0", + "\xD1\x7B" => "\xE5\xBD\xA7", + "\xD1\x7C" => "\xE6\x81\x9D", + "\xD1\x7D" => "\xE6\x81\x9A", + "\xD1\x7E" => "\xE6\x81\xA7", + "\xD1\xA1" => "\xE6\x81\x81", + "\xD1\xA2" => "\xE6\x82\xA2", + "\xD1\xA3" => "\xE6\x82\x88", + "\xD1\xA4" => "\xE6\x82\x80", + "\xD1\xA5" => "\xE6\x82\x92", + "\xD1\xA6" => "\xE6\x82\x81", + "\xD1\xA7" => "\xE6\x82\x9D", + "\xD1\xA8" => "\xE6\x82\x83", + "\xD1\xA9" => "\xE6\x82\x95", + "\xD1\xAA" => "\xE6\x82\x9B", + "\xD1\xAB" => "\xE6\x82\x97", + "\xD1\xAC" => "\xE6\x82\x87", + "\xD1\xAD" => "\xE6\x82\x9C", + "\xD1\xAE" => "\xE6\x82\x8E", + "\xD1\xAF" => "\xE6\x88\x99", + "\xD1\xB0" => "\xE6\x89\x86", + "\xD1\xB1" => "\xE6\x8B\xB2", + "\xD1\xB2" => "\xE6\x8C\x90", + "\xD1\xB3" => "\xE6\x8D\x96", + "\xD1\xB4" => "\xE6\x8C\xAC", + "\xD1\xB5" => "\xE6\x8D\x84", + "\xD1\xB6" => "\xE6\x8D\x85", + "\xD1\xB7" => "\xE6\x8C\xB6", + "\xD1\xB8" => "\xE6\x8D\x83", + "\xD1\xB9" => "\xE6\x8F\xA4", + "\xD1\xBA" => "\xE6\x8C\xB9", + "\xD1\xBB" => "\xE6\x8D\x8B", + "\xD1\xBC" => "\xE6\x8D\x8A", + "\xD1\xBD" => "\xE6\x8C\xBC", + "\xD1\xBE" => "\xE6\x8C\xA9", + "\xD1\xBF" => "\xE6\x8D\x81", + "\xD1\xC0" => "\xE6\x8C\xB4", + "\xD1\xC1" => "\xE6\x8D\x98", + "\xD1\xC2" => "\xE6\x8D\x94", + "\xD1\xC3" => "\xE6\x8D\x99", + "\xD1\xC4" => "\xE6\x8C\xAD", + "\xD1\xC5" => "\xE6\x8D\x87", + "\xD1\xC6" => "\xE6\x8C\xB3", + "\xD1\xC7" => "\xE6\x8D\x9A", + "\xD1\xC8" => "\xE6\x8D\x91", + "\xD1\xC9" => "\xE6\x8C\xB8", + "\xD1\xCA" => "\xE6\x8D\x97", + "\xD1\xCB" => "\xE6\x8D\x80", + "\xD1\xCC" => "\xE6\x8D\x88", + "\xD1\xCD" => "\xE6\x95\x8A", + "\xD1\xCE" => "\xE6\x95\x86", + "\xD1\xCF" => "\xE6\x97\x86", + "\xD1\xD0" => "\xE6\x97\x83", + "\xD1\xD1" => "\xE6\x97\x84", + "\xD1\xD2" => "\xE6\x97\x82", + "\xD1\xD3" => "\xE6\x99\x8A", + "\xD1\xD4" => "\xE6\x99\x9F", + "\xD1\xD5" => "\xE6\x99\x87", + "\xD1\xD6" => "\xE6\x99\x91", + "\xD1\xD7" => "\xE6\x9C\x92", + "\xD1\xD8" => "\xE6\x9C\x93", + "\xD1\xD9" => "\xE6\xA0\x9F", + "\xD1\xDA" => "\xE6\xA0\x9A", + "\xD1\xDB" => "\xE6\xA1\x89", + "\xD1\xDC" => "\xE6\xA0\xB2", + "\xD1\xDD" => "\xE6\xA0\xB3", + "\xD1\xDE" => "\xE6\xA0\xBB", + "\xD1\xDF" => "\xE6\xA1\x8B", + "\xD1\xE0" => "\xE6\xA1\x8F", + "\xD1\xE1" => "\xE6\xA0\x96", + "\xD1\xE2" => "\xE6\xA0\xB1", + "\xD1\xE3" => "\xE6\xA0\x9C", + "\xD1\xE4" => "\xE6\xA0\xB5", + "\xD1\xE5" => "\xE6\xA0\xAB", + "\xD1\xE6" => "\xE6\xA0\xAD", + "\xD1\xE7" => "\xE6\xA0\xAF", + "\xD1\xE8" => "\xE6\xA1\x8E", + "\xD1\xE9" => "\xE6\xA1\x84", + "\xD1\xEA" => "\xE6\xA0\xB4", + "\xD1\xEB" => "\xE6\xA0\x9D", + "\xD1\xEC" => "\xE6\xA0\x92", + "\xD1\xED" => "\xE6\xA0\x94", + "\xD1\xEE" => "\xE6\xA0\xA6", + "\xD1\xEF" => "\xE6\xA0\xA8", + "\xD1\xF0" => "\xE6\xA0\xAE", + "\xD1\xF1" => "\xE6\xA1\x8D", + "\xD1\xF2" => "\xE6\xA0\xBA", + "\xD1\xF3" => "\xE6\xA0\xA5", + "\xD1\xF4" => "\xE6\xA0\xA0", + "\xD1\xF5" => "\xE6\xAC\xAC", + "\xD1\xF6" => "\xE6\xAC\xAF", + "\xD1\xF7" => "\xE6\xAC\xAD", + "\xD1\xF8" => "\xE6\xAC\xB1", + "\xD1\xF9" => "\xE6\xAC\xB4", + "\xD1\xFA" => "\xE6\xAD\xAD", + "\xD1\xFB" => "\xE8\x82\x82", + "\xD1\xFC" => "\xE6\xAE\x88", + "\xD1\xFD" => "\xE6\xAF\xA6", + "\xD1\xFE" => "\xE6\xAF\xA4", + "\xD2\x40" => "\xE6\xAF\xA8", + "\xD2\x41" => "\xE6\xAF\xA3", + "\xD2\x42" => "\xE6\xAF\xA2", + "\xD2\x43" => "\xE6\xAF\xA7", + "\xD2\x44" => "\xE6\xB0\xA5", + "\xD2\x45" => "\xE6\xB5\xBA", + "\xD2\x46" => "\xE6\xB5\xA3", + "\xD2\x47" => "\xE6\xB5\xA4", + "\xD2\x48" => "\xE6\xB5\xB6", + "\xD2\x49" => "\xE6\xB4\x8D", + "\xD2\x4A" => "\xE6\xB5\xA1", + "\xD2\x4B" => "\xE6\xB6\x92", + "\xD2\x4C" => "\xE6\xB5\x98", + "\xD2\x4D" => "\xE6\xB5\xA2", + "\xD2\x4E" => "\xE6\xB5\xAD", + "\xD2\x4F" => "\xE6\xB5\xAF", + "\xD2\x50" => "\xE6\xB6\x91", + "\xD2\x51" => "\xE6\xB6\x8D", + "\xD2\x52" => "\xE6\xB7\xAF", + "\xD2\x53" => "\xE6\xB5\xBF", + "\xD2\x54" => "\xE6\xB6\x86", + "\xD2\x55" => "\xE6\xB5\x9E", + "\xD2\x56" => "\xE6\xB5\xA7", + "\xD2\x57" => "\xE6\xB5\xA0", + "\xD2\x58" => "\xE6\xB6\x97", + "\xD2\x59" => "\xE6\xB5\xB0", + "\xD2\x5A" => "\xE6\xB5\xBC", + "\xD2\x5B" => "\xE6\xB5\x9F", + "\xD2\x5C" => "\xE6\xB6\x82", + "\xD2\x5D" => "\xE6\xB6\x98", + "\xD2\x5E" => "\xE6\xB4\xAF", + "\xD2\x5F" => "\xE6\xB5\xA8", + "\xD2\x60" => "\xE6\xB6\x8B", + "\xD2\x61" => "\xE6\xB5\xBE", + "\xD2\x62" => "\xE6\xB6\x80", + "\xD2\x63" => "\xE6\xB6\x84", + "\xD2\x64" => "\xE6\xB4\x96", + "\xD2\x65" => "\xE6\xB6\x83", + "\xD2\x66" => "\xE6\xB5\xBB", + "\xD2\x67" => "\xE6\xB5\xBD", + "\xD2\x68" => "\xE6\xB5\xB5", + "\xD2\x69" => "\xE6\xB6\x90", + "\xD2\x6A" => "\xE7\x83\x9C", + "\xD2\x6B" => "\xE7\x83\x93", + "\xD2\x6C" => "\xE7\x83\x91", + "\xD2\x6D" => "\xE7\x83\x9D", + "\xD2\x6E" => "\xE7\x83\x8B", + "\xD2\x6F" => "\xE7\xBC\xB9", + "\xD2\x70" => "\xE7\x83\xA2", + "\xD2\x71" => "\xE7\x83\x97", + "\xD2\x72" => "\xE7\x83\x92", + "\xD2\x73" => "\xE7\x83\x9E", + "\xD2\x74" => "\xE7\x83\xA0", + "\xD2\x75" => "\xE7\x83\x94", + "\xD2\x76" => "\xE7\x83\x8D", + "\xD2\x77" => "\xE7\x83\x85", + "\xD2\x78" => "\xE7\x83\x86", + "\xD2\x79" => "\xE7\x83\x87", + "\xD2\x7A" => "\xE7\x83\x9A", + "\xD2\x7B" => "\xE7\x83\x8E", + "\xD2\x7C" => "\xE7\x83\xA1", + "\xD2\x7D" => "\xE7\x89\x82", + "\xD2\x7E" => "\xE7\x89\xB8", + "\xD2\xA1" => "\xE7\x89\xB7", + "\xD2\xA2" => "\xE7\x89\xB6", + "\xD2\xA3" => "\xE7\x8C\x80", + "\xD2\xA4" => "\xE7\x8B\xBA", + "\xD2\xA5" => "\xE7\x8B\xB4", + "\xD2\xA6" => "\xE7\x8B\xBE", + "\xD2\xA7" => "\xE7\x8B\xB6", + "\xD2\xA8" => "\xE7\x8B\xB3", + "\xD2\xA9" => "\xE7\x8B\xBB", + "\xD2\xAA" => "\xE7\x8C\x81", + "\xD2\xAB" => "\xE7\x8F\x93", + "\xD2\xAC" => "\xE7\x8F\x99", + "\xD2\xAD" => "\xE7\x8F\xA5", + "\xD2\xAE" => "\xE7\x8F\x96", + "\xD2\xAF" => "\xE7\x8E\xBC", + "\xD2\xB0" => "\xE7\x8F\xA7", + "\xD2\xB1" => "\xE7\x8F\xA3", + "\xD2\xB2" => "\xE7\x8F\xA9", + "\xD2\xB3" => "\xE7\x8F\x9C", + "\xD2\xB4" => "\xE7\x8F\x92", + "\xD2\xB5" => "\xE7\x8F\x9B", + "\xD2\xB6" => "\xE7\x8F\x94", + "\xD2\xB7" => "\xE7\x8F\x9D", + "\xD2\xB8" => "\xE7\x8F\x9A", + "\xD2\xB9" => "\xE7\x8F\x97", + "\xD2\xBA" => "\xE7\x8F\x98", + "\xD2\xBB" => "\xE7\x8F\xA8", + "\xD2\xBC" => "\xE7\x93\x9E", + "\xD2\xBD" => "\xE7\x93\x9F", + "\xD2\xBE" => "\xE7\x93\xB4", + "\xD2\xBF" => "\xE7\x93\xB5", + "\xD2\xC0" => "\xE7\x94\xA1", + "\xD2\xC1" => "\xE7\x95\x9B", + "\xD2\xC2" => "\xE7\x95\x9F", + "\xD2\xC3" => "\xE7\x96\xB0", + "\xD2\xC4" => "\xE7\x97\x81", + "\xD2\xC5" => "\xE7\x96\xBB", + "\xD2\xC6" => "\xE7\x97\x84", + "\xD2\xC7" => "\xE7\x97\x80", + "\xD2\xC8" => "\xE7\x96\xBF", + "\xD2\xC9" => "\xE7\x96\xB6", + "\xD2\xCA" => "\xE7\x96\xBA", + "\xD2\xCB" => "\xE7\x9A\x8A", + "\xD2\xCC" => "\xE7\x9B\x89", + "\xD2\xCD" => "\xE7\x9C\x9D", + "\xD2\xCE" => "\xE7\x9C\x9B", + "\xD2\xCF" => "\xE7\x9C\x90", + "\xD2\xD0" => "\xE7\x9C\x93", + "\xD2\xD1" => "\xE7\x9C\x92", + "\xD2\xD2" => "\xE7\x9C\xA3", + "\xD2\xD3" => "\xE7\x9C\x91", + "\xD2\xD4" => "\xE7\x9C\x95", + "\xD2\xD5" => "\xE7\x9C\x99", + "\xD2\xD6" => "\xE7\x9C\x9A", + "\xD2\xD7" => "\xE7\x9C\xA2", + "\xD2\xD8" => "\xE7\x9C\xA7", + "\xD2\xD9" => "\xE7\xA0\xA3", + "\xD2\xDA" => "\xE7\xA0\xAC", + "\xD2\xDB" => "\xE7\xA0\xA2", + "\xD2\xDC" => "\xE7\xA0\xB5", + "\xD2\xDD" => "\xE7\xA0\xAF", + "\xD2\xDE" => "\xE7\xA0\xA8", + "\xD2\xDF" => "\xE7\xA0\xAE", + "\xD2\xE0" => "\xE7\xA0\xAB", + "\xD2\xE1" => "\xE7\xA0\xA1", + "\xD2\xE2" => "\xE7\xA0\xA9", + "\xD2\xE3" => "\xE7\xA0\xB3", + "\xD2\xE4" => "\xE7\xA0\xAA", + "\xD2\xE5" => "\xE7\xA0\xB1", + "\xD2\xE6" => "\xE7\xA5\x94", + "\xD2\xE7" => "\xE7\xA5\x9B", + "\xD2\xE8" => "\xE7\xA5\x8F", + "\xD2\xE9" => "\xE7\xA5\x9C", + "\xD2\xEA" => "\xE7\xA5\x93", + "\xD2\xEB" => "\xE7\xA5\x92", + "\xD2\xEC" => "\xE7\xA5\x91", + "\xD2\xED" => "\xE7\xA7\xAB", + "\xD2\xEE" => "\xE7\xA7\xAC", + "\xD2\xEF" => "\xE7\xA7\xA0", + "\xD2\xF0" => "\xE7\xA7\xAE", + "\xD2\xF1" => "\xE7\xA7\xAD", + "\xD2\xF2" => "\xE7\xA7\xAA", + "\xD2\xF3" => "\xE7\xA7\x9C", + "\xD2\xF4" => "\xE7\xA7\x9E", + "\xD2\xF5" => "\xE7\xA7\x9D", + "\xD2\xF6" => "\xE7\xAA\x86", + "\xD2\xF7" => "\xE7\xAA\x89", + "\xD2\xF8" => "\xE7\xAA\x85", + "\xD2\xF9" => "\xE7\xAA\x8B", + "\xD2\xFA" => "\xE7\xAA\x8C", + "\xD2\xFB" => "\xE7\xAA\x8A", + "\xD2\xFC" => "\xE7\xAA\x87", + "\xD2\xFD" => "\xE7\xAB\x98", + "\xD2\xFE" => "\xE7\xAC\x90", + "\xD3\x40" => "\xE7\xAC\x84", + "\xD3\x41" => "\xE7\xAC\x93", + "\xD3\x42" => "\xE7\xAC\x85", + "\xD3\x43" => "\xE7\xAC\x8F", + "\xD3\x44" => "\xE7\xAC\x88", + "\xD3\x45" => "\xE7\xAC\x8A", + "\xD3\x46" => "\xE7\xAC\x8E", + "\xD3\x47" => "\xE7\xAC\x89", + "\xD3\x48" => "\xE7\xAC\x92", + "\xD3\x49" => "\xE7\xB2\x84", + "\xD3\x4A" => "\xE7\xB2\x91", + "\xD3\x4B" => "\xE7\xB2\x8A", + "\xD3\x4C" => "\xE7\xB2\x8C", + "\xD3\x4D" => "\xE7\xB2\x88", + "\xD3\x4E" => "\xE7\xB2\x8D", + "\xD3\x4F" => "\xE7\xB2\x85", + "\xD3\x50" => "\xE7\xB4\x9E", + "\xD3\x51" => "\xE7\xB4\x9D", + "\xD3\x52" => "\xE7\xB4\x91", + "\xD3\x53" => "\xE7\xB4\x8E", + "\xD3\x54" => "\xE7\xB4\x98", + "\xD3\x55" => "\xE7\xB4\x96", + "\xD3\x56" => "\xE7\xB4\x93", + "\xD3\x57" => "\xE7\xB4\x9F", + "\xD3\x58" => "\xE7\xB4\x92", + "\xD3\x59" => "\xE7\xB4\x8F", + "\xD3\x5A" => "\xE7\xB4\x8C", + "\xD3\x5B" => "\xE7\xBD\x9C", + "\xD3\x5C" => "\xE7\xBD\xA1", + "\xD3\x5D" => "\xE7\xBD\x9E", + "\xD3\x5E" => "\xE7\xBD\xA0", + "\xD3\x5F" => "\xE7\xBD\x9D", + "\xD3\x60" => "\xE7\xBD\x9B", + "\xD3\x61" => "\xE7\xBE\x96", + "\xD3\x62" => "\xE7\xBE\x92", + "\xD3\x63" => "\xE7\xBF\x83", + "\xD3\x64" => "\xE7\xBF\x82", + "\xD3\x65" => "\xE7\xBF\x80", + "\xD3\x66" => "\xE8\x80\x96", + "\xD3\x67" => "\xE8\x80\xBE", + "\xD3\x68" => "\xE8\x80\xB9", + "\xD3\x69" => "\xE8\x83\xBA", + "\xD3\x6A" => "\xE8\x83\xB2", + "\xD3\x6B" => "\xE8\x83\xB9", + "\xD3\x6C" => "\xE8\x83\xB5", + "\xD3\x6D" => "\xE8\x84\x81", + "\xD3\x6E" => "\xE8\x83\xBB", + "\xD3\x6F" => "\xE8\x84\x80", + "\xD3\x70" => "\xE8\x88\x81", + "\xD3\x71" => "\xE8\x88\xAF", + "\xD3\x72" => "\xE8\x88\xA5", + "\xD3\x73" => "\xE8\x8C\xB3", + "\xD3\x74" => "\xE8\x8C\xAD", + "\xD3\x75" => "\xE8\x8D\x84", + "\xD3\x76" => "\xE8\x8C\x99", + "\xD3\x77" => "\xE8\x8D\x91", + "\xD3\x78" => "\xE8\x8C\xA5", + "\xD3\x79" => "\xE8\x8D\x96", + "\xD3\x7A" => "\xE8\x8C\xBF", + "\xD3\x7B" => "\xE8\x8D\x81", + "\xD3\x7C" => "\xE8\x8C\xA6", + "\xD3\x7D" => "\xE8\x8C\x9C", + "\xD3\x7E" => "\xE8\x8C\xA2", + "\xD3\xA1" => "\xE8\x8D\x82", + "\xD3\xA2" => "\xE8\x8D\x8E", + "\xD3\xA3" => "\xE8\x8C\x9B", + "\xD3\xA4" => "\xE8\x8C\xAA", + "\xD3\xA5" => "\xE8\x8C\x88", + "\xD3\xA6" => "\xE8\x8C\xBC", + "\xD3\xA7" => "\xE8\x8D\x8D", + "\xD3\xA8" => "\xE8\x8C\x96", + "\xD3\xA9" => "\xE8\x8C\xA4", + "\xD3\xAA" => "\xE8\x8C\xA0", + "\xD3\xAB" => "\xE8\x8C\xB7", + "\xD3\xAC" => "\xE8\x8C\xAF", + "\xD3\xAD" => "\xE8\x8C\xA9", + "\xD3\xAE" => "\xE8\x8D\x87", + "\xD3\xAF" => "\xE8\x8D\x85", + "\xD3\xB0" => "\xE8\x8D\x8C", + "\xD3\xB1" => "\xE8\x8D\x93", + "\xD3\xB2" => "\xE8\x8C\x9E", + "\xD3\xB3" => "\xE8\x8C\xAC", + "\xD3\xB4" => "\xE8\x8D\x8B", + "\xD3\xB5" => "\xE8\x8C\xA7", + "\xD3\xB6" => "\xE8\x8D\x88", + "\xD3\xB7" => "\xE8\x99\x93", + "\xD3\xB8" => "\xE8\x99\x92", + "\xD3\xB9" => "\xE8\x9A\xA2", + "\xD3\xBA" => "\xE8\x9A\xA8", + "\xD3\xBB" => "\xE8\x9A\x96", + "\xD3\xBC" => "\xE8\x9A\x8D", + "\xD3\xBD" => "\xE8\x9A\x91", + "\xD3\xBE" => "\xE8\x9A\x9E", + "\xD3\xBF" => "\xE8\x9A\x87", + "\xD3\xC0" => "\xE8\x9A\x97", + "\xD3\xC1" => "\xE8\x9A\x86", + "\xD3\xC2" => "\xE8\x9A\x8B", + "\xD3\xC3" => "\xE8\x9A\x9A", + "\xD3\xC4" => "\xE8\x9A\x85", + "\xD3\xC5" => "\xE8\x9A\xA5", + "\xD3\xC6" => "\xE8\x9A\x99", + "\xD3\xC7" => "\xE8\x9A\xA1", + "\xD3\xC8" => "\xE8\x9A\xA7", + "\xD3\xC9" => "\xE8\x9A\x95", + "\xD3\xCA" => "\xE8\x9A\x98", + "\xD3\xCB" => "\xE8\x9A\x8E", + "\xD3\xCC" => "\xE8\x9A\x9D", + "\xD3\xCD" => "\xE8\x9A\x90", + "\xD3\xCE" => "\xE8\x9A\x94", + "\xD3\xCF" => "\xE8\xA1\x83", + "\xD3\xD0" => "\xE8\xA1\x84", + "\xD3\xD1" => "\xE8\xA1\xAD", + "\xD3\xD2" => "\xE8\xA1\xB5", + "\xD3\xD3" => "\xE8\xA1\xB6", + "\xD3\xD4" => "\xE8\xA1\xB2", + "\xD3\xD5" => "\xE8\xA2\x80", + "\xD3\xD6" => "\xE8\xA1\xB1", + "\xD3\xD7" => "\xE8\xA1\xBF", + "\xD3\xD8" => "\xE8\xA1\xAF", + "\xD3\xD9" => "\xE8\xA2\x83", + "\xD3\xDA" => "\xE8\xA1\xBE", + "\xD3\xDB" => "\xE8\xA1\xB4", + "\xD3\xDC" => "\xE8\xA1\xBC", + "\xD3\xDD" => "\xE8\xA8\x92", + "\xD3\xDE" => "\xE8\xB1\x87", + "\xD3\xDF" => "\xE8\xB1\x97", + "\xD3\xE0" => "\xE8\xB1\xBB", + "\xD3\xE1" => "\xE8\xB2\xA4", + "\xD3\xE2" => "\xE8\xB2\xA3", + "\xD3\xE3" => "\xE8\xB5\xB6", + "\xD3\xE4" => "\xE8\xB5\xB8", + "\xD3\xE5" => "\xE8\xB6\xB5", + "\xD3\xE6" => "\xE8\xB6\xB7", + "\xD3\xE7" => "\xE8\xB6\xB6", + "\xD3\xE8" => "\xE8\xBB\x91", + "\xD3\xE9" => "\xE8\xBB\x93", + "\xD3\xEA" => "\xE8\xBF\xBE", + "\xD3\xEB" => "\xE8\xBF\xB5", + "\xD3\xEC" => "\xE9\x80\x82", + "\xD3\xED" => "\xE8\xBF\xBF", + "\xD3\xEE" => "\xE8\xBF\xBB", + "\xD3\xEF" => "\xE9\x80\x84", + "\xD3\xF0" => "\xE8\xBF\xBC", + "\xD3\xF1" => "\xE8\xBF\xB6", + "\xD3\xF2" => "\xE9\x83\x96", + "\xD3\xF3" => "\xE9\x83\xA0", + "\xD3\xF4" => "\xE9\x83\x99", + "\xD3\xF5" => "\xE9\x83\x9A", + "\xD3\xF6" => "\xE9\x83\xA3", + "\xD3\xF7" => "\xE9\x83\x9F", + "\xD3\xF8" => "\xE9\x83\xA5", + "\xD3\xF9" => "\xE9\x83\x98", + "\xD3\xFA" => "\xE9\x83\x9B", + "\xD3\xFB" => "\xE9\x83\x97", + "\xD3\xFC" => "\xE9\x83\x9C", + "\xD3\xFD" => "\xE9\x83\xA4", + "\xD3\xFE" => "\xE9\x85\x90", + "\xD4\x40" => "\xE9\x85\x8E", + "\xD4\x41" => "\xE9\x85\x8F", + "\xD4\x42" => "\xE9\x87\x95", + "\xD4\x43" => "\xE9\x87\xA2", + "\xD4\x44" => "\xE9\x87\x9A", + "\xD4\x45" => "\xE9\x99\x9C", + "\xD4\x46" => "\xE9\x99\x9F", + "\xD4\x47" => "\xE9\x9A\xBC", + "\xD4\x48" => "\xE9\xA3\xA3", + "\xD4\x49" => "\xE9\xAB\x9F", + "\xD4\x4A" => "\xE9\xAC\xAF", + "\xD4\x4B" => "\xE4\xB9\xBF", + "\xD4\x4C" => "\xE5\x81\xB0", + "\xD4\x4D" => "\xE5\x81\xAA", + "\xD4\x4E" => "\xE5\x81\xA1", + "\xD4\x4F" => "\xE5\x81\x9E", + "\xD4\x50" => "\xE5\x81\xA0", + "\xD4\x51" => "\xE5\x81\x93", + "\xD4\x52" => "\xE5\x81\x8B", + "\xD4\x53" => "\xE5\x81\x9D", + "\xD4\x54" => "\xE5\x81\xB2", + "\xD4\x55" => "\xE5\x81\x88", + "\xD4\x56" => "\xE5\x81\x8D", + "\xD4\x57" => "\xE5\x81\x81", + "\xD4\x58" => "\xE5\x81\x9B", + "\xD4\x59" => "\xE5\x81\x8A", + "\xD4\x5A" => "\xE5\x81\xA2", + "\xD4\x5B" => "\xE5\x80\x95", + "\xD4\x5C" => "\xE5\x81\x85", + "\xD4\x5D" => "\xE5\x81\x9F", + "\xD4\x5E" => "\xE5\x81\xA9", + "\xD4\x5F" => "\xE5\x81\xAB", + "\xD4\x60" => "\xE5\x81\xA3", + "\xD4\x61" => "\xE5\x81\xA4", + "\xD4\x62" => "\xE5\x81\x86", + "\xD4\x63" => "\xE5\x81\x80", + "\xD4\x64" => "\xE5\x81\xAE", + "\xD4\x65" => "\xE5\x81\xB3", + "\xD4\x66" => "\xE5\x81\x97", + "\xD4\x67" => "\xE5\x81\x91", + "\xD4\x68" => "\xE5\x87\x90", + "\xD4\x69" => "\xE5\x89\xAB", + "\xD4\x6A" => "\xE5\x89\xAD", + "\xD4\x6B" => "\xE5\x89\xAC", + "\xD4\x6C" => "\xE5\x89\xAE", + "\xD4\x6D" => "\xE5\x8B\x96", + "\xD4\x6E" => "\xE5\x8B\x93", + "\xD4\x6F" => "\xE5\x8C\xAD", + "\xD4\x70" => "\xE5\x8E\x9C", + "\xD4\x71" => "\xE5\x95\xB5", + "\xD4\x72" => "\xE5\x95\xB6", + "\xD4\x73" => "\xE5\x94\xBC", + "\xD4\x74" => "\xE5\x95\x8D", + "\xD4\x75" => "\xE5\x95\x90", + "\xD4\x76" => "\xE5\x94\xB4", + "\xD4\x77" => "\xE5\x94\xAA", + "\xD4\x78" => "\xE5\x95\x91", + "\xD4\x79" => "\xE5\x95\xA2", + "\xD4\x7A" => "\xE5\x94\xB6", + "\xD4\x7B" => "\xE5\x94\xB5", + "\xD4\x7C" => "\xE5\x94\xB0", + "\xD4\x7D" => "\xE5\x95\x92", + "\xD4\x7E" => "\xE5\x95\x85", + "\xD4\xA1" => "\xE5\x94\x8C", + "\xD4\xA2" => "\xE5\x94\xB2", + "\xD4\xA3" => "\xE5\x95\xA5", + "\xD4\xA4" => "\xE5\x95\x8E", + "\xD4\xA5" => "\xE5\x94\xB9", + "\xD4\xA6" => "\xE5\x95\x88", + "\xD4\xA7" => "\xE5\x94\xAD", + "\xD4\xA8" => "\xE5\x94\xBB", + "\xD4\xA9" => "\xE5\x95\x80", + "\xD4\xAA" => "\xE5\x95\x8B", + "\xD4\xAB" => "\xE5\x9C\x8A", + "\xD4\xAC" => "\xE5\x9C\x87", + "\xD4\xAD" => "\xE5\x9F\xBB", + "\xD4\xAE" => "\xE5\xA0\x94", + "\xD4\xAF" => "\xE5\x9F\xA2", + "\xD4\xB0" => "\xE5\x9F\xB6", + "\xD4\xB1" => "\xE5\x9F\x9C", + "\xD4\xB2" => "\xE5\x9F\xB4", + "\xD4\xB3" => "\xE5\xA0\x80", + "\xD4\xB4" => "\xE5\x9F\xAD", + "\xD4\xB5" => "\xE5\x9F\xBD", + "\xD4\xB6" => "\xE5\xA0\x88", + "\xD4\xB7" => "\xE5\x9F\xB8", + "\xD4\xB8" => "\xE5\xA0\x8B", + "\xD4\xB9" => "\xE5\x9F\xB3", + "\xD4\xBA" => "\xE5\x9F\x8F", + "\xD4\xBB" => "\xE5\xA0\x87", + "\xD4\xBC" => "\xE5\x9F\xAE", + "\xD4\xBD" => "\xE5\x9F\xA3", + "\xD4\xBE" => "\xE5\x9F\xB2", + "\xD4\xBF" => "\xE5\x9F\xA5", + "\xD4\xC0" => "\xE5\x9F\xAC", + "\xD4\xC1" => "\xE5\x9F\xA1", + "\xD4\xC2" => "\xE5\xA0\x8E", + "\xD4\xC3" => "\xE5\x9F\xBC", + "\xD4\xC4" => "\xE5\xA0\x90", + "\xD4\xC5" => "\xE5\x9F\xA7", + "\xD4\xC6" => "\xE5\xA0\x81", + "\xD4\xC7" => "\xE5\xA0\x8C", + "\xD4\xC8" => "\xE5\x9F\xB1", + "\xD4\xC9" => "\xE5\x9F\xA9", + "\xD4\xCA" => "\xE5\x9F\xB0", + "\xD4\xCB" => "\xE5\xA0\x8D", + "\xD4\xCC" => "\xE5\xA0\x84", + "\xD4\xCD" => "\xE5\xA5\x9C", + "\xD4\xCE" => "\xE5\xA9\xA0", + "\xD4\xCF" => "\xE5\xA9\x98", + "\xD4\xD0" => "\xE5\xA9\x95", + "\xD4\xD1" => "\xE5\xA9\xA7", + "\xD4\xD2" => "\xE5\xA9\x9E", + "\xD4\xD3" => "\xE5\xA8\xB8", + "\xD4\xD4" => "\xE5\xA8\xB5", + "\xD4\xD5" => "\xE5\xA9\xAD", + "\xD4\xD6" => "\xE5\xA9\x90", + "\xD4\xD7" => "\xE5\xA9\x9F", + "\xD4\xD8" => "\xE5\xA9\xA5", + "\xD4\xD9" => "\xE5\xA9\xAC", + "\xD4\xDA" => "\xE5\xA9\x93", + "\xD4\xDB" => "\xE5\xA9\xA4", + "\xD4\xDC" => "\xE5\xA9\x97", + "\xD4\xDD" => "\xE5\xA9\x83", + "\xD4\xDE" => "\xE5\xA9\x9D", + "\xD4\xDF" => "\xE5\xA9\x92", + "\xD4\xE0" => "\xE5\xA9\x84", + "\xD4\xE1" => "\xE5\xA9\x9B", + "\xD4\xE2" => "\xE5\xA9\x88", + "\xD4\xE3" => "\xE5\xAA\x8E", + "\xD4\xE4" => "\xE5\xA8\xBE", + "\xD4\xE5" => "\xE5\xA9\x8D", + "\xD4\xE6" => "\xE5\xA8\xB9", + "\xD4\xE7" => "\xE5\xA9\x8C", + "\xD4\xE8" => "\xE5\xA9\xB0", + "\xD4\xE9" => "\xE5\xA9\xA9", + "\xD4\xEA" => "\xE5\xA9\x87", + "\xD4\xEB" => "\xE5\xA9\x91", + "\xD4\xEC" => "\xE5\xA9\x96", + "\xD4\xED" => "\xE5\xA9\x82", + "\xD4\xEE" => "\xE5\xA9\x9C", + "\xD4\xEF" => "\xE5\xAD\xB2", + "\xD4\xF0" => "\xE5\xAD\xAE", + "\xD4\xF1" => "\xE5\xAF\x81", + "\xD4\xF2" => "\xE5\xAF\x80", + "\xD4\xF3" => "\xE5\xB1\x99", + "\xD4\xF4" => "\xE5\xB4\x9E", + "\xD4\xF5" => "\xE5\xB4\x8B", + "\xD4\xF6" => "\xE5\xB4\x9D", + "\xD4\xF7" => "\xE5\xB4\x9A", + "\xD4\xF8" => "\xE5\xB4\xA0", + "\xD4\xF9" => "\xE5\xB4\x8C", + "\xD4\xFA" => "\xE5\xB4\xA8", + "\xD4\xFB" => "\xE5\xB4\x8D", + "\xD4\xFC" => "\xE5\xB4\xA6", + "\xD4\xFD" => "\xE5\xB4\xA5", + "\xD4\xFE" => "\xE5\xB4\x8F", + "\xD5\x40" => "\xE5\xB4\xB0", + "\xD5\x41" => "\xE5\xB4\x92", + "\xD5\x42" => "\xE5\xB4\xA3", + "\xD5\x43" => "\xE5\xB4\x9F", + "\xD5\x44" => "\xE5\xB4\xAE", + "\xD5\x45" => "\xE5\xB8\xBE", + "\xD5\x46" => "\xE5\xB8\xB4", + "\xD5\x47" => "\xE5\xBA\xB1", + "\xD5\x48" => "\xE5\xBA\xB4", + "\xD5\x49" => "\xE5\xBA\xB9", + "\xD5\x4A" => "\xE5\xBA\xB2", + "\xD5\x4B" => "\xE5\xBA\xB3", + "\xD5\x4C" => "\xE5\xBC\xB6", + "\xD5\x4D" => "\xE5\xBC\xB8", + "\xD5\x4E" => "\xE5\xBE\x9B", + "\xD5\x4F" => "\xE5\xBE\x96", + "\xD5\x50" => "\xE5\xBE\x9F", + "\xD5\x51" => "\xE6\x82\x8A", + "\xD5\x52" => "\xE6\x82\x90", + "\xD5\x53" => "\xE6\x82\x86", + "\xD5\x54" => "\xE6\x82\xBE", + "\xD5\x55" => "\xE6\x82\xB0", + "\xD5\x56" => "\xE6\x82\xBA", + "\xD5\x57" => "\xE6\x83\x93", + "\xD5\x58" => "\xE6\x83\x94", + "\xD5\x59" => "\xE6\x83\x8F", + "\xD5\x5A" => "\xE6\x83\xA4", + "\xD5\x5B" => "\xE6\x83\x99", + "\xD5\x5C" => "\xE6\x83\x9D", + "\xD5\x5D" => "\xE6\x83\x88", + "\xD5\x5E" => "\xE6\x82\xB1", + "\xD5\x5F" => "\xE6\x83\x9B", + "\xD5\x60" => "\xE6\x82\xB7", + "\xD5\x61" => "\xE6\x83\x8A", + "\xD5\x62" => "\xE6\x82\xBF", + "\xD5\x63" => "\xE6\x83\x83", + "\xD5\x64" => "\xE6\x83\x8D", + "\xD5\x65" => "\xE6\x83\x80", + "\xD5\x66" => "\xE6\x8C\xB2", + "\xD5\x67" => "\xE6\x8D\xA5", + "\xD5\x68" => "\xE6\x8E\x8A", + "\xD5\x69" => "\xE6\x8E\x82", + "\xD5\x6A" => "\xE6\x8D\xBD", + "\xD5\x6B" => "\xE6\x8E\xBD", + "\xD5\x6C" => "\xE6\x8E\x9E", + "\xD5\x6D" => "\xE6\x8E\xAD", + "\xD5\x6E" => "\xE6\x8E\x9D", + "\xD5\x6F" => "\xE6\x8E\x97", + "\xD5\x70" => "\xE6\x8E\xAB", + "\xD5\x71" => "\xE6\x8E\x8E", + "\xD5\x72" => "\xE6\x8D\xAF", + "\xD5\x73" => "\xE6\x8E\x87", + "\xD5\x74" => "\xE6\x8E\x90", + "\xD5\x75" => "\xE6\x8D\xAE", + "\xD5\x76" => "\xE6\x8E\xAF", + "\xD5\x77" => "\xE6\x8D\xB5", + "\xD5\x78" => "\xE6\x8E\x9C", + "\xD5\x79" => "\xE6\x8D\xAD", + "\xD5\x7A" => "\xE6\x8E\xAE", + "\xD5\x7B" => "\xE6\x8D\xBC", + "\xD5\x7C" => "\xE6\x8E\xA4", + "\xD5\x7D" => "\xE6\x8C\xBB", + "\xD5\x7E" => "\xE6\x8E\x9F", + "\xD5\xA1" => "\xE6\x8D\xB8", + "\xD5\xA2" => "\xE6\x8E\x85", + "\xD5\xA3" => "\xE6\x8E\x81", + "\xD5\xA4" => "\xE6\x8E\x91", + "\xD5\xA5" => "\xE6\x8E\x8D", + "\xD5\xA6" => "\xE6\x8D\xB0", + "\xD5\xA7" => "\xE6\x95\x93", + "\xD5\xA8" => "\xE6\x97\x8D", + "\xD5\xA9" => "\xE6\x99\xA5", + "\xD5\xAA" => "\xE6\x99\xA1", + "\xD5\xAB" => "\xE6\x99\x9B", + "\xD5\xAC" => "\xE6\x99\x99", + "\xD5\xAD" => "\xE6\x99\x9C", + "\xD5\xAE" => "\xE6\x99\xA2", + "\xD5\xAF" => "\xE6\x9C\x98", + "\xD5\xB0" => "\xE6\xA1\xB9", + "\xD5\xB1" => "\xE6\xA2\x87", + "\xD5\xB2" => "\xE6\xA2\x90", + "\xD5\xB3" => "\xE6\xA2\x9C", + "\xD5\xB4" => "\xE6\xA1\xAD", + "\xD5\xB5" => "\xE6\xA1\xAE", + "\xD5\xB6" => "\xE6\xA2\xAE", + "\xD5\xB7" => "\xE6\xA2\xAB", + "\xD5\xB8" => "\xE6\xA5\x96", + "\xD5\xB9" => "\xE6\xA1\xAF", + "\xD5\xBA" => "\xE6\xA2\xA3", + "\xD5\xBB" => "\xE6\xA2\xAC", + "\xD5\xBC" => "\xE6\xA2\xA9", + "\xD5\xBD" => "\xE6\xA1\xB5", + "\xD5\xBE" => "\xE6\xA1\xB4", + "\xD5\xBF" => "\xE6\xA2\xB2", + "\xD5\xC0" => "\xE6\xA2\x8F", + "\xD5\xC1" => "\xE6\xA1\xB7", + "\xD5\xC2" => "\xE6\xA2\x92", + "\xD5\xC3" => "\xE6\xA1\xBC", + "\xD5\xC4" => "\xE6\xA1\xAB", + "\xD5\xC5" => "\xE6\xA1\xB2", + "\xD5\xC6" => "\xE6\xA2\xAA", + "\xD5\xC7" => "\xE6\xA2\x80", + "\xD5\xC8" => "\xE6\xA1\xB1", + "\xD5\xC9" => "\xE6\xA1\xBE", + "\xD5\xCA" => "\xE6\xA2\x9B", + "\xD5\xCB" => "\xE6\xA2\x96", + "\xD5\xCC" => "\xE6\xA2\x8B", + "\xD5\xCD" => "\xE6\xA2\xA0", + "\xD5\xCE" => "\xE6\xA2\x89", + "\xD5\xCF" => "\xE6\xA2\xA4", + "\xD5\xD0" => "\xE6\xA1\xB8", + "\xD5\xD1" => "\xE6\xA1\xBB", + "\xD5\xD2" => "\xE6\xA2\x91", + "\xD5\xD3" => "\xE6\xA2\x8C", + "\xD5\xD4" => "\xE6\xA2\x8A", + "\xD5\xD5" => "\xE6\xA1\xBD", + "\xD5\xD6" => "\xE6\xAC\xB6", + "\xD5\xD7" => "\xE6\xAC\xB3", + "\xD5\xD8" => "\xE6\xAC\xB7", + "\xD5\xD9" => "\xE6\xAC\xB8", + "\xD5\xDA" => "\xE6\xAE\x91", + "\xD5\xDB" => "\xE6\xAE\x8F", + "\xD5\xDC" => "\xE6\xAE\x8D", + "\xD5\xDD" => "\xE6\xAE\x8E", + "\xD5\xDE" => "\xE6\xAE\x8C", + "\xD5\xDF" => "\xE6\xB0\xAA", + "\xD5\xE0" => "\xE6\xB7\x80", + "\xD5\xE1" => "\xE6\xB6\xAB", + "\xD5\xE2" => "\xE6\xB6\xB4", + "\xD5\xE3" => "\xE6\xB6\xB3", + "\xD5\xE4" => "\xE6\xB9\xB4", + "\xD5\xE5" => "\xE6\xB6\xAC", + "\xD5\xE6" => "\xE6\xB7\xA9", + "\xD5\xE7" => "\xE6\xB7\xA2", + "\xD5\xE8" => "\xE6\xB6\xB7", + "\xD5\xE9" => "\xE6\xB7\xB6", + "\xD5\xEA" => "\xE6\xB7\x94", + "\xD5\xEB" => "\xE6\xB8\x80", + "\xD5\xEC" => "\xE6\xB7\x88", + "\xD5\xED" => "\xE6\xB7\xA0", + "\xD5\xEE" => "\xE6\xB7\x9F", + "\xD5\xEF" => "\xE6\xB7\x96", + "\xD5\xF0" => "\xE6\xB6\xBE", + "\xD5\xF1" => "\xE6\xB7\xA5", + "\xD5\xF2" => "\xE6\xB7\x9C", + "\xD5\xF3" => "\xE6\xB7\x9D", + "\xD5\xF4" => "\xE6\xB7\x9B", + "\xD5\xF5" => "\xE6\xB7\xB4", + "\xD5\xF6" => "\xE6\xB7\x8A", + "\xD5\xF7" => "\xE6\xB6\xBD", + "\xD5\xF8" => "\xE6\xB7\xAD", + "\xD5\xF9" => "\xE6\xB7\xB0", + "\xD5\xFA" => "\xE6\xB6\xBA", + "\xD5\xFB" => "\xE6\xB7\x95", + "\xD5\xFC" => "\xE6\xB7\x82", + "\xD5\xFD" => "\xE6\xB7\x8F", + "\xD5\xFE" => "\xE6\xB7\x89", + "\xD6\x40" => "\xE6\xB7\x90", + "\xD6\x41" => "\xE6\xB7\xB2", + "\xD6\x42" => "\xE6\xB7\x93", + "\xD6\x43" => "\xE6\xB7\xBD", + "\xD6\x44" => "\xE6\xB7\x97", + "\xD6\x45" => "\xE6\xB7\x8D", + "\xD6\x46" => "\xE6\xB7\xA3", + "\xD6\x47" => "\xE6\xB6\xBB", + "\xD6\x48" => "\xE7\x83\xBA", + "\xD6\x49" => "\xE7\x84\x8D", + "\xD6\x4A" => "\xE7\x83\xB7", + "\xD6\x4B" => "\xE7\x84\x97", + "\xD6\x4C" => "\xE7\x83\xB4", + "\xD6\x4D" => "\xE7\x84\x8C", + "\xD6\x4E" => "\xE7\x83\xB0", + "\xD6\x4F" => "\xE7\x84\x84", + "\xD6\x50" => "\xE7\x83\xB3", + "\xD6\x51" => "\xE7\x84\x90", + "\xD6\x52" => "\xE7\x83\xBC", + "\xD6\x53" => "\xE7\x83\xBF", + "\xD6\x54" => "\xE7\x84\x86", + "\xD6\x55" => "\xE7\x84\x93", + "\xD6\x56" => "\xE7\x84\x80", + "\xD6\x57" => "\xE7\x83\xB8", + "\xD6\x58" => "\xE7\x83\xB6", + "\xD6\x59" => "\xE7\x84\x8B", + "\xD6\x5A" => "\xE7\x84\x82", + "\xD6\x5B" => "\xE7\x84\x8E", + "\xD6\x5C" => "\xE7\x89\xBE", + "\xD6\x5D" => "\xE7\x89\xBB", + "\xD6\x5E" => "\xE7\x89\xBC", + "\xD6\x5F" => "\xE7\x89\xBF", + "\xD6\x60" => "\xE7\x8C\x9D", + "\xD6\x61" => "\xE7\x8C\x97", + "\xD6\x62" => "\xE7\x8C\x87", + "\xD6\x63" => "\xE7\x8C\x91", + "\xD6\x64" => "\xE7\x8C\x98", + "\xD6\x65" => "\xE7\x8C\x8A", + "\xD6\x66" => "\xE7\x8C\x88", + "\xD6\x67" => "\xE7\x8B\xBF", + "\xD6\x68" => "\xE7\x8C\x8F", + "\xD6\x69" => "\xE7\x8C\x9E", + "\xD6\x6A" => "\xE7\x8E\x88", + "\xD6\x6B" => "\xE7\x8F\xB6", + "\xD6\x6C" => "\xE7\x8F\xB8", + "\xD6\x6D" => "\xE7\x8F\xB5", + "\xD6\x6E" => "\xE7\x90\x84", + "\xD6\x6F" => "\xE7\x90\x81", + "\xD6\x70" => "\xE7\x8F\xBD", + "\xD6\x71" => "\xE7\x90\x87", + "\xD6\x72" => "\xE7\x90\x80", + "\xD6\x73" => "\xE7\x8F\xBA", + "\xD6\x74" => "\xE7\x8F\xBC", + "\xD6\x75" => "\xE7\x8F\xBF", + "\xD6\x76" => "\xE7\x90\x8C", + "\xD6\x77" => "\xE7\x90\x8B", + "\xD6\x78" => "\xE7\x8F\xB4", + "\xD6\x79" => "\xE7\x90\x88", + "\xD6\x7A" => "\xE7\x95\xA4", + "\xD6\x7B" => "\xE7\x95\xA3", + "\xD6\x7C" => "\xE7\x97\x8E", + "\xD6\x7D" => "\xE7\x97\x92", + "\xD6\x7E" => "\xE7\x97\x8F", + "\xD6\xA1" => "\xE7\x97\x8B", + "\xD6\xA2" => "\xE7\x97\x8C", + "\xD6\xA3" => "\xE7\x97\x91", + "\xD6\xA4" => "\xE7\x97\x90", + "\xD6\xA5" => "\xE7\x9A\x8F", + "\xD6\xA6" => "\xE7\x9A\x89", + "\xD6\xA7" => "\xE7\x9B\x93", + "\xD6\xA8" => "\xE7\x9C\xB9", + "\xD6\xA9" => "\xE7\x9C\xAF", + "\xD6\xAA" => "\xE7\x9C\xAD", + "\xD6\xAB" => "\xE7\x9C\xB1", + "\xD6\xAC" => "\xE7\x9C\xB2", + "\xD6\xAD" => "\xE7\x9C\xB4", + "\xD6\xAE" => "\xE7\x9C\xB3", + "\xD6\xAF" => "\xE7\x9C\xBD", + "\xD6\xB0" => "\xE7\x9C\xA5", + "\xD6\xB1" => "\xE7\x9C\xBB", + "\xD6\xB2" => "\xE7\x9C\xB5", + "\xD6\xB3" => "\xE7\xA1\x88", + "\xD6\xB4" => "\xE7\xA1\x92", + "\xD6\xB5" => "\xE7\xA1\x89", + "\xD6\xB6" => "\xE7\xA1\x8D", + "\xD6\xB7" => "\xE7\xA1\x8A", + "\xD6\xB8" => "\xE7\xA1\x8C", + "\xD6\xB9" => "\xE7\xA0\xA6", + "\xD6\xBA" => "\xE7\xA1\x85", + "\xD6\xBB" => "\xE7\xA1\x90", + "\xD6\xBC" => "\xE7\xA5\xA4", + "\xD6\xBD" => "\xE7\xA5\xA7", + "\xD6\xBE" => "\xE7\xA5\xA9", + "\xD6\xBF" => "\xE7\xA5\xAA", + "\xD6\xC0" => "\xE7\xA5\xA3", + "\xD6\xC1" => "\xE7\xA5\xAB", + "\xD6\xC2" => "\xE7\xA5\xA1", + "\xD6\xC3" => "\xE7\xA6\xBB", + "\xD6\xC4" => "\xE7\xA7\xBA", + "\xD6\xC5" => "\xE7\xA7\xB8", + "\xD6\xC6" => "\xE7\xA7\xB6", + "\xD6\xC7" => "\xE7\xA7\xB7", + "\xD6\xC8" => "\xE7\xAA\x8F", + "\xD6\xC9" => "\xE7\xAA\x94", + "\xD6\xCA" => "\xE7\xAA\x90", + "\xD6\xCB" => "\xE7\xAC\xB5", + "\xD6\xCC" => "\xE7\xAD\x87", + "\xD6\xCD" => "\xE7\xAC\xB4", + "\xD6\xCE" => "\xE7\xAC\xA5", + "\xD6\xCF" => "\xE7\xAC\xB0", + "\xD6\xD0" => "\xE7\xAC\xA2", + "\xD6\xD1" => "\xE7\xAC\xA4", + "\xD6\xD2" => "\xE7\xAC\xB3", + "\xD6\xD3" => "\xE7\xAC\x98", + "\xD6\xD4" => "\xE7\xAC\xAA", + "\xD6\xD5" => "\xE7\xAC\x9D", + "\xD6\xD6" => "\xE7\xAC\xB1", + "\xD6\xD7" => "\xE7\xAC\xAB", + "\xD6\xD8" => "\xE7\xAC\xAD", + "\xD6\xD9" => "\xE7\xAC\xAF", + "\xD6\xDA" => "\xE7\xAC\xB2", + "\xD6\xDB" => "\xE7\xAC\xB8", + "\xD6\xDC" => "\xE7\xAC\x9A", + "\xD6\xDD" => "\xE7\xAC\xA3", + "\xD6\xDE" => "\xE7\xB2\x94", + "\xD6\xDF" => "\xE7\xB2\x98", + "\xD6\xE0" => "\xE7\xB2\x96", + "\xD6\xE1" => "\xE7\xB2\xA3", + "\xD6\xE2" => "\xE7\xB4\xB5", + "\xD6\xE3" => "\xE7\xB4\xBD", + "\xD6\xE4" => "\xE7\xB4\xB8", + "\xD6\xE5" => "\xE7\xB4\xB6", + "\xD6\xE6" => "\xE7\xB4\xBA", + "\xD6\xE7" => "\xE7\xB5\x85", + "\xD6\xE8" => "\xE7\xB4\xAC", + "\xD6\xE9" => "\xE7\xB4\xA9", + "\xD6\xEA" => "\xE7\xB5\x81", + "\xD6\xEB" => "\xE7\xB5\x87", + "\xD6\xEC" => "\xE7\xB4\xBE", + "\xD6\xED" => "\xE7\xB4\xBF", + "\xD6\xEE" => "\xE7\xB5\x8A", + "\xD6\xEF" => "\xE7\xB4\xBB", + "\xD6\xF0" => "\xE7\xB4\xA8", + "\xD6\xF1" => "\xE7\xBD\xA3", + "\xD6\xF2" => "\xE7\xBE\x95", + "\xD6\xF3" => "\xE7\xBE\x9C", + "\xD6\xF4" => "\xE7\xBE\x9D", + "\xD6\xF5" => "\xE7\xBE\x9B", + "\xD6\xF6" => "\xE7\xBF\x8A", + "\xD6\xF7" => "\xE7\xBF\x8B", + "\xD6\xF8" => "\xE7\xBF\x8D", + "\xD6\xF9" => "\xE7\xBF\x90", + "\xD6\xFA" => "\xE7\xBF\x91", + "\xD6\xFB" => "\xE7\xBF\x87", + "\xD6\xFC" => "\xE7\xBF\x8F", + "\xD6\xFD" => "\xE7\xBF\x89", + "\xD6\xFE" => "\xE8\x80\x9F", + "\xD7\x40" => "\xE8\x80\x9E", + "\xD7\x41" => "\xE8\x80\x9B", + "\xD7\x42" => "\xE8\x81\x87", + "\xD7\x43" => "\xE8\x81\x83", + "\xD7\x44" => "\xE8\x81\x88", + "\xD7\x45" => "\xE8\x84\x98", + "\xD7\x46" => "\xE8\x84\xA5", + "\xD7\x47" => "\xE8\x84\x99", + "\xD7\x48" => "\xE8\x84\x9B", + "\xD7\x49" => "\xE8\x84\xAD", + "\xD7\x4A" => "\xE8\x84\x9F", + "\xD7\x4B" => "\xE8\x84\xAC", + "\xD7\x4C" => "\xE8\x84\x9E", + "\xD7\x4D" => "\xE8\x84\xA1", + "\xD7\x4E" => "\xE8\x84\x95", + "\xD7\x4F" => "\xE8\x84\xA7", + "\xD7\x50" => "\xE8\x84\x9D", + "\xD7\x51" => "\xE8\x84\xA2", + "\xD7\x52" => "\xE8\x88\x91", + "\xD7\x53" => "\xE8\x88\xB8", + "\xD7\x54" => "\xE8\x88\xB3", + "\xD7\x55" => "\xE8\x88\xBA", + "\xD7\x56" => "\xE8\x88\xB4", + "\xD7\x57" => "\xE8\x88\xB2", + "\xD7\x58" => "\xE8\x89\xB4", + "\xD7\x59" => "\xE8\x8E\x90", + "\xD7\x5A" => "\xE8\x8E\xA3", + "\xD7\x5B" => "\xE8\x8E\xA8", + "\xD7\x5C" => "\xE8\x8E\x8D", + "\xD7\x5D" => "\xE8\x8D\xBA", + "\xD7\x5E" => "\xE8\x8D\xB3", + "\xD7\x5F" => "\xE8\x8E\xA4", + "\xD7\x60" => "\xE8\x8D\xB4", + "\xD7\x61" => "\xE8\x8E\x8F", + "\xD7\x62" => "\xE8\x8E\x81", + "\xD7\x63" => "\xE8\x8E\x95", + "\xD7\x64" => "\xE8\x8E\x99", + "\xD7\x65" => "\xE8\x8D\xB5", + "\xD7\x66" => "\xE8\x8E\x94", + "\xD7\x67" => "\xE8\x8E\xA9", + "\xD7\x68" => "\xE8\x8D\xBD", + "\xD7\x69" => "\xE8\x8E\x83", + "\xD7\x6A" => "\xE8\x8E\x8C", + "\xD7\x6B" => "\xE8\x8E\x9D", + "\xD7\x6C" => "\xE8\x8E\x9B", + "\xD7\x6D" => "\xE8\x8E\xAA", + "\xD7\x6E" => "\xE8\x8E\x8B", + "\xD7\x6F" => "\xE8\x8D\xBE", + "\xD7\x70" => "\xE8\x8E\xA5", + "\xD7\x71" => "\xE8\x8E\xAF", + "\xD7\x72" => "\xE8\x8E\x88", + "\xD7\x73" => "\xE8\x8E\x97", + "\xD7\x74" => "\xE8\x8E\xB0", + "\xD7\x75" => "\xE8\x8D\xBF", + "\xD7\x76" => "\xE8\x8E\xA6", + "\xD7\x77" => "\xE8\x8E\x87", + "\xD7\x78" => "\xE8\x8E\xAE", + "\xD7\x79" => "\xE8\x8D\xB6", + "\xD7\x7A" => "\xE8\x8E\x9A", + "\xD7\x7B" => "\xE8\x99\x99", + "\xD7\x7C" => "\xE8\x99\x96", + "\xD7\x7D" => "\xE8\x9A\xBF", + "\xD7\x7E" => "\xE8\x9A\xB7", + "\xD7\xA1" => "\xE8\x9B\x82", + "\xD7\xA2" => "\xE8\x9B\x81", + "\xD7\xA3" => "\xE8\x9B\x85", + "\xD7\xA4" => "\xE8\x9A\xBA", + "\xD7\xA5" => "\xE8\x9A\xB0", + "\xD7\xA6" => "\xE8\x9B\x88", + "\xD7\xA7" => "\xE8\x9A\xB9", + "\xD7\xA8" => "\xE8\x9A\xB3", + "\xD7\xA9" => "\xE8\x9A\xB8", + "\xD7\xAA" => "\xE8\x9B\x8C", + "\xD7\xAB" => "\xE8\x9A\xB4", + "\xD7\xAC" => "\xE8\x9A\xBB", + "\xD7\xAD" => "\xE8\x9A\xBC", + "\xD7\xAE" => "\xE8\x9B\x83", + "\xD7\xAF" => "\xE8\x9A\xBD", + "\xD7\xB0" => "\xE8\x9A\xBE", + "\xD7\xB1" => "\xE8\xA1\x92", + "\xD7\xB2" => "\xE8\xA2\x89", + "\xD7\xB3" => "\xE8\xA2\x95", + "\xD7\xB4" => "\xE8\xA2\xA8", + "\xD7\xB5" => "\xE8\xA2\xA2", + "\xD7\xB6" => "\xE8\xA2\xAA", + "\xD7\xB7" => "\xE8\xA2\x9A", + "\xD7\xB8" => "\xE8\xA2\x91", + "\xD7\xB9" => "\xE8\xA2\xA1", + "\xD7\xBA" => "\xE8\xA2\x9F", + "\xD7\xBB" => "\xE8\xA2\x98", + "\xD7\xBC" => "\xE8\xA2\xA7", + "\xD7\xBD" => "\xE8\xA2\x99", + "\xD7\xBE" => "\xE8\xA2\x9B", + "\xD7\xBF" => "\xE8\xA2\x97", + "\xD7\xC0" => "\xE8\xA2\xA4", + "\xD7\xC1" => "\xE8\xA2\xAC", + "\xD7\xC2" => "\xE8\xA2\x8C", + "\xD7\xC3" => "\xE8\xA2\x93", + "\xD7\xC4" => "\xE8\xA2\x8E", + "\xD7\xC5" => "\xE8\xA6\x82", + "\xD7\xC6" => "\xE8\xA7\x96", + "\xD7\xC7" => "\xE8\xA7\x99", + "\xD7\xC8" => "\xE8\xA7\x95", + "\xD7\xC9" => "\xE8\xA8\xB0", + "\xD7\xCA" => "\xE8\xA8\xA7", + "\xD7\xCB" => "\xE8\xA8\xAC", + "\xD7\xCC" => "\xE8\xA8\x9E", + "\xD7\xCD" => "\xE8\xB0\xB9", + "\xD7\xCE" => "\xE8\xB0\xBB", + "\xD7\xCF" => "\xE8\xB1\x9C", + "\xD7\xD0" => "\xE8\xB1\x9D", + "\xD7\xD1" => "\xE8\xB1\xBD", + "\xD7\xD2" => "\xE8\xB2\xA5", + "\xD7\xD3" => "\xE8\xB5\xBD", + "\xD7\xD4" => "\xE8\xB5\xBB", + "\xD7\xD5" => "\xE8\xB5\xB9", + "\xD7\xD6" => "\xE8\xB6\xBC", + "\xD7\xD7" => "\xE8\xB7\x82", + "\xD7\xD8" => "\xE8\xB6\xB9", + "\xD7\xD9" => "\xE8\xB6\xBF", + "\xD7\xDA" => "\xE8\xB7\x81", + "\xD7\xDB" => "\xE8\xBB\x98", + "\xD7\xDC" => "\xE8\xBB\x9E", + "\xD7\xDD" => "\xE8\xBB\x9D", + "\xD7\xDE" => "\xE8\xBB\x9C", + "\xD7\xDF" => "\xE8\xBB\x97", + "\xD7\xE0" => "\xE8\xBB\xA0", + "\xD7\xE1" => "\xE8\xBB\xA1", + "\xD7\xE2" => "\xE9\x80\xA4", + "\xD7\xE3" => "\xE9\x80\x8B", + "\xD7\xE4" => "\xE9\x80\x91", + "\xD7\xE5" => "\xE9\x80\x9C", + "\xD7\xE6" => "\xE9\x80\x8C", + "\xD7\xE7" => "\xE9\x80\xA1", + "\xD7\xE8" => "\xE9\x83\xAF", + "\xD7\xE9" => "\xE9\x83\xAA", + "\xD7\xEA" => "\xE9\x83\xB0", + "\xD7\xEB" => "\xE9\x83\xB4", + "\xD7\xEC" => "\xE9\x83\xB2", + "\xD7\xED" => "\xE9\x83\xB3", + "\xD7\xEE" => "\xE9\x83\x94", + "\xD7\xEF" => "\xE9\x83\xAB", + "\xD7\xF0" => "\xE9\x83\xAC", + "\xD7\xF1" => "\xE9\x83\xA9", + "\xD7\xF2" => "\xE9\x85\x96", + "\xD7\xF3" => "\xE9\x85\x98", + "\xD7\xF4" => "\xE9\x85\x9A", + "\xD7\xF5" => "\xE9\x85\x93", + "\xD7\xF6" => "\xE9\x85\x95", + "\xD7\xF7" => "\xE9\x87\xAC", + "\xD7\xF8" => "\xE9\x87\xB4", + "\xD7\xF9" => "\xE9\x87\xB1", + "\xD7\xFA" => "\xE9\x87\xB3", + "\xD7\xFB" => "\xE9\x87\xB8", + "\xD7\xFC" => "\xE9\x87\xA4", + "\xD7\xFD" => "\xE9\x87\xB9", + "\xD7\xFE" => "\xE9\x87\xAA", + "\xD8\x40" => "\xE9\x87\xAB", + "\xD8\x41" => "\xE9\x87\xB7", + "\xD8\x42" => "\xE9\x87\xA8", + "\xD8\x43" => "\xE9\x87\xAE", + "\xD8\x44" => "\xE9\x95\xBA", + "\xD8\x45" => "\xE9\x96\x86", + "\xD8\x46" => "\xE9\x96\x88", + "\xD8\x47" => "\xE9\x99\xBC", + "\xD8\x48" => "\xE9\x99\xAD", + "\xD8\x49" => "\xE9\x99\xAB", + "\xD8\x4A" => "\xE9\x99\xB1", + "\xD8\x4B" => "\xE9\x99\xAF", + "\xD8\x4C" => "\xE9\x9A\xBF", + "\xD8\x4D" => "\xE9\x9D\xAA", + "\xD8\x4E" => "\xE9\xA0\x84", + "\xD8\x4F" => "\xE9\xA3\xA5", + "\xD8\x50" => "\xE9\xA6\x97", + "\xD8\x51" => "\xE5\x82\x9B", + "\xD8\x52" => "\xE5\x82\x95", + "\xD8\x53" => "\xE5\x82\x94", + "\xD8\x54" => "\xE5\x82\x9E", + "\xD8\x55" => "\xE5\x82\x8B", + "\xD8\x56" => "\xE5\x82\xA3", + "\xD8\x57" => "\xE5\x82\x83", + "\xD8\x58" => "\xE5\x82\x8C", + "\xD8\x59" => "\xE5\x82\x8E", + "\xD8\x5A" => "\xE5\x82\x9D", + "\xD8\x5B" => "\xE5\x81\xA8", + "\xD8\x5C" => "\xE5\x82\x9C", + "\xD8\x5D" => "\xE5\x82\x92", + "\xD8\x5E" => "\xE5\x82\x82", + "\xD8\x5F" => "\xE5\x82\x87", + "\xD8\x60" => "\xE5\x85\x9F", + "\xD8\x61" => "\xE5\x87\x94", + "\xD8\x62" => "\xE5\x8C\x92", + "\xD8\x63" => "\xE5\x8C\x91", + "\xD8\x64" => "\xE5\x8E\xA4", + "\xD8\x65" => "\xE5\x8E\xA7", + "\xD8\x66" => "\xE5\x96\x91", + "\xD8\x67" => "\xE5\x96\xA8", + "\xD8\x68" => "\xE5\x96\xA5", + "\xD8\x69" => "\xE5\x96\xAD", + "\xD8\x6A" => "\xE5\x95\xB7", + "\xD8\x6B" => "\xE5\x99\x85", + "\xD8\x6C" => "\xE5\x96\xA2", + "\xD8\x6D" => "\xE5\x96\x93", + "\xD8\x6E" => "\xE5\x96\x88", + "\xD8\x6F" => "\xE5\x96\x8F", + "\xD8\x70" => "\xE5\x96\xB5", + "\xD8\x71" => "\xE5\x96\x81", + "\xD8\x72" => "\xE5\x96\xA3", + "\xD8\x73" => "\xE5\x96\x92", + "\xD8\x74" => "\xE5\x96\xA4", + "\xD8\x75" => "\xE5\x95\xBD", + "\xD8\x76" => "\xE5\x96\x8C", + "\xD8\x77" => "\xE5\x96\xA6", + "\xD8\x78" => "\xE5\x95\xBF", + "\xD8\x79" => "\xE5\x96\x95", + "\xD8\x7A" => "\xE5\x96\xA1", + "\xD8\x7B" => "\xE5\x96\x8E", + "\xD8\x7C" => "\xE5\x9C\x8C", + "\xD8\x7D" => "\xE5\xA0\xA9", + "\xD8\x7E" => "\xE5\xA0\xB7", + "\xD8\xA1" => "\xE5\xA0\x99", + "\xD8\xA2" => "\xE5\xA0\x9E", + "\xD8\xA3" => "\xE5\xA0\xA7", + "\xD8\xA4" => "\xE5\xA0\xA3", + "\xD8\xA5" => "\xE5\xA0\xA8", + "\xD8\xA6" => "\xE5\x9F\xB5", + "\xD8\xA7" => "\xE5\xA1\x88", + "\xD8\xA8" => "\xE5\xA0\xA5", + "\xD8\xA9" => "\xE5\xA0\x9C", + "\xD8\xAA" => "\xE5\xA0\x9B", + "\xD8\xAB" => "\xE5\xA0\xB3", + "\xD8\xAC" => "\xE5\xA0\xBF", + "\xD8\xAD" => "\xE5\xA0\xB6", + "\xD8\xAE" => "\xE5\xA0\xAE", + "\xD8\xAF" => "\xE5\xA0\xB9", + "\xD8\xB0" => "\xE5\xA0\xB8", + "\xD8\xB1" => "\xE5\xA0\xAD", + "\xD8\xB2" => "\xE5\xA0\xAC", + "\xD8\xB3" => "\xE5\xA0\xBB", + "\xD8\xB4" => "\xE5\xA5\xA1", + "\xD8\xB5" => "\xE5\xAA\xAF", + "\xD8\xB6" => "\xE5\xAA\x94", + "\xD8\xB7" => "\xE5\xAA\x9F", + "\xD8\xB8" => "\xE5\xA9\xBA", + "\xD8\xB9" => "\xE5\xAA\xA2", + "\xD8\xBA" => "\xE5\xAA\x9E", + "\xD8\xBB" => "\xE5\xA9\xB8", + "\xD8\xBC" => "\xE5\xAA\xA6", + "\xD8\xBD" => "\xE5\xA9\xBC", + "\xD8\xBE" => "\xE5\xAA\xA5", + "\xD8\xBF" => "\xE5\xAA\xAC", + "\xD8\xC0" => "\xE5\xAA\x95", + "\xD8\xC1" => "\xE5\xAA\xAE", + "\xD8\xC2" => "\xE5\xA8\xB7", + "\xD8\xC3" => "\xE5\xAA\x84", + "\xD8\xC4" => "\xE5\xAA\x8A", + "\xD8\xC5" => "\xE5\xAA\x97", + "\xD8\xC6" => "\xE5\xAA\x83", + "\xD8\xC7" => "\xE5\xAA\x8B", + "\xD8\xC8" => "\xE5\xAA\xA9", + "\xD8\xC9" => "\xE5\xA9\xBB", + "\xD8\xCA" => "\xE5\xA9\xBD", + "\xD8\xCB" => "\xE5\xAA\x8C", + "\xD8\xCC" => "\xE5\xAA\x9C", + "\xD8\xCD" => "\xE5\xAA\x8F", + "\xD8\xCE" => "\xE5\xAA\x93", + "\xD8\xCF" => "\xE5\xAA\x9D", + "\xD8\xD0" => "\xE5\xAF\xAA", + "\xD8\xD1" => "\xE5\xAF\x8D", + "\xD8\xD2" => "\xE5\xAF\x8B", + "\xD8\xD3" => "\xE5\xAF\x94", + "\xD8\xD4" => "\xE5\xAF\x91", + "\xD8\xD5" => "\xE5\xAF\x8A", + "\xD8\xD6" => "\xE5\xAF\x8E", + "\xD8\xD7" => "\xE5\xB0\x8C", + "\xD8\xD8" => "\xE5\xB0\xB0", + "\xD8\xD9" => "\xE5\xB4\xB7", + "\xD8\xDA" => "\xE5\xB5\x83", + "\xD8\xDB" => "\xE5\xB5\xAB", + "\xD8\xDC" => "\xE5\xB5\x81", + "\xD8\xDD" => "\xE5\xB5\x8B", + "\xD8\xDE" => "\xE5\xB4\xBF", + "\xD8\xDF" => "\xE5\xB4\xB5", + "\xD8\xE0" => "\xE5\xB5\x91", + "\xD8\xE1" => "\xE5\xB5\x8E", + "\xD8\xE2" => "\xE5\xB5\x95", + "\xD8\xE3" => "\xE5\xB4\xB3", + "\xD8\xE4" => "\xE5\xB4\xBA", + "\xD8\xE5" => "\xE5\xB5\x92", + "\xD8\xE6" => "\xE5\xB4\xBD", + "\xD8\xE7" => "\xE5\xB4\xB1", + "\xD8\xE8" => "\xE5\xB5\x99", + "\xD8\xE9" => "\xE5\xB5\x82", + "\xD8\xEA" => "\xE5\xB4\xB9", + "\xD8\xEB" => "\xE5\xB5\x89", + "\xD8\xEC" => "\xE5\xB4\xB8", + "\xD8\xED" => "\xE5\xB4\xBC", + "\xD8\xEE" => "\xE5\xB4\xB2", + "\xD8\xEF" => "\xE5\xB4\xB6", + "\xD8\xF0" => "\xE5\xB5\x80", + "\xD8\xF1" => "\xE5\xB5\x85", + "\xD8\xF2" => "\xE5\xB9\x84", + "\xD8\xF3" => "\xE5\xB9\x81", + "\xD8\xF4" => "\xE5\xBD\x98", + "\xD8\xF5" => "\xE5\xBE\xA6", + "\xD8\xF6" => "\xE5\xBE\xA5", + "\xD8\xF7" => "\xE5\xBE\xAB", + "\xD8\xF8" => "\xE6\x83\x89", + "\xD8\xF9" => "\xE6\x82\xB9", + "\xD8\xFA" => "\xE6\x83\x8C", + "\xD8\xFB" => "\xE6\x83\xA2", + "\xD8\xFC" => "\xE6\x83\x8E", + "\xD8\xFD" => "\xE6\x83\x84", + "\xD8\xFE" => "\xE6\x84\x94", + "\xD9\x40" => "\xE6\x83\xB2", + "\xD9\x41" => "\xE6\x84\x8A", + "\xD9\x42" => "\xE6\x84\x96", + "\xD9\x43" => "\xE6\x84\x85", + "\xD9\x44" => "\xE6\x83\xB5", + "\xD9\x45" => "\xE6\x84\x93", + "\xD9\x46" => "\xE6\x83\xB8", + "\xD9\x47" => "\xE6\x83\xBC", + "\xD9\x48" => "\xE6\x83\xBE", + "\xD9\x49" => "\xE6\x83\x81", + "\xD9\x4A" => "\xE6\x84\x83", + "\xD9\x4B" => "\xE6\x84\x98", + "\xD9\x4C" => "\xE6\x84\x9D", + "\xD9\x4D" => "\xE6\x84\x90", + "\xD9\x4E" => "\xE6\x83\xBF", + "\xD9\x4F" => "\xE6\x84\x84", + "\xD9\x50" => "\xE6\x84\x8B", + "\xD9\x51" => "\xE6\x89\x8A", + "\xD9\x52" => "\xE6\x8E\x94", + "\xD9\x53" => "\xE6\x8E\xB1", + "\xD9\x54" => "\xE6\x8E\xB0", + "\xD9\x55" => "\xE6\x8F\x8E", + "\xD9\x56" => "\xE6\x8F\xA5", + "\xD9\x57" => "\xE6\x8F\xA8", + "\xD9\x58" => "\xE6\x8F\xAF", + "\xD9\x59" => "\xE6\x8F\x83", + "\xD9\x5A" => "\xE6\x92\x9D", + "\xD9\x5B" => "\xE6\x8F\xB3", + "\xD9\x5C" => "\xE6\x8F\x8A", + "\xD9\x5D" => "\xE6\x8F\xA0", + "\xD9\x5E" => "\xE6\x8F\xB6", + "\xD9\x5F" => "\xE6\x8F\x95", + "\xD9\x60" => "\xE6\x8F\xB2", + "\xD9\x61" => "\xE6\x8F\xB5", + "\xD9\x62" => "\xE6\x91\xA1", + "\xD9\x63" => "\xE6\x8F\x9F", + "\xD9\x64" => "\xE6\x8E\xBE", + "\xD9\x65" => "\xE6\x8F\x9D", + "\xD9\x66" => "\xE6\x8F\x9C", + "\xD9\x67" => "\xE6\x8F\x84", + "\xD9\x68" => "\xE6\x8F\x98", + "\xD9\x69" => "\xE6\x8F\x93", + "\xD9\x6A" => "\xE6\x8F\x82", + "\xD9\x6B" => "\xE6\x8F\x87", + "\xD9\x6C" => "\xE6\x8F\x8C", + "\xD9\x6D" => "\xE6\x8F\x8B", + "\xD9\x6E" => "\xE6\x8F\x88", + "\xD9\x6F" => "\xE6\x8F\xB0", + "\xD9\x70" => "\xE6\x8F\x97", + "\xD9\x71" => "\xE6\x8F\x99", + "\xD9\x72" => "\xE6\x94\xB2", + "\xD9\x73" => "\xE6\x95\xA7", + "\xD9\x74" => "\xE6\x95\xAA", + "\xD9\x75" => "\xE6\x95\xA4", + "\xD9\x76" => "\xE6\x95\x9C", + "\xD9\x77" => "\xE6\x95\xA8", + "\xD9\x78" => "\xE6\x95\xA5", + "\xD9\x79" => "\xE6\x96\x8C", + "\xD9\x7A" => "\xE6\x96\x9D", + "\xD9\x7B" => "\xE6\x96\x9E", + "\xD9\x7C" => "\xE6\x96\xAE", + "\xD9\x7D" => "\xE6\x97\x90", + "\xD9\x7E" => "\xE6\x97\x92", + "\xD9\xA1" => "\xE6\x99\xBC", + "\xD9\xA2" => "\xE6\x99\xAC", + "\xD9\xA3" => "\xE6\x99\xBB", + "\xD9\xA4" => "\xE6\x9A\x80", + "\xD9\xA5" => "\xE6\x99\xB1", + "\xD9\xA6" => "\xE6\x99\xB9", + "\xD9\xA7" => "\xE6\x99\xAA", + "\xD9\xA8" => "\xE6\x99\xB2", + "\xD9\xA9" => "\xE6\x9C\x81", + "\xD9\xAA" => "\xE6\xA4\x8C", + "\xD9\xAB" => "\xE6\xA3\x93", + "\xD9\xAC" => "\xE6\xA4\x84", + "\xD9\xAD" => "\xE6\xA3\x9C", + "\xD9\xAE" => "\xE6\xA4\xAA", + "\xD9\xAF" => "\xE6\xA3\xAC", + "\xD9\xB0" => "\xE6\xA3\xAA", + "\xD9\xB1" => "\xE6\xA3\xB1", + "\xD9\xB2" => "\xE6\xA4\x8F", + "\xD9\xB3" => "\xE6\xA3\x96", + "\xD9\xB4" => "\xE6\xA3\xB7", + "\xD9\xB5" => "\xE6\xA3\xAB", + "\xD9\xB6" => "\xE6\xA3\xA4", + "\xD9\xB7" => "\xE6\xA3\xB6", + "\xD9\xB8" => "\xE6\xA4\x93", + "\xD9\xB9" => "\xE6\xA4\x90", + "\xD9\xBA" => "\xE6\xA3\xB3", + "\xD9\xBB" => "\xE6\xA3\xA1", + "\xD9\xBC" => "\xE6\xA4\x87", + "\xD9\xBD" => "\xE6\xA3\x8C", + "\xD9\xBE" => "\xE6\xA4\x88", + "\xD9\xBF" => "\xE6\xA5\xB0", + "\xD9\xC0" => "\xE6\xA2\xB4", + "\xD9\xC1" => "\xE6\xA4\x91", + "\xD9\xC2" => "\xE6\xA3\xAF", + "\xD9\xC3" => "\xE6\xA3\x86", + "\xD9\xC4" => "\xE6\xA4\x94", + "\xD9\xC5" => "\xE6\xA3\xB8", + "\xD9\xC6" => "\xE6\xA3\x90", + "\xD9\xC7" => "\xE6\xA3\xBD", + "\xD9\xC8" => "\xE6\xA3\xBC", + "\xD9\xC9" => "\xE6\xA3\xA8", + "\xD9\xCA" => "\xE6\xA4\x8B", + "\xD9\xCB" => "\xE6\xA4\x8A", + "\xD9\xCC" => "\xE6\xA4\x97", + "\xD9\xCD" => "\xE6\xA3\x8E", + "\xD9\xCE" => "\xE6\xA3\x88", + "\xD9\xCF" => "\xE6\xA3\x9D", + "\xD9\xD0" => "\xE6\xA3\x9E", + "\xD9\xD1" => "\xE6\xA3\xA6", + "\xD9\xD2" => "\xE6\xA3\xB4", + "\xD9\xD3" => "\xE6\xA3\x91", + "\xD9\xD4" => "\xE6\xA4\x86", + "\xD9\xD5" => "\xE6\xA3\x94", + "\xD9\xD6" => "\xE6\xA3\xA9", + "\xD9\xD7" => "\xE6\xA4\x95", + "\xD9\xD8" => "\xE6\xA4\xA5", + "\xD9\xD9" => "\xE6\xA3\x87", + "\xD9\xDA" => "\xE6\xAC\xB9", + "\xD9\xDB" => "\xE6\xAC\xBB", + "\xD9\xDC" => "\xE6\xAC\xBF", + "\xD9\xDD" => "\xE6\xAC\xBC", + "\xD9\xDE" => "\xE6\xAE\x94", + "\xD9\xDF" => "\xE6\xAE\x97", + "\xD9\xE0" => "\xE6\xAE\x99", + "\xD9\xE1" => "\xE6\xAE\x95", + "\xD9\xE2" => "\xE6\xAE\xBD", + "\xD9\xE3" => "\xE6\xAF\xB0", + "\xD9\xE4" => "\xE6\xAF\xB2", + "\xD9\xE5" => "\xE6\xAF\xB3", + "\xD9\xE6" => "\xE6\xB0\xB0", + "\xD9\xE7" => "\xE6\xB7\xBC", + "\xD9\xE8" => "\xE6\xB9\x86", + "\xD9\xE9" => "\xE6\xB9\x87", + "\xD9\xEA" => "\xE6\xB8\x9F", + "\xD9\xEB" => "\xE6\xB9\x89", + "\xD9\xEC" => "\xE6\xBA\x88", + "\xD9\xED" => "\xE6\xB8\xBC", + "\xD9\xEE" => "\xE6\xB8\xBD", + "\xD9\xEF" => "\xE6\xB9\x85", + "\xD9\xF0" => "\xE6\xB9\xA2", + "\xD9\xF1" => "\xE6\xB8\xAB", + "\xD9\xF2" => "\xE6\xB8\xBF", + "\xD9\xF3" => "\xE6\xB9\x81", + "\xD9\xF4" => "\xE6\xB9\x9D", + "\xD9\xF5" => "\xE6\xB9\xB3", + "\xD9\xF6" => "\xE6\xB8\x9C", + "\xD9\xF7" => "\xE6\xB8\xB3", + "\xD9\xF8" => "\xE6\xB9\x8B", + "\xD9\xF9" => "\xE6\xB9\x80", + "\xD9\xFA" => "\xE6\xB9\x91", + "\xD9\xFB" => "\xE6\xB8\xBB", + "\xD9\xFC" => "\xE6\xB8\x83", + "\xD9\xFD" => "\xE6\xB8\xAE", + "\xD9\xFE" => "\xE6\xB9\x9E", + "\xDA\x40" => "\xE6\xB9\xA8", + "\xDA\x41" => "\xE6\xB9\x9C", + "\xDA\x42" => "\xE6\xB9\xA1", + "\xDA\x43" => "\xE6\xB8\xB1", + "\xDA\x44" => "\xE6\xB8\xA8", + "\xDA\x45" => "\xE6\xB9\xA0", + "\xDA\x46" => "\xE6\xB9\xB1", + "\xDA\x47" => "\xE6\xB9\xAB", + "\xDA\x48" => "\xE6\xB8\xB9", + "\xDA\x49" => "\xE6\xB8\xA2", + "\xDA\x4A" => "\xE6\xB8\xB0", + "\xDA\x4B" => "\xE6\xB9\x93", + "\xDA\x4C" => "\xE6\xB9\xA5", + "\xDA\x4D" => "\xE6\xB8\xA7", + "\xDA\x4E" => "\xE6\xB9\xB8", + "\xDA\x4F" => "\xE6\xB9\xA4", + "\xDA\x50" => "\xE6\xB9\xB7", + "\xDA\x51" => "\xE6\xB9\x95", + "\xDA\x52" => "\xE6\xB9\xB9", + "\xDA\x53" => "\xE6\xB9\x92", + "\xDA\x54" => "\xE6\xB9\xA6", + "\xDA\x55" => "\xE6\xB8\xB5", + "\xDA\x56" => "\xE6\xB8\xB6", + "\xDA\x57" => "\xE6\xB9\x9A", + "\xDA\x58" => "\xE7\x84\xA0", + "\xDA\x59" => "\xE7\x84\x9E", + "\xDA\x5A" => "\xE7\x84\xAF", + "\xDA\x5B" => "\xE7\x83\xBB", + "\xDA\x5C" => "\xE7\x84\xAE", + "\xDA\x5D" => "\xE7\x84\xB1", + "\xDA\x5E" => "\xE7\x84\xA3", + "\xDA\x5F" => "\xE7\x84\xA5", + "\xDA\x60" => "\xE7\x84\xA2", + "\xDA\x61" => "\xE7\x84\xB2", + "\xDA\x62" => "\xE7\x84\x9F", + "\xDA\x63" => "\xE7\x84\xA8", + "\xDA\x64" => "\xE7\x84\xBA", + "\xDA\x65" => "\xE7\x84\x9B", + "\xDA\x66" => "\xE7\x89\x8B", + "\xDA\x67" => "\xE7\x89\x9A", + "\xDA\x68" => "\xE7\x8A\x88", + "\xDA\x69" => "\xE7\x8A\x89", + "\xDA\x6A" => "\xE7\x8A\x86", + "\xDA\x6B" => "\xE7\x8A\x85", + "\xDA\x6C" => "\xE7\x8A\x8B", + "\xDA\x6D" => "\xE7\x8C\x92", + "\xDA\x6E" => "\xE7\x8C\x8B", + "\xDA\x6F" => "\xE7\x8C\xB0", + "\xDA\x70" => "\xE7\x8C\xA2", + "\xDA\x71" => "\xE7\x8C\xB1", + "\xDA\x72" => "\xE7\x8C\xB3", + "\xDA\x73" => "\xE7\x8C\xA7", + "\xDA\x74" => "\xE7\x8C\xB2", + "\xDA\x75" => "\xE7\x8C\xAD", + "\xDA\x76" => "\xE7\x8C\xA6", + "\xDA\x77" => "\xE7\x8C\xA3", + "\xDA\x78" => "\xE7\x8C\xB5", + "\xDA\x79" => "\xE7\x8C\x8C", + "\xDA\x7A" => "\xE7\x90\xAE", + "\xDA\x7B" => "\xE7\x90\xAC", + "\xDA\x7C" => "\xE7\x90\xB0", + "\xDA\x7D" => "\xE7\x90\xAB", + "\xDA\x7E" => "\xE7\x90\x96", + "\xDA\xA1" => "\xE7\x90\x9A", + "\xDA\xA2" => "\xE7\x90\xA1", + "\xDA\xA3" => "\xE7\x90\xAD", + "\xDA\xA4" => "\xE7\x90\xB1", + "\xDA\xA5" => "\xE7\x90\xA4", + "\xDA\xA6" => "\xE7\x90\xA3", + "\xDA\xA7" => "\xE7\x90\x9D", + "\xDA\xA8" => "\xE7\x90\xA9", + "\xDA\xA9" => "\xE7\x90\xA0", + "\xDA\xAA" => "\xE7\x90\xB2", + "\xDA\xAB" => "\xE7\x93\xBB", + "\xDA\xAC" => "\xE7\x94\xAF", + "\xDA\xAD" => "\xE7\x95\xAF", + "\xDA\xAE" => "\xE7\x95\xAC", + "\xDA\xAF" => "\xE7\x97\xA7", + "\xDA\xB0" => "\xE7\x97\x9A", + "\xDA\xB1" => "\xE7\x97\xA1", + "\xDA\xB2" => "\xE7\x97\xA6", + "\xDA\xB3" => "\xE7\x97\x9D", + "\xDA\xB4" => "\xE7\x97\x9F", + "\xDA\xB5" => "\xE7\x97\xA4", + "\xDA\xB6" => "\xE7\x97\x97", + "\xDA\xB7" => "\xE7\x9A\x95", + "\xDA\xB8" => "\xE7\x9A\x92", + "\xDA\xB9" => "\xE7\x9B\x9A", + "\xDA\xBA" => "\xE7\x9D\x86", + "\xDA\xBB" => "\xE7\x9D\x87", + "\xDA\xBC" => "\xE7\x9D\x84", + "\xDA\xBD" => "\xE7\x9D\x8D", + "\xDA\xBE" => "\xE7\x9D\x85", + "\xDA\xBF" => "\xE7\x9D\x8A", + "\xDA\xC0" => "\xE7\x9D\x8E", + "\xDA\xC1" => "\xE7\x9D\x8B", + "\xDA\xC2" => "\xE7\x9D\x8C", + "\xDA\xC3" => "\xE7\x9F\x9E", + "\xDA\xC4" => "\xE7\x9F\xAC", + "\xDA\xC5" => "\xE7\xA1\xA0", + "\xDA\xC6" => "\xE7\xA1\xA4", + "\xDA\xC7" => "\xE7\xA1\xA5", + "\xDA\xC8" => "\xE7\xA1\x9C", + "\xDA\xC9" => "\xE7\xA1\xAD", + "\xDA\xCA" => "\xE7\xA1\xB1", + "\xDA\xCB" => "\xE7\xA1\xAA", + "\xDA\xCC" => "\xE7\xA1\xAE", + "\xDA\xCD" => "\xE7\xA1\xB0", + "\xDA\xCE" => "\xE7\xA1\xA9", + "\xDA\xCF" => "\xE7\xA1\xA8", + "\xDA\xD0" => "\xE7\xA1\x9E", + "\xDA\xD1" => "\xE7\xA1\xA2", + "\xDA\xD2" => "\xE7\xA5\xB4", + "\xDA\xD3" => "\xE7\xA5\xB3", + "\xDA\xD4" => "\xE7\xA5\xB2", + "\xDA\xD5" => "\xE7\xA5\xB0", + "\xDA\xD6" => "\xE7\xA8\x82", + "\xDA\xD7" => "\xE7\xA8\x8A", + "\xDA\xD8" => "\xE7\xA8\x83", + "\xDA\xD9" => "\xE7\xA8\x8C", + "\xDA\xDA" => "\xE7\xA8\x84", + "\xDA\xDB" => "\xE7\xAA\x99", + "\xDA\xDC" => "\xE7\xAB\xA6", + "\xDA\xDD" => "\xE7\xAB\xA4", + "\xDA\xDE" => "\xE7\xAD\x8A", + "\xDA\xDF" => "\xE7\xAC\xBB", + "\xDA\xE0" => "\xE7\xAD\x84", + "\xDA\xE1" => "\xE7\xAD\x88", + "\xDA\xE2" => "\xE7\xAD\x8C", + "\xDA\xE3" => "\xE7\xAD\x8E", + "\xDA\xE4" => "\xE7\xAD\x80", + "\xDA\xE5" => "\xE7\xAD\x98", + "\xDA\xE6" => "\xE7\xAD\x85", + "\xDA\xE7" => "\xE7\xB2\xA2", + "\xDA\xE8" => "\xE7\xB2\x9E", + "\xDA\xE9" => "\xE7\xB2\xA8", + "\xDA\xEA" => "\xE7\xB2\xA1", + "\xDA\xEB" => "\xE7\xB5\x98", + "\xDA\xEC" => "\xE7\xB5\xAF", + "\xDA\xED" => "\xE7\xB5\xA3", + "\xDA\xEE" => "\xE7\xB5\x93", + "\xDA\xEF" => "\xE7\xB5\x96", + "\xDA\xF0" => "\xE7\xB5\xA7", + "\xDA\xF1" => "\xE7\xB5\xAA", + "\xDA\xF2" => "\xE7\xB5\x8F", + "\xDA\xF3" => "\xE7\xB5\xAD", + "\xDA\xF4" => "\xE7\xB5\x9C", + "\xDA\xF5" => "\xE7\xB5\xAB", + "\xDA\xF6" => "\xE7\xB5\x92", + "\xDA\xF7" => "\xE7\xB5\x94", + "\xDA\xF8" => "\xE7\xB5\xA9", + "\xDA\xF9" => "\xE7\xB5\x91", + "\xDA\xFA" => "\xE7\xB5\x9F", + "\xDA\xFB" => "\xE7\xB5\x8E", + "\xDA\xFC" => "\xE7\xBC\xBE", + "\xDA\xFD" => "\xE7\xBC\xBF", + "\xDA\xFE" => "\xE7\xBD\xA5", + "\xDB\x40" => "\xE7\xBD\xA6", + "\xDB\x41" => "\xE7\xBE\xA2", + "\xDB\x42" => "\xE7\xBE\xA0", + "\xDB\x43" => "\xE7\xBE\xA1", + "\xDB\x44" => "\xE7\xBF\x97", + "\xDB\x45" => "\xE8\x81\x91", + "\xDB\x46" => "\xE8\x81\x8F", + "\xDB\x47" => "\xE8\x81\x90", + "\xDB\x48" => "\xE8\x83\xBE", + "\xDB\x49" => "\xE8\x83\x94", + "\xDB\x4A" => "\xE8\x85\x83", + "\xDB\x4B" => "\xE8\x85\x8A", + "\xDB\x4C" => "\xE8\x85\x92", + "\xDB\x4D" => "\xE8\x85\x8F", + "\xDB\x4E" => "\xE8\x85\x87", + "\xDB\x4F" => "\xE8\x84\xBD", + "\xDB\x50" => "\xE8\x85\x8D", + "\xDB\x51" => "\xE8\x84\xBA", + "\xDB\x52" => "\xE8\x87\xA6", + "\xDB\x53" => "\xE8\x87\xAE", + "\xDB\x54" => "\xE8\x87\xB7", + "\xDB\x55" => "\xE8\x87\xB8", + "\xDB\x56" => "\xE8\x87\xB9", + "\xDB\x57" => "\xE8\x88\x84", + "\xDB\x58" => "\xE8\x88\xBC", + "\xDB\x59" => "\xE8\x88\xBD", + "\xDB\x5A" => "\xE8\x88\xBF", + "\xDB\x5B" => "\xE8\x89\xB5", + "\xDB\x5C" => "\xE8\x8C\xBB", + "\xDB\x5D" => "\xE8\x8F\x8F", + "\xDB\x5E" => "\xE8\x8F\xB9", + "\xDB\x5F" => "\xE8\x90\xA3", + "\xDB\x60" => "\xE8\x8F\x80", + "\xDB\x61" => "\xE8\x8F\xA8", + "\xDB\x62" => "\xE8\x90\x92", + "\xDB\x63" => "\xE8\x8F\xA7", + "\xDB\x64" => "\xE8\x8F\xA4", + "\xDB\x65" => "\xE8\x8F\xBC", + "\xDB\x66" => "\xE8\x8F\xB6", + "\xDB\x67" => "\xE8\x90\x90", + "\xDB\x68" => "\xE8\x8F\x86", + "\xDB\x69" => "\xE8\x8F\x88", + "\xDB\x6A" => "\xE8\x8F\xAB", + "\xDB\x6B" => "\xE8\x8F\xA3", + "\xDB\x6C" => "\xE8\x8E\xBF", + "\xDB\x6D" => "\xE8\x90\x81", + "\xDB\x6E" => "\xE8\x8F\x9D", + "\xDB\x6F" => "\xE8\x8F\xA5", + "\xDB\x70" => "\xE8\x8F\x98", + "\xDB\x71" => "\xE8\x8F\xBF", + "\xDB\x72" => "\xE8\x8F\xA1", + "\xDB\x73" => "\xE8\x8F\x8B", + "\xDB\x74" => "\xE8\x8F\x8E", + "\xDB\x75" => "\xE8\x8F\x96", + "\xDB\x76" => "\xE8\x8F\xB5", + "\xDB\x77" => "\xE8\x8F\x89", + "\xDB\x78" => "\xE8\x90\x89", + "\xDB\x79" => "\xE8\x90\x8F", + "\xDB\x7A" => "\xE8\x8F\x9E", + "\xDB\x7B" => "\xE8\x90\x91", + "\xDB\x7C" => "\xE8\x90\x86", + "\xDB\x7D" => "\xE8\x8F\x82", + "\xDB\x7E" => "\xE8\x8F\xB3", + "\xDB\xA1" => "\xE8\x8F\x95", + "\xDB\xA2" => "\xE8\x8F\xBA", + "\xDB\xA3" => "\xE8\x8F\x87", + "\xDB\xA4" => "\xE8\x8F\x91", + "\xDB\xA5" => "\xE8\x8F\xAA", + "\xDB\xA6" => "\xE8\x90\x93", + "\xDB\xA7" => "\xE8\x8F\x83", + "\xDB\xA8" => "\xE8\x8F\xAC", + "\xDB\xA9" => "\xE8\x8F\xAE", + "\xDB\xAA" => "\xE8\x8F\x84", + "\xDB\xAB" => "\xE8\x8F\xBB", + "\xDB\xAC" => "\xE8\x8F\x97", + "\xDB\xAD" => "\xE8\x8F\xA2", + "\xDB\xAE" => "\xE8\x90\x9B", + "\xDB\xAF" => "\xE8\x8F\x9B", + "\xDB\xB0" => "\xE8\x8F\xBE", + "\xDB\xB1" => "\xE8\x9B\x98", + "\xDB\xB2" => "\xE8\x9B\xA2", + "\xDB\xB3" => "\xE8\x9B\xA6", + "\xDB\xB4" => "\xE8\x9B\x93", + "\xDB\xB5" => "\xE8\x9B\xA3", + "\xDB\xB6" => "\xE8\x9B\x9A", + "\xDB\xB7" => "\xE8\x9B\xAA", + "\xDB\xB8" => "\xE8\x9B\x9D", + "\xDB\xB9" => "\xE8\x9B\xAB", + "\xDB\xBA" => "\xE8\x9B\x9C", + "\xDB\xBB" => "\xE8\x9B\xAC", + "\xDB\xBC" => "\xE8\x9B\xA9", + "\xDB\xBD" => "\xE8\x9B\x97", + "\xDB\xBE" => "\xE8\x9B\xA8", + "\xDB\xBF" => "\xE8\x9B\x91", + "\xDB\xC0" => "\xE8\xA1\x88", + "\xDB\xC1" => "\xE8\xA1\x96", + "\xDB\xC2" => "\xE8\xA1\x95", + "\xDB\xC3" => "\xE8\xA2\xBA", + "\xDB\xC4" => "\xE8\xA3\x97", + "\xDB\xC5" => "\xE8\xA2\xB9", + "\xDB\xC6" => "\xE8\xA2\xB8", + "\xDB\xC7" => "\xE8\xA3\x80", + "\xDB\xC8" => "\xE8\xA2\xBE", + "\xDB\xC9" => "\xE8\xA2\xB6", + "\xDB\xCA" => "\xE8\xA2\xBC", + "\xDB\xCB" => "\xE8\xA2\xB7", + "\xDB\xCC" => "\xE8\xA2\xBD", + "\xDB\xCD" => "\xE8\xA2\xB2", + "\xDB\xCE" => "\xE8\xA4\x81", + "\xDB\xCF" => "\xE8\xA3\x89", + "\xDB\xD0" => "\xE8\xA6\x95", + "\xDB\xD1" => "\xE8\xA6\x98", + "\xDB\xD2" => "\xE8\xA6\x97", + "\xDB\xD3" => "\xE8\xA7\x9D", + "\xDB\xD4" => "\xE8\xA7\x9A", + "\xDB\xD5" => "\xE8\xA7\x9B", + "\xDB\xD6" => "\xE8\xA9\x8E", + "\xDB\xD7" => "\xE8\xA9\x8D", + "\xDB\xD8" => "\xE8\xA8\xB9", + "\xDB\xD9" => "\xE8\xA9\x99", + "\xDB\xDA" => "\xE8\xA9\x80", + "\xDB\xDB" => "\xE8\xA9\x97", + "\xDB\xDC" => "\xE8\xA9\x98", + "\xDB\xDD" => "\xE8\xA9\x84", + "\xDB\xDE" => "\xE8\xA9\x85", + "\xDB\xDF" => "\xE8\xA9\x92", + "\xDB\xE0" => "\xE8\xA9\x88", + "\xDB\xE1" => "\xE8\xA9\x91", + "\xDB\xE2" => "\xE8\xA9\x8A", + "\xDB\xE3" => "\xE8\xA9\x8C", + "\xDB\xE4" => "\xE8\xA9\x8F", + "\xDB\xE5" => "\xE8\xB1\x9F", + "\xDB\xE6" => "\xE8\xB2\x81", + "\xDB\xE7" => "\xE8\xB2\x80", + "\xDB\xE8" => "\xE8\xB2\xBA", + "\xDB\xE9" => "\xE8\xB2\xBE", + "\xDB\xEA" => "\xE8\xB2\xB0", + "\xDB\xEB" => "\xE8\xB2\xB9", + "\xDB\xEC" => "\xE8\xB2\xB5", + "\xDB\xED" => "\xE8\xB6\x84", + "\xDB\xEE" => "\xE8\xB6\x80", + "\xDB\xEF" => "\xE8\xB6\x89", + "\xDB\xF0" => "\xE8\xB7\x98", + "\xDB\xF1" => "\xE8\xB7\x93", + "\xDB\xF2" => "\xE8\xB7\x8D", + "\xDB\xF3" => "\xE8\xB7\x87", + "\xDB\xF4" => "\xE8\xB7\x96", + "\xDB\xF5" => "\xE8\xB7\x9C", + "\xDB\xF6" => "\xE8\xB7\x8F", + "\xDB\xF7" => "\xE8\xB7\x95", + "\xDB\xF8" => "\xE8\xB7\x99", + "\xDB\xF9" => "\xE8\xB7\x88", + "\xDB\xFA" => "\xE8\xB7\x97", + "\xDB\xFB" => "\xE8\xB7\x85", + "\xDB\xFC" => "\xE8\xBB\xAF", + "\xDB\xFD" => "\xE8\xBB\xB7", + "\xDB\xFE" => "\xE8\xBB\xBA", + "\xDC\x40" => "\xE8\xBB\xB9", + "\xDC\x41" => "\xE8\xBB\xA6", + "\xDC\x42" => "\xE8\xBB\xAE", + "\xDC\x43" => "\xE8\xBB\xA5", + "\xDC\x44" => "\xE8\xBB\xB5", + "\xDC\x45" => "\xE8\xBB\xA7", + "\xDC\x46" => "\xE8\xBB\xA8", + "\xDC\x47" => "\xE8\xBB\xB6", + "\xDC\x48" => "\xE8\xBB\xAB", + "\xDC\x49" => "\xE8\xBB\xB1", + "\xDC\x4A" => "\xE8\xBB\xAC", + "\xDC\x4B" => "\xE8\xBB\xB4", + "\xDC\x4C" => "\xE8\xBB\xA9", + "\xDC\x4D" => "\xE9\x80\xAD", + "\xDC\x4E" => "\xE9\x80\xB4", + "\xDC\x4F" => "\xE9\x80\xAF", + "\xDC\x50" => "\xE9\x84\x86", + "\xDC\x51" => "\xE9\x84\xAC", + "\xDC\x52" => "\xE9\x84\x84", + "\xDC\x53" => "\xE9\x83\xBF", + "\xDC\x54" => "\xE9\x83\xBC", + "\xDC\x55" => "\xE9\x84\x88", + "\xDC\x56" => "\xE9\x83\xB9", + "\xDC\x57" => "\xE9\x83\xBB", + "\xDC\x58" => "\xE9\x84\x81", + "\xDC\x59" => "\xE9\x84\x80", + "\xDC\x5A" => "\xE9\x84\x87", + "\xDC\x5B" => "\xE9\x84\x85", + "\xDC\x5C" => "\xE9\x84\x83", + "\xDC\x5D" => "\xE9\x85\xA1", + "\xDC\x5E" => "\xE9\x85\xA4", + "\xDC\x5F" => "\xE9\x85\x9F", + "\xDC\x60" => "\xE9\x85\xA2", + "\xDC\x61" => "\xE9\x85\xA0", + "\xDC\x62" => "\xE9\x88\x81", + "\xDC\x63" => "\xE9\x88\x8A", + "\xDC\x64" => "\xE9\x88\xA5", + "\xDC\x65" => "\xE9\x88\x83", + "\xDC\x66" => "\xE9\x88\x9A", + "\xDC\x67" => "\xE9\x88\xA6", + "\xDC\x68" => "\xE9\x88\x8F", + "\xDC\x69" => "\xE9\x88\x8C", + "\xDC\x6A" => "\xE9\x88\x80", + "\xDC\x6B" => "\xE9\x88\x92", + "\xDC\x6C" => "\xE9\x87\xBF", + "\xDC\x6D" => "\xE9\x87\xBD", + "\xDC\x6E" => "\xE9\x88\x86", + "\xDC\x6F" => "\xE9\x88\x84", + "\xDC\x70" => "\xE9\x88\xA7", + "\xDC\x71" => "\xE9\x88\x82", + "\xDC\x72" => "\xE9\x88\x9C", + "\xDC\x73" => "\xE9\x88\xA4", + "\xDC\x74" => "\xE9\x88\x99", + "\xDC\x75" => "\xE9\x88\x97", + "\xDC\x76" => "\xE9\x88\x85", + "\xDC\x77" => "\xE9\x88\x96", + "\xDC\x78" => "\xE9\x95\xBB", + "\xDC\x79" => "\xE9\x96\x8D", + "\xDC\x7A" => "\xE9\x96\x8C", + "\xDC\x7B" => "\xE9\x96\x90", + "\xDC\x7C" => "\xE9\x9A\x87", + "\xDC\x7D" => "\xE9\x99\xBE", + "\xDC\x7E" => "\xE9\x9A\x88", + "\xDC\xA1" => "\xE9\x9A\x89", + "\xDC\xA2" => "\xE9\x9A\x83", + "\xDC\xA3" => "\xE9\x9A\x80", + "\xDC\xA4" => "\xE9\x9B\x82", + "\xDC\xA5" => "\xE9\x9B\x88", + "\xDC\xA6" => "\xE9\x9B\x83", + "\xDC\xA7" => "\xE9\x9B\xB1", + "\xDC\xA8" => "\xE9\x9B\xB0", + "\xDC\xA9" => "\xE9\x9D\xAC", + "\xDC\xAA" => "\xE9\x9D\xB0", + "\xDC\xAB" => "\xE9\x9D\xAE", + "\xDC\xAC" => "\xE9\xA0\x87", + "\xDC\xAD" => "\xE9\xA2\xA9", + "\xDC\xAE" => "\xE9\xA3\xAB", + "\xDC\xAF" => "\xE9\xB3\xA6", + "\xDC\xB0" => "\xE9\xBB\xB9", + "\xDC\xB1" => "\xE4\xBA\x83", + "\xDC\xB2" => "\xE4\xBA\x84", + "\xDC\xB3" => "\xE4\xBA\xB6", + "\xDC\xB4" => "\xE5\x82\xBD", + "\xDC\xB5" => "\xE5\x82\xBF", + "\xDC\xB6" => "\xE5\x83\x86", + "\xDC\xB7" => "\xE5\x82\xAE", + "\xDC\xB8" => "\xE5\x83\x84", + "\xDC\xB9" => "\xE5\x83\x8A", + "\xDC\xBA" => "\xE5\x82\xB4", + "\xDC\xBB" => "\xE5\x83\x88", + "\xDC\xBC" => "\xE5\x83\x82", + "\xDC\xBD" => "\xE5\x82\xB0", + "\xDC\xBE" => "\xE5\x83\x81", + "\xDC\xBF" => "\xE5\x82\xBA", + "\xDC\xC0" => "\xE5\x82\xB1", + "\xDC\xC1" => "\xE5\x83\x8B", + "\xDC\xC2" => "\xE5\x83\x89", + "\xDC\xC3" => "\xE5\x82\xB6", + "\xDC\xC4" => "\xE5\x82\xB8", + "\xDC\xC5" => "\xE5\x87\x97", + "\xDC\xC6" => "\xE5\x89\xBA", + "\xDC\xC7" => "\xE5\x89\xB8", + "\xDC\xC8" => "\xE5\x89\xBB", + "\xDC\xC9" => "\xE5\x89\xBC", + "\xDC\xCA" => "\xE5\x97\x83", + "\xDC\xCB" => "\xE5\x97\x9B", + "\xDC\xCC" => "\xE5\x97\x8C", + "\xDC\xCD" => "\xE5\x97\x90", + "\xDC\xCE" => "\xE5\x97\x8B", + "\xDC\xCF" => "\xE5\x97\x8A", + "\xDC\xD0" => "\xE5\x97\x9D", + "\xDC\xD1" => "\xE5\x97\x80", + "\xDC\xD2" => "\xE5\x97\x94", + "\xDC\xD3" => "\xE5\x97\x84", + "\xDC\xD4" => "\xE5\x97\xA9", + "\xDC\xD5" => "\xE5\x96\xBF", + "\xDC\xD6" => "\xE5\x97\x92", + "\xDC\xD7" => "\xE5\x96\x8D", + "\xDC\xD8" => "\xE5\x97\x8F", + "\xDC\xD9" => "\xE5\x97\x95", + "\xDC\xDA" => "\xE5\x97\xA2", + "\xDC\xDB" => "\xE5\x97\x96", + "\xDC\xDC" => "\xE5\x97\x88", + "\xDC\xDD" => "\xE5\x97\xB2", + "\xDC\xDE" => "\xE5\x97\x8D", + "\xDC\xDF" => "\xE5\x97\x99", + "\xDC\xE0" => "\xE5\x97\x82", + "\xDC\xE1" => "\xE5\x9C\x94", + "\xDC\xE2" => "\xE5\xA1\x93", + "\xDC\xE3" => "\xE5\xA1\xA8", + "\xDC\xE4" => "\xE5\xA1\xA4", + "\xDC\xE5" => "\xE5\xA1\x8F", + "\xDC\xE6" => "\xE5\xA1\x8D", + "\xDC\xE7" => "\xE5\xA1\x89", + "\xDC\xE8" => "\xE5\xA1\xAF", + "\xDC\xE9" => "\xE5\xA1\x95", + "\xDC\xEA" => "\xE5\xA1\x8E", + "\xDC\xEB" => "\xE5\xA1\x9D", + "\xDC\xEC" => "\xE5\xA1\x99", + "\xDC\xED" => "\xE5\xA1\xA5", + "\xDC\xEE" => "\xE5\xA1\x9B", + "\xDC\xEF" => "\xE5\xA0\xBD", + "\xDC\xF0" => "\xE5\xA1\xA3", + "\xDC\xF1" => "\xE5\xA1\xB1", + "\xDC\xF2" => "\xE5\xA3\xBC", + "\xDC\xF3" => "\xE5\xAB\x87", + "\xDC\xF4" => "\xE5\xAB\x84", + "\xDC\xF5" => "\xE5\xAB\x8B", + "\xDC\xF6" => "\xE5\xAA\xBA", + "\xDC\xF7" => "\xE5\xAA\xB8", + "\xDC\xF8" => "\xE5\xAA\xB1", + "\xDC\xF9" => "\xE5\xAA\xB5", + "\xDC\xFA" => "\xE5\xAA\xB0", + "\xDC\xFB" => "\xE5\xAA\xBF", + "\xDC\xFC" => "\xE5\xAB\x88", + "\xDC\xFD" => "\xE5\xAA\xBB", + "\xDC\xFE" => "\xE5\xAB\x86", + "\xDD\x40" => "\xE5\xAA\xB7", + "\xDD\x41" => "\xE5\xAB\x80", + "\xDD\x42" => "\xE5\xAB\x8A", + "\xDD\x43" => "\xE5\xAA\xB4", + "\xDD\x44" => "\xE5\xAA\xB6", + "\xDD\x45" => "\xE5\xAB\x8D", + "\xDD\x46" => "\xE5\xAA\xB9", + "\xDD\x47" => "\xE5\xAA\x90", + "\xDD\x48" => "\xE5\xAF\x96", + "\xDD\x49" => "\xE5\xAF\x98", + "\xDD\x4A" => "\xE5\xAF\x99", + "\xDD\x4B" => "\xE5\xB0\x9F", + "\xDD\x4C" => "\xE5\xB0\xB3", + "\xDD\x4D" => "\xE5\xB5\xB1", + "\xDD\x4E" => "\xE5\xB5\xA3", + "\xDD\x4F" => "\xE5\xB5\x8A", + "\xDD\x50" => "\xE5\xB5\xA5", + "\xDD\x51" => "\xE5\xB5\xB2", + "\xDD\x52" => "\xE5\xB5\xAC", + "\xDD\x53" => "\xE5\xB5\x9E", + "\xDD\x54" => "\xE5\xB5\xA8", + "\xDD\x55" => "\xE5\xB5\xA7", + "\xDD\x56" => "\xE5\xB5\xA2", + "\xDD\x57" => "\xE5\xB7\xB0", + "\xDD\x58" => "\xE5\xB9\x8F", + "\xDD\x59" => "\xE5\xB9\x8E", + "\xDD\x5A" => "\xE5\xB9\x8A", + "\xDD\x5B" => "\xE5\xB9\x8D", + "\xDD\x5C" => "\xE5\xB9\x8B", + "\xDD\x5D" => "\xE5\xBB\x85", + "\xDD\x5E" => "\xE5\xBB\x8C", + "\xDD\x5F" => "\xE5\xBB\x86", + "\xDD\x60" => "\xE5\xBB\x8B", + "\xDD\x61" => "\xE5\xBB\x87", + "\xDD\x62" => "\xE5\xBD\x80", + "\xDD\x63" => "\xE5\xBE\xAF", + "\xDD\x64" => "\xE5\xBE\xAD", + "\xDD\x65" => "\xE6\x83\xB7", + "\xDD\x66" => "\xE6\x85\x89", + "\xDD\x67" => "\xE6\x85\x8A", + "\xDD\x68" => "\xE6\x84\xAB", + "\xDD\x69" => "\xE6\x85\x85", + "\xDD\x6A" => "\xE6\x84\xB6", + "\xDD\x6B" => "\xE6\x84\xB2", + "\xDD\x6C" => "\xE6\x84\xAE", + "\xDD\x6D" => "\xE6\x85\x86", + "\xDD\x6E" => "\xE6\x84\xAF", + "\xDD\x6F" => "\xE6\x85\x8F", + "\xDD\x70" => "\xE6\x84\xA9", + "\xDD\x71" => "\xE6\x85\x80", + "\xDD\x72" => "\xE6\x88\xA0", + "\xDD\x73" => "\xE9\x85\xA8", + "\xDD\x74" => "\xE6\x88\xA3", + "\xDD\x75" => "\xE6\x88\xA5", + "\xDD\x76" => "\xE6\x88\xA4", + "\xDD\x77" => "\xE6\x8F\x85", + "\xDD\x78" => "\xE6\x8F\xB1", + "\xDD\x79" => "\xE6\x8F\xAB", + "\xDD\x7A" => "\xE6\x90\x90", + "\xDD\x7B" => "\xE6\x90\x92", + "\xDD\x7C" => "\xE6\x90\x89", + "\xDD\x7D" => "\xE6\x90\xA0", + "\xDD\x7E" => "\xE6\x90\xA4", + "\xDD\xA1" => "\xE6\x90\xB3", + "\xDD\xA2" => "\xE6\x91\x83", + "\xDD\xA3" => "\xE6\x90\x9F", + "\xDD\xA4" => "\xE6\x90\x95", + "\xDD\xA5" => "\xE6\x90\x98", + "\xDD\xA6" => "\xE6\x90\xB9", + "\xDD\xA7" => "\xE6\x90\xB7", + "\xDD\xA8" => "\xE6\x90\xA2", + "\xDD\xA9" => "\xE6\x90\xA3", + "\xDD\xAA" => "\xE6\x90\x8C", + "\xDD\xAB" => "\xE6\x90\xA6", + "\xDD\xAC" => "\xE6\x90\xB0", + "\xDD\xAD" => "\xE6\x90\xA8", + "\xDD\xAE" => "\xE6\x91\x81", + "\xDD\xAF" => "\xE6\x90\xB5", + "\xDD\xB0" => "\xE6\x90\xAF", + "\xDD\xB1" => "\xE6\x90\x8A", + "\xDD\xB2" => "\xE6\x90\x9A", + "\xDD\xB3" => "\xE6\x91\x80", + "\xDD\xB4" => "\xE6\x90\xA5", + "\xDD\xB5" => "\xE6\x90\xA7", + "\xDD\xB6" => "\xE6\x90\x8B", + "\xDD\xB7" => "\xE6\x8F\xA7", + "\xDD\xB8" => "\xE6\x90\x9B", + "\xDD\xB9" => "\xE6\x90\xAE", + "\xDD\xBA" => "\xE6\x90\xA1", + "\xDD\xBB" => "\xE6\x90\x8E", + "\xDD\xBC" => "\xE6\x95\xAF", + "\xDD\xBD" => "\xE6\x96\x92", + "\xDD\xBE" => "\xE6\x97\x93", + "\xDD\xBF" => "\xE6\x9A\x86", + "\xDD\xC0" => "\xE6\x9A\x8C", + "\xDD\xC1" => "\xE6\x9A\x95", + "\xDD\xC2" => "\xE6\x9A\x90", + "\xDD\xC3" => "\xE6\x9A\x8B", + "\xDD\xC4" => "\xE6\x9A\x8A", + "\xDD\xC5" => "\xE6\x9A\x99", + "\xDD\xC6" => "\xE6\x9A\x94", + "\xDD\xC7" => "\xE6\x99\xB8", + "\xDD\xC8" => "\xE6\x9C\xA0", + "\xDD\xC9" => "\xE6\xA5\xA6", + "\xDD\xCA" => "\xE6\xA5\x9F", + "\xDD\xCB" => "\xE6\xA4\xB8", + "\xDD\xCC" => "\xE6\xA5\x8E", + "\xDD\xCD" => "\xE6\xA5\xA2", + "\xDD\xCE" => "\xE6\xA5\xB1", + "\xDD\xCF" => "\xE6\xA4\xBF", + "\xDD\xD0" => "\xE6\xA5\x85", + "\xDD\xD1" => "\xE6\xA5\xAA", + "\xDD\xD2" => "\xE6\xA4\xB9", + "\xDD\xD3" => "\xE6\xA5\x82", + "\xDD\xD4" => "\xE6\xA5\x97", + "\xDD\xD5" => "\xE6\xA5\x99", + "\xDD\xD6" => "\xE6\xA5\xBA", + "\xDD\xD7" => "\xE6\xA5\x88", + "\xDD\xD8" => "\xE6\xA5\x89", + "\xDD\xD9" => "\xE6\xA4\xB5", + "\xDD\xDA" => "\xE6\xA5\xAC", + "\xDD\xDB" => "\xE6\xA4\xB3", + "\xDD\xDC" => "\xE6\xA4\xBD", + "\xDD\xDD" => "\xE6\xA5\xA5", + "\xDD\xDE" => "\xE6\xA3\xB0", + "\xDD\xDF" => "\xE6\xA5\xB8", + "\xDD\xE0" => "\xE6\xA4\xB4", + "\xDD\xE1" => "\xE6\xA5\xA9", + "\xDD\xE2" => "\xE6\xA5\x80", + "\xDD\xE3" => "\xE6\xA5\xAF", + "\xDD\xE4" => "\xE6\xA5\x84", + "\xDD\xE5" => "\xE6\xA5\xB6", + "\xDD\xE6" => "\xE6\xA5\x98", + "\xDD\xE7" => "\xE6\xA5\x81", + "\xDD\xE8" => "\xE6\xA5\xB4", + "\xDD\xE9" => "\xE6\xA5\x8C", + "\xDD\xEA" => "\xE6\xA4\xBB", + "\xDD\xEB" => "\xE6\xA5\x8B", + "\xDD\xEC" => "\xE6\xA4\xB7", + "\xDD\xED" => "\xE6\xA5\x9C", + "\xDD\xEE" => "\xE6\xA5\x8F", + "\xDD\xEF" => "\xE6\xA5\x91", + "\xDD\xF0" => "\xE6\xA4\xB2", + "\xDD\xF1" => "\xE6\xA5\x92", + "\xDD\xF2" => "\xE6\xA4\xAF", + "\xDD\xF3" => "\xE6\xA5\xBB", + "\xDD\xF4" => "\xE6\xA4\xBC", + "\xDD\xF5" => "\xE6\xAD\x86", + "\xDD\xF6" => "\xE6\xAD\x85", + "\xDD\xF7" => "\xE6\xAD\x83", + "\xDD\xF8" => "\xE6\xAD\x82", + "\xDD\xF9" => "\xE6\xAD\x88", + "\xDD\xFA" => "\xE6\xAD\x81", + "\xDD\xFB" => "\xE6\xAE\x9B", + "\xDD\xFC" => "\xEF\xA8\x8D", + "\xDD\xFD" => "\xE6\xAF\xBB", + "\xDD\xFE" => "\xE6\xAF\xBC", + "\xDE\x40" => "\xE6\xAF\xB9", + "\xDE\x41" => "\xE6\xAF\xB7", + "\xDE\x42" => "\xE6\xAF\xB8", + "\xDE\x43" => "\xE6\xBA\x9B", + "\xDE\x44" => "\xE6\xBB\x96", + "\xDE\x45" => "\xE6\xBB\x88", + "\xDE\x46" => "\xE6\xBA\x8F", + "\xDE\x47" => "\xE6\xBB\x80", + "\xDE\x48" => "\xE6\xBA\x9F", + "\xDE\x49" => "\xE6\xBA\x93", + "\xDE\x4A" => "\xE6\xBA\x94", + "\xDE\x4B" => "\xE6\xBA\xA0", + "\xDE\x4C" => "\xE6\xBA\xB1", + "\xDE\x4D" => "\xE6\xBA\xB9", + "\xDE\x4E" => "\xE6\xBB\x86", + "\xDE\x4F" => "\xE6\xBB\x92", + "\xDE\x50" => "\xE6\xBA\xBD", + "\xDE\x51" => "\xE6\xBB\x81", + "\xDE\x52" => "\xE6\xBA\x9E", + "\xDE\x53" => "\xE6\xBB\x89", + "\xDE\x54" => "\xE6\xBA\xB7", + "\xDE\x55" => "\xE6\xBA\xB0", + "\xDE\x56" => "\xE6\xBB\x8D", + "\xDE\x57" => "\xE6\xBA\xA6", + "\xDE\x58" => "\xE6\xBB\x8F", + "\xDE\x59" => "\xE6\xBA\xB2", + "\xDE\x5A" => "\xE6\xBA\xBE", + "\xDE\x5B" => "\xE6\xBB\x83", + "\xDE\x5C" => "\xE6\xBB\x9C", + "\xDE\x5D" => "\xE6\xBB\x98", + "\xDE\x5E" => "\xE6\xBA\x99", + "\xDE\x5F" => "\xE6\xBA\x92", + "\xDE\x60" => "\xE6\xBA\x8E", + "\xDE\x61" => "\xE6\xBA\x8D", + "\xDE\x62" => "\xE6\xBA\xA4", + "\xDE\x63" => "\xE6\xBA\xA1", + "\xDE\x64" => "\xE6\xBA\xBF", + "\xDE\x65" => "\xE6\xBA\xB3", + "\xDE\x66" => "\xE6\xBB\x90", + "\xDE\x67" => "\xE6\xBB\x8A", + "\xDE\x68" => "\xE6\xBA\x97", + "\xDE\x69" => "\xE6\xBA\xAE", + "\xDE\x6A" => "\xE6\xBA\xA3", + "\xDE\x6B" => "\xE7\x85\x87", + "\xDE\x6C" => "\xE7\x85\x94", + "\xDE\x6D" => "\xE7\x85\x92", + "\xDE\x6E" => "\xE7\x85\xA3", + "\xDE\x6F" => "\xE7\x85\xA0", + "\xDE\x70" => "\xE7\x85\x81", + "\xDE\x71" => "\xE7\x85\x9D", + "\xDE\x72" => "\xE7\x85\xA2", + "\xDE\x73" => "\xE7\x85\xB2", + "\xDE\x74" => "\xE7\x85\xB8", + "\xDE\x75" => "\xE7\x85\xAA", + "\xDE\x76" => "\xE7\x85\xA1", + "\xDE\x77" => "\xE7\x85\x82", + "\xDE\x78" => "\xE7\x85\x98", + "\xDE\x79" => "\xE7\x85\x83", + "\xDE\x7A" => "\xE7\x85\x8B", + "\xDE\x7B" => "\xE7\x85\xB0", + "\xDE\x7C" => "\xE7\x85\x9F", + "\xDE\x7D" => "\xE7\x85\x90", + "\xDE\x7E" => "\xE7\x85\x93", + "\xDE\xA1" => "\xE7\x85\x84", + "\xDE\xA2" => "\xE7\x85\x8D", + "\xDE\xA3" => "\xE7\x85\x9A", + "\xDE\xA4" => "\xE7\x89\x8F", + "\xDE\xA5" => "\xE7\x8A\x8D", + "\xDE\xA6" => "\xE7\x8A\x8C", + "\xDE\xA7" => "\xE7\x8A\x91", + "\xDE\xA8" => "\xE7\x8A\x90", + "\xDE\xA9" => "\xE7\x8A\x8E", + "\xDE\xAA" => "\xE7\x8C\xBC", + "\xDE\xAB" => "\xE7\x8D\x82", + "\xDE\xAC" => "\xE7\x8C\xBB", + "\xDE\xAD" => "\xE7\x8C\xBA", + "\xDE\xAE" => "\xE7\x8D\x80", + "\xDE\xAF" => "\xE7\x8D\x8A", + "\xDE\xB0" => "\xE7\x8D\x89", + "\xDE\xB1" => "\xE7\x91\x84", + "\xDE\xB2" => "\xE7\x91\x8A", + "\xDE\xB3" => "\xE7\x91\x8B", + "\xDE\xB4" => "\xE7\x91\x92", + "\xDE\xB5" => "\xE7\x91\x91", + "\xDE\xB6" => "\xE7\x91\x97", + "\xDE\xB7" => "\xE7\x91\x80", + "\xDE\xB8" => "\xE7\x91\x8F", + "\xDE\xB9" => "\xE7\x91\x90", + "\xDE\xBA" => "\xE7\x91\x8E", + "\xDE\xBB" => "\xE7\x91\x82", + "\xDE\xBC" => "\xE7\x91\x86", + "\xDE\xBD" => "\xE7\x91\x8D", + "\xDE\xBE" => "\xE7\x91\x94", + "\xDE\xBF" => "\xE7\x93\xA1", + "\xDE\xC0" => "\xE7\x93\xBF", + "\xDE\xC1" => "\xE7\x93\xBE", + "\xDE\xC2" => "\xE7\x93\xBD", + "\xDE\xC3" => "\xE7\x94\x9D", + "\xDE\xC4" => "\xE7\x95\xB9", + "\xDE\xC5" => "\xE7\x95\xB7", + "\xDE\xC6" => "\xE6\xA6\x83", + "\xDE\xC7" => "\xE7\x97\xAF", + "\xDE\xC8" => "\xE7\x98\x8F", + "\xDE\xC9" => "\xE7\x98\x83", + "\xDE\xCA" => "\xE7\x97\xB7", + "\xDE\xCB" => "\xE7\x97\xBE", + "\xDE\xCC" => "\xE7\x97\xBC", + "\xDE\xCD" => "\xE7\x97\xB9", + "\xDE\xCE" => "\xE7\x97\xB8", + "\xDE\xCF" => "\xE7\x98\x90", + "\xDE\xD0" => "\xE7\x97\xBB", + "\xDE\xD1" => "\xE7\x97\xB6", + "\xDE\xD2" => "\xE7\x97\xAD", + "\xDE\xD3" => "\xE7\x97\xB5", + "\xDE\xD4" => "\xE7\x97\xBD", + "\xDE\xD5" => "\xE7\x9A\x99", + "\xDE\xD6" => "\xE7\x9A\xB5", + "\xDE\xD7" => "\xE7\x9B\x9D", + "\xDE\xD8" => "\xE7\x9D\x95", + "\xDE\xD9" => "\xE7\x9D\x9F", + "\xDE\xDA" => "\xE7\x9D\xA0", + "\xDE\xDB" => "\xE7\x9D\x92", + "\xDE\xDC" => "\xE7\x9D\x96", + "\xDE\xDD" => "\xE7\x9D\x9A", + "\xDE\xDE" => "\xE7\x9D\xA9", + "\xDE\xDF" => "\xE7\x9D\xA7", + "\xDE\xE0" => "\xE7\x9D\x94", + "\xDE\xE1" => "\xE7\x9D\x99", + "\xDE\xE2" => "\xE7\x9D\xAD", + "\xDE\xE3" => "\xE7\x9F\xA0", + "\xDE\xE4" => "\xE7\xA2\x87", + "\xDE\xE5" => "\xE7\xA2\x9A", + "\xDE\xE6" => "\xE7\xA2\x94", + "\xDE\xE7" => "\xE7\xA2\x8F", + "\xDE\xE8" => "\xE7\xA2\x84", + "\xDE\xE9" => "\xE7\xA2\x95", + "\xDE\xEA" => "\xE7\xA2\x85", + "\xDE\xEB" => "\xE7\xA2\x86", + "\xDE\xEC" => "\xE7\xA2\xA1", + "\xDE\xED" => "\xE7\xA2\x83", + "\xDE\xEE" => "\xE7\xA1\xB9", + "\xDE\xEF" => "\xE7\xA2\x99", + "\xDE\xF0" => "\xE7\xA2\x80", + "\xDE\xF1" => "\xE7\xA2\x96", + "\xDE\xF2" => "\xE7\xA1\xBB", + "\xDE\xF3" => "\xE7\xA5\xBC", + "\xDE\xF4" => "\xE7\xA6\x82", + "\xDE\xF5" => "\xE7\xA5\xBD", + "\xDE\xF6" => "\xE7\xA5\xB9", + "\xDE\xF7" => "\xE7\xA8\x91", + "\xDE\xF8" => "\xE7\xA8\x98", + "\xDE\xF9" => "\xE7\xA8\x99", + "\xDE\xFA" => "\xE7\xA8\x92", + "\xDE\xFB" => "\xE7\xA8\x97", + "\xDE\xFC" => "\xE7\xA8\x95", + "\xDE\xFD" => "\xE7\xA8\xA2", + "\xDE\xFE" => "\xE7\xA8\x93", + "\xDF\x40" => "\xE7\xA8\x9B", + "\xDF\x41" => "\xE7\xA8\x90", + "\xDF\x42" => "\xE7\xAA\xA3", + "\xDF\x43" => "\xE7\xAA\xA2", + "\xDF\x44" => "\xE7\xAA\x9E", + "\xDF\x45" => "\xE7\xAB\xAB", + "\xDF\x46" => "\xE7\xAD\xA6", + "\xDF\x47" => "\xE7\xAD\xA4", + "\xDF\x48" => "\xE7\xAD\xAD", + "\xDF\x49" => "\xE7\xAD\xB4", + "\xDF\x4A" => "\xE7\xAD\xA9", + "\xDF\x4B" => "\xE7\xAD\xB2", + "\xDF\x4C" => "\xE7\xAD\xA5", + "\xDF\x4D" => "\xE7\xAD\xB3", + "\xDF\x4E" => "\xE7\xAD\xB1", + "\xDF\x4F" => "\xE7\xAD\xB0", + "\xDF\x50" => "\xE7\xAD\xA1", + "\xDF\x51" => "\xE7\xAD\xB8", + "\xDF\x52" => "\xE7\xAD\xB6", + "\xDF\x53" => "\xE7\xAD\xA3", + "\xDF\x54" => "\xE7\xB2\xB2", + "\xDF\x55" => "\xE7\xB2\xB4", + "\xDF\x56" => "\xE7\xB2\xAF", + "\xDF\x57" => "\xE7\xB6\x88", + "\xDF\x58" => "\xE7\xB6\x86", + "\xDF\x59" => "\xE7\xB6\x80", + "\xDF\x5A" => "\xE7\xB6\x8D", + "\xDF\x5B" => "\xE7\xB5\xBF", + "\xDF\x5C" => "\xE7\xB6\x85", + "\xDF\x5D" => "\xE7\xB5\xBA", + "\xDF\x5E" => "\xE7\xB6\x8E", + "\xDF\x5F" => "\xE7\xB5\xBB", + "\xDF\x60" => "\xE7\xB6\x83", + "\xDF\x61" => "\xE7\xB5\xBC", + "\xDF\x62" => "\xE7\xB6\x8C", + "\xDF\x63" => "\xE7\xB6\x94", + "\xDF\x64" => "\xE7\xB6\x84", + "\xDF\x65" => "\xE7\xB5\xBD", + "\xDF\x66" => "\xE7\xB6\x92", + "\xDF\x67" => "\xE7\xBD\xAD", + "\xDF\x68" => "\xE7\xBD\xAB", + "\xDF\x69" => "\xE7\xBD\xA7", + "\xDF\x6A" => "\xE7\xBD\xA8", + "\xDF\x6B" => "\xE7\xBD\xAC", + "\xDF\x6C" => "\xE7\xBE\xA6", + "\xDF\x6D" => "\xE7\xBE\xA5", + "\xDF\x6E" => "\xE7\xBE\xA7", + "\xDF\x6F" => "\xE7\xBF\x9B", + "\xDF\x70" => "\xE7\xBF\x9C", + "\xDF\x71" => "\xE8\x80\xA1", + "\xDF\x72" => "\xE8\x85\xA4", + "\xDF\x73" => "\xE8\x85\xA0", + "\xDF\x74" => "\xE8\x85\xB7", + "\xDF\x75" => "\xE8\x85\x9C", + "\xDF\x76" => "\xE8\x85\xA9", + "\xDF\x77" => "\xE8\x85\x9B", + "\xDF\x78" => "\xE8\x85\xA2", + "\xDF\x79" => "\xE8\x85\xB2", + "\xDF\x7A" => "\xE6\x9C\xA1", + "\xDF\x7B" => "\xE8\x85\x9E", + "\xDF\x7C" => "\xE8\x85\xB6", + "\xDF\x7D" => "\xE8\x85\xA7", + "\xDF\x7E" => "\xE8\x85\xAF", + "\xDF\xA1" => "\xE8\x85\x84", + "\xDF\xA2" => "\xE8\x85\xA1", + "\xDF\xA3" => "\xE8\x88\x9D", + "\xDF\xA4" => "\xE8\x89\x89", + "\xDF\xA5" => "\xE8\x89\x84", + "\xDF\xA6" => "\xE8\x89\x80", + "\xDF\xA7" => "\xE8\x89\x82", + "\xDF\xA8" => "\xE8\x89\x85", + "\xDF\xA9" => "\xE8\x93\xB1", + "\xDF\xAA" => "\xE8\x90\xBF", + "\xDF\xAB" => "\xE8\x91\x96", + "\xDF\xAC" => "\xE8\x91\xB6", + "\xDF\xAD" => "\xE8\x91\xB9", + "\xDF\xAE" => "\xE8\x92\x8F", + "\xDF\xAF" => "\xE8\x92\x8D", + "\xDF\xB0" => "\xE8\x91\xA5", + "\xDF\xB1" => "\xE8\x91\x91", + "\xDF\xB2" => "\xE8\x91\x80", + "\xDF\xB3" => "\xE8\x92\x86", + "\xDF\xB4" => "\xE8\x91\xA7", + "\xDF\xB5" => "\xE8\x90\xB0", + "\xDF\xB6" => "\xE8\x91\x8D", + "\xDF\xB7" => "\xE8\x91\xBD", + "\xDF\xB8" => "\xE8\x91\x9A", + "\xDF\xB9" => "\xE8\x91\x99", + "\xDF\xBA" => "\xE8\x91\xB4", + "\xDF\xBB" => "\xE8\x91\xB3", + "\xDF\xBC" => "\xE8\x91\x9D", + "\xDF\xBD" => "\xE8\x94\x87", + "\xDF\xBE" => "\xE8\x91\x9E", + "\xDF\xBF" => "\xE8\x90\xB7", + "\xDF\xC0" => "\xE8\x90\xBA", + "\xDF\xC1" => "\xE8\x90\xB4", + "\xDF\xC2" => "\xE8\x91\xBA", + "\xDF\xC3" => "\xE8\x91\x83", + "\xDF\xC4" => "\xE8\x91\xB8", + "\xDF\xC5" => "\xE8\x90\xB2", + "\xDF\xC6" => "\xE8\x91\x85", + "\xDF\xC7" => "\xE8\x90\xA9", + "\xDF\xC8" => "\xE8\x8F\x99", + "\xDF\xC9" => "\xE8\x91\x8B", + "\xDF\xCA" => "\xE8\x90\xAF", + "\xDF\xCB" => "\xE8\x91\x82", + "\xDF\xCC" => "\xE8\x90\xAD", + "\xDF\xCD" => "\xE8\x91\x9F", + "\xDF\xCE" => "\xE8\x91\xB0", + "\xDF\xCF" => "\xE8\x90\xB9", + "\xDF\xD0" => "\xE8\x91\x8E", + "\xDF\xD1" => "\xE8\x91\x8C", + "\xDF\xD2" => "\xE8\x91\x92", + "\xDF\xD3" => "\xE8\x91\xAF", + "\xDF\xD4" => "\xE8\x93\x85", + "\xDF\xD5" => "\xE8\x92\x8E", + "\xDF\xD6" => "\xE8\x90\xBB", + "\xDF\xD7" => "\xE8\x91\x87", + "\xDF\xD8" => "\xE8\x90\xB6", + "\xDF\xD9" => "\xE8\x90\xB3", + "\xDF\xDA" => "\xE8\x91\xA8", + "\xDF\xDB" => "\xE8\x91\xBE", + "\xDF\xDC" => "\xE8\x91\x84", + "\xDF\xDD" => "\xE8\x90\xAB", + "\xDF\xDE" => "\xE8\x91\xA0", + "\xDF\xDF" => "\xE8\x91\x94", + "\xDF\xE0" => "\xE8\x91\xAE", + "\xDF\xE1" => "\xE8\x91\x90", + "\xDF\xE2" => "\xE8\x9C\x8B", + "\xDF\xE3" => "\xE8\x9C\x84", + "\xDF\xE4" => "\xE8\x9B\xB7", + "\xDF\xE5" => "\xE8\x9C\x8C", + "\xDF\xE6" => "\xE8\x9B\xBA", + "\xDF\xE7" => "\xE8\x9B\x96", + "\xDF\xE8" => "\xE8\x9B\xB5", + "\xDF\xE9" => "\xE8\x9D\x8D", + "\xDF\xEA" => "\xE8\x9B\xB8", + "\xDF\xEB" => "\xE8\x9C\x8E", + "\xDF\xEC" => "\xE8\x9C\x89", + "\xDF\xED" => "\xE8\x9C\x81", + "\xDF\xEE" => "\xE8\x9B\xB6", + "\xDF\xEF" => "\xE8\x9C\x8D", + "\xDF\xF0" => "\xE8\x9C\x85", + "\xDF\xF1" => "\xE8\xA3\x96", + "\xDF\xF2" => "\xE8\xA3\x8B", + "\xDF\xF3" => "\xE8\xA3\x8D", + "\xDF\xF4" => "\xE8\xA3\x8E", + "\xDF\xF5" => "\xE8\xA3\x9E", + "\xDF\xF6" => "\xE8\xA3\x9B", + "\xDF\xF7" => "\xE8\xA3\x9A", + "\xDF\xF8" => "\xE8\xA3\x8C", + "\xDF\xF9" => "\xE8\xA3\x90", + "\xDF\xFA" => "\xE8\xA6\x85", + "\xDF\xFB" => "\xE8\xA6\x9B", + "\xDF\xFC" => "\xE8\xA7\x9F", + "\xDF\xFD" => "\xE8\xA7\xA5", + "\xDF\xFE" => "\xE8\xA7\xA4", + "\xE0\x40" => "\xE8\xA7\xA1", + "\xE0\x41" => "\xE8\xA7\xA0", + "\xE0\x42" => "\xE8\xA7\xA2", + "\xE0\x43" => "\xE8\xA7\x9C", + "\xE0\x44" => "\xE8\xA7\xA6", + "\xE0\x45" => "\xE8\xA9\xB6", + "\xE0\x46" => "\xE8\xAA\x86", + "\xE0\x47" => "\xE8\xA9\xBF", + "\xE0\x48" => "\xE8\xA9\xA1", + "\xE0\x49" => "\xE8\xA8\xBF", + "\xE0\x4A" => "\xE8\xA9\xB7", + "\xE0\x4B" => "\xE8\xAA\x82", + "\xE0\x4C" => "\xE8\xAA\x84", + "\xE0\x4D" => "\xE8\xA9\xB5", + "\xE0\x4E" => "\xE8\xAA\x83", + "\xE0\x4F" => "\xE8\xAA\x81", + "\xE0\x50" => "\xE8\xA9\xB4", + "\xE0\x51" => "\xE8\xA9\xBA", + "\xE0\x52" => "\xE8\xB0\xBC", + "\xE0\x53" => "\xE8\xB1\x8B", + "\xE0\x54" => "\xE8\xB1\x8A", + "\xE0\x55" => "\xE8\xB1\xA5", + "\xE0\x56" => "\xE8\xB1\xA4", + "\xE0\x57" => "\xE8\xB1\xA6", + "\xE0\x58" => "\xE8\xB2\x86", + "\xE0\x59" => "\xE8\xB2\x84", + "\xE0\x5A" => "\xE8\xB2\x85", + "\xE0\x5B" => "\xE8\xB3\x8C", + "\xE0\x5C" => "\xE8\xB5\xA8", + "\xE0\x5D" => "\xE8\xB5\xA9", + "\xE0\x5E" => "\xE8\xB6\x91", + "\xE0\x5F" => "\xE8\xB6\x8C", + "\xE0\x60" => "\xE8\xB6\x8E", + "\xE0\x61" => "\xE8\xB6\x8F", + "\xE0\x62" => "\xE8\xB6\x8D", + "\xE0\x63" => "\xE8\xB6\x93", + "\xE0\x64" => "\xE8\xB6\x94", + "\xE0\x65" => "\xE8\xB6\x90", + "\xE0\x66" => "\xE8\xB6\x92", + "\xE0\x67" => "\xE8\xB7\xB0", + "\xE0\x68" => "\xE8\xB7\xA0", + "\xE0\x69" => "\xE8\xB7\xAC", + "\xE0\x6A" => "\xE8\xB7\xB1", + "\xE0\x6B" => "\xE8\xB7\xAE", + "\xE0\x6C" => "\xE8\xB7\x90", + "\xE0\x6D" => "\xE8\xB7\xA9", + "\xE0\x6E" => "\xE8\xB7\xA3", + "\xE0\x6F" => "\xE8\xB7\xA2", + "\xE0\x70" => "\xE8\xB7\xA7", + "\xE0\x71" => "\xE8\xB7\xB2", + "\xE0\x72" => "\xE8\xB7\xAB", + "\xE0\x73" => "\xE8\xB7\xB4", + "\xE0\x74" => "\xE8\xBC\x86", + "\xE0\x75" => "\xE8\xBB\xBF", + "\xE0\x76" => "\xE8\xBC\x81", + "\xE0\x77" => "\xE8\xBC\x80", + "\xE0\x78" => "\xE8\xBC\x85", + "\xE0\x79" => "\xE8\xBC\x87", + "\xE0\x7A" => "\xE8\xBC\x88", + "\xE0\x7B" => "\xE8\xBC\x82", + "\xE0\x7C" => "\xE8\xBC\x8B", + "\xE0\x7D" => "\xE9\x81\x92", + "\xE0\x7E" => "\xE9\x80\xBF", + "\xE0\xA1" => "\xE9\x81\x84", + "\xE0\xA2" => "\xE9\x81\x89", + "\xE0\xA3" => "\xE9\x80\xBD", + "\xE0\xA4" => "\xE9\x84\x90", + "\xE0\xA5" => "\xE9\x84\x8D", + "\xE0\xA6" => "\xE9\x84\x8F", + "\xE0\xA7" => "\xE9\x84\x91", + "\xE0\xA8" => "\xE9\x84\x96", + "\xE0\xA9" => "\xE9\x84\x94", + "\xE0\xAA" => "\xE9\x84\x8B", + "\xE0\xAB" => "\xE9\x84\x8E", + "\xE0\xAC" => "\xE9\x85\xAE", + "\xE0\xAD" => "\xE9\x85\xAF", + "\xE0\xAE" => "\xE9\x89\x88", + "\xE0\xAF" => "\xE9\x89\x92", + "\xE0\xB0" => "\xE9\x88\xB0", + "\xE0\xB1" => "\xE9\x88\xBA", + "\xE0\xB2" => "\xE9\x89\xA6", + "\xE0\xB3" => "\xE9\x88\xB3", + "\xE0\xB4" => "\xE9\x89\xA5", + "\xE0\xB5" => "\xE9\x89\x9E", + "\xE0\xB6" => "\xE9\x8A\x83", + "\xE0\xB7" => "\xE9\x88\xAE", + "\xE0\xB8" => "\xE9\x89\x8A", + "\xE0\xB9" => "\xE9\x89\x86", + "\xE0\xBA" => "\xE9\x89\xAD", + "\xE0\xBB" => "\xE9\x89\xAC", + "\xE0\xBC" => "\xE9\x89\x8F", + "\xE0\xBD" => "\xE9\x89\xA0", + "\xE0\xBE" => "\xE9\x89\xA7", + "\xE0\xBF" => "\xE9\x89\xAF", + "\xE0\xC0" => "\xE9\x88\xB6", + "\xE0\xC1" => "\xE9\x89\xA1", + "\xE0\xC2" => "\xE9\x89\xB0", + "\xE0\xC3" => "\xE9\x88\xB1", + "\xE0\xC4" => "\xE9\x89\x94", + "\xE0\xC5" => "\xE9\x89\xA3", + "\xE0\xC6" => "\xE9\x89\x90", + "\xE0\xC7" => "\xE9\x89\xB2", + "\xE0\xC8" => "\xE9\x89\x8E", + "\xE0\xC9" => "\xE9\x89\x93", + "\xE0\xCA" => "\xE9\x89\x8C", + "\xE0\xCB" => "\xE9\x89\x96", + "\xE0\xCC" => "\xE9\x88\xB2", + "\xE0\xCD" => "\xE9\x96\x9F", + "\xE0\xCE" => "\xE9\x96\x9C", + "\xE0\xCF" => "\xE9\x96\x9E", + "\xE0\xD0" => "\xE9\x96\x9B", + "\xE0\xD1" => "\xE9\x9A\x92", + "\xE0\xD2" => "\xE9\x9A\x93", + "\xE0\xD3" => "\xE9\x9A\x91", + "\xE0\xD4" => "\xE9\x9A\x97", + "\xE0\xD5" => "\xE9\x9B\x8E", + "\xE0\xD6" => "\xE9\x9B\xBA", + "\xE0\xD7" => "\xE9\x9B\xBD", + "\xE0\xD8" => "\xE9\x9B\xB8", + "\xE0\xD9" => "\xE9\x9B\xB5", + "\xE0\xDA" => "\xE9\x9D\xB3", + "\xE0\xDB" => "\xE9\x9D\xB7", + "\xE0\xDC" => "\xE9\x9D\xB8", + "\xE0\xDD" => "\xE9\x9D\xB2", + "\xE0\xDE" => "\xE9\xA0\x8F", + "\xE0\xDF" => "\xE9\xA0\x8D", + "\xE0\xE0" => "\xE9\xA0\x8E", + "\xE0\xE1" => "\xE9\xA2\xAC", + "\xE0\xE2" => "\xE9\xA3\xB6", + "\xE0\xE3" => "\xE9\xA3\xB9", + "\xE0\xE4" => "\xE9\xA6\xAF", + "\xE0\xE5" => "\xE9\xA6\xB2", + "\xE0\xE6" => "\xE9\xA6\xB0", + "\xE0\xE7" => "\xE9\xA6\xB5", + "\xE0\xE8" => "\xE9\xAA\xAD", + "\xE0\xE9" => "\xE9\xAA\xAB", + "\xE0\xEA" => "\xE9\xAD\x9B", + "\xE0\xEB" => "\xE9\xB3\xAA", + "\xE0\xEC" => "\xE9\xB3\xAD", + "\xE0\xED" => "\xE9\xB3\xA7", + "\xE0\xEE" => "\xE9\xBA\x80", + "\xE0\xEF" => "\xE9\xBB\xBD", + "\xE0\xF0" => "\xE5\x83\xA6", + "\xE0\xF1" => "\xE5\x83\x94", + "\xE0\xF2" => "\xE5\x83\x97", + "\xE0\xF3" => "\xE5\x83\xA8", + "\xE0\xF4" => "\xE5\x83\xB3", + "\xE0\xF5" => "\xE5\x83\x9B", + "\xE0\xF6" => "\xE5\x83\xAA", + "\xE0\xF7" => "\xE5\x83\x9D", + "\xE0\xF8" => "\xE5\x83\xA4", + "\xE0\xF9" => "\xE5\x83\x93", + "\xE0\xFA" => "\xE5\x83\xAC", + "\xE0\xFB" => "\xE5\x83\xB0", + "\xE0\xFC" => "\xE5\x83\xAF", + "\xE0\xFD" => "\xE5\x83\xA3", + "\xE0\xFE" => "\xE5\x83\xA0", + "\xE1\x40" => "\xE5\x87\x98", + "\xE1\x41" => "\xE5\x8A\x80", + "\xE1\x42" => "\xE5\x8A\x81", + "\xE1\x43" => "\xE5\x8B\xA9", + "\xE1\x44" => "\xE5\x8B\xAB", + "\xE1\x45" => "\xE5\x8C\xB0", + "\xE1\x46" => "\xE5\x8E\xAC", + "\xE1\x47" => "\xE5\x98\xA7", + "\xE1\x48" => "\xE5\x98\x95", + "\xE1\x49" => "\xE5\x98\x8C", + "\xE1\x4A" => "\xE5\x98\x92", + "\xE1\x4B" => "\xE5\x97\xBC", + "\xE1\x4C" => "\xE5\x98\x8F", + "\xE1\x4D" => "\xE5\x98\x9C", + "\xE1\x4E" => "\xE5\x98\x81", + "\xE1\x4F" => "\xE5\x98\x93", + "\xE1\x50" => "\xE5\x98\x82", + "\xE1\x51" => "\xE5\x97\xBA", + "\xE1\x52" => "\xE5\x98\x9D", + "\xE1\x53" => "\xE5\x98\x84", + "\xE1\x54" => "\xE5\x97\xBF", + "\xE1\x55" => "\xE5\x97\xB9", + "\xE1\x56" => "\xE5\xA2\x89", + "\xE1\x57" => "\xE5\xA1\xBC", + "\xE1\x58" => "\xE5\xA2\x90", + "\xE1\x59" => "\xE5\xA2\x98", + "\xE1\x5A" => "\xE5\xA2\x86", + "\xE1\x5B" => "\xE5\xA2\x81", + "\xE1\x5C" => "\xE5\xA1\xBF", + "\xE1\x5D" => "\xE5\xA1\xB4", + "\xE1\x5E" => "\xE5\xA2\x8B", + "\xE1\x5F" => "\xE5\xA1\xBA", + "\xE1\x60" => "\xE5\xA2\x87", + "\xE1\x61" => "\xE5\xA2\x91", + "\xE1\x62" => "\xE5\xA2\x8E", + "\xE1\x63" => "\xE5\xA1\xB6", + "\xE1\x64" => "\xE5\xA2\x82", + "\xE1\x65" => "\xE5\xA2\x88", + "\xE1\x66" => "\xE5\xA1\xBB", + "\xE1\x67" => "\xE5\xA2\x94", + "\xE1\x68" => "\xE5\xA2\x8F", + "\xE1\x69" => "\xE5\xA3\xBE", + "\xE1\x6A" => "\xE5\xA5\xAB", + "\xE1\x6B" => "\xE5\xAB\x9C", + "\xE1\x6C" => "\xE5\xAB\xAE", + "\xE1\x6D" => "\xE5\xAB\xA5", + "\xE1\x6E" => "\xE5\xAB\x95", + "\xE1\x6F" => "\xE5\xAB\xAA", + "\xE1\x70" => "\xE5\xAB\x9A", + "\xE1\x71" => "\xE5\xAB\xAD", + "\xE1\x72" => "\xE5\xAB\xAB", + "\xE1\x73" => "\xE5\xAB\xB3", + "\xE1\x74" => "\xE5\xAB\xA2", + "\xE1\x75" => "\xE5\xAB\xA0", + "\xE1\x76" => "\xE5\xAB\x9B", + "\xE1\x77" => "\xE5\xAB\xAC", + "\xE1\x78" => "\xE5\xAB\x9E", + "\xE1\x79" => "\xE5\xAB\x9D", + "\xE1\x7A" => "\xE5\xAB\x99", + "\xE1\x7B" => "\xE5\xAB\xA8", + "\xE1\x7C" => "\xE5\xAB\x9F", + "\xE1\x7D" => "\xE5\xAD\xB7", + "\xE1\x7E" => "\xE5\xAF\xA0", + "\xE1\xA1" => "\xE5\xAF\xA3", + "\xE1\xA2" => "\xE5\xB1\xA3", + "\xE1\xA3" => "\xE5\xB6\x82", + "\xE1\xA4" => "\xE5\xB6\x80", + "\xE1\xA5" => "\xE5\xB5\xBD", + "\xE1\xA6" => "\xE5\xB6\x86", + "\xE1\xA7" => "\xE5\xB5\xBA", + "\xE1\xA8" => "\xE5\xB6\x81", + "\xE1\xA9" => "\xE5\xB5\xB7", + "\xE1\xAA" => "\xE5\xB6\x8A", + "\xE1\xAB" => "\xE5\xB6\x89", + "\xE1\xAC" => "\xE5\xB6\x88", + "\xE1\xAD" => "\xE5\xB5\xBE", + "\xE1\xAE" => "\xE5\xB5\xBC", + "\xE1\xAF" => "\xE5\xB6\x8D", + "\xE1\xB0" => "\xE5\xB5\xB9", + "\xE1\xB1" => "\xE5\xB5\xBF", + "\xE1\xB2" => "\xE5\xB9\x98", + "\xE1\xB3" => "\xE5\xB9\x99", + "\xE1\xB4" => "\xE5\xB9\x93", + "\xE1\xB5" => "\xE5\xBB\x98", + "\xE1\xB6" => "\xE5\xBB\x91", + "\xE1\xB7" => "\xE5\xBB\x97", + "\xE1\xB8" => "\xE5\xBB\x8E", + "\xE1\xB9" => "\xE5\xBB\x9C", + "\xE1\xBA" => "\xE5\xBB\x95", + "\xE1\xBB" => "\xE5\xBB\x99", + "\xE1\xBC" => "\xE5\xBB\x92", + "\xE1\xBD" => "\xE5\xBB\x94", + "\xE1\xBE" => "\xE5\xBD\x84", + "\xE1\xBF" => "\xE5\xBD\x83", + "\xE1\xC0" => "\xE5\xBD\xAF", + "\xE1\xC1" => "\xE5\xBE\xB6", + "\xE1\xC2" => "\xE6\x84\xAC", + "\xE1\xC3" => "\xE6\x84\xA8", + "\xE1\xC4" => "\xE6\x85\x81", + "\xE1\xC5" => "\xE6\x85\x9E", + "\xE1\xC6" => "\xE6\x85\xB1", + "\xE1\xC7" => "\xE6\x85\xB3", + "\xE1\xC8" => "\xE6\x85\x92", + "\xE1\xC9" => "\xE6\x85\x93", + "\xE1\xCA" => "\xE6\x85\xB2", + "\xE1\xCB" => "\xE6\x85\xAC", + "\xE1\xCC" => "\xE6\x86\x80", + "\xE1\xCD" => "\xE6\x85\xB4", + "\xE1\xCE" => "\xE6\x85\x94", + "\xE1\xCF" => "\xE6\x85\xBA", + "\xE1\xD0" => "\xE6\x85\x9B", + "\xE1\xD1" => "\xE6\x85\xA5", + "\xE1\xD2" => "\xE6\x84\xBB", + "\xE1\xD3" => "\xE6\x85\xAA", + "\xE1\xD4" => "\xE6\x85\xA1", + "\xE1\xD5" => "\xE6\x85\x96", + "\xE1\xD6" => "\xE6\x88\xA9", + "\xE1\xD7" => "\xE6\x88\xA7", + "\xE1\xD8" => "\xE6\x88\xAB", + "\xE1\xD9" => "\xE6\x90\xAB", + "\xE1\xDA" => "\xE6\x91\x8D", + "\xE1\xDB" => "\xE6\x91\x9B", + "\xE1\xDC" => "\xE6\x91\x9D", + "\xE1\xDD" => "\xE6\x91\xB4", + "\xE1\xDE" => "\xE6\x91\xB6", + "\xE1\xDF" => "\xE6\x91\xB2", + "\xE1\xE0" => "\xE6\x91\xB3", + "\xE1\xE1" => "\xE6\x91\xBD", + "\xE1\xE2" => "\xE6\x91\xB5", + "\xE1\xE3" => "\xE6\x91\xA6", + "\xE1\xE4" => "\xE6\x92\xA6", + "\xE1\xE5" => "\xE6\x91\x8E", + "\xE1\xE6" => "\xE6\x92\x82", + "\xE1\xE7" => "\xE6\x91\x9E", + "\xE1\xE8" => "\xE6\x91\x9C", + "\xE1\xE9" => "\xE6\x91\x8B", + "\xE1\xEA" => "\xE6\x91\x93", + "\xE1\xEB" => "\xE6\x91\xA0", + "\xE1\xEC" => "\xE6\x91\x90", + "\xE1\xED" => "\xE6\x91\xBF", + "\xE1\xEE" => "\xE6\x90\xBF", + "\xE1\xEF" => "\xE6\x91\xAC", + "\xE1\xF0" => "\xE6\x91\xAB", + "\xE1\xF1" => "\xE6\x91\x99", + "\xE1\xF2" => "\xE6\x91\xA5", + "\xE1\xF3" => "\xE6\x91\xB7", + "\xE1\xF4" => "\xE6\x95\xB3", + "\xE1\xF5" => "\xE6\x96\xA0", + "\xE1\xF6" => "\xE6\x9A\xA1", + "\xE1\xF7" => "\xE6\x9A\xA0", + "\xE1\xF8" => "\xE6\x9A\x9F", + "\xE1\xF9" => "\xE6\x9C\x85", + "\xE1\xFA" => "\xE6\x9C\x84", + "\xE1\xFB" => "\xE6\x9C\xA2", + "\xE1\xFC" => "\xE6\xA6\xB1", + "\xE1\xFD" => "\xE6\xA6\xB6", + "\xE1\xFE" => "\xE6\xA7\x89", + "\xE2\x40" => "\xE6\xA6\xA0", + "\xE2\x41" => "\xE6\xA7\x8E", + "\xE2\x42" => "\xE6\xA6\x96", + "\xE2\x43" => "\xE6\xA6\xB0", + "\xE2\x44" => "\xE6\xA6\xAC", + "\xE2\x45" => "\xE6\xA6\xBC", + "\xE2\x46" => "\xE6\xA6\x91", + "\xE2\x47" => "\xE6\xA6\x99", + "\xE2\x48" => "\xE6\xA6\x8E", + "\xE2\x49" => "\xE6\xA6\xA7", + "\xE2\x4A" => "\xE6\xA6\x8D", + "\xE2\x4B" => "\xE6\xA6\xA9", + "\xE2\x4C" => "\xE6\xA6\xBE", + "\xE2\x4D" => "\xE6\xA6\xAF", + "\xE2\x4E" => "\xE6\xA6\xBF", + "\xE2\x4F" => "\xE6\xA7\x84", + "\xE2\x50" => "\xE6\xA6\xBD", + "\xE2\x51" => "\xE6\xA6\xA4", + "\xE2\x52" => "\xE6\xA7\x94", + "\xE2\x53" => "\xE6\xA6\xB9", + "\xE2\x54" => "\xE6\xA7\x8A", + "\xE2\x55" => "\xE6\xA6\x9A", + "\xE2\x56" => "\xE6\xA7\x8F", + "\xE2\x57" => "\xE6\xA6\xB3", + "\xE2\x58" => "\xE6\xA6\x93", + "\xE2\x59" => "\xE6\xA6\xAA", + "\xE2\x5A" => "\xE6\xA6\xA1", + "\xE2\x5B" => "\xE6\xA6\x9E", + "\xE2\x5C" => "\xE6\xA7\x99", + "\xE2\x5D" => "\xE6\xA6\x97", + "\xE2\x5E" => "\xE6\xA6\x90", + "\xE2\x5F" => "\xE6\xA7\x82", + "\xE2\x60" => "\xE6\xA6\xB5", + "\xE2\x61" => "\xE6\xA6\xA5", + "\xE2\x62" => "\xE6\xA7\x86", + "\xE2\x63" => "\xE6\xAD\x8A", + "\xE2\x64" => "\xE6\xAD\x8D", + "\xE2\x65" => "\xE6\xAD\x8B", + "\xE2\x66" => "\xE6\xAE\x9E", + "\xE2\x67" => "\xE6\xAE\x9F", + "\xE2\x68" => "\xE6\xAE\xA0", + "\xE2\x69" => "\xE6\xAF\x83", + "\xE2\x6A" => "\xE6\xAF\x84", + "\xE2\x6B" => "\xE6\xAF\xBE", + "\xE2\x6C" => "\xE6\xBB\x8E", + "\xE2\x6D" => "\xE6\xBB\xB5", + "\xE2\x6E" => "\xE6\xBB\xB1", + "\xE2\x6F" => "\xE6\xBC\x83", + "\xE2\x70" => "\xE6\xBC\xA5", + "\xE2\x71" => "\xE6\xBB\xB8", + "\xE2\x72" => "\xE6\xBC\xB7", + "\xE2\x73" => "\xE6\xBB\xBB", + "\xE2\x74" => "\xE6\xBC\xAE", + "\xE2\x75" => "\xE6\xBC\x89", + "\xE2\x76" => "\xE6\xBD\x8E", + "\xE2\x77" => "\xE6\xBC\x99", + "\xE2\x78" => "\xE6\xBC\x9A", + "\xE2\x79" => "\xE6\xBC\xA7", + "\xE2\x7A" => "\xE6\xBC\x98", + "\xE2\x7B" => "\xE6\xBC\xBB", + "\xE2\x7C" => "\xE6\xBC\x92", + "\xE2\x7D" => "\xE6\xBB\xAD", + "\xE2\x7E" => "\xE6\xBC\x8A", + "\xE2\xA1" => "\xE6\xBC\xB6", + "\xE2\xA2" => "\xE6\xBD\xB3", + "\xE2\xA3" => "\xE6\xBB\xB9", + "\xE2\xA4" => "\xE6\xBB\xAE", + "\xE2\xA5" => "\xE6\xBC\xAD", + "\xE2\xA6" => "\xE6\xBD\x80", + "\xE2\xA7" => "\xE6\xBC\xB0", + "\xE2\xA8" => "\xE6\xBC\xBC", + "\xE2\xA9" => "\xE6\xBC\xB5", + "\xE2\xAA" => "\xE6\xBB\xAB", + "\xE2\xAB" => "\xE6\xBC\x87", + "\xE2\xAC" => "\xE6\xBC\x8E", + "\xE2\xAD" => "\xE6\xBD\x83", + "\xE2\xAE" => "\xE6\xBC\x85", + "\xE2\xAF" => "\xE6\xBB\xBD", + "\xE2\xB0" => "\xE6\xBB\xB6", + "\xE2\xB1" => "\xE6\xBC\xB9", + "\xE2\xB2" => "\xE6\xBC\x9C", + "\xE2\xB3" => "\xE6\xBB\xBC", + "\xE2\xB4" => "\xE6\xBC\xBA", + "\xE2\xB5" => "\xE6\xBC\x9F", + "\xE2\xB6" => "\xE6\xBC\x8D", + "\xE2\xB7" => "\xE6\xBC\x9E", + "\xE2\xB8" => "\xE6\xBC\x88", + "\xE2\xB9" => "\xE6\xBC\xA1", + "\xE2\xBA" => "\xE7\x86\x87", + "\xE2\xBB" => "\xE7\x86\x90", + "\xE2\xBC" => "\xE7\x86\x89", + "\xE2\xBD" => "\xE7\x86\x80", + "\xE2\xBE" => "\xE7\x86\x85", + "\xE2\xBF" => "\xE7\x86\x82", + "\xE2\xC0" => "\xE7\x86\x8F", + "\xE2\xC1" => "\xE7\x85\xBB", + "\xE2\xC2" => "\xE7\x86\x86", + "\xE2\xC3" => "\xE7\x86\x81", + "\xE2\xC4" => "\xE7\x86\x97", + "\xE2\xC5" => "\xE7\x89\x84", + "\xE2\xC6" => "\xE7\x89\x93", + "\xE2\xC7" => "\xE7\x8A\x97", + "\xE2\xC8" => "\xE7\x8A\x95", + "\xE2\xC9" => "\xE7\x8A\x93", + "\xE2\xCA" => "\xE7\x8D\x83", + "\xE2\xCB" => "\xE7\x8D\x8D", + "\xE2\xCC" => "\xE7\x8D\x91", + "\xE2\xCD" => "\xE7\x8D\x8C", + "\xE2\xCE" => "\xE7\x91\xA2", + "\xE2\xCF" => "\xE7\x91\xB3", + "\xE2\xD0" => "\xE7\x91\xB1", + "\xE2\xD1" => "\xE7\x91\xB5", + "\xE2\xD2" => "\xE7\x91\xB2", + "\xE2\xD3" => "\xE7\x91\xA7", + "\xE2\xD4" => "\xE7\x91\xAE", + "\xE2\xD5" => "\xE7\x94\x80", + "\xE2\xD6" => "\xE7\x94\x82", + "\xE2\xD7" => "\xE7\x94\x83", + "\xE2\xD8" => "\xE7\x95\xBD", + "\xE2\xD9" => "\xE7\x96\x90", + "\xE2\xDA" => "\xE7\x98\x96", + "\xE2\xDB" => "\xE7\x98\x88", + "\xE2\xDC" => "\xE7\x98\x8C", + "\xE2\xDD" => "\xE7\x98\x95", + "\xE2\xDE" => "\xE7\x98\x91", + "\xE2\xDF" => "\xE7\x98\x8A", + "\xE2\xE0" => "\xE7\x98\x94", + "\xE2\xE1" => "\xE7\x9A\xB8", + "\xE2\xE2" => "\xE7\x9E\x81", + "\xE2\xE3" => "\xE7\x9D\xBC", + "\xE2\xE4" => "\xE7\x9E\x85", + "\xE2\xE5" => "\xE7\x9E\x82", + "\xE2\xE6" => "\xE7\x9D\xAE", + "\xE2\xE7" => "\xE7\x9E\x80", + "\xE2\xE8" => "\xE7\x9D\xAF", + "\xE2\xE9" => "\xE7\x9D\xBE", + "\xE2\xEA" => "\xE7\x9E\x83", + "\xE2\xEB" => "\xE7\xA2\xB2", + "\xE2\xEC" => "\xE7\xA2\xAA", + "\xE2\xED" => "\xE7\xA2\xB4", + "\xE2\xEE" => "\xE7\xA2\xAD", + "\xE2\xEF" => "\xE7\xA2\xA8", + "\xE2\xF0" => "\xE7\xA1\xBE", + "\xE2\xF1" => "\xE7\xA2\xAB", + "\xE2\xF2" => "\xE7\xA2\x9E", + "\xE2\xF3" => "\xE7\xA2\xA5", + "\xE2\xF4" => "\xE7\xA2\xA0", + "\xE2\xF5" => "\xE7\xA2\xAC", + "\xE2\xF6" => "\xE7\xA2\xA2", + "\xE2\xF7" => "\xE7\xA2\xA4", + "\xE2\xF8" => "\xE7\xA6\x98", + "\xE2\xF9" => "\xE7\xA6\x8A", + "\xE2\xFA" => "\xE7\xA6\x8B", + "\xE2\xFB" => "\xE7\xA6\x96", + "\xE2\xFC" => "\xE7\xA6\x95", + "\xE2\xFD" => "\xE7\xA6\x94", + "\xE2\xFE" => "\xE7\xA6\x93", + "\xE3\x40" => "\xE7\xA6\x97", + "\xE3\x41" => "\xE7\xA6\x88", + "\xE3\x42" => "\xE7\xA6\x92", + "\xE3\x43" => "\xE7\xA6\x90", + "\xE3\x44" => "\xE7\xA8\xAB", + "\xE3\x45" => "\xE7\xA9\x8A", + "\xE3\x46" => "\xE7\xA8\xB0", + "\xE3\x47" => "\xE7\xA8\xAF", + "\xE3\x48" => "\xE7\xA8\xA8", + "\xE3\x49" => "\xE7\xA8\xA6", + "\xE3\x4A" => "\xE7\xAA\xA8", + "\xE3\x4B" => "\xE7\xAA\xAB", + "\xE3\x4C" => "\xE7\xAA\xAC", + "\xE3\x4D" => "\xE7\xAB\xAE", + "\xE3\x4E" => "\xE7\xAE\x88", + "\xE3\x4F" => "\xE7\xAE\x9C", + "\xE3\x50" => "\xE7\xAE\x8A", + "\xE3\x51" => "\xE7\xAE\x91", + "\xE3\x52" => "\xE7\xAE\x90", + "\xE3\x53" => "\xE7\xAE\x96", + "\xE3\x54" => "\xE7\xAE\x8D", + "\xE3\x55" => "\xE7\xAE\x8C", + "\xE3\x56" => "\xE7\xAE\x9B", + "\xE3\x57" => "\xE7\xAE\x8E", + "\xE3\x58" => "\xE7\xAE\x85", + "\xE3\x59" => "\xE7\xAE\x98", + "\xE3\x5A" => "\xE5\x8A\x84", + "\xE3\x5B" => "\xE7\xAE\x99", + "\xE3\x5C" => "\xE7\xAE\xA4", + "\xE3\x5D" => "\xE7\xAE\x82", + "\xE3\x5E" => "\xE7\xB2\xBB", + "\xE3\x5F" => "\xE7\xB2\xBF", + "\xE3\x60" => "\xE7\xB2\xBC", + "\xE3\x61" => "\xE7\xB2\xBA", + "\xE3\x62" => "\xE7\xB6\xA7", + "\xE3\x63" => "\xE7\xB6\xB7", + "\xE3\x64" => "\xE7\xB7\x82", + "\xE3\x65" => "\xE7\xB6\xA3", + "\xE3\x66" => "\xE7\xB6\xAA", + "\xE3\x67" => "\xE7\xB7\x81", + "\xE3\x68" => "\xE7\xB7\x80", + "\xE3\x69" => "\xE7\xB7\x85", + "\xE3\x6A" => "\xE7\xB6\x9D", + "\xE3\x6B" => "\xE7\xB7\x8E", + "\xE3\x6C" => "\xE7\xB7\x84", + "\xE3\x6D" => "\xE7\xB7\x86", + "\xE3\x6E" => "\xE7\xB7\x8B", + "\xE3\x6F" => "\xE7\xB7\x8C", + "\xE3\x70" => "\xE7\xB6\xAF", + "\xE3\x71" => "\xE7\xB6\xB9", + "\xE3\x72" => "\xE7\xB6\x96", + "\xE3\x73" => "\xE7\xB6\xBC", + "\xE3\x74" => "\xE7\xB6\x9F", + "\xE3\x75" => "\xE7\xB6\xA6", + "\xE3\x76" => "\xE7\xB6\xAE", + "\xE3\x77" => "\xE7\xB6\xA9", + "\xE3\x78" => "\xE7\xB6\xA1", + "\xE3\x79" => "\xE7\xB7\x89", + "\xE3\x7A" => "\xE7\xBD\xB3", + "\xE3\x7B" => "\xE7\xBF\xA2", + "\xE3\x7C" => "\xE7\xBF\xA3", + "\xE3\x7D" => "\xE7\xBF\xA5", + "\xE3\x7E" => "\xE7\xBF\x9E", + "\xE3\xA1" => "\xE8\x80\xA4", + "\xE3\xA2" => "\xE8\x81\x9D", + "\xE3\xA3" => "\xE8\x81\x9C", + "\xE3\xA4" => "\xE8\x86\x89", + "\xE3\xA5" => "\xE8\x86\x86", + "\xE3\xA6" => "\xE8\x86\x83", + "\xE3\xA7" => "\xE8\x86\x87", + "\xE3\xA8" => "\xE8\x86\x8D", + "\xE3\xA9" => "\xE8\x86\x8C", + "\xE3\xAA" => "\xE8\x86\x8B", + "\xE3\xAB" => "\xE8\x88\x95", + "\xE3\xAC" => "\xE8\x92\x97", + "\xE3\xAD" => "\xE8\x92\xA4", + "\xE3\xAE" => "\xE8\x92\xA1", + "\xE3\xAF" => "\xE8\x92\x9F", + "\xE3\xB0" => "\xE8\x92\xBA", + "\xE3\xB1" => "\xE8\x93\x8E", + "\xE3\xB2" => "\xE8\x93\x82", + "\xE3\xB3" => "\xE8\x92\xAC", + "\xE3\xB4" => "\xE8\x92\xAE", + "\xE3\xB5" => "\xE8\x92\xAB", + "\xE3\xB6" => "\xE8\x92\xB9", + "\xE3\xB7" => "\xE8\x92\xB4", + "\xE3\xB8" => "\xE8\x93\x81", + "\xE3\xB9" => "\xE8\x93\x8D", + "\xE3\xBA" => "\xE8\x92\xAA", + "\xE3\xBB" => "\xE8\x92\x9A", + "\xE3\xBC" => "\xE8\x92\xB1", + "\xE3\xBD" => "\xE8\x93\x90", + "\xE3\xBE" => "\xE8\x92\x9D", + "\xE3\xBF" => "\xE8\x92\xA7", + "\xE3\xC0" => "\xE8\x92\xBB", + "\xE3\xC1" => "\xE8\x92\xA2", + "\xE3\xC2" => "\xE8\x92\x94", + "\xE3\xC3" => "\xE8\x93\x87", + "\xE3\xC4" => "\xE8\x93\x8C", + "\xE3\xC5" => "\xE8\x92\x9B", + "\xE3\xC6" => "\xE8\x92\xA9", + "\xE3\xC7" => "\xE8\x92\xAF", + "\xE3\xC8" => "\xE8\x92\xA8", + "\xE3\xC9" => "\xE8\x93\x96", + "\xE3\xCA" => "\xE8\x92\x98", + "\xE3\xCB" => "\xE8\x92\xB6", + "\xE3\xCC" => "\xE8\x93\x8F", + "\xE3\xCD" => "\xE8\x92\xA0", + "\xE3\xCE" => "\xE8\x93\x97", + "\xE3\xCF" => "\xE8\x93\x94", + "\xE3\xD0" => "\xE8\x93\x92", + "\xE3\xD1" => "\xE8\x93\x9B", + "\xE3\xD2" => "\xE8\x92\xB0", + "\xE3\xD3" => "\xE8\x92\x91", + "\xE3\xD4" => "\xE8\x99\xA1", + "\xE3\xD5" => "\xE8\x9C\xB3", + "\xE3\xD6" => "\xE8\x9C\xA3", + "\xE3\xD7" => "\xE8\x9C\xA8", + "\xE3\xD8" => "\xE8\x9D\xAB", + "\xE3\xD9" => "\xE8\x9D\x80", + "\xE3\xDA" => "\xE8\x9C\xAE", + "\xE3\xDB" => "\xE8\x9C\x9E", + "\xE3\xDC" => "\xE8\x9C\xA1", + "\xE3\xDD" => "\xE8\x9C\x99", + "\xE3\xDE" => "\xE8\x9C\x9B", + "\xE3\xDF" => "\xE8\x9D\x83", + "\xE3\xE0" => "\xE8\x9C\xAC", + "\xE3\xE1" => "\xE8\x9D\x81", + "\xE3\xE2" => "\xE8\x9C\xBE", + "\xE3\xE3" => "\xE8\x9D\x86", + "\xE3\xE4" => "\xE8\x9C\xA0", + "\xE3\xE5" => "\xE8\x9C\xB2", + "\xE3\xE6" => "\xE8\x9C\xAA", + "\xE3\xE7" => "\xE8\x9C\xAD", + "\xE3\xE8" => "\xE8\x9C\xBC", + "\xE3\xE9" => "\xE8\x9C\x92", + "\xE3\xEA" => "\xE8\x9C\xBA", + "\xE3\xEB" => "\xE8\x9C\xB1", + "\xE3\xEC" => "\xE8\x9C\xB5", + "\xE3\xED" => "\xE8\x9D\x82", + "\xE3\xEE" => "\xE8\x9C\xA6", + "\xE3\xEF" => "\xE8\x9C\xA7", + "\xE3\xF0" => "\xE8\x9C\xB8", + "\xE3\xF1" => "\xE8\x9C\xA4", + "\xE3\xF2" => "\xE8\x9C\x9A", + "\xE3\xF3" => "\xE8\x9C\xB0", + "\xE3\xF4" => "\xE8\x9C\x91", + "\xE3\xF5" => "\xE8\xA3\xB7", + "\xE3\xF6" => "\xE8\xA3\xA7", + "\xE3\xF7" => "\xE8\xA3\xB1", + "\xE3\xF8" => "\xE8\xA3\xB2", + "\xE3\xF9" => "\xE8\xA3\xBA", + "\xE3\xFA" => "\xE8\xA3\xBE", + "\xE3\xFB" => "\xE8\xA3\xAE", + "\xE3\xFC" => "\xE8\xA3\xBC", + "\xE3\xFD" => "\xE8\xA3\xB6", + "\xE3\xFE" => "\xE8\xA3\xBB", + "\xE4\x40" => "\xE8\xA3\xB0", + "\xE4\x41" => "\xE8\xA3\xAC", + "\xE4\x42" => "\xE8\xA3\xAB", + "\xE4\x43" => "\xE8\xA6\x9D", + "\xE4\x44" => "\xE8\xA6\xA1", + "\xE4\x45" => "\xE8\xA6\x9F", + "\xE4\x46" => "\xE8\xA6\x9E", + "\xE4\x47" => "\xE8\xA7\xA9", + "\xE4\x48" => "\xE8\xA7\xAB", + "\xE4\x49" => "\xE8\xA7\xA8", + "\xE4\x4A" => "\xE8\xAA\xAB", + "\xE4\x4B" => "\xE8\xAA\x99", + "\xE4\x4C" => "\xE8\xAA\x8B", + "\xE4\x4D" => "\xE8\xAA\x92", + "\xE4\x4E" => "\xE8\xAA\x8F", + "\xE4\x4F" => "\xE8\xAA\x96", + "\xE4\x50" => "\xE8\xB0\xBD", + "\xE4\x51" => "\xE8\xB1\xA8", + "\xE4\x52" => "\xE8\xB1\xA9", + "\xE4\x53" => "\xE8\xB3\x95", + "\xE4\x54" => "\xE8\xB3\x8F", + "\xE4\x55" => "\xE8\xB3\x97", + "\xE4\x56" => "\xE8\xB6\x96", + "\xE4\x57" => "\xE8\xB8\x89", + "\xE4\x58" => "\xE8\xB8\x82", + "\xE4\x59" => "\xE8\xB7\xBF", + "\xE4\x5A" => "\xE8\xB8\x8D", + "\xE4\x5B" => "\xE8\xB7\xBD", + "\xE4\x5C" => "\xE8\xB8\x8A", + "\xE4\x5D" => "\xE8\xB8\x83", + "\xE4\x5E" => "\xE8\xB8\x87", + "\xE4\x5F" => "\xE8\xB8\x86", + "\xE4\x60" => "\xE8\xB8\x85", + "\xE4\x61" => "\xE8\xB7\xBE", + "\xE4\x62" => "\xE8\xB8\x80", + "\xE4\x63" => "\xE8\xB8\x84", + "\xE4\x64" => "\xE8\xBC\x90", + "\xE4\x65" => "\xE8\xBC\x91", + "\xE4\x66" => "\xE8\xBC\x8E", + "\xE4\x67" => "\xE8\xBC\x8D", + "\xE4\x68" => "\xE9\x84\xA3", + "\xE4\x69" => "\xE9\x84\x9C", + "\xE4\x6A" => "\xE9\x84\xA0", + "\xE4\x6B" => "\xE9\x84\xA2", + "\xE4\x6C" => "\xE9\x84\x9F", + "\xE4\x6D" => "\xE9\x84\x9D", + "\xE4\x6E" => "\xE9\x84\x9A", + "\xE4\x6F" => "\xE9\x84\xA4", + "\xE4\x70" => "\xE9\x84\xA1", + "\xE4\x71" => "\xE9\x84\x9B", + "\xE4\x72" => "\xE9\x85\xBA", + "\xE4\x73" => "\xE9\x85\xB2", + "\xE4\x74" => "\xE9\x85\xB9", + "\xE4\x75" => "\xE9\x85\xB3", + "\xE4\x76" => "\xE9\x8A\xA5", + "\xE4\x77" => "\xE9\x8A\xA4", + "\xE4\x78" => "\xE9\x89\xB6", + "\xE4\x79" => "\xE9\x8A\x9B", + "\xE4\x7A" => "\xE9\x89\xBA", + "\xE4\x7B" => "\xE9\x8A\xA0", + "\xE4\x7C" => "\xE9\x8A\x94", + "\xE4\x7D" => "\xE9\x8A\xAA", + "\xE4\x7E" => "\xE9\x8A\x8D", + "\xE4\xA1" => "\xE9\x8A\xA6", + "\xE4\xA2" => "\xE9\x8A\x9A", + "\xE4\xA3" => "\xE9\x8A\xAB", + "\xE4\xA4" => "\xE9\x89\xB9", + "\xE4\xA5" => "\xE9\x8A\x97", + "\xE4\xA6" => "\xE9\x89\xBF", + "\xE4\xA7" => "\xE9\x8A\xA3", + "\xE4\xA8" => "\xE9\x8B\xAE", + "\xE4\xA9" => "\xE9\x8A\x8E", + "\xE4\xAA" => "\xE9\x8A\x82", + "\xE4\xAB" => "\xE9\x8A\x95", + "\xE4\xAC" => "\xE9\x8A\xA2", + "\xE4\xAD" => "\xE9\x89\xBD", + "\xE4\xAE" => "\xE9\x8A\x88", + "\xE4\xAF" => "\xE9\x8A\xA1", + "\xE4\xB0" => "\xE9\x8A\x8A", + "\xE4\xB1" => "\xE9\x8A\x86", + "\xE4\xB2" => "\xE9\x8A\x8C", + "\xE4\xB3" => "\xE9\x8A\x99", + "\xE4\xB4" => "\xE9\x8A\xA7", + "\xE4\xB5" => "\xE9\x89\xBE", + "\xE4\xB6" => "\xE9\x8A\x87", + "\xE4\xB7" => "\xE9\x8A\xA9", + "\xE4\xB8" => "\xE9\x8A\x9D", + "\xE4\xB9" => "\xE9\x8A\x8B", + "\xE4\xBA" => "\xE9\x88\xAD", + "\xE4\xBB" => "\xE9\x9A\x9E", + "\xE4\xBC" => "\xE9\x9A\xA1", + "\xE4\xBD" => "\xE9\x9B\xBF", + "\xE4\xBE" => "\xE9\x9D\x98", + "\xE4\xBF" => "\xE9\x9D\xBD", + "\xE4\xC0" => "\xE9\x9D\xBA", + "\xE4\xC1" => "\xE9\x9D\xBE", + "\xE4\xC2" => "\xE9\x9E\x83", + "\xE4\xC3" => "\xE9\x9E\x80", + "\xE4\xC4" => "\xE9\x9E\x82", + "\xE4\xC5" => "\xE9\x9D\xBB", + "\xE4\xC6" => "\xE9\x9E\x84", + "\xE4\xC7" => "\xE9\x9E\x81", + "\xE4\xC8" => "\xE9\x9D\xBF", + "\xE4\xC9" => "\xE9\x9F\x8E", + "\xE4\xCA" => "\xE9\x9F\x8D", + "\xE4\xCB" => "\xE9\xA0\x96", + "\xE4\xCC" => "\xE9\xA2\xAD", + "\xE4\xCD" => "\xE9\xA2\xAE", + "\xE4\xCE" => "\xE9\xA4\x82", + "\xE4\xCF" => "\xE9\xA4\x80", + "\xE4\xD0" => "\xE9\xA4\x87", + "\xE4\xD1" => "\xE9\xA6\x9D", + "\xE4\xD2" => "\xE9\xA6\x9C", + "\xE4\xD3" => "\xE9\xA7\x83", + "\xE4\xD4" => "\xE9\xA6\xB9", + "\xE4\xD5" => "\xE9\xA6\xBB", + "\xE4\xD6" => "\xE9\xA6\xBA", + "\xE4\xD7" => "\xE9\xA7\x82", + "\xE4\xD8" => "\xE9\xA6\xBD", + "\xE4\xD9" => "\xE9\xA7\x87", + "\xE4\xDA" => "\xE9\xAA\xB1", + "\xE4\xDB" => "\xE9\xAB\xA3", + "\xE4\xDC" => "\xE9\xAB\xA7", + "\xE4\xDD" => "\xE9\xAC\xBE", + "\xE4\xDE" => "\xE9\xAC\xBF", + "\xE4\xDF" => "\xE9\xAD\xA0", + "\xE4\xE0" => "\xE9\xAD\xA1", + "\xE4\xE1" => "\xE9\xAD\x9F", + "\xE4\xE2" => "\xE9\xB3\xB1", + "\xE4\xE3" => "\xE9\xB3\xB2", + "\xE4\xE4" => "\xE9\xB3\xB5", + "\xE4\xE5" => "\xE9\xBA\xA7", + "\xE4\xE6" => "\xE5\x83\xBF", + "\xE4\xE7" => "\xE5\x84\x83", + "\xE4\xE8" => "\xE5\x84\xB0", + "\xE4\xE9" => "\xE5\x83\xB8", + "\xE4\xEA" => "\xE5\x84\x86", + "\xE4\xEB" => "\xE5\x84\x87", + "\xE4\xEC" => "\xE5\x83\xB6", + "\xE4\xED" => "\xE5\x83\xBE", + "\xE4\xEE" => "\xE5\x84\x8B", + "\xE4\xEF" => "\xE5\x84\x8C", + "\xE4\xF0" => "\xE5\x83\xBD", + "\xE4\xF1" => "\xE5\x84\x8A", + "\xE4\xF2" => "\xE5\x8A\x8B", + "\xE4\xF3" => "\xE5\x8A\x8C", + "\xE4\xF4" => "\xE5\x8B\xB1", + "\xE4\xF5" => "\xE5\x8B\xAF", + "\xE4\xF6" => "\xE5\x99\x88", + "\xE4\xF7" => "\xE5\x99\x82", + "\xE4\xF8" => "\xE5\x99\x8C", + "\xE4\xF9" => "\xE5\x98\xB5", + "\xE4\xFA" => "\xE5\x99\x81", + "\xE4\xFB" => "\xE5\x99\x8A", + "\xE4\xFC" => "\xE5\x99\x89", + "\xE4\xFD" => "\xE5\x99\x86", + "\xE4\xFE" => "\xE5\x99\x98", + "\xE5\x40" => "\xE5\x99\x9A", + "\xE5\x41" => "\xE5\x99\x80", + "\xE5\x42" => "\xE5\x98\xB3", + "\xE5\x43" => "\xE5\x98\xBD", + "\xE5\x44" => "\xE5\x98\xAC", + "\xE5\x45" => "\xE5\x98\xBE", + "\xE5\x46" => "\xE5\x98\xB8", + "\xE5\x47" => "\xE5\x98\xAA", + "\xE5\x48" => "\xE5\x98\xBA", + "\xE5\x49" => "\xE5\x9C\x9A", + "\xE5\x4A" => "\xE5\xA2\xAB", + "\xE5\x4B" => "\xE5\xA2\x9D", + "\xE5\x4C" => "\xE5\xA2\xB1", + "\xE5\x4D" => "\xE5\xA2\xA0", + "\xE5\x4E" => "\xE5\xA2\xA3", + "\xE5\x4F" => "\xE5\xA2\xAF", + "\xE5\x50" => "\xE5\xA2\xAC", + "\xE5\x51" => "\xE5\xA2\xA5", + "\xE5\x52" => "\xE5\xA2\xA1", + "\xE5\x53" => "\xE5\xA3\xBF", + "\xE5\x54" => "\xE5\xAB\xBF", + "\xE5\x55" => "\xE5\xAB\xB4", + "\xE5\x56" => "\xE5\xAB\xBD", + "\xE5\x57" => "\xE5\xAB\xB7", + "\xE5\x58" => "\xE5\xAB\xB6", + "\xE5\x59" => "\xE5\xAC\x83", + "\xE5\x5A" => "\xE5\xAB\xB8", + "\xE5\x5B" => "\xE5\xAC\x82", + "\xE5\x5C" => "\xE5\xAB\xB9", + "\xE5\x5D" => "\xE5\xAC\x81", + "\xE5\x5E" => "\xE5\xAC\x87", + "\xE5\x5F" => "\xE5\xAC\x85", + "\xE5\x60" => "\xE5\xAC\x8F", + "\xE5\x61" => "\xE5\xB1\xA7", + "\xE5\x62" => "\xE5\xB6\x99", + "\xE5\x63" => "\xE5\xB6\x97", + "\xE5\x64" => "\xE5\xB6\x9F", + "\xE5\x65" => "\xE5\xB6\x92", + "\xE5\x66" => "\xE5\xB6\xA2", + "\xE5\x67" => "\xE5\xB6\x93", + "\xE5\x68" => "\xE5\xB6\x95", + "\xE5\x69" => "\xE5\xB6\xA0", + "\xE5\x6A" => "\xE5\xB6\x9C", + "\xE5\x6B" => "\xE5\xB6\xA1", + "\xE5\x6C" => "\xE5\xB6\x9A", + "\xE5\x6D" => "\xE5\xB6\x9E", + "\xE5\x6E" => "\xE5\xB9\xA9", + "\xE5\x6F" => "\xE5\xB9\x9D", + "\xE5\x70" => "\xE5\xB9\xA0", + "\xE5\x71" => "\xE5\xB9\x9C", + "\xE5\x72" => "\xE7\xB7\xB3", + "\xE5\x73" => "\xE5\xBB\x9B", + "\xE5\x74" => "\xE5\xBB\x9E", + "\xE5\x75" => "\xE5\xBB\xA1", + "\xE5\x76" => "\xE5\xBD\x89", + "\xE5\x77" => "\xE5\xBE\xB2", + "\xE5\x78" => "\xE6\x86\x8B", + "\xE5\x79" => "\xE6\x86\x83", + "\xE5\x7A" => "\xE6\x85\xB9", + "\xE5\x7B" => "\xE6\x86\xB1", + "\xE5\x7C" => "\xE6\x86\xB0", + "\xE5\x7D" => "\xE6\x86\xA2", + "\xE5\x7E" => "\xE6\x86\x89", + "\xE5\xA1" => "\xE6\x86\x9B", + "\xE5\xA2" => "\xE6\x86\x93", + "\xE5\xA3" => "\xE6\x86\xAF", + "\xE5\xA4" => "\xE6\x86\xAD", + "\xE5\xA5" => "\xE6\x86\x9F", + "\xE5\xA6" => "\xE6\x86\x92", + "\xE5\xA7" => "\xE6\x86\xAA", + "\xE5\xA8" => "\xE6\x86\xA1", + "\xE5\xA9" => "\xE6\x86\x8D", + "\xE5\xAA" => "\xE6\x85\xA6", + "\xE5\xAB" => "\xE6\x86\xB3", + "\xE5\xAC" => "\xE6\x88\xAD", + "\xE5\xAD" => "\xE6\x91\xAE", + "\xE5\xAE" => "\xE6\x91\xB0", + "\xE5\xAF" => "\xE6\x92\x96", + "\xE5\xB0" => "\xE6\x92\xA0", + "\xE5\xB1" => "\xE6\x92\x85", + "\xE5\xB2" => "\xE6\x92\x97", + "\xE5\xB3" => "\xE6\x92\x9C", + "\xE5\xB4" => "\xE6\x92\x8F", + "\xE5\xB5" => "\xE6\x92\x8B", + "\xE5\xB6" => "\xE6\x92\x8A", + "\xE5\xB7" => "\xE6\x92\x8C", + "\xE5\xB8" => "\xE6\x92\xA3", + "\xE5\xB9" => "\xE6\x92\x9F", + "\xE5\xBA" => "\xE6\x91\xA8", + "\xE5\xBB" => "\xE6\x92\xB1", + "\xE5\xBC" => "\xE6\x92\x98", + "\xE5\xBD" => "\xE6\x95\xB6", + "\xE5\xBE" => "\xE6\x95\xBA", + "\xE5\xBF" => "\xE6\x95\xB9", + "\xE5\xC0" => "\xE6\x95\xBB", + "\xE5\xC1" => "\xE6\x96\xB2", + "\xE5\xC2" => "\xE6\x96\xB3", + "\xE5\xC3" => "\xE6\x9A\xB5", + "\xE5\xC4" => "\xE6\x9A\xB0", + "\xE5\xC5" => "\xE6\x9A\xA9", + "\xE5\xC6" => "\xE6\x9A\xB2", + "\xE5\xC7" => "\xE6\x9A\xB7", + "\xE5\xC8" => "\xE6\x9A\xAA", + "\xE5\xC9" => "\xE6\x9A\xAF", + "\xE5\xCA" => "\xE6\xA8\x80", + "\xE5\xCB" => "\xE6\xA8\x86", + "\xE5\xCC" => "\xE6\xA8\x97", + "\xE5\xCD" => "\xE6\xA7\xA5", + "\xE5\xCE" => "\xE6\xA7\xB8", + "\xE5\xCF" => "\xE6\xA8\x95", + "\xE5\xD0" => "\xE6\xA7\xB1", + "\xE5\xD1" => "\xE6\xA7\xA4", + "\xE5\xD2" => "\xE6\xA8\xA0", + "\xE5\xD3" => "\xE6\xA7\xBF", + "\xE5\xD4" => "\xE6\xA7\xAC", + "\xE5\xD5" => "\xE6\xA7\xA2", + "\xE5\xD6" => "\xE6\xA8\x9B", + "\xE5\xD7" => "\xE6\xA8\x9D", + "\xE5\xD8" => "\xE6\xA7\xBE", + "\xE5\xD9" => "\xE6\xA8\xA7", + "\xE5\xDA" => "\xE6\xA7\xB2", + "\xE5\xDB" => "\xE6\xA7\xAE", + "\xE5\xDC" => "\xE6\xA8\x94", + "\xE5\xDD" => "\xE6\xA7\xB7", + "\xE5\xDE" => "\xE6\xA7\xA7", + "\xE5\xDF" => "\xE6\xA9\x80", + "\xE5\xE0" => "\xE6\xA8\x88", + "\xE5\xE1" => "\xE6\xA7\xA6", + "\xE5\xE2" => "\xE6\xA7\xBB", + "\xE5\xE3" => "\xE6\xA8\x8D", + "\xE5\xE4" => "\xE6\xA7\xBC", + "\xE5\xE5" => "\xE6\xA7\xAB", + "\xE5\xE6" => "\xE6\xA8\x89", + "\xE5\xE7" => "\xE6\xA8\x84", + "\xE5\xE8" => "\xE6\xA8\x98", + "\xE5\xE9" => "\xE6\xA8\xA5", + "\xE5\xEA" => "\xE6\xA8\x8F", + "\xE5\xEB" => "\xE6\xA7\xB6", + "\xE5\xEC" => "\xE6\xA8\xA6", + "\xE5\xED" => "\xE6\xA8\x87", + "\xE5\xEE" => "\xE6\xA7\xB4", + "\xE5\xEF" => "\xE6\xA8\x96", + "\xE5\xF0" => "\xE6\xAD\x91", + "\xE5\xF1" => "\xE6\xAE\xA5", + "\xE5\xF2" => "\xE6\xAE\xA3", + "\xE5\xF3" => "\xE6\xAE\xA2", + "\xE5\xF4" => "\xE6\xAE\xA6", + "\xE5\xF5" => "\xE6\xB0\x81", + "\xE5\xF6" => "\xE6\xB0\x80", + "\xE5\xF7" => "\xE6\xAF\xBF", + "\xE5\xF8" => "\xE6\xB0\x82", + "\xE5\xF9" => "\xE6\xBD\x81", + "\xE5\xFA" => "\xE6\xBC\xA6", + "\xE5\xFB" => "\xE6\xBD\xBE", + "\xE5\xFC" => "\xE6\xBE\x87", + "\xE5\xFD" => "\xE6\xBF\x86", + "\xE5\xFE" => "\xE6\xBE\x92", + "\xE6\x40" => "\xE6\xBE\x8D", + "\xE6\x41" => "\xE6\xBE\x89", + "\xE6\x42" => "\xE6\xBE\x8C", + "\xE6\x43" => "\xE6\xBD\xA2", + "\xE6\x44" => "\xE6\xBD\x8F", + "\xE6\x45" => "\xE6\xBE\x85", + "\xE6\x46" => "\xE6\xBD\x9A", + "\xE6\x47" => "\xE6\xBE\x96", + "\xE6\x48" => "\xE6\xBD\xB6", + "\xE6\x49" => "\xE6\xBD\xAC", + "\xE6\x4A" => "\xE6\xBE\x82", + "\xE6\x4B" => "\xE6\xBD\x95", + "\xE6\x4C" => "\xE6\xBD\xB2", + "\xE6\x4D" => "\xE6\xBD\x92", + "\xE6\x4E" => "\xE6\xBD\x90", + "\xE6\x4F" => "\xE6\xBD\x97", + "\xE6\x50" => "\xE6\xBE\x94", + "\xE6\x51" => "\xE6\xBE\x93", + "\xE6\x52" => "\xE6\xBD\x9D", + "\xE6\x53" => "\xE6\xBC\x80", + "\xE6\x54" => "\xE6\xBD\xA1", + "\xE6\x55" => "\xE6\xBD\xAB", + "\xE6\x56" => "\xE6\xBD\xBD", + "\xE6\x57" => "\xE6\xBD\xA7", + "\xE6\x58" => "\xE6\xBE\x90", + "\xE6\x59" => "\xE6\xBD\x93", + "\xE6\x5A" => "\xE6\xBE\x8B", + "\xE6\x5B" => "\xE6\xBD\xA9", + "\xE6\x5C" => "\xE6\xBD\xBF", + "\xE6\x5D" => "\xE6\xBE\x95", + "\xE6\x5E" => "\xE6\xBD\xA3", + "\xE6\x5F" => "\xE6\xBD\xB7", + "\xE6\x60" => "\xE6\xBD\xAA", + "\xE6\x61" => "\xE6\xBD\xBB", + "\xE6\x62" => "\xE7\x86\xB2", + "\xE6\x63" => "\xE7\x86\xAF", + "\xE6\x64" => "\xE7\x86\x9B", + "\xE6\x65" => "\xE7\x86\xB0", + "\xE6\x66" => "\xE7\x86\xA0", + "\xE6\x67" => "\xE7\x86\x9A", + "\xE6\x68" => "\xE7\x86\xA9", + "\xE6\x69" => "\xE7\x86\xB5", + "\xE6\x6A" => "\xE7\x86\x9D", + "\xE6\x6B" => "\xE7\x86\xA5", + "\xE6\x6C" => "\xE7\x86\x9E", + "\xE6\x6D" => "\xE7\x86\xA4", + "\xE6\x6E" => "\xE7\x86\xA1", + "\xE6\x6F" => "\xE7\x86\xAA", + "\xE6\x70" => "\xE7\x86\x9C", + "\xE6\x71" => "\xE7\x86\xA7", + "\xE6\x72" => "\xE7\x86\xB3", + "\xE6\x73" => "\xE7\x8A\x98", + "\xE6\x74" => "\xE7\x8A\x9A", + "\xE6\x75" => "\xE7\x8D\x98", + "\xE6\x76" => "\xE7\x8D\x92", + "\xE6\x77" => "\xE7\x8D\x9E", + "\xE6\x78" => "\xE7\x8D\x9F", + "\xE6\x79" => "\xE7\x8D\xA0", + "\xE6\x7A" => "\xE7\x8D\x9D", + "\xE6\x7B" => "\xE7\x8D\x9B", + "\xE6\x7C" => "\xE7\x8D\xA1", + "\xE6\x7D" => "\xE7\x8D\x9A", + "\xE6\x7E" => "\xE7\x8D\x99", + "\xE6\xA1" => "\xE7\x8D\xA2", + "\xE6\xA2" => "\xE7\x92\x87", + "\xE6\xA3" => "\xE7\x92\x89", + "\xE6\xA4" => "\xE7\x92\x8A", + "\xE6\xA5" => "\xE7\x92\x86", + "\xE6\xA6" => "\xE7\x92\x81", + "\xE6\xA7" => "\xE7\x91\xBD", + "\xE6\xA8" => "\xE7\x92\x85", + "\xE6\xA9" => "\xE7\x92\x88", + "\xE6\xAA" => "\xE7\x91\xBC", + "\xE6\xAB" => "\xE7\x91\xB9", + "\xE6\xAC" => "\xE7\x94\x88", + "\xE6\xAD" => "\xE7\x94\x87", + "\xE6\xAE" => "\xE7\x95\xBE", + "\xE6\xAF" => "\xE7\x98\xA5", + "\xE6\xB0" => "\xE7\x98\x9E", + "\xE6\xB1" => "\xE7\x98\x99", + "\xE6\xB2" => "\xE7\x98\x9D", + "\xE6\xB3" => "\xE7\x98\x9C", + "\xE6\xB4" => "\xE7\x98\xA3", + "\xE6\xB5" => "\xE7\x98\x9A", + "\xE6\xB6" => "\xE7\x98\xA8", + "\xE6\xB7" => "\xE7\x98\x9B", + "\xE6\xB8" => "\xE7\x9A\x9C", + "\xE6\xB9" => "\xE7\x9A\x9D", + "\xE6\xBA" => "\xE7\x9A\x9E", + "\xE6\xBB" => "\xE7\x9A\x9B", + "\xE6\xBC" => "\xE7\x9E\x8D", + "\xE6\xBD" => "\xE7\x9E\x8F", + "\xE6\xBE" => "\xE7\x9E\x89", + "\xE6\xBF" => "\xE7\x9E\x88", + "\xE6\xC0" => "\xE7\xA3\x8D", + "\xE6\xC1" => "\xE7\xA2\xBB", + "\xE6\xC2" => "\xE7\xA3\x8F", + "\xE6\xC3" => "\xE7\xA3\x8C", + "\xE6\xC4" => "\xE7\xA3\x91", + "\xE6\xC5" => "\xE7\xA3\x8E", + "\xE6\xC6" => "\xE7\xA3\x94", + "\xE6\xC7" => "\xE7\xA3\x88", + "\xE6\xC8" => "\xE7\xA3\x83", + "\xE6\xC9" => "\xE7\xA3\x84", + "\xE6\xCA" => "\xE7\xA3\x89", + "\xE6\xCB" => "\xE7\xA6\x9A", + "\xE6\xCC" => "\xE7\xA6\xA1", + "\xE6\xCD" => "\xE7\xA6\xA0", + "\xE6\xCE" => "\xE7\xA6\x9C", + "\xE6\xCF" => "\xE7\xA6\xA2", + "\xE6\xD0" => "\xE7\xA6\x9B", + "\xE6\xD1" => "\xE6\xAD\xB6", + "\xE6\xD2" => "\xE7\xA8\xB9", + "\xE6\xD3" => "\xE7\xAA\xB2", + "\xE6\xD4" => "\xE7\xAA\xB4", + "\xE6\xD5" => "\xE7\xAA\xB3", + "\xE6\xD6" => "\xE7\xAE\xB7", + "\xE6\xD7" => "\xE7\xAF\x8B", + "\xE6\xD8" => "\xE7\xAE\xBE", + "\xE6\xD9" => "\xE7\xAE\xAC", + "\xE6\xDA" => "\xE7\xAF\x8E", + "\xE6\xDB" => "\xE7\xAE\xAF", + "\xE6\xDC" => "\xE7\xAE\xB9", + "\xE6\xDD" => "\xE7\xAF\x8A", + "\xE6\xDE" => "\xE7\xAE\xB5", + "\xE6\xDF" => "\xE7\xB3\x85", + "\xE6\xE0" => "\xE7\xB3\x88", + "\xE6\xE1" => "\xE7\xB3\x8C", + "\xE6\xE2" => "\xE7\xB3\x8B", + "\xE6\xE3" => "\xE7\xB7\xB7", + "\xE6\xE4" => "\xE7\xB7\x9B", + "\xE6\xE5" => "\xE7\xB7\xAA", + "\xE6\xE6" => "\xE7\xB7\xA7", + "\xE6\xE7" => "\xE7\xB7\x97", + "\xE6\xE8" => "\xE7\xB7\xA1", + "\xE6\xE9" => "\xE7\xB8\x83", + "\xE6\xEA" => "\xE7\xB7\xBA", + "\xE6\xEB" => "\xE7\xB7\xA6", + "\xE6\xEC" => "\xE7\xB7\xB6", + "\xE6\xED" => "\xE7\xB7\xB1", + "\xE6\xEE" => "\xE7\xB7\xB0", + "\xE6\xEF" => "\xE7\xB7\xAE", + "\xE6\xF0" => "\xE7\xB7\x9F", + "\xE6\xF1" => "\xE7\xBD\xB6", + "\xE6\xF2" => "\xE7\xBE\xAC", + "\xE6\xF3" => "\xE7\xBE\xB0", + "\xE6\xF4" => "\xE7\xBE\xAD", + "\xE6\xF5" => "\xE7\xBF\xAD", + "\xE6\xF6" => "\xE7\xBF\xAB", + "\xE6\xF7" => "\xE7\xBF\xAA", + "\xE6\xF8" => "\xE7\xBF\xAC", + "\xE6\xF9" => "\xE7\xBF\xA6", + "\xE6\xFA" => "\xE7\xBF\xA8", + "\xE6\xFB" => "\xE8\x81\xA4", + "\xE6\xFC" => "\xE8\x81\xA7", + "\xE6\xFD" => "\xE8\x86\xA3", + "\xE6\xFE" => "\xE8\x86\x9F", + "\xE7\x40" => "\xE8\x86\x9E", + "\xE7\x41" => "\xE8\x86\x95", + "\xE7\x42" => "\xE8\x86\xA2", + "\xE7\x43" => "\xE8\x86\x99", + "\xE7\x44" => "\xE8\x86\x97", + "\xE7\x45" => "\xE8\x88\x96", + "\xE7\x46" => "\xE8\x89\x8F", + "\xE7\x47" => "\xE8\x89\x93", + "\xE7\x48" => "\xE8\x89\x92", + "\xE7\x49" => "\xE8\x89\x90", + "\xE7\x4A" => "\xE8\x89\x8E", + "\xE7\x4B" => "\xE8\x89\x91", + "\xE7\x4C" => "\xE8\x94\xA4", + "\xE7\x4D" => "\xE8\x94\xBB", + "\xE7\x4E" => "\xE8\x94\x8F", + "\xE7\x4F" => "\xE8\x94\x80", + "\xE7\x50" => "\xE8\x94\xA9", + "\xE7\x51" => "\xE8\x94\x8E", + "\xE7\x52" => "\xE8\x94\x89", + "\xE7\x53" => "\xE8\x94\x8D", + "\xE7\x54" => "\xE8\x94\x9F", + "\xE7\x55" => "\xE8\x94\x8A", + "\xE7\x56" => "\xE8\x94\xA7", + "\xE7\x57" => "\xE8\x94\x9C", + "\xE7\x58" => "\xE8\x93\xBB", + "\xE7\x59" => "\xE8\x94\xAB", + "\xE7\x5A" => "\xE8\x93\xBA", + "\xE7\x5B" => "\xE8\x94\x88", + "\xE7\x5C" => "\xE8\x94\x8C", + "\xE7\x5D" => "\xE8\x93\xB4", + "\xE7\x5E" => "\xE8\x94\xAA", + "\xE7\x5F" => "\xE8\x93\xB2", + "\xE7\x60" => "\xE8\x94\x95", + "\xE7\x61" => "\xE8\x93\xB7", + "\xE7\x62" => "\xE8\x93\xAB", + "\xE7\x63" => "\xE8\x93\xB3", + "\xE7\x64" => "\xE8\x93\xBC", + "\xE7\x65" => "\xE8\x94\x92", + "\xE7\x66" => "\xE8\x93\xAA", + "\xE7\x67" => "\xE8\x93\xA9", + "\xE7\x68" => "\xE8\x94\x96", + "\xE7\x69" => "\xE8\x93\xBE", + "\xE7\x6A" => "\xE8\x94\xA8", + "\xE7\x6B" => "\xE8\x94\x9D", + "\xE7\x6C" => "\xE8\x94\xAE", + "\xE7\x6D" => "\xE8\x94\x82", + "\xE7\x6E" => "\xE8\x93\xBD", + "\xE7\x6F" => "\xE8\x94\x9E", + "\xE7\x70" => "\xE8\x93\xB6", + "\xE7\x71" => "\xE8\x94\xB1", + "\xE7\x72" => "\xE8\x94\xA6", + "\xE7\x73" => "\xE8\x93\xA7", + "\xE7\x74" => "\xE8\x93\xA8", + "\xE7\x75" => "\xE8\x93\xB0", + "\xE7\x76" => "\xE8\x93\xAF", + "\xE7\x77" => "\xE8\x93\xB9", + "\xE7\x78" => "\xE8\x94\x98", + "\xE7\x79" => "\xE8\x94\xA0", + "\xE7\x7A" => "\xE8\x94\xB0", + "\xE7\x7B" => "\xE8\x94\x8B", + "\xE7\x7C" => "\xE8\x94\x99", + "\xE7\x7D" => "\xE8\x94\xAF", + "\xE7\x7E" => "\xE8\x99\xA2", + "\xE7\xA1" => "\xE8\x9D\x96", + "\xE7\xA2" => "\xE8\x9D\xA3", + "\xE7\xA3" => "\xE8\x9D\xA4", + "\xE7\xA4" => "\xE8\x9D\xB7", + "\xE7\xA5" => "\xE8\x9F\xA1", + "\xE7\xA6" => "\xE8\x9D\xB3", + "\xE7\xA7" => "\xE8\x9D\x98", + "\xE7\xA8" => "\xE8\x9D\x94", + "\xE7\xA9" => "\xE8\x9D\x9B", + "\xE7\xAA" => "\xE8\x9D\x92", + "\xE7\xAB" => "\xE8\x9D\xA1", + "\xE7\xAC" => "\xE8\x9D\x9A", + "\xE7\xAD" => "\xE8\x9D\x91", + "\xE7\xAE" => "\xE8\x9D\x9E", + "\xE7\xAF" => "\xE8\x9D\xAD", + "\xE7\xB0" => "\xE8\x9D\xAA", + "\xE7\xB1" => "\xE8\x9D\x90", + "\xE7\xB2" => "\xE8\x9D\x8E", + "\xE7\xB3" => "\xE8\x9D\x9F", + "\xE7\xB4" => "\xE8\x9D\x9D", + "\xE7\xB5" => "\xE8\x9D\xAF", + "\xE7\xB6" => "\xE8\x9D\xAC", + "\xE7\xB7" => "\xE8\x9D\xBA", + "\xE7\xB8" => "\xE8\x9D\xAE", + "\xE7\xB9" => "\xE8\x9D\x9C", + "\xE7\xBA" => "\xE8\x9D\xA5", + "\xE7\xBB" => "\xE8\x9D\x8F", + "\xE7\xBC" => "\xE8\x9D\xBB", + "\xE7\xBD" => "\xE8\x9D\xB5", + "\xE7\xBE" => "\xE8\x9D\xA2", + "\xE7\xBF" => "\xE8\x9D\xA7", + "\xE7\xC0" => "\xE8\x9D\xA9", + "\xE7\xC1" => "\xE8\xA1\x9A", + "\xE7\xC2" => "\xE8\xA4\x85", + "\xE7\xC3" => "\xE8\xA4\x8C", + "\xE7\xC4" => "\xE8\xA4\x94", + "\xE7\xC5" => "\xE8\xA4\x8B", + "\xE7\xC6" => "\xE8\xA4\x97", + "\xE7\xC7" => "\xE8\xA4\x98", + "\xE7\xC8" => "\xE8\xA4\x99", + "\xE7\xC9" => "\xE8\xA4\x86", + "\xE7\xCA" => "\xE8\xA4\x96", + "\xE7\xCB" => "\xE8\xA4\x91", + "\xE7\xCC" => "\xE8\xA4\x8E", + "\xE7\xCD" => "\xE8\xA4\x89", + "\xE7\xCE" => "\xE8\xA6\xA2", + "\xE7\xCF" => "\xE8\xA6\xA4", + "\xE7\xD0" => "\xE8\xA6\xA3", + "\xE7\xD1" => "\xE8\xA7\xAD", + "\xE7\xD2" => "\xE8\xA7\xB0", + "\xE7\xD3" => "\xE8\xA7\xAC", + "\xE7\xD4" => "\xE8\xAB\x8F", + "\xE7\xD5" => "\xE8\xAB\x86", + "\xE7\xD6" => "\xE8\xAA\xB8", + "\xE7\xD7" => "\xE8\xAB\x93", + "\xE7\xD8" => "\xE8\xAB\x91", + "\xE7\xD9" => "\xE8\xAB\x94", + "\xE7\xDA" => "\xE8\xAB\x95", + "\xE7\xDB" => "\xE8\xAA\xBB", + "\xE7\xDC" => "\xE8\xAB\x97", + "\xE7\xDD" => "\xE8\xAA\xBE", + "\xE7\xDE" => "\xE8\xAB\x80", + "\xE7\xDF" => "\xE8\xAB\x85", + "\xE7\xE0" => "\xE8\xAB\x98", + "\xE7\xE1" => "\xE8\xAB\x83", + "\xE7\xE2" => "\xE8\xAA\xBA", + "\xE7\xE3" => "\xE8\xAA\xBD", + "\xE7\xE4" => "\xE8\xAB\x99", + "\xE7\xE5" => "\xE8\xB0\xBE", + "\xE7\xE6" => "\xE8\xB1\x8D", + "\xE7\xE7" => "\xE8\xB2\x8F", + "\xE7\xE8" => "\xE8\xB3\xA5", + "\xE7\xE9" => "\xE8\xB3\x9F", + "\xE7\xEA" => "\xE8\xB3\x99", + "\xE7\xEB" => "\xE8\xB3\xA8", + "\xE7\xEC" => "\xE8\xB3\x9A", + "\xE7\xED" => "\xE8\xB3\x9D", + "\xE7\xEE" => "\xE8\xB3\xA7", + "\xE7\xEF" => "\xE8\xB6\xA0", + "\xE7\xF0" => "\xE8\xB6\x9C", + "\xE7\xF1" => "\xE8\xB6\xA1", + "\xE7\xF2" => "\xE8\xB6\x9B", + "\xE7\xF3" => "\xE8\xB8\xA0", + "\xE7\xF4" => "\xE8\xB8\xA3", + "\xE7\xF5" => "\xE8\xB8\xA5", + "\xE7\xF6" => "\xE8\xB8\xA4", + "\xE7\xF7" => "\xE8\xB8\xAE", + "\xE7\xF8" => "\xE8\xB8\x95", + "\xE7\xF9" => "\xE8\xB8\x9B", + "\xE7\xFA" => "\xE8\xB8\x96", + "\xE7\xFB" => "\xE8\xB8\x91", + "\xE7\xFC" => "\xE8\xB8\x99", + "\xE7\xFD" => "\xE8\xB8\xA6", + "\xE7\xFE" => "\xE8\xB8\xA7", + "\xE8\x40" => "\xE8\xB8\x94", + "\xE8\x41" => "\xE8\xB8\x92", + "\xE8\x42" => "\xE8\xB8\x98", + "\xE8\x43" => "\xE8\xB8\x93", + "\xE8\x44" => "\xE8\xB8\x9C", + "\xE8\x45" => "\xE8\xB8\x97", + "\xE8\x46" => "\xE8\xB8\x9A", + "\xE8\x47" => "\xE8\xBC\xAC", + "\xE8\x48" => "\xE8\xBC\xA4", + "\xE8\x49" => "\xE8\xBC\x98", + "\xE8\x4A" => "\xE8\xBC\x9A", + "\xE8\x4B" => "\xE8\xBC\xA0", + "\xE8\x4C" => "\xE8\xBC\xA3", + "\xE8\x4D" => "\xE8\xBC\x96", + "\xE8\x4E" => "\xE8\xBC\x97", + "\xE8\x4F" => "\xE9\x81\xB3", + "\xE8\x50" => "\xE9\x81\xB0", + "\xE8\x51" => "\xE9\x81\xAF", + "\xE8\x52" => "\xE9\x81\xA7", + "\xE8\x53" => "\xE9\x81\xAB", + "\xE8\x54" => "\xE9\x84\xAF", + "\xE8\x55" => "\xE9\x84\xAB", + "\xE8\x56" => "\xE9\x84\xA9", + "\xE8\x57" => "\xE9\x84\xAA", + "\xE8\x58" => "\xE9\x84\xB2", + "\xE8\x59" => "\xE9\x84\xA6", + "\xE8\x5A" => "\xE9\x84\xAE", + "\xE8\x5B" => "\xE9\x86\x85", + "\xE8\x5C" => "\xE9\x86\x86", + "\xE8\x5D" => "\xE9\x86\x8A", + "\xE8\x5E" => "\xE9\x86\x81", + "\xE8\x5F" => "\xE9\x86\x82", + "\xE8\x60" => "\xE9\x86\x84", + "\xE8\x61" => "\xE9\x86\x80", + "\xE8\x62" => "\xE9\x8B\x90", + "\xE8\x63" => "\xE9\x8B\x83", + "\xE8\x64" => "\xE9\x8B\x84", + "\xE8\x65" => "\xE9\x8B\x80", + "\xE8\x66" => "\xE9\x8B\x99", + "\xE8\x67" => "\xE9\x8A\xB6", + "\xE8\x68" => "\xE9\x8B\x8F", + "\xE8\x69" => "\xE9\x8B\xB1", + "\xE8\x6A" => "\xE9\x8B\x9F", + "\xE8\x6B" => "\xE9\x8B\x98", + "\xE8\x6C" => "\xE9\x8B\xA9", + "\xE8\x6D" => "\xE9\x8B\x97", + "\xE8\x6E" => "\xE9\x8B\x9D", + "\xE8\x6F" => "\xE9\x8B\x8C", + "\xE8\x70" => "\xE9\x8B\xAF", + "\xE8\x71" => "\xE9\x8B\x82", + "\xE8\x72" => "\xE9\x8B\xA8", + "\xE8\x73" => "\xE9\x8B\x8A", + "\xE8\x74" => "\xE9\x8B\x88", + "\xE8\x75" => "\xE9\x8B\x8E", + "\xE8\x76" => "\xE9\x8B\xA6", + "\xE8\x77" => "\xE9\x8B\x8D", + "\xE8\x78" => "\xE9\x8B\x95", + "\xE8\x79" => "\xE9\x8B\x89", + "\xE8\x7A" => "\xE9\x8B\xA0", + "\xE8\x7B" => "\xE9\x8B\x9E", + "\xE8\x7C" => "\xE9\x8B\xA7", + "\xE8\x7D" => "\xE9\x8B\x91", + "\xE8\x7E" => "\xE9\x8B\x93", + "\xE8\xA1" => "\xE9\x8A\xB5", + "\xE8\xA2" => "\xE9\x8B\xA1", + "\xE8\xA3" => "\xE9\x8B\x86", + "\xE8\xA4" => "\xE9\x8A\xB4", + "\xE8\xA5" => "\xE9\x95\xBC", + "\xE8\xA6" => "\xE9\x96\xAC", + "\xE8\xA7" => "\xE9\x96\xAB", + "\xE8\xA8" => "\xE9\x96\xAE", + "\xE8\xA9" => "\xE9\x96\xB0", + "\xE8\xAA" => "\xE9\x9A\xA4", + "\xE8\xAB" => "\xE9\x9A\xA2", + "\xE8\xAC" => "\xE9\x9B\x93", + "\xE8\xAD" => "\xE9\x9C\x85", + "\xE8\xAE" => "\xE9\x9C\x88", + "\xE8\xAF" => "\xE9\x9C\x82", + "\xE8\xB0" => "\xE9\x9D\x9A", + "\xE8\xB1" => "\xE9\x9E\x8A", + "\xE8\xB2" => "\xE9\x9E\x8E", + "\xE8\xB3" => "\xE9\x9E\x88", + "\xE8\xB4" => "\xE9\x9F\x90", + "\xE8\xB5" => "\xE9\x9F\x8F", + "\xE8\xB6" => "\xE9\xA0\x9E", + "\xE8\xB7" => "\xE9\xA0\x9D", + "\xE8\xB8" => "\xE9\xA0\xA6", + "\xE8\xB9" => "\xE9\xA0\xA9", + "\xE8\xBA" => "\xE9\xA0\xA8", + "\xE8\xBB" => "\xE9\xA0\xA0", + "\xE8\xBC" => "\xE9\xA0\x9B", + "\xE8\xBD" => "\xE9\xA0\xA7", + "\xE8\xBE" => "\xE9\xA2\xB2", + "\xE8\xBF" => "\xE9\xA4\x88", + "\xE8\xC0" => "\xE9\xA3\xBA", + "\xE8\xC1" => "\xE9\xA4\x91", + "\xE8\xC2" => "\xE9\xA4\x94", + "\xE8\xC3" => "\xE9\xA4\x96", + "\xE8\xC4" => "\xE9\xA4\x97", + "\xE8\xC5" => "\xE9\xA4\x95", + "\xE8\xC6" => "\xE9\xA7\x9C", + "\xE8\xC7" => "\xE9\xA7\x8D", + "\xE8\xC8" => "\xE9\xA7\x8F", + "\xE8\xC9" => "\xE9\xA7\x93", + "\xE8\xCA" => "\xE9\xA7\x94", + "\xE8\xCB" => "\xE9\xA7\x8E", + "\xE8\xCC" => "\xE9\xA7\x89", + "\xE8\xCD" => "\xE9\xA7\x96", + "\xE8\xCE" => "\xE9\xA7\x98", + "\xE8\xCF" => "\xE9\xA7\x8B", + "\xE8\xD0" => "\xE9\xA7\x97", + "\xE8\xD1" => "\xE9\xA7\x8C", + "\xE8\xD2" => "\xE9\xAA\xB3", + "\xE8\xD3" => "\xE9\xAB\xAC", + "\xE8\xD4" => "\xE9\xAB\xAB", + "\xE8\xD5" => "\xE9\xAB\xB3", + "\xE8\xD6" => "\xE9\xAB\xB2", + "\xE8\xD7" => "\xE9\xAB\xB1", + "\xE8\xD8" => "\xE9\xAD\x86", + "\xE8\xD9" => "\xE9\xAD\x83", + "\xE8\xDA" => "\xE9\xAD\xA7", + "\xE8\xDB" => "\xE9\xAD\xB4", + "\xE8\xDC" => "\xE9\xAD\xB1", + "\xE8\xDD" => "\xE9\xAD\xA6", + "\xE8\xDE" => "\xE9\xAD\xB6", + "\xE8\xDF" => "\xE9\xAD\xB5", + "\xE8\xE0" => "\xE9\xAD\xB0", + "\xE8\xE1" => "\xE9\xAD\xA8", + "\xE8\xE2" => "\xE9\xAD\xA4", + "\xE8\xE3" => "\xE9\xAD\xAC", + "\xE8\xE4" => "\xE9\xB3\xBC", + "\xE8\xE5" => "\xE9\xB3\xBA", + "\xE8\xE6" => "\xE9\xB3\xBD", + "\xE8\xE7" => "\xE9\xB3\xBF", + "\xE8\xE8" => "\xE9\xB3\xB7", + "\xE8\xE9" => "\xE9\xB4\x87", + "\xE8\xEA" => "\xE9\xB4\x80", + "\xE8\xEB" => "\xE9\xB3\xB9", + "\xE8\xEC" => "\xE9\xB3\xBB", + "\xE8\xED" => "\xE9\xB4\x88", + "\xE8\xEE" => "\xE9\xB4\x85", + "\xE8\xEF" => "\xE9\xB4\x84", + "\xE8\xF0" => "\xE9\xBA\x83", + "\xE8\xF1" => "\xE9\xBB\x93", + "\xE8\xF2" => "\xE9\xBC\x8F", + "\xE8\xF3" => "\xE9\xBC\x90", + "\xE8\xF4" => "\xE5\x84\x9C", + "\xE8\xF5" => "\xE5\x84\x93", + "\xE8\xF6" => "\xE5\x84\x97", + "\xE8\xF7" => "\xE5\x84\x9A", + "\xE8\xF8" => "\xE5\x84\x91", + "\xE8\xF9" => "\xE5\x87\x9E", + "\xE8\xFA" => "\xE5\x8C\xB4", + "\xE8\xFB" => "\xE5\x8F\xA1", + "\xE8\xFC" => "\xE5\x99\xB0", + "\xE8\xFD" => "\xE5\x99\xA0", + "\xE8\xFE" => "\xE5\x99\xAE", + "\xE9\x40" => "\xE5\x99\xB3", + "\xE9\x41" => "\xE5\x99\xA6", + "\xE9\x42" => "\xE5\x99\xA3", + "\xE9\x43" => "\xE5\x99\xAD", + "\xE9\x44" => "\xE5\x99\xB2", + "\xE9\x45" => "\xE5\x99\x9E", + "\xE9\x46" => "\xE5\x99\xB7", + "\xE9\x47" => "\xE5\x9C\x9C", + "\xE9\x48" => "\xE5\x9C\x9B", + "\xE9\x49" => "\xE5\xA3\x88", + "\xE9\x4A" => "\xE5\xA2\xBD", + "\xE9\x4B" => "\xE5\xA3\x89", + "\xE9\x4C" => "\xE5\xA2\xBF", + "\xE9\x4D" => "\xE5\xA2\xBA", + "\xE9\x4E" => "\xE5\xA3\x82", + "\xE9\x4F" => "\xE5\xA2\xBC", + "\xE9\x50" => "\xE5\xA3\x86", + "\xE9\x51" => "\xE5\xAC\x97", + "\xE9\x52" => "\xE5\xAC\x99", + "\xE9\x53" => "\xE5\xAC\x9B", + "\xE9\x54" => "\xE5\xAC\xA1", + "\xE9\x55" => "\xE5\xAC\x94", + "\xE9\x56" => "\xE5\xAC\x93", + "\xE9\x57" => "\xE5\xAC\x90", + "\xE9\x58" => "\xE5\xAC\x96", + "\xE9\x59" => "\xE5\xAC\xA8", + "\xE9\x5A" => "\xE5\xAC\x9A", + "\xE9\x5B" => "\xE5\xAC\xA0", + "\xE9\x5C" => "\xE5\xAC\x9E", + "\xE9\x5D" => "\xE5\xAF\xAF", + "\xE9\x5E" => "\xE5\xB6\xAC", + "\xE9\x5F" => "\xE5\xB6\xB1", + "\xE9\x60" => "\xE5\xB6\xA9", + "\xE9\x61" => "\xE5\xB6\xA7", + "\xE9\x62" => "\xE5\xB6\xB5", + "\xE9\x63" => "\xE5\xB6\xB0", + "\xE9\x64" => "\xE5\xB6\xAE", + "\xE9\x65" => "\xE5\xB6\xAA", + "\xE9\x66" => "\xE5\xB6\xA8", + "\xE9\x67" => "\xE5\xB6\xB2", + "\xE9\x68" => "\xE5\xB6\xAD", + "\xE9\x69" => "\xE5\xB6\xAF", + "\xE9\x6A" => "\xE5\xB6\xB4", + "\xE9\x6B" => "\xE5\xB9\xA7", + "\xE9\x6C" => "\xE5\xB9\xA8", + "\xE9\x6D" => "\xE5\xB9\xA6", + "\xE9\x6E" => "\xE5\xB9\xAF", + "\xE9\x6F" => "\xE5\xBB\xA9", + "\xE9\x70" => "\xE5\xBB\xA7", + "\xE9\x71" => "\xE5\xBB\xA6", + "\xE9\x72" => "\xE5\xBB\xA8", + "\xE9\x73" => "\xE5\xBB\xA5", + "\xE9\x74" => "\xE5\xBD\x8B", + "\xE9\x75" => "\xE5\xBE\xBC", + "\xE9\x76" => "\xE6\x86\x9D", + "\xE9\x77" => "\xE6\x86\xA8", + "\xE9\x78" => "\xE6\x86\x96", + "\xE9\x79" => "\xE6\x87\x85", + "\xE9\x7A" => "\xE6\x86\xB4", + "\xE9\x7B" => "\xE6\x87\x86", + "\xE9\x7C" => "\xE6\x87\x81", + "\xE9\x7D" => "\xE6\x87\x8C", + "\xE9\x7E" => "\xE6\x86\xBA", + "\xE9\xA1" => "\xE6\x86\xBF", + "\xE9\xA2" => "\xE6\x86\xB8", + "\xE9\xA3" => "\xE6\x86\x8C", + "\xE9\xA4" => "\xE6\x93\x97", + "\xE9\xA5" => "\xE6\x93\x96", + "\xE9\xA6" => "\xE6\x93\x90", + "\xE9\xA7" => "\xE6\x93\x8F", + "\xE9\xA8" => "\xE6\x93\x89", + "\xE9\xA9" => "\xE6\x92\xBD", + "\xE9\xAA" => "\xE6\x92\x89", + "\xE9\xAB" => "\xE6\x93\x83", + "\xE9\xAC" => "\xE6\x93\x9B", + "\xE9\xAD" => "\xE6\x93\xB3", + "\xE9\xAE" => "\xE6\x93\x99", + "\xE9\xAF" => "\xE6\x94\xB3", + "\xE9\xB0" => "\xE6\x95\xBF", + "\xE9\xB1" => "\xE6\x95\xBC", + "\xE9\xB2" => "\xE6\x96\xA2", + "\xE9\xB3" => "\xE6\x9B\x88", + "\xE9\xB4" => "\xE6\x9A\xBE", + "\xE9\xB5" => "\xE6\x9B\x80", + "\xE9\xB6" => "\xE6\x9B\x8A", + "\xE9\xB7" => "\xE6\x9B\x8B", + "\xE9\xB8" => "\xE6\x9B\x8F", + "\xE9\xB9" => "\xE6\x9A\xBD", + "\xE9\xBA" => "\xE6\x9A\xBB", + "\xE9\xBB" => "\xE6\x9A\xBA", + "\xE9\xBC" => "\xE6\x9B\x8C", + "\xE9\xBD" => "\xE6\x9C\xA3", + "\xE9\xBE" => "\xE6\xA8\xB4", + "\xE9\xBF" => "\xE6\xA9\xA6", + "\xE9\xC0" => "\xE6\xA9\x89", + "\xE9\xC1" => "\xE6\xA9\xA7", + "\xE9\xC2" => "\xE6\xA8\xB2", + "\xE9\xC3" => "\xE6\xA9\xA8", + "\xE9\xC4" => "\xE6\xA8\xBE", + "\xE9\xC5" => "\xE6\xA9\x9D", + "\xE9\xC6" => "\xE6\xA9\xAD", + "\xE9\xC7" => "\xE6\xA9\xB6", + "\xE9\xC8" => "\xE6\xA9\x9B", + "\xE9\xC9" => "\xE6\xA9\x91", + "\xE9\xCA" => "\xE6\xA8\xA8", + "\xE9\xCB" => "\xE6\xA9\x9A", + "\xE9\xCC" => "\xE6\xA8\xBB", + "\xE9\xCD" => "\xE6\xA8\xBF", + "\xE9\xCE" => "\xE6\xA9\x81", + "\xE9\xCF" => "\xE6\xA9\xAA", + "\xE9\xD0" => "\xE6\xA9\xA4", + "\xE9\xD1" => "\xE6\xA9\x90", + "\xE9\xD2" => "\xE6\xA9\x8F", + "\xE9\xD3" => "\xE6\xA9\x94", + "\xE9\xD4" => "\xE6\xA9\xAF", + "\xE9\xD5" => "\xE6\xA9\xA9", + "\xE9\xD6" => "\xE6\xA9\xA0", + "\xE9\xD7" => "\xE6\xA8\xBC", + "\xE9\xD8" => "\xE6\xA9\x9E", + "\xE9\xD9" => "\xE6\xA9\x96", + "\xE9\xDA" => "\xE6\xA9\x95", + "\xE9\xDB" => "\xE6\xA9\x8D", + "\xE9\xDC" => "\xE6\xA9\x8E", + "\xE9\xDD" => "\xE6\xA9\x86", + "\xE9\xDE" => "\xE6\xAD\x95", + "\xE9\xDF" => "\xE6\xAD\x94", + "\xE9\xE0" => "\xE6\xAD\x96", + "\xE9\xE1" => "\xE6\xAE\xA7", + "\xE9\xE2" => "\xE6\xAE\xAA", + "\xE9\xE3" => "\xE6\xAE\xAB", + "\xE9\xE4" => "\xE6\xAF\x88", + "\xE9\xE5" => "\xE6\xAF\x87", + "\xE9\xE6" => "\xE6\xB0\x84", + "\xE9\xE7" => "\xE6\xB0\x83", + "\xE9\xE8" => "\xE6\xB0\x86", + "\xE9\xE9" => "\xE6\xBE\xAD", + "\xE9\xEA" => "\xE6\xBF\x8B", + "\xE9\xEB" => "\xE6\xBE\xA3", + "\xE9\xEC" => "\xE6\xBF\x87", + "\xE9\xED" => "\xE6\xBE\xBC", + "\xE9\xEE" => "\xE6\xBF\x8E", + "\xE9\xEF" => "\xE6\xBF\x88", + "\xE9\xF0" => "\xE6\xBD\x9E", + "\xE9\xF1" => "\xE6\xBF\x84", + "\xE9\xF2" => "\xE6\xBE\xBD", + "\xE9\xF3" => "\xE6\xBE\x9E", + "\xE9\xF4" => "\xE6\xBF\x8A", + "\xE9\xF5" => "\xE6\xBE\xA8", + "\xE9\xF6" => "\xE7\x80\x84", + "\xE9\xF7" => "\xE6\xBE\xA5", + "\xE9\xF8" => "\xE6\xBE\xAE", + "\xE9\xF9" => "\xE6\xBE\xBA", + "\xE9\xFA" => "\xE6\xBE\xAC", + "\xE9\xFB" => "\xE6\xBE\xAA", + "\xE9\xFC" => "\xE6\xBF\x8F", + "\xE9\xFD" => "\xE6\xBE\xBF", + "\xE9\xFE" => "\xE6\xBE\xB8", + "\xEA\x40" => "\xE6\xBE\xA2", + "\xEA\x41" => "\xE6\xBF\x89", + "\xEA\x42" => "\xE6\xBE\xAB", + "\xEA\x43" => "\xE6\xBF\x8D", + "\xEA\x44" => "\xE6\xBE\xAF", + "\xEA\x45" => "\xE6\xBE\xB2", + "\xEA\x46" => "\xE6\xBE\xB0", + "\xEA\x47" => "\xE7\x87\x85", + "\xEA\x48" => "\xE7\x87\x82", + "\xEA\x49" => "\xE7\x86\xBF", + "\xEA\x4A" => "\xE7\x86\xB8", + "\xEA\x4B" => "\xE7\x87\x96", + "\xEA\x4C" => "\xE7\x87\x80", + "\xEA\x4D" => "\xE7\x87\x81", + "\xEA\x4E" => "\xE7\x87\x8B", + "\xEA\x4F" => "\xE7\x87\x94", + "\xEA\x50" => "\xE7\x87\x8A", + "\xEA\x51" => "\xE7\x87\x87", + "\xEA\x52" => "\xE7\x87\x8F", + "\xEA\x53" => "\xE7\x86\xBD", + "\xEA\x54" => "\xE7\x87\x98", + "\xEA\x55" => "\xE7\x86\xBC", + "\xEA\x56" => "\xE7\x87\x86", + "\xEA\x57" => "\xE7\x87\x9A", + "\xEA\x58" => "\xE7\x87\x9B", + "\xEA\x59" => "\xE7\x8A\x9D", + "\xEA\x5A" => "\xE7\x8A\x9E", + "\xEA\x5B" => "\xE7\x8D\xA9", + "\xEA\x5C" => "\xE7\x8D\xA6", + "\xEA\x5D" => "\xE7\x8D\xA7", + "\xEA\x5E" => "\xE7\x8D\xAC", + "\xEA\x5F" => "\xE7\x8D\xA5", + "\xEA\x60" => "\xE7\x8D\xAB", + "\xEA\x61" => "\xE7\x8D\xAA", + "\xEA\x62" => "\xE7\x91\xBF", + "\xEA\x63" => "\xE7\x92\x9A", + "\xEA\x64" => "\xE7\x92\xA0", + "\xEA\x65" => "\xE7\x92\x94", + "\xEA\x66" => "\xE7\x92\x92", + "\xEA\x67" => "\xE7\x92\x95", + "\xEA\x68" => "\xE7\x92\xA1", + "\xEA\x69" => "\xE7\x94\x8B", + "\xEA\x6A" => "\xE7\x96\x80", + "\xEA\x6B" => "\xE7\x98\xAF", + "\xEA\x6C" => "\xE7\x98\xAD", + "\xEA\x6D" => "\xE7\x98\xB1", + "\xEA\x6E" => "\xE7\x98\xBD", + "\xEA\x6F" => "\xE7\x98\xB3", + "\xEA\x70" => "\xE7\x98\xBC", + "\xEA\x71" => "\xE7\x98\xB5", + "\xEA\x72" => "\xE7\x98\xB2", + "\xEA\x73" => "\xE7\x98\xB0", + "\xEA\x74" => "\xE7\x9A\xBB", + "\xEA\x75" => "\xE7\x9B\xA6", + "\xEA\x76" => "\xE7\x9E\x9A", + "\xEA\x77" => "\xE7\x9E\x9D", + "\xEA\x78" => "\xE7\x9E\xA1", + "\xEA\x79" => "\xE7\x9E\x9C", + "\xEA\x7A" => "\xE7\x9E\x9B", + "\xEA\x7B" => "\xE7\x9E\xA2", + "\xEA\x7C" => "\xE7\x9E\xA3", + "\xEA\x7D" => "\xE7\x9E\x95", + "\xEA\x7E" => "\xE7\x9E\x99", + "\xEA\xA1" => "\xE7\x9E\x97", + "\xEA\xA2" => "\xE7\xA3\x9D", + "\xEA\xA3" => "\xE7\xA3\xA9", + "\xEA\xA4" => "\xE7\xA3\xA5", + "\xEA\xA5" => "\xE7\xA3\xAA", + "\xEA\xA6" => "\xE7\xA3\x9E", + "\xEA\xA7" => "\xE7\xA3\xA3", + "\xEA\xA8" => "\xE7\xA3\x9B", + "\xEA\xA9" => "\xE7\xA3\xA1", + "\xEA\xAA" => "\xE7\xA3\xA2", + "\xEA\xAB" => "\xE7\xA3\xAD", + "\xEA\xAC" => "\xE7\xA3\x9F", + "\xEA\xAD" => "\xE7\xA3\xA0", + "\xEA\xAE" => "\xE7\xA6\xA4", + "\xEA\xAF" => "\xE7\xA9\x84", + "\xEA\xB0" => "\xE7\xA9\x88", + "\xEA\xB1" => "\xE7\xA9\x87", + "\xEA\xB2" => "\xE7\xAA\xB6", + "\xEA\xB3" => "\xE7\xAA\xB8", + "\xEA\xB4" => "\xE7\xAA\xB5", + "\xEA\xB5" => "\xE7\xAA\xB1", + "\xEA\xB6" => "\xE7\xAA\xB7", + "\xEA\xB7" => "\xE7\xAF\x9E", + "\xEA\xB8" => "\xE7\xAF\xA3", + "\xEA\xB9" => "\xE7\xAF\xA7", + "\xEA\xBA" => "\xE7\xAF\x9D", + "\xEA\xBB" => "\xE7\xAF\x95", + "\xEA\xBC" => "\xE7\xAF\xA5", + "\xEA\xBD" => "\xE7\xAF\x9A", + "\xEA\xBE" => "\xE7\xAF\xA8", + "\xEA\xBF" => "\xE7\xAF\xB9", + "\xEA\xC0" => "\xE7\xAF\x94", + "\xEA\xC1" => "\xE7\xAF\xAA", + "\xEA\xC2" => "\xE7\xAF\xA2", + "\xEA\xC3" => "\xE7\xAF\x9C", + "\xEA\xC4" => "\xE7\xAF\xAB", + "\xEA\xC5" => "\xE7\xAF\x98", + "\xEA\xC6" => "\xE7\xAF\x9F", + "\xEA\xC7" => "\xE7\xB3\x92", + "\xEA\xC8" => "\xE7\xB3\x94", + "\xEA\xC9" => "\xE7\xB3\x97", + "\xEA\xCA" => "\xE7\xB3\x90", + "\xEA\xCB" => "\xE7\xB3\x91", + "\xEA\xCC" => "\xE7\xB8\x92", + "\xEA\xCD" => "\xE7\xB8\xA1", + "\xEA\xCE" => "\xE7\xB8\x97", + "\xEA\xCF" => "\xE7\xB8\x8C", + "\xEA\xD0" => "\xE7\xB8\x9F", + "\xEA\xD1" => "\xE7\xB8\xA0", + "\xEA\xD2" => "\xE7\xB8\x93", + "\xEA\xD3" => "\xE7\xB8\x8E", + "\xEA\xD4" => "\xE7\xB8\x9C", + "\xEA\xD5" => "\xE7\xB8\x95", + "\xEA\xD6" => "\xE7\xB8\x9A", + "\xEA\xD7" => "\xE7\xB8\xA2", + "\xEA\xD8" => "\xE7\xB8\x8B", + "\xEA\xD9" => "\xE7\xB8\x8F", + "\xEA\xDA" => "\xE7\xB8\x96", + "\xEA\xDB" => "\xE7\xB8\x8D", + "\xEA\xDC" => "\xE7\xB8\x94", + "\xEA\xDD" => "\xE7\xB8\xA5", + "\xEA\xDE" => "\xE7\xB8\xA4", + "\xEA\xDF" => "\xE7\xBD\x83", + "\xEA\xE0" => "\xE7\xBD\xBB", + "\xEA\xE1" => "\xE7\xBD\xBC", + "\xEA\xE2" => "\xE7\xBD\xBA", + "\xEA\xE3" => "\xE7\xBE\xB1", + "\xEA\xE4" => "\xE7\xBF\xAF", + "\xEA\xE5" => "\xE8\x80\xAA", + "\xEA\xE6" => "\xE8\x80\xA9", + "\xEA\xE7" => "\xE8\x81\xAC", + "\xEA\xE8" => "\xE8\x86\xB1", + "\xEA\xE9" => "\xE8\x86\xA6", + "\xEA\xEA" => "\xE8\x86\xAE", + "\xEA\xEB" => "\xE8\x86\xB9", + "\xEA\xEC" => "\xE8\x86\xB5", + "\xEA\xED" => "\xE8\x86\xAB", + "\xEA\xEE" => "\xE8\x86\xB0", + "\xEA\xEF" => "\xE8\x86\xAC", + "\xEA\xF0" => "\xE8\x86\xB4", + "\xEA\xF1" => "\xE8\x86\xB2", + "\xEA\xF2" => "\xE8\x86\xB7", + "\xEA\xF3" => "\xE8\x86\xA7", + "\xEA\xF4" => "\xE8\x87\xB2", + "\xEA\xF5" => "\xE8\x89\x95", + "\xEA\xF6" => "\xE8\x89\x96", + "\xEA\xF7" => "\xE8\x89\x97", + "\xEA\xF8" => "\xE8\x95\x96", + "\xEA\xF9" => "\xE8\x95\x85", + "\xEA\xFA" => "\xE8\x95\xAB", + "\xEA\xFB" => "\xE8\x95\x8D", + "\xEA\xFC" => "\xE8\x95\x93", + "\xEA\xFD" => "\xE8\x95\xA1", + "\xEA\xFE" => "\xE8\x95\x98", + "\xEB\x40" => "\xE8\x95\x80", + "\xEB\x41" => "\xE8\x95\x86", + "\xEB\x42" => "\xE8\x95\xA4", + "\xEB\x43" => "\xE8\x95\x81", + "\xEB\x44" => "\xE8\x95\xA2", + "\xEB\x45" => "\xE8\x95\x84", + "\xEB\x46" => "\xE8\x95\x91", + "\xEB\x47" => "\xE8\x95\x87", + "\xEB\x48" => "\xE8\x95\xA3", + "\xEB\x49" => "\xE8\x94\xBE", + "\xEB\x4A" => "\xE8\x95\x9B", + "\xEB\x4B" => "\xE8\x95\xB1", + "\xEB\x4C" => "\xE8\x95\x8E", + "\xEB\x4D" => "\xE8\x95\xAE", + "\xEB\x4E" => "\xE8\x95\xB5", + "\xEB\x4F" => "\xE8\x95\x95", + "\xEB\x50" => "\xE8\x95\xA7", + "\xEB\x51" => "\xE8\x95\xA0", + "\xEB\x52" => "\xE8\x96\x8C", + "\xEB\x53" => "\xE8\x95\xA6", + "\xEB\x54" => "\xE8\x95\x9D", + "\xEB\x55" => "\xE8\x95\x94", + "\xEB\x56" => "\xE8\x95\xA5", + "\xEB\x57" => "\xE8\x95\xAC", + "\xEB\x58" => "\xE8\x99\xA3", + "\xEB\x59" => "\xE8\x99\xA5", + "\xEB\x5A" => "\xE8\x99\xA4", + "\xEB\x5B" => "\xE8\x9E\x9B", + "\xEB\x5C" => "\xE8\x9E\x8F", + "\xEB\x5D" => "\xE8\x9E\x97", + "\xEB\x5E" => "\xE8\x9E\x93", + "\xEB\x5F" => "\xE8\x9E\x92", + "\xEB\x60" => "\xE8\x9E\x88", + "\xEB\x61" => "\xE8\x9E\x81", + "\xEB\x62" => "\xE8\x9E\x96", + "\xEB\x63" => "\xE8\x9E\x98", + "\xEB\x64" => "\xE8\x9D\xB9", + "\xEB\x65" => "\xE8\x9E\x87", + "\xEB\x66" => "\xE8\x9E\xA3", + "\xEB\x67" => "\xE8\x9E\x85", + "\xEB\x68" => "\xE8\x9E\x90", + "\xEB\x69" => "\xE8\x9E\x91", + "\xEB\x6A" => "\xE8\x9E\x9D", + "\xEB\x6B" => "\xE8\x9E\x84", + "\xEB\x6C" => "\xE8\x9E\x94", + "\xEB\x6D" => "\xE8\x9E\x9C", + "\xEB\x6E" => "\xE8\x9E\x9A", + "\xEB\x6F" => "\xE8\x9E\x89", + "\xEB\x70" => "\xE8\xA4\x9E", + "\xEB\x71" => "\xE8\xA4\xA6", + "\xEB\x72" => "\xE8\xA4\xB0", + "\xEB\x73" => "\xE8\xA4\xAD", + "\xEB\x74" => "\xE8\xA4\xAE", + "\xEB\x75" => "\xE8\xA4\xA7", + "\xEB\x76" => "\xE8\xA4\xB1", + "\xEB\x77" => "\xE8\xA4\xA2", + "\xEB\x78" => "\xE8\xA4\xA9", + "\xEB\x79" => "\xE8\xA4\xA3", + "\xEB\x7A" => "\xE8\xA4\xAF", + "\xEB\x7B" => "\xE8\xA4\xAC", + "\xEB\x7C" => "\xE8\xA4\x9F", + "\xEB\x7D" => "\xE8\xA7\xB1", + "\xEB\x7E" => "\xE8\xAB\xA0", + "\xEB\xA1" => "\xE8\xAB\xA2", + "\xEB\xA2" => "\xE8\xAB\xB2", + "\xEB\xA3" => "\xE8\xAB\xB4", + "\xEB\xA4" => "\xE8\xAB\xB5", + "\xEB\xA5" => "\xE8\xAB\x9D", + "\xEB\xA6" => "\xE8\xAC\x94", + "\xEB\xA7" => "\xE8\xAB\xA4", + "\xEB\xA8" => "\xE8\xAB\x9F", + "\xEB\xA9" => "\xE8\xAB\xB0", + "\xEB\xAA" => "\xE8\xAB\x88", + "\xEB\xAB" => "\xE8\xAB\x9E", + "\xEB\xAC" => "\xE8\xAB\xA1", + "\xEB\xAD" => "\xE8\xAB\xA8", + "\xEB\xAE" => "\xE8\xAB\xBF", + "\xEB\xAF" => "\xE8\xAB\xAF", + "\xEB\xB0" => "\xE8\xAB\xBB", + "\xEB\xB1" => "\xE8\xB2\x91", + "\xEB\xB2" => "\xE8\xB2\x92", + "\xEB\xB3" => "\xE8\xB2\x90", + "\xEB\xB4" => "\xE8\xB3\xB5", + "\xEB\xB5" => "\xE8\xB3\xAE", + "\xEB\xB6" => "\xE8\xB3\xB1", + "\xEB\xB7" => "\xE8\xB3\xB0", + "\xEB\xB8" => "\xE8\xB3\xB3", + "\xEB\xB9" => "\xE8\xB5\xAC", + "\xEB\xBA" => "\xE8\xB5\xAE", + "\xEB\xBB" => "\xE8\xB6\xA5", + "\xEB\xBC" => "\xE8\xB6\xA7", + "\xEB\xBD" => "\xE8\xB8\xB3", + "\xEB\xBE" => "\xE8\xB8\xBE", + "\xEB\xBF" => "\xE8\xB8\xB8", + "\xEB\xC0" => "\xE8\xB9\x80", + "\xEB\xC1" => "\xE8\xB9\x85", + "\xEB\xC2" => "\xE8\xB8\xB6", + "\xEB\xC3" => "\xE8\xB8\xBC", + "\xEB\xC4" => "\xE8\xB8\xBD", + "\xEB\xC5" => "\xE8\xB9\x81", + "\xEB\xC6" => "\xE8\xB8\xB0", + "\xEB\xC7" => "\xE8\xB8\xBF", + "\xEB\xC8" => "\xE8\xBA\xBD", + "\xEB\xC9" => "\xE8\xBC\xB6", + "\xEB\xCA" => "\xE8\xBC\xAE", + "\xEB\xCB" => "\xE8\xBC\xB5", + "\xEB\xCC" => "\xE8\xBC\xB2", + "\xEB\xCD" => "\xE8\xBC\xB9", + "\xEB\xCE" => "\xE8\xBC\xB7", + "\xEB\xCF" => "\xE8\xBC\xB4", + "\xEB\xD0" => "\xE9\x81\xB6", + "\xEB\xD1" => "\xE9\x81\xB9", + "\xEB\xD2" => "\xE9\x81\xBB", + "\xEB\xD3" => "\xE9\x82\x86", + "\xEB\xD4" => "\xE9\x83\xBA", + "\xEB\xD5" => "\xE9\x84\xB3", + "\xEB\xD6" => "\xE9\x84\xB5", + "\xEB\xD7" => "\xE9\x84\xB6", + "\xEB\xD8" => "\xE9\x86\x93", + "\xEB\xD9" => "\xE9\x86\x90", + "\xEB\xDA" => "\xE9\x86\x91", + "\xEB\xDB" => "\xE9\x86\x8D", + "\xEB\xDC" => "\xE9\x86\x8F", + "\xEB\xDD" => "\xE9\x8C\xA7", + "\xEB\xDE" => "\xE9\x8C\x9E", + "\xEB\xDF" => "\xE9\x8C\x88", + "\xEB\xE0" => "\xE9\x8C\x9F", + "\xEB\xE1" => "\xE9\x8C\x86", + "\xEB\xE2" => "\xE9\x8C\x8F", + "\xEB\xE3" => "\xE9\x8D\xBA", + "\xEB\xE4" => "\xE9\x8C\xB8", + "\xEB\xE5" => "\xE9\x8C\xBC", + "\xEB\xE6" => "\xE9\x8C\x9B", + "\xEB\xE7" => "\xE9\x8C\xA3", + "\xEB\xE8" => "\xE9\x8C\x92", + "\xEB\xE9" => "\xE9\x8C\x81", + "\xEB\xEA" => "\xE9\x8D\x86", + "\xEB\xEB" => "\xE9\x8C\xAD", + "\xEB\xEC" => "\xE9\x8C\x8E", + "\xEB\xED" => "\xE9\x8C\x8D", + "\xEB\xEE" => "\xE9\x8B\x8B", + "\xEB\xEF" => "\xE9\x8C\x9D", + "\xEB\xF0" => "\xE9\x8B\xBA", + "\xEB\xF1" => "\xE9\x8C\xA5", + "\xEB\xF2" => "\xE9\x8C\x93", + "\xEB\xF3" => "\xE9\x8B\xB9", + "\xEB\xF4" => "\xE9\x8B\xB7", + "\xEB\xF5" => "\xE9\x8C\xB4", + "\xEB\xF6" => "\xE9\x8C\x82", + "\xEB\xF7" => "\xE9\x8C\xA4", + "\xEB\xF8" => "\xE9\x8B\xBF", + "\xEB\xF9" => "\xE9\x8C\xA9", + "\xEB\xFA" => "\xE9\x8C\xB9", + "\xEB\xFB" => "\xE9\x8C\xB5", + "\xEB\xFC" => "\xE9\x8C\xAA", + "\xEB\xFD" => "\xE9\x8C\x94", + "\xEB\xFE" => "\xE9\x8C\x8C", + "\xEC\x40" => "\xE9\x8C\x8B", + "\xEC\x41" => "\xE9\x8B\xBE", + "\xEC\x42" => "\xE9\x8C\x89", + "\xEC\x43" => "\xE9\x8C\x80", + "\xEC\x44" => "\xE9\x8B\xBB", + "\xEC\x45" => "\xE9\x8C\x96", + "\xEC\x46" => "\xE9\x96\xBC", + "\xEC\x47" => "\xE9\x97\x8D", + "\xEC\x48" => "\xE9\x96\xBE", + "\xEC\x49" => "\xE9\x96\xB9", + "\xEC\x4A" => "\xE9\x96\xBA", + "\xEC\x4B" => "\xE9\x96\xB6", + "\xEC\x4C" => "\xE9\x96\xBF", + "\xEC\x4D" => "\xE9\x96\xB5", + "\xEC\x4E" => "\xE9\x96\xBD", + "\xEC\x4F" => "\xE9\x9A\xA9", + "\xEC\x50" => "\xE9\x9B\x94", + "\xEC\x51" => "\xE9\x9C\x8B", + "\xEC\x52" => "\xE9\x9C\x92", + "\xEC\x53" => "\xE9\x9C\x90", + "\xEC\x54" => "\xE9\x9E\x99", + "\xEC\x55" => "\xE9\x9E\x97", + "\xEC\x56" => "\xE9\x9E\x94", + "\xEC\x57" => "\xE9\x9F\xB0", + "\xEC\x58" => "\xE9\x9F\xB8", + "\xEC\x59" => "\xE9\xA0\xB5", + "\xEC\x5A" => "\xE9\xA0\xAF", + "\xEC\x5B" => "\xE9\xA0\xB2", + "\xEC\x5C" => "\xE9\xA4\xA4", + "\xEC\x5D" => "\xE9\xA4\x9F", + "\xEC\x5E" => "\xE9\xA4\xA7", + "\xEC\x5F" => "\xE9\xA4\xA9", + "\xEC\x60" => "\xE9\xA6\x9E", + "\xEC\x61" => "\xE9\xA7\xAE", + "\xEC\x62" => "\xE9\xA7\xAC", + "\xEC\x63" => "\xE9\xA7\xA5", + "\xEC\x64" => "\xE9\xA7\xA4", + "\xEC\x65" => "\xE9\xA7\xB0", + "\xEC\x66" => "\xE9\xA7\xA3", + "\xEC\x67" => "\xE9\xA7\xAA", + "\xEC\x68" => "\xE9\xA7\xA9", + "\xEC\x69" => "\xE9\xA7\xA7", + "\xEC\x6A" => "\xE9\xAA\xB9", + "\xEC\x6B" => "\xE9\xAA\xBF", + "\xEC\x6C" => "\xE9\xAA\xB4", + "\xEC\x6D" => "\xE9\xAA\xBB", + "\xEC\x6E" => "\xE9\xAB\xB6", + "\xEC\x6F" => "\xE9\xAB\xBA", + "\xEC\x70" => "\xE9\xAB\xB9", + "\xEC\x71" => "\xE9\xAB\xB7", + "\xEC\x72" => "\xE9\xAC\xB3", + "\xEC\x73" => "\xE9\xAE\x80", + "\xEC\x74" => "\xE9\xAE\x85", + "\xEC\x75" => "\xE9\xAE\x87", + "\xEC\x76" => "\xE9\xAD\xBC", + "\xEC\x77" => "\xE9\xAD\xBE", + "\xEC\x78" => "\xE9\xAD\xBB", + "\xEC\x79" => "\xE9\xAE\x82", + "\xEC\x7A" => "\xE9\xAE\x93", + "\xEC\x7B" => "\xE9\xAE\x92", + "\xEC\x7C" => "\xE9\xAE\x90", + "\xEC\x7D" => "\xE9\xAD\xBA", + "\xEC\x7E" => "\xE9\xAE\x95", + "\xEC\xA1" => "\xE9\xAD\xBD", + "\xEC\xA2" => "\xE9\xAE\x88", + "\xEC\xA3" => "\xE9\xB4\xA5", + "\xEC\xA4" => "\xE9\xB4\x97", + "\xEC\xA5" => "\xE9\xB4\xA0", + "\xEC\xA6" => "\xE9\xB4\x9E", + "\xEC\xA7" => "\xE9\xB4\x94", + "\xEC\xA8" => "\xE9\xB4\xA9", + "\xEC\xA9" => "\xE9\xB4\x9D", + "\xEC\xAA" => "\xE9\xB4\x98", + "\xEC\xAB" => "\xE9\xB4\xA2", + "\xEC\xAC" => "\xE9\xB4\x90", + "\xEC\xAD" => "\xE9\xB4\x99", + "\xEC\xAE" => "\xE9\xB4\x9F", + "\xEC\xAF" => "\xE9\xBA\x88", + "\xEC\xB0" => "\xE9\xBA\x86", + "\xEC\xB1" => "\xE9\xBA\x87", + "\xEC\xB2" => "\xE9\xBA\xAE", + "\xEC\xB3" => "\xE9\xBA\xAD", + "\xEC\xB4" => "\xE9\xBB\x95", + "\xEC\xB5" => "\xE9\xBB\x96", + "\xEC\xB6" => "\xE9\xBB\xBA", + "\xEC\xB7" => "\xE9\xBC\x92", + "\xEC\xB8" => "\xE9\xBC\xBD", + "\xEC\xB9" => "\xE5\x84\xA6", + "\xEC\xBA" => "\xE5\x84\xA5", + "\xEC\xBB" => "\xE5\x84\xA2", + "\xEC\xBC" => "\xE5\x84\xA4", + "\xEC\xBD" => "\xE5\x84\xA0", + "\xEC\xBE" => "\xE5\x84\xA9", + "\xEC\xBF" => "\xE5\x8B\xB4", + "\xEC\xC0" => "\xE5\x9A\x93", + "\xEC\xC1" => "\xE5\x9A\x8C", + "\xEC\xC2" => "\xE5\x9A\x8D", + "\xEC\xC3" => "\xE5\x9A\x86", + "\xEC\xC4" => "\xE5\x9A\x84", + "\xEC\xC5" => "\xE5\x9A\x83", + "\xEC\xC6" => "\xE5\x99\xBE", + "\xEC\xC7" => "\xE5\x9A\x82", + "\xEC\xC8" => "\xE5\x99\xBF", + "\xEC\xC9" => "\xE5\x9A\x81", + "\xEC\xCA" => "\xE5\xA3\x96", + "\xEC\xCB" => "\xE5\xA3\x94", + "\xEC\xCC" => "\xE5\xA3\x8F", + "\xEC\xCD" => "\xE5\xA3\x92", + "\xEC\xCE" => "\xE5\xAC\xAD", + "\xEC\xCF" => "\xE5\xAC\xA5", + "\xEC\xD0" => "\xE5\xAC\xB2", + "\xEC\xD1" => "\xE5\xAC\xA3", + "\xEC\xD2" => "\xE5\xAC\xAC", + "\xEC\xD3" => "\xE5\xAC\xA7", + "\xEC\xD4" => "\xE5\xAC\xA6", + "\xEC\xD5" => "\xE5\xAC\xAF", + "\xEC\xD6" => "\xE5\xAC\xAE", + "\xEC\xD7" => "\xE5\xAD\xBB", + "\xEC\xD8" => "\xE5\xAF\xB1", + "\xEC\xD9" => "\xE5\xAF\xB2", + "\xEC\xDA" => "\xE5\xB6\xB7", + "\xEC\xDB" => "\xE5\xB9\xAC", + "\xEC\xDC" => "\xE5\xB9\xAA", + "\xEC\xDD" => "\xE5\xBE\xBE", + "\xEC\xDE" => "\xE5\xBE\xBB", + "\xEC\xDF" => "\xE6\x87\x83", + "\xEC\xE0" => "\xE6\x86\xB5", + "\xEC\xE1" => "\xE6\x86\xBC", + "\xEC\xE2" => "\xE6\x87\xA7", + "\xEC\xE3" => "\xE6\x87\xA0", + "\xEC\xE4" => "\xE6\x87\xA5", + "\xEC\xE5" => "\xE6\x87\xA4", + "\xEC\xE6" => "\xE6\x87\xA8", + "\xEC\xE7" => "\xE6\x87\x9E", + "\xEC\xE8" => "\xE6\x93\xAF", + "\xEC\xE9" => "\xE6\x93\xA9", + "\xEC\xEA" => "\xE6\x93\xA3", + "\xEC\xEB" => "\xE6\x93\xAB", + "\xEC\xEC" => "\xE6\x93\xA4", + "\xEC\xED" => "\xE6\x93\xA8", + "\xEC\xEE" => "\xE6\x96\x81", + "\xEC\xEF" => "\xE6\x96\x80", + "\xEC\xF0" => "\xE6\x96\xB6", + "\xEC\xF1" => "\xE6\x97\x9A", + "\xEC\xF2" => "\xE6\x9B\x92", + "\xEC\xF3" => "\xE6\xAA\x8D", + "\xEC\xF4" => "\xE6\xAA\x96", + "\xEC\xF5" => "\xE6\xAA\x81", + "\xEC\xF6" => "\xE6\xAA\xA5", + "\xEC\xF7" => "\xE6\xAA\x89", + "\xEC\xF8" => "\xE6\xAA\x9F", + "\xEC\xF9" => "\xE6\xAA\x9B", + "\xEC\xFA" => "\xE6\xAA\xA1", + "\xEC\xFB" => "\xE6\xAA\x9E", + "\xEC\xFC" => "\xE6\xAA\x87", + "\xEC\xFD" => "\xE6\xAA\x93", + "\xEC\xFE" => "\xE6\xAA\x8E", + "\xED\x40" => "\xE6\xAA\x95", + "\xED\x41" => "\xE6\xAA\x83", + "\xED\x42" => "\xE6\xAA\xA8", + "\xED\x43" => "\xE6\xAA\xA4", + "\xED\x44" => "\xE6\xAA\x91", + "\xED\x45" => "\xE6\xA9\xBF", + "\xED\x46" => "\xE6\xAA\xA6", + "\xED\x47" => "\xE6\xAA\x9A", + "\xED\x48" => "\xE6\xAA\x85", + "\xED\x49" => "\xE6\xAA\x8C", + "\xED\x4A" => "\xE6\xAA\x92", + "\xED\x4B" => "\xE6\xAD\x9B", + "\xED\x4C" => "\xE6\xAE\xAD", + "\xED\x4D" => "\xE6\xB0\x89", + "\xED\x4E" => "\xE6\xBF\x8C", + "\xED\x4F" => "\xE6\xBE\xA9", + "\xED\x50" => "\xE6\xBF\xB4", + "\xED\x51" => "\xE6\xBF\x94", + "\xED\x52" => "\xE6\xBF\xA3", + "\xED\x53" => "\xE6\xBF\x9C", + "\xED\x54" => "\xE6\xBF\xAD", + "\xED\x55" => "\xE6\xBF\xA7", + "\xED\x56" => "\xE6\xBF\xA6", + "\xED\x57" => "\xE6\xBF\x9E", + "\xED\x58" => "\xE6\xBF\xB2", + "\xED\x59" => "\xE6\xBF\x9D", + "\xED\x5A" => "\xE6\xBF\xA2", + "\xED\x5B" => "\xE6\xBF\xA8", + "\xED\x5C" => "\xE7\x87\xA1", + "\xED\x5D" => "\xE7\x87\xB1", + "\xED\x5E" => "\xE7\x87\xA8", + "\xED\x5F" => "\xE7\x87\xB2", + "\xED\x60" => "\xE7\x87\xA4", + "\xED\x61" => "\xE7\x87\xB0", + "\xED\x62" => "\xE7\x87\xA2", + "\xED\x63" => "\xE7\x8D\xB3", + "\xED\x64" => "\xE7\x8D\xAE", + "\xED\x65" => "\xE7\x8D\xAF", + "\xED\x66" => "\xE7\x92\x97", + "\xED\x67" => "\xE7\x92\xB2", + "\xED\x68" => "\xE7\x92\xAB", + "\xED\x69" => "\xE7\x92\x90", + "\xED\x6A" => "\xE7\x92\xAA", + "\xED\x6B" => "\xE7\x92\xAD", + "\xED\x6C" => "\xE7\x92\xB1", + "\xED\x6D" => "\xE7\x92\xA5", + "\xED\x6E" => "\xE7\x92\xAF", + "\xED\x6F" => "\xE7\x94\x90", + "\xED\x70" => "\xE7\x94\x91", + "\xED\x71" => "\xE7\x94\x92", + "\xED\x72" => "\xE7\x94\x8F", + "\xED\x73" => "\xE7\x96\x84", + "\xED\x74" => "\xE7\x99\x83", + "\xED\x75" => "\xE7\x99\x88", + "\xED\x76" => "\xE7\x99\x89", + "\xED\x77" => "\xE7\x99\x87", + "\xED\x78" => "\xE7\x9A\xA4", + "\xED\x79" => "\xE7\x9B\xA9", + "\xED\x7A" => "\xE7\x9E\xB5", + "\xED\x7B" => "\xE7\x9E\xAB", + "\xED\x7C" => "\xE7\x9E\xB2", + "\xED\x7D" => "\xE7\x9E\xB7", + "\xED\x7E" => "\xE7\x9E\xB6", + "\xED\xA1" => "\xE7\x9E\xB4", + "\xED\xA2" => "\xE7\x9E\xB1", + "\xED\xA3" => "\xE7\x9E\xA8", + "\xED\xA4" => "\xE7\x9F\xB0", + "\xED\xA5" => "\xE7\xA3\xB3", + "\xED\xA6" => "\xE7\xA3\xBD", + "\xED\xA7" => "\xE7\xA4\x82", + "\xED\xA8" => "\xE7\xA3\xBB", + "\xED\xA9" => "\xE7\xA3\xBC", + "\xED\xAA" => "\xE7\xA3\xB2", + "\xED\xAB" => "\xE7\xA4\x85", + "\xED\xAC" => "\xE7\xA3\xB9", + "\xED\xAD" => "\xE7\xA3\xBE", + "\xED\xAE" => "\xE7\xA4\x84", + "\xED\xAF" => "\xE7\xA6\xAB", + "\xED\xB0" => "\xE7\xA6\xA8", + "\xED\xB1" => "\xE7\xA9\x9C", + "\xED\xB2" => "\xE7\xA9\x9B", + "\xED\xB3" => "\xE7\xA9\x96", + "\xED\xB4" => "\xE7\xA9\x98", + "\xED\xB5" => "\xE7\xA9\x94", + "\xED\xB6" => "\xE7\xA9\x9A", + "\xED\xB7" => "\xE7\xAA\xBE", + "\xED\xB8" => "\xE7\xAB\x80", + "\xED\xB9" => "\xE7\xAB\x81", + "\xED\xBA" => "\xE7\xB0\x85", + "\xED\xBB" => "\xE7\xB0\x8F", + "\xED\xBC" => "\xE7\xAF\xB2", + "\xED\xBD" => "\xE7\xB0\x80", + "\xED\xBE" => "\xE7\xAF\xBF", + "\xED\xBF" => "\xE7\xAF\xBB", + "\xED\xC0" => "\xE7\xB0\x8E", + "\xED\xC1" => "\xE7\xAF\xB4", + "\xED\xC2" => "\xE7\xB0\x8B", + "\xED\xC3" => "\xE7\xAF\xB3", + "\xED\xC4" => "\xE7\xB0\x82", + "\xED\xC5" => "\xE7\xB0\x89", + "\xED\xC6" => "\xE7\xB0\x83", + "\xED\xC7" => "\xE7\xB0\x81", + "\xED\xC8" => "\xE7\xAF\xB8", + "\xED\xC9" => "\xE7\xAF\xBD", + "\xED\xCA" => "\xE7\xB0\x86", + "\xED\xCB" => "\xE7\xAF\xB0", + "\xED\xCC" => "\xE7\xAF\xB1", + "\xED\xCD" => "\xE7\xB0\x90", + "\xED\xCE" => "\xE7\xB0\x8A", + "\xED\xCF" => "\xE7\xB3\xA8", + "\xED\xD0" => "\xE7\xB8\xAD", + "\xED\xD1" => "\xE7\xB8\xBC", + "\xED\xD2" => "\xE7\xB9\x82", + "\xED\xD3" => "\xE7\xB8\xB3", + "\xED\xD4" => "\xE9\xA1\x88", + "\xED\xD5" => "\xE7\xB8\xB8", + "\xED\xD6" => "\xE7\xB8\xAA", + "\xED\xD7" => "\xE7\xB9\x89", + "\xED\xD8" => "\xE7\xB9\x80", + "\xED\xD9" => "\xE7\xB9\x87", + "\xED\xDA" => "\xE7\xB8\xA9", + "\xED\xDB" => "\xE7\xB9\x8C", + "\xED\xDC" => "\xE7\xB8\xB0", + "\xED\xDD" => "\xE7\xB8\xBB", + "\xED\xDE" => "\xE7\xB8\xB6", + "\xED\xDF" => "\xE7\xB9\x84", + "\xED\xE0" => "\xE7\xB8\xBA", + "\xED\xE1" => "\xE7\xBD\x85", + "\xED\xE2" => "\xE7\xBD\xBF", + "\xED\xE3" => "\xE7\xBD\xBE", + "\xED\xE4" => "\xE7\xBD\xBD", + "\xED\xE5" => "\xE7\xBF\xB4", + "\xED\xE6" => "\xE7\xBF\xB2", + "\xED\xE7" => "\xE8\x80\xAC", + "\xED\xE8" => "\xE8\x86\xBB", + "\xED\xE9" => "\xE8\x87\x84", + "\xED\xEA" => "\xE8\x87\x8C", + "\xED\xEB" => "\xE8\x87\x8A", + "\xED\xEC" => "\xE8\x87\x85", + "\xED\xED" => "\xE8\x87\x87", + "\xED\xEE" => "\xE8\x86\xBC", + "\xED\xEF" => "\xE8\x87\xA9", + "\xED\xF0" => "\xE8\x89\x9B", + "\xED\xF1" => "\xE8\x89\x9A", + "\xED\xF2" => "\xE8\x89\x9C", + "\xED\xF3" => "\xE8\x96\x83", + "\xED\xF4" => "\xE8\x96\x80", + "\xED\xF5" => "\xE8\x96\x8F", + "\xED\xF6" => "\xE8\x96\xA7", + "\xED\xF7" => "\xE8\x96\x95", + "\xED\xF8" => "\xE8\x96\xA0", + "\xED\xF9" => "\xE8\x96\x8B", + "\xED\xFA" => "\xE8\x96\xA3", + "\xED\xFB" => "\xE8\x95\xBB", + "\xED\xFC" => "\xE8\x96\xA4", + "\xED\xFD" => "\xE8\x96\x9A", + "\xED\xFE" => "\xE8\x96\x9E", + "\xEE\x40" => "\xE8\x95\xB7", + "\xEE\x41" => "\xE8\x95\xBC", + "\xEE\x42" => "\xE8\x96\x89", + "\xEE\x43" => "\xE8\x96\xA1", + "\xEE\x44" => "\xE8\x95\xBA", + "\xEE\x45" => "\xE8\x95\xB8", + "\xEE\x46" => "\xE8\x95\x97", + "\xEE\x47" => "\xE8\x96\x8E", + "\xEE\x48" => "\xE8\x96\x96", + "\xEE\x49" => "\xE8\x96\x86", + "\xEE\x4A" => "\xE8\x96\x8D", + "\xEE\x4B" => "\xE8\x96\x99", + "\xEE\x4C" => "\xE8\x96\x9D", + "\xEE\x4D" => "\xE8\x96\x81", + "\xEE\x4E" => "\xE8\x96\xA2", + "\xEE\x4F" => "\xE8\x96\x82", + "\xEE\x50" => "\xE8\x96\x88", + "\xEE\x51" => "\xE8\x96\x85", + "\xEE\x52" => "\xE8\x95\xB9", + "\xEE\x53" => "\xE8\x95\xB6", + "\xEE\x54" => "\xE8\x96\x98", + "\xEE\x55" => "\xE8\x96\x90", + "\xEE\x56" => "\xE8\x96\x9F", + "\xEE\x57" => "\xE8\x99\xA8", + "\xEE\x58" => "\xE8\x9E\xBE", + "\xEE\x59" => "\xE8\x9E\xAA", + "\xEE\x5A" => "\xE8\x9E\xAD", + "\xEE\x5B" => "\xE8\x9F\x85", + "\xEE\x5C" => "\xE8\x9E\xB0", + "\xEE\x5D" => "\xE8\x9E\xAC", + "\xEE\x5E" => "\xE8\x9E\xB9", + "\xEE\x5F" => "\xE8\x9E\xB5", + "\xEE\x60" => "\xE8\x9E\xBC", + "\xEE\x61" => "\xE8\x9E\xAE", + "\xEE\x62" => "\xE8\x9F\x89", + "\xEE\x63" => "\xE8\x9F\x83", + "\xEE\x64" => "\xE8\x9F\x82", + "\xEE\x65" => "\xE8\x9F\x8C", + "\xEE\x66" => "\xE8\x9E\xB7", + "\xEE\x67" => "\xE8\x9E\xAF", + "\xEE\x68" => "\xE8\x9F\x84", + "\xEE\x69" => "\xE8\x9F\x8A", + "\xEE\x6A" => "\xE8\x9E\xB4", + "\xEE\x6B" => "\xE8\x9E\xB6", + "\xEE\x6C" => "\xE8\x9E\xBF", + "\xEE\x6D" => "\xE8\x9E\xB8", + "\xEE\x6E" => "\xE8\x9E\xBD", + "\xEE\x6F" => "\xE8\x9F\x9E", + "\xEE\x70" => "\xE8\x9E\xB2", + "\xEE\x71" => "\xE8\xA4\xB5", + "\xEE\x72" => "\xE8\xA4\xB3", + "\xEE\x73" => "\xE8\xA4\xBC", + "\xEE\x74" => "\xE8\xA4\xBE", + "\xEE\x75" => "\xE8\xA5\x81", + "\xEE\x76" => "\xE8\xA5\x92", + "\xEE\x77" => "\xE8\xA4\xB7", + "\xEE\x78" => "\xE8\xA5\x82", + "\xEE\x79" => "\xE8\xA6\xAD", + "\xEE\x7A" => "\xE8\xA6\xAF", + "\xEE\x7B" => "\xE8\xA6\xAE", + "\xEE\x7C" => "\xE8\xA7\xB2", + "\xEE\x7D" => "\xE8\xA7\xB3", + "\xEE\x7E" => "\xE8\xAC\x9E", + "\xEE\xA1" => "\xE8\xAC\x98", + "\xEE\xA2" => "\xE8\xAC\x96", + "\xEE\xA3" => "\xE8\xAC\x91", + "\xEE\xA4" => "\xE8\xAC\x85", + "\xEE\xA5" => "\xE8\xAC\x8B", + "\xEE\xA6" => "\xE8\xAC\xA2", + "\xEE\xA7" => "\xE8\xAC\x8F", + "\xEE\xA8" => "\xE8\xAC\x92", + "\xEE\xA9" => "\xE8\xAC\x95", + "\xEE\xAA" => "\xE8\xAC\x87", + "\xEE\xAB" => "\xE8\xAC\x8D", + "\xEE\xAC" => "\xE8\xAC\x88", + "\xEE\xAD" => "\xE8\xAC\x86", + "\xEE\xAE" => "\xE8\xAC\x9C", + "\xEE\xAF" => "\xE8\xAC\x93", + "\xEE\xB0" => "\xE8\xAC\x9A", + "\xEE\xB1" => "\xE8\xB1\x8F", + "\xEE\xB2" => "\xE8\xB1\xB0", + "\xEE\xB3" => "\xE8\xB1\xB2", + "\xEE\xB4" => "\xE8\xB1\xB1", + "\xEE\xB5" => "\xE8\xB1\xAF", + "\xEE\xB6" => "\xE8\xB2\x95", + "\xEE\xB7" => "\xE8\xB2\x94", + "\xEE\xB8" => "\xE8\xB3\xB9", + "\xEE\xB9" => "\xE8\xB5\xAF", + "\xEE\xBA" => "\xE8\xB9\x8E", + "\xEE\xBB" => "\xE8\xB9\x8D", + "\xEE\xBC" => "\xE8\xB9\x93", + "\xEE\xBD" => "\xE8\xB9\x90", + "\xEE\xBE" => "\xE8\xB9\x8C", + "\xEE\xBF" => "\xE8\xB9\x87", + "\xEE\xC0" => "\xE8\xBD\x83", + "\xEE\xC1" => "\xE8\xBD\x80", + "\xEE\xC2" => "\xE9\x82\x85", + "\xEE\xC3" => "\xE9\x81\xBE", + "\xEE\xC4" => "\xE9\x84\xB8", + "\xEE\xC5" => "\xE9\x86\x9A", + "\xEE\xC6" => "\xE9\x86\xA2", + "\xEE\xC7" => "\xE9\x86\x9B", + "\xEE\xC8" => "\xE9\x86\x99", + "\xEE\xC9" => "\xE9\x86\x9F", + "\xEE\xCA" => "\xE9\x86\xA1", + "\xEE\xCB" => "\xE9\x86\x9D", + "\xEE\xCC" => "\xE9\x86\xA0", + "\xEE\xCD" => "\xE9\x8E\xA1", + "\xEE\xCE" => "\xE9\x8E\x83", + "\xEE\xCF" => "\xE9\x8E\xAF", + "\xEE\xD0" => "\xE9\x8D\xA4", + "\xEE\xD1" => "\xE9\x8D\x96", + "\xEE\xD2" => "\xE9\x8D\x87", + "\xEE\xD3" => "\xE9\x8D\xBC", + "\xEE\xD4" => "\xE9\x8D\x98", + "\xEE\xD5" => "\xE9\x8D\x9C", + "\xEE\xD6" => "\xE9\x8D\xB6", + "\xEE\xD7" => "\xE9\x8D\x89", + "\xEE\xD8" => "\xE9\x8D\x90", + "\xEE\xD9" => "\xE9\x8D\x91", + "\xEE\xDA" => "\xE9\x8D\xA0", + "\xEE\xDB" => "\xE9\x8D\xAD", + "\xEE\xDC" => "\xE9\x8E\x8F", + "\xEE\xDD" => "\xE9\x8D\x8C", + "\xEE\xDE" => "\xE9\x8D\xAA", + "\xEE\xDF" => "\xE9\x8D\xB9", + "\xEE\xE0" => "\xE9\x8D\x97", + "\xEE\xE1" => "\xE9\x8D\x95", + "\xEE\xE2" => "\xE9\x8D\x92", + "\xEE\xE3" => "\xE9\x8D\x8F", + "\xEE\xE4" => "\xE9\x8D\xB1", + "\xEE\xE5" => "\xE9\x8D\xB7", + "\xEE\xE6" => "\xE9\x8D\xBB", + "\xEE\xE7" => "\xE9\x8D\xA1", + "\xEE\xE8" => "\xE9\x8D\x9E", + "\xEE\xE9" => "\xE9\x8D\xA3", + "\xEE\xEA" => "\xE9\x8D\xA7", + "\xEE\xEB" => "\xE9\x8E\x80", + "\xEE\xEC" => "\xE9\x8D\x8E", + "\xEE\xED" => "\xE9\x8D\x99", + "\xEE\xEE" => "\xE9\x97\x87", + "\xEE\xEF" => "\xE9\x97\x80", + "\xEE\xF0" => "\xE9\x97\x89", + "\xEE\xF1" => "\xE9\x97\x83", + "\xEE\xF2" => "\xE9\x97\x85", + "\xEE\xF3" => "\xE9\x96\xB7", + "\xEE\xF4" => "\xE9\x9A\xAE", + "\xEE\xF5" => "\xE9\x9A\xB0", + "\xEE\xF6" => "\xE9\x9A\xAC", + "\xEE\xF7" => "\xE9\x9C\xA0", + "\xEE\xF8" => "\xE9\x9C\x9F", + "\xEE\xF9" => "\xE9\x9C\x98", + "\xEE\xFA" => "\xE9\x9C\x9D", + "\xEE\xFB" => "\xE9\x9C\x99", + "\xEE\xFC" => "\xE9\x9E\x9A", + "\xEE\xFD" => "\xE9\x9E\xA1", + "\xEE\xFE" => "\xE9\x9E\x9C", + "\xEF\x40" => "\xE9\x9E\x9E", + "\xEF\x41" => "\xE9\x9E\x9D", + "\xEF\x42" => "\xE9\x9F\x95", + "\xEF\x43" => "\xE9\x9F\x94", + "\xEF\x44" => "\xE9\x9F\xB1", + "\xEF\x45" => "\xE9\xA1\x81", + "\xEF\x46" => "\xE9\xA1\x84", + "\xEF\x47" => "\xE9\xA1\x8A", + "\xEF\x48" => "\xE9\xA1\x89", + "\xEF\x49" => "\xE9\xA1\x85", + "\xEF\x4A" => "\xE9\xA1\x83", + "\xEF\x4B" => "\xE9\xA4\xA5", + "\xEF\x4C" => "\xE9\xA4\xAB", + "\xEF\x4D" => "\xE9\xA4\xAC", + "\xEF\x4E" => "\xE9\xA4\xAA", + "\xEF\x4F" => "\xE9\xA4\xB3", + "\xEF\x50" => "\xE9\xA4\xB2", + "\xEF\x51" => "\xE9\xA4\xAF", + "\xEF\x52" => "\xE9\xA4\xAD", + "\xEF\x53" => "\xE9\xA4\xB1", + "\xEF\x54" => "\xE9\xA4\xB0", + "\xEF\x55" => "\xE9\xA6\x98", + "\xEF\x56" => "\xE9\xA6\xA3", + "\xEF\x57" => "\xE9\xA6\xA1", + "\xEF\x58" => "\xE9\xA8\x82", + "\xEF\x59" => "\xE9\xA7\xBA", + "\xEF\x5A" => "\xE9\xA7\xB4", + "\xEF\x5B" => "\xE9\xA7\xB7", + "\xEF\x5C" => "\xE9\xA7\xB9", + "\xEF\x5D" => "\xE9\xA7\xB8", + "\xEF\x5E" => "\xE9\xA7\xB6", + "\xEF\x5F" => "\xE9\xA7\xBB", + "\xEF\x60" => "\xE9\xA7\xBD", + "\xEF\x61" => "\xE9\xA7\xBE", + "\xEF\x62" => "\xE9\xA7\xBC", + "\xEF\x63" => "\xE9\xA8\x83", + "\xEF\x64" => "\xE9\xAA\xBE", + "\xEF\x65" => "\xE9\xAB\xBE", + "\xEF\x66" => "\xE9\xAB\xBD", + "\xEF\x67" => "\xE9\xAC\x81", + "\xEF\x68" => "\xE9\xAB\xBC", + "\xEF\x69" => "\xE9\xAD\x88", + "\xEF\x6A" => "\xE9\xAE\x9A", + "\xEF\x6B" => "\xE9\xAE\xA8", + "\xEF\x6C" => "\xE9\xAE\x9E", + "\xEF\x6D" => "\xE9\xAE\x9B", + "\xEF\x6E" => "\xE9\xAE\xA6", + "\xEF\x6F" => "\xE9\xAE\xA1", + "\xEF\x70" => "\xE9\xAE\xA5", + "\xEF\x71" => "\xE9\xAE\xA4", + "\xEF\x72" => "\xE9\xAE\x86", + "\xEF\x73" => "\xE9\xAE\xA2", + "\xEF\x74" => "\xE9\xAE\xA0", + "\xEF\x75" => "\xE9\xAE\xAF", + "\xEF\x76" => "\xE9\xB4\xB3", + "\xEF\x77" => "\xE9\xB5\x81", + "\xEF\x78" => "\xE9\xB5\xA7", + "\xEF\x79" => "\xE9\xB4\xB6", + "\xEF\x7A" => "\xE9\xB4\xAE", + "\xEF\x7B" => "\xE9\xB4\xAF", + "\xEF\x7C" => "\xE9\xB4\xB1", + "\xEF\x7D" => "\xE9\xB4\xB8", + "\xEF\x7E" => "\xE9\xB4\xB0", + "\xEF\xA1" => "\xE9\xB5\x85", + "\xEF\xA2" => "\xE9\xB5\x82", + "\xEF\xA3" => "\xE9\xB5\x83", + "\xEF\xA4" => "\xE9\xB4\xBE", + "\xEF\xA5" => "\xE9\xB4\xB7", + "\xEF\xA6" => "\xE9\xB5\x80", + "\xEF\xA7" => "\xE9\xB4\xBD", + "\xEF\xA8" => "\xE7\xBF\xB5", + "\xEF\xA9" => "\xE9\xB4\xAD", + "\xEF\xAA" => "\xE9\xBA\x8A", + "\xEF\xAB" => "\xE9\xBA\x89", + "\xEF\xAC" => "\xE9\xBA\x8D", + "\xEF\xAD" => "\xE9\xBA\xB0", + "\xEF\xAE" => "\xE9\xBB\x88", + "\xEF\xAF" => "\xE9\xBB\x9A", + "\xEF\xB0" => "\xE9\xBB\xBB", + "\xEF\xB1" => "\xE9\xBB\xBF", + "\xEF\xB2" => "\xE9\xBC\xA4", + "\xEF\xB3" => "\xE9\xBC\xA3", + "\xEF\xB4" => "\xE9\xBC\xA2", + "\xEF\xB5" => "\xE9\xBD\x94", + "\xEF\xB6" => "\xE9\xBE\xA0", + "\xEF\xB7" => "\xE5\x84\xB1", + "\xEF\xB8" => "\xE5\x84\xAD", + "\xEF\xB9" => "\xE5\x84\xAE", + "\xEF\xBA" => "\xE5\x9A\x98", + "\xEF\xBB" => "\xE5\x9A\x9C", + "\xEF\xBC" => "\xE5\x9A\x97", + "\xEF\xBD" => "\xE5\x9A\x9A", + "\xEF\xBE" => "\xE5\x9A\x9D", + "\xEF\xBF" => "\xE5\x9A\x99", + "\xEF\xC0" => "\xE5\xA5\xB0", + "\xEF\xC1" => "\xE5\xAC\xBC", + "\xEF\xC2" => "\xE5\xB1\xA9", + "\xEF\xC3" => "\xE5\xB1\xAA", + "\xEF\xC4" => "\xE5\xB7\x80", + "\xEF\xC5" => "\xE5\xB9\xAD", + "\xEF\xC6" => "\xE5\xB9\xAE", + "\xEF\xC7" => "\xE6\x87\x98", + "\xEF\xC8" => "\xE6\x87\x9F", + "\xEF\xC9" => "\xE6\x87\xAD", + "\xEF\xCA" => "\xE6\x87\xAE", + "\xEF\xCB" => "\xE6\x87\xB1", + "\xEF\xCC" => "\xE6\x87\xAA", + "\xEF\xCD" => "\xE6\x87\xB0", + "\xEF\xCE" => "\xE6\x87\xAB", + "\xEF\xCF" => "\xE6\x87\x96", + "\xEF\xD0" => "\xE6\x87\xA9", + "\xEF\xD1" => "\xE6\x93\xBF", + "\xEF\xD2" => "\xE6\x94\x84", + "\xEF\xD3" => "\xE6\x93\xBD", + "\xEF\xD4" => "\xE6\x93\xB8", + "\xEF\xD5" => "\xE6\x94\x81", + "\xEF\xD6" => "\xE6\x94\x83", + "\xEF\xD7" => "\xE6\x93\xBC", + "\xEF\xD8" => "\xE6\x96\x94", + "\xEF\xD9" => "\xE6\x97\x9B", + "\xEF\xDA" => "\xE6\x9B\x9A", + "\xEF\xDB" => "\xE6\x9B\x9B", + "\xEF\xDC" => "\xE6\x9B\x98", + "\xEF\xDD" => "\xE6\xAB\x85", + "\xEF\xDE" => "\xE6\xAA\xB9", + "\xEF\xDF" => "\xE6\xAA\xBD", + "\xEF\xE0" => "\xE6\xAB\xA1", + "\xEF\xE1" => "\xE6\xAB\x86", + "\xEF\xE2" => "\xE6\xAA\xBA", + "\xEF\xE3" => "\xE6\xAA\xB6", + "\xEF\xE4" => "\xE6\xAA\xB7", + "\xEF\xE5" => "\xE6\xAB\x87", + "\xEF\xE6" => "\xE6\xAA\xB4", + "\xEF\xE7" => "\xE6\xAA\xAD", + "\xEF\xE8" => "\xE6\xAD\x9E", + "\xEF\xE9" => "\xE6\xAF\x89", + "\xEF\xEA" => "\xE6\xB0\x8B", + "\xEF\xEB" => "\xE7\x80\x87", + "\xEF\xEC" => "\xE7\x80\x8C", + "\xEF\xED" => "\xE7\x80\x8D", + "\xEF\xEE" => "\xE7\x80\x81", + "\xEF\xEF" => "\xE7\x80\x85", + "\xEF\xF0" => "\xE7\x80\x94", + "\xEF\xF1" => "\xE7\x80\x8E", + "\xEF\xF2" => "\xE6\xBF\xBF", + "\xEF\xF3" => "\xE7\x80\x80", + "\xEF\xF4" => "\xE6\xBF\xBB", + "\xEF\xF5" => "\xE7\x80\xA6", + "\xEF\xF6" => "\xE6\xBF\xBC", + "\xEF\xF7" => "\xE6\xBF\xB7", + "\xEF\xF8" => "\xE7\x80\x8A", + "\xEF\xF9" => "\xE7\x88\x81", + "\xEF\xFA" => "\xE7\x87\xBF", + "\xEF\xFB" => "\xE7\x87\xB9", + "\xEF\xFC" => "\xE7\x88\x83", + "\xEF\xFD" => "\xE7\x87\xBD", + "\xEF\xFE" => "\xE7\x8D\xB6", + "\xF0\x40" => "\xE7\x92\xB8", + "\xF0\x41" => "\xE7\x93\x80", + "\xF0\x42" => "\xE7\x92\xB5", + "\xF0\x43" => "\xE7\x93\x81", + "\xF0\x44" => "\xE7\x92\xBE", + "\xF0\x45" => "\xE7\x92\xB6", + "\xF0\x46" => "\xE7\x92\xBB", + "\xF0\x47" => "\xE7\x93\x82", + "\xF0\x48" => "\xE7\x94\x94", + "\xF0\x49" => "\xE7\x94\x93", + "\xF0\x4A" => "\xE7\x99\x9C", + "\xF0\x4B" => "\xE7\x99\xA4", + "\xF0\x4C" => "\xE7\x99\x99", + "\xF0\x4D" => "\xE7\x99\x90", + "\xF0\x4E" => "\xE7\x99\x93", + "\xF0\x4F" => "\xE7\x99\x97", + "\xF0\x50" => "\xE7\x99\x9A", + "\xF0\x51" => "\xE7\x9A\xA6", + "\xF0\x52" => "\xE7\x9A\xBD", + "\xF0\x53" => "\xE7\x9B\xAC", + "\xF0\x54" => "\xE7\x9F\x82", + "\xF0\x55" => "\xE7\x9E\xBA", + "\xF0\x56" => "\xE7\xA3\xBF", + "\xF0\x57" => "\xE7\xA4\x8C", + "\xF0\x58" => "\xE7\xA4\x93", + "\xF0\x59" => "\xE7\xA4\x94", + "\xF0\x5A" => "\xE7\xA4\x89", + "\xF0\x5B" => "\xE7\xA4\x90", + "\xF0\x5C" => "\xE7\xA4\x92", + "\xF0\x5D" => "\xE7\xA4\x91", + "\xF0\x5E" => "\xE7\xA6\xAD", + "\xF0\x5F" => "\xE7\xA6\xAC", + "\xF0\x60" => "\xE7\xA9\x9F", + "\xF0\x61" => "\xE7\xB0\x9C", + "\xF0\x62" => "\xE7\xB0\xA9", + "\xF0\x63" => "\xE7\xB0\x99", + "\xF0\x64" => "\xE7\xB0\xA0", + "\xF0\x65" => "\xE7\xB0\x9F", + "\xF0\x66" => "\xE7\xB0\xAD", + "\xF0\x67" => "\xE7\xB0\x9D", + "\xF0\x68" => "\xE7\xB0\xA6", + "\xF0\x69" => "\xE7\xB0\xA8", + "\xF0\x6A" => "\xE7\xB0\xA2", + "\xF0\x6B" => "\xE7\xB0\xA5", + "\xF0\x6C" => "\xE7\xB0\xB0", + "\xF0\x6D" => "\xE7\xB9\x9C", + "\xF0\x6E" => "\xE7\xB9\x90", + "\xF0\x6F" => "\xE7\xB9\x96", + "\xF0\x70" => "\xE7\xB9\xA3", + "\xF0\x71" => "\xE7\xB9\x98", + "\xF0\x72" => "\xE7\xB9\xA2", + "\xF0\x73" => "\xE7\xB9\x9F", + "\xF0\x74" => "\xE7\xB9\x91", + "\xF0\x75" => "\xE7\xB9\xA0", + "\xF0\x76" => "\xE7\xB9\x97", + "\xF0\x77" => "\xE7\xB9\x93", + "\xF0\x78" => "\xE7\xBE\xB5", + "\xF0\x79" => "\xE7\xBE\xB3", + "\xF0\x7A" => "\xE7\xBF\xB7", + "\xF0\x7B" => "\xE7\xBF\xB8", + "\xF0\x7C" => "\xE8\x81\xB5", + "\xF0\x7D" => "\xE8\x87\x91", + "\xF0\x7E" => "\xE8\x87\x92", + "\xF0\xA1" => "\xE8\x87\x90", + "\xF0\xA2" => "\xE8\x89\x9F", + "\xF0\xA3" => "\xE8\x89\x9E", + "\xF0\xA4" => "\xE8\x96\xB4", + "\xF0\xA5" => "\xE8\x97\x86", + "\xF0\xA6" => "\xE8\x97\x80", + "\xF0\xA7" => "\xE8\x97\x83", + "\xF0\xA8" => "\xE8\x97\x82", + "\xF0\xA9" => "\xE8\x96\xB3", + "\xF0\xAA" => "\xE8\x96\xB5", + "\xF0\xAB" => "\xE8\x96\xBD", + "\xF0\xAC" => "\xE8\x97\x87", + "\xF0\xAD" => "\xE8\x97\x84", + "\xF0\xAE" => "\xE8\x96\xBF", + "\xF0\xAF" => "\xE8\x97\x8B", + "\xF0\xB0" => "\xE8\x97\x8E", + "\xF0\xB1" => "\xE8\x97\x88", + "\xF0\xB2" => "\xE8\x97\x85", + "\xF0\xB3" => "\xE8\x96\xB1", + "\xF0\xB4" => "\xE8\x96\xB6", + "\xF0\xB5" => "\xE8\x97\x92", + "\xF0\xB6" => "\xE8\x98\xA4", + "\xF0\xB7" => "\xE8\x96\xB8", + "\xF0\xB8" => "\xE8\x96\xB7", + "\xF0\xB9" => "\xE8\x96\xBE", + "\xF0\xBA" => "\xE8\x99\xA9", + "\xF0\xBB" => "\xE8\x9F\xA7", + "\xF0\xBC" => "\xE8\x9F\xA6", + "\xF0\xBD" => "\xE8\x9F\xA2", + "\xF0\xBE" => "\xE8\x9F\x9B", + "\xF0\xBF" => "\xE8\x9F\xAB", + "\xF0\xC0" => "\xE8\x9F\xAA", + "\xF0\xC1" => "\xE8\x9F\xA5", + "\xF0\xC2" => "\xE8\x9F\x9F", + "\xF0\xC3" => "\xE8\x9F\xB3", + "\xF0\xC4" => "\xE8\x9F\xA4", + "\xF0\xC5" => "\xE8\x9F\x94", + "\xF0\xC6" => "\xE8\x9F\x9C", + "\xF0\xC7" => "\xE8\x9F\x93", + "\xF0\xC8" => "\xE8\x9F\xAD", + "\xF0\xC9" => "\xE8\x9F\x98", + "\xF0\xCA" => "\xE8\x9F\xA3", + "\xF0\xCB" => "\xE8\x9E\xA4", + "\xF0\xCC" => "\xE8\x9F\x97", + "\xF0\xCD" => "\xE8\x9F\x99", + "\xF0\xCE" => "\xE8\xA0\x81", + "\xF0\xCF" => "\xE8\x9F\xB4", + "\xF0\xD0" => "\xE8\x9F\xA8", + "\xF0\xD1" => "\xE8\x9F\x9D", + "\xF0\xD2" => "\xE8\xA5\x93", + "\xF0\xD3" => "\xE8\xA5\x8B", + "\xF0\xD4" => "\xE8\xA5\x8F", + "\xF0\xD5" => "\xE8\xA5\x8C", + "\xF0\xD6" => "\xE8\xA5\x86", + "\xF0\xD7" => "\xE8\xA5\x90", + "\xF0\xD8" => "\xE8\xA5\x91", + "\xF0\xD9" => "\xE8\xA5\x89", + "\xF0\xDA" => "\xE8\xAC\xAA", + "\xF0\xDB" => "\xE8\xAC\xA7", + "\xF0\xDC" => "\xE8\xAC\xA3", + "\xF0\xDD" => "\xE8\xAC\xB3", + "\xF0\xDE" => "\xE8\xAC\xB0", + "\xF0\xDF" => "\xE8\xAC\xB5", + "\xF0\xE0" => "\xE8\xAD\x87", + "\xF0\xE1" => "\xE8\xAC\xAF", + "\xF0\xE2" => "\xE8\xAC\xBC", + "\xF0\xE3" => "\xE8\xAC\xBE", + "\xF0\xE4" => "\xE8\xAC\xB1", + "\xF0\xE5" => "\xE8\xAC\xA5", + "\xF0\xE6" => "\xE8\xAC\xB7", + "\xF0\xE7" => "\xE8\xAC\xA6", + "\xF0\xE8" => "\xE8\xAC\xB6", + "\xF0\xE9" => "\xE8\xAC\xAE", + "\xF0\xEA" => "\xE8\xAC\xA4", + "\xF0\xEB" => "\xE8\xAC\xBB", + "\xF0\xEC" => "\xE8\xAC\xBD", + "\xF0\xED" => "\xE8\xAC\xBA", + "\xF0\xEE" => "\xE8\xB1\x82", + "\xF0\xEF" => "\xE8\xB1\xB5", + "\xF0\xF0" => "\xE8\xB2\x99", + "\xF0\xF1" => "\xE8\xB2\x98", + "\xF0\xF2" => "\xE8\xB2\x97", + "\xF0\xF3" => "\xE8\xB3\xBE", + "\xF0\xF4" => "\xE8\xB4\x84", + "\xF0\xF5" => "\xE8\xB4\x82", + "\xF0\xF6" => "\xE8\xB4\x80", + "\xF0\xF7" => "\xE8\xB9\x9C", + "\xF0\xF8" => "\xE8\xB9\xA2", + "\xF0\xF9" => "\xE8\xB9\xA0", + "\xF0\xFA" => "\xE8\xB9\x97", + "\xF0\xFB" => "\xE8\xB9\x96", + "\xF0\xFC" => "\xE8\xB9\x9E", + "\xF0\xFD" => "\xE8\xB9\xA5", + "\xF0\xFE" => "\xE8\xB9\xA7", + "\xF1\x40" => "\xE8\xB9\x9B", + "\xF1\x41" => "\xE8\xB9\x9A", + "\xF1\x42" => "\xE8\xB9\xA1", + "\xF1\x43" => "\xE8\xB9\x9D", + "\xF1\x44" => "\xE8\xB9\xA9", + "\xF1\x45" => "\xE8\xB9\x94", + "\xF1\x46" => "\xE8\xBD\x86", + "\xF1\x47" => "\xE8\xBD\x87", + "\xF1\x48" => "\xE8\xBD\x88", + "\xF1\x49" => "\xE8\xBD\x8B", + "\xF1\x4A" => "\xE9\x84\xA8", + "\xF1\x4B" => "\xE9\x84\xBA", + "\xF1\x4C" => "\xE9\x84\xBB", + "\xF1\x4D" => "\xE9\x84\xBE", + "\xF1\x4E" => "\xE9\x86\xA8", + "\xF1\x4F" => "\xE9\x86\xA5", + "\xF1\x50" => "\xE9\x86\xA7", + "\xF1\x51" => "\xE9\x86\xAF", + "\xF1\x52" => "\xE9\x86\xAA", + "\xF1\x53" => "\xE9\x8E\xB5", + "\xF1\x54" => "\xE9\x8E\x8C", + "\xF1\x55" => "\xE9\x8E\x92", + "\xF1\x56" => "\xE9\x8E\xB7", + "\xF1\x57" => "\xE9\x8E\x9B", + "\xF1\x58" => "\xE9\x8E\x9D", + "\xF1\x59" => "\xE9\x8E\x89", + "\xF1\x5A" => "\xE9\x8E\xA7", + "\xF1\x5B" => "\xE9\x8E\x8E", + "\xF1\x5C" => "\xE9\x8E\xAA", + "\xF1\x5D" => "\xE9\x8E\x9E", + "\xF1\x5E" => "\xE9\x8E\xA6", + "\xF1\x5F" => "\xE9\x8E\x95", + "\xF1\x60" => "\xE9\x8E\x88", + "\xF1\x61" => "\xE9\x8E\x99", + "\xF1\x62" => "\xE9\x8E\x9F", + "\xF1\x63" => "\xE9\x8E\x8D", + "\xF1\x64" => "\xE9\x8E\xB1", + "\xF1\x65" => "\xE9\x8E\x91", + "\xF1\x66" => "\xE9\x8E\xB2", + "\xF1\x67" => "\xE9\x8E\xA4", + "\xF1\x68" => "\xE9\x8E\xA8", + "\xF1\x69" => "\xE9\x8E\xB4", + "\xF1\x6A" => "\xE9\x8E\xA3", + "\xF1\x6B" => "\xE9\x8E\xA5", + "\xF1\x6C" => "\xE9\x97\x92", + "\xF1\x6D" => "\xE9\x97\x93", + "\xF1\x6E" => "\xE9\x97\x91", + "\xF1\x6F" => "\xE9\x9A\xB3", + "\xF1\x70" => "\xE9\x9B\x97", + "\xF1\x71" => "\xE9\x9B\x9A", + "\xF1\x72" => "\xE5\xB7\x82", + "\xF1\x73" => "\xE9\x9B\x9F", + "\xF1\x74" => "\xE9\x9B\x98", + "\xF1\x75" => "\xE9\x9B\x9D", + "\xF1\x76" => "\xE9\x9C\xA3", + "\xF1\x77" => "\xE9\x9C\xA2", + "\xF1\x78" => "\xE9\x9C\xA5", + "\xF1\x79" => "\xE9\x9E\xAC", + "\xF1\x7A" => "\xE9\x9E\xAE", + "\xF1\x7B" => "\xE9\x9E\xA8", + "\xF1\x7C" => "\xE9\x9E\xAB", + "\xF1\x7D" => "\xE9\x9E\xA4", + "\xF1\x7E" => "\xE9\x9E\xAA", + "\xF1\xA1" => "\xE9\x9E\xA2", + "\xF1\xA2" => "\xE9\x9E\xA5", + "\xF1\xA3" => "\xE9\x9F\x97", + "\xF1\xA4" => "\xE9\x9F\x99", + "\xF1\xA5" => "\xE9\x9F\x96", + "\xF1\xA6" => "\xE9\x9F\x98", + "\xF1\xA7" => "\xE9\x9F\xBA", + "\xF1\xA8" => "\xE9\xA1\x90", + "\xF1\xA9" => "\xE9\xA1\x91", + "\xF1\xAA" => "\xE9\xA1\x92", + "\xF1\xAB" => "\xE9\xA2\xB8", + "\xF1\xAC" => "\xE9\xA5\x81", + "\xF1\xAD" => "\xE9\xA4\xBC", + "\xF1\xAE" => "\xE9\xA4\xBA", + "\xF1\xAF" => "\xE9\xA8\x8F", + "\xF1\xB0" => "\xE9\xA8\x8B", + "\xF1\xB1" => "\xE9\xA8\x89", + "\xF1\xB2" => "\xE9\xA8\x8D", + "\xF1\xB3" => "\xE9\xA8\x84", + "\xF1\xB4" => "\xE9\xA8\x91", + "\xF1\xB5" => "\xE9\xA8\x8A", + "\xF1\xB6" => "\xE9\xA8\x85", + "\xF1\xB7" => "\xE9\xA8\x87", + "\xF1\xB8" => "\xE9\xA8\x86", + "\xF1\xB9" => "\xE9\xAB\x80", + "\xF1\xBA" => "\xE9\xAB\x9C", + "\xF1\xBB" => "\xE9\xAC\x88", + "\xF1\xBC" => "\xE9\xAC\x84", + "\xF1\xBD" => "\xE9\xAC\x85", + "\xF1\xBE" => "\xE9\xAC\xA9", + "\xF1\xBF" => "\xE9\xAC\xB5", + "\xF1\xC0" => "\xE9\xAD\x8A", + "\xF1\xC1" => "\xE9\xAD\x8C", + "\xF1\xC2" => "\xE9\xAD\x8B", + "\xF1\xC3" => "\xE9\xAF\x87", + "\xF1\xC4" => "\xE9\xAF\x86", + "\xF1\xC5" => "\xE9\xAF\x83", + "\xF1\xC6" => "\xE9\xAE\xBF", + "\xF1\xC7" => "\xE9\xAF\x81", + "\xF1\xC8" => "\xE9\xAE\xB5", + "\xF1\xC9" => "\xE9\xAE\xB8", + "\xF1\xCA" => "\xE9\xAF\x93", + "\xF1\xCB" => "\xE9\xAE\xB6", + "\xF1\xCC" => "\xE9\xAF\x84", + "\xF1\xCD" => "\xE9\xAE\xB9", + "\xF1\xCE" => "\xE9\xAE\xBD", + "\xF1\xCF" => "\xE9\xB5\x9C", + "\xF1\xD0" => "\xE9\xB5\x93", + "\xF1\xD1" => "\xE9\xB5\x8F", + "\xF1\xD2" => "\xE9\xB5\x8A", + "\xF1\xD3" => "\xE9\xB5\x9B", + "\xF1\xD4" => "\xE9\xB5\x8B", + "\xF1\xD5" => "\xE9\xB5\x99", + "\xF1\xD6" => "\xE9\xB5\x96", + "\xF1\xD7" => "\xE9\xB5\x8C", + "\xF1\xD8" => "\xE9\xB5\x97", + "\xF1\xD9" => "\xE9\xB5\x92", + "\xF1\xDA" => "\xE9\xB5\x94", + "\xF1\xDB" => "\xE9\xB5\x9F", + "\xF1\xDC" => "\xE9\xB5\x98", + "\xF1\xDD" => "\xE9\xB5\x9A", + "\xF1\xDE" => "\xE9\xBA\x8E", + "\xF1\xDF" => "\xE9\xBA\x8C", + "\xF1\xE0" => "\xE9\xBB\x9F", + "\xF1\xE1" => "\xE9\xBC\x81", + "\xF1\xE2" => "\xE9\xBC\x80", + "\xF1\xE3" => "\xE9\xBC\x96", + "\xF1\xE4" => "\xE9\xBC\xA5", + "\xF1\xE5" => "\xE9\xBC\xAB", + "\xF1\xE6" => "\xE9\xBC\xAA", + "\xF1\xE7" => "\xE9\xBC\xA9", + "\xF1\xE8" => "\xE9\xBC\xA8", + "\xF1\xE9" => "\xE9\xBD\x8C", + "\xF1\xEA" => "\xE9\xBD\x95", + "\xF1\xEB" => "\xE5\x84\xB4", + "\xF1\xEC" => "\xE5\x84\xB5", + "\xF1\xED" => "\xE5\x8A\x96", + "\xF1\xEE" => "\xE5\x8B\xB7", + "\xF1\xEF" => "\xE5\x8E\xB4", + "\xF1\xF0" => "\xE5\x9A\xAB", + "\xF1\xF1" => "\xE5\x9A\xAD", + "\xF1\xF2" => "\xE5\x9A\xA6", + "\xF1\xF3" => "\xE5\x9A\xA7", + "\xF1\xF4" => "\xE5\x9A\xAA", + "\xF1\xF5" => "\xE5\x9A\xAC", + "\xF1\xF6" => "\xE5\xA3\x9A", + "\xF1\xF7" => "\xE5\xA3\x9D", + "\xF1\xF8" => "\xE5\xA3\x9B", + "\xF1\xF9" => "\xE5\xA4\x92", + "\xF1\xFA" => "\xE5\xAC\xBD", + "\xF1\xFB" => "\xE5\xAC\xBE", + "\xF1\xFC" => "\xE5\xAC\xBF", + "\xF1\xFD" => "\xE5\xB7\x83", + "\xF1\xFE" => "\xE5\xB9\xB0", + "\xF2\x40" => "\xE5\xBE\xBF", + "\xF2\x41" => "\xE6\x87\xBB", + "\xF2\x42" => "\xE6\x94\x87", + "\xF2\x43" => "\xE6\x94\x90", + "\xF2\x44" => "\xE6\x94\x8D", + "\xF2\x45" => "\xE6\x94\x89", + "\xF2\x46" => "\xE6\x94\x8C", + "\xF2\x47" => "\xE6\x94\x8E", + "\xF2\x48" => "\xE6\x96\x84", + "\xF2\x49" => "\xE6\x97\x9E", + "\xF2\x4A" => "\xE6\x97\x9D", + "\xF2\x4B" => "\xE6\x9B\x9E", + "\xF2\x4C" => "\xE6\xAB\xA7", + "\xF2\x4D" => "\xE6\xAB\xA0", + "\xF2\x4E" => "\xE6\xAB\x8C", + "\xF2\x4F" => "\xE6\xAB\x91", + "\xF2\x50" => "\xE6\xAB\x99", + "\xF2\x51" => "\xE6\xAB\x8B", + "\xF2\x52" => "\xE6\xAB\x9F", + "\xF2\x53" => "\xE6\xAB\x9C", + "\xF2\x54" => "\xE6\xAB\x90", + "\xF2\x55" => "\xE6\xAB\xAB", + "\xF2\x56" => "\xE6\xAB\x8F", + "\xF2\x57" => "\xE6\xAB\x8D", + "\xF2\x58" => "\xE6\xAB\x9E", + "\xF2\x59" => "\xE6\xAD\xA0", + "\xF2\x5A" => "\xE6\xAE\xB0", + "\xF2\x5B" => "\xE6\xB0\x8C", + "\xF2\x5C" => "\xE7\x80\x99", + "\xF2\x5D" => "\xE7\x80\xA7", + "\xF2\x5E" => "\xE7\x80\xA0", + "\xF2\x5F" => "\xE7\x80\x96", + "\xF2\x60" => "\xE7\x80\xAB", + "\xF2\x61" => "\xE7\x80\xA1", + "\xF2\x62" => "\xE7\x80\xA2", + "\xF2\x63" => "\xE7\x80\xA3", + "\xF2\x64" => "\xE7\x80\xA9", + "\xF2\x65" => "\xE7\x80\x97", + "\xF2\x66" => "\xE7\x80\xA4", + "\xF2\x67" => "\xE7\x80\x9C", + "\xF2\x68" => "\xE7\x80\xAA", + "\xF2\x69" => "\xE7\x88\x8C", + "\xF2\x6A" => "\xE7\x88\x8A", + "\xF2\x6B" => "\xE7\x88\x87", + "\xF2\x6C" => "\xE7\x88\x82", + "\xF2\x6D" => "\xE7\x88\x85", + "\xF2\x6E" => "\xE7\x8A\xA5", + "\xF2\x6F" => "\xE7\x8A\xA6", + "\xF2\x70" => "\xE7\x8A\xA4", + "\xF2\x71" => "\xE7\x8A\xA3", + "\xF2\x72" => "\xE7\x8A\xA1", + "\xF2\x73" => "\xE7\x93\x8B", + "\xF2\x74" => "\xE7\x93\x85", + "\xF2\x75" => "\xE7\x92\xB7", + "\xF2\x76" => "\xE7\x93\x83", + "\xF2\x77" => "\xE7\x94\x96", + "\xF2\x78" => "\xE7\x99\xA0", + "\xF2\x79" => "\xE7\x9F\x89", + "\xF2\x7A" => "\xE7\x9F\x8A", + "\xF2\x7B" => "\xE7\x9F\x84", + "\xF2\x7C" => "\xE7\x9F\xB1", + "\xF2\x7D" => "\xE7\xA4\x9D", + "\xF2\x7E" => "\xE7\xA4\x9B", + "\xF2\xA1" => "\xE7\xA4\xA1", + "\xF2\xA2" => "\xE7\xA4\x9C", + "\xF2\xA3" => "\xE7\xA4\x97", + "\xF2\xA4" => "\xE7\xA4\x9E", + "\xF2\xA5" => "\xE7\xA6\xB0", + "\xF2\xA6" => "\xE7\xA9\xA7", + "\xF2\xA7" => "\xE7\xA9\xA8", + "\xF2\xA8" => "\xE7\xB0\xB3", + "\xF2\xA9" => "\xE7\xB0\xBC", + "\xF2\xAA" => "\xE7\xB0\xB9", + "\xF2\xAB" => "\xE7\xB0\xAC", + "\xF2\xAC" => "\xE7\xB0\xBB", + "\xF2\xAD" => "\xE7\xB3\xAC", + "\xF2\xAE" => "\xE7\xB3\xAA", + "\xF2\xAF" => "\xE7\xB9\xB6", + "\xF2\xB0" => "\xE7\xB9\xB5", + "\xF2\xB1" => "\xE7\xB9\xB8", + "\xF2\xB2" => "\xE7\xB9\xB0", + "\xF2\xB3" => "\xE7\xB9\xB7", + "\xF2\xB4" => "\xE7\xB9\xAF", + "\xF2\xB5" => "\xE7\xB9\xBA", + "\xF2\xB6" => "\xE7\xB9\xB2", + "\xF2\xB7" => "\xE7\xB9\xB4", + "\xF2\xB8" => "\xE7\xB9\xA8", + "\xF2\xB9" => "\xE7\xBD\x8B", + "\xF2\xBA" => "\xE7\xBD\x8A", + "\xF2\xBB" => "\xE7\xBE\x83", + "\xF2\xBC" => "\xE7\xBE\x86", + "\xF2\xBD" => "\xE7\xBE\xB7", + "\xF2\xBE" => "\xE7\xBF\xBD", + "\xF2\xBF" => "\xE7\xBF\xBE", + "\xF2\xC0" => "\xE8\x81\xB8", + "\xF2\xC1" => "\xE8\x87\x97", + "\xF2\xC2" => "\xE8\x87\x95", + "\xF2\xC3" => "\xE8\x89\xA4", + "\xF2\xC4" => "\xE8\x89\xA1", + "\xF2\xC5" => "\xE8\x89\xA3", + "\xF2\xC6" => "\xE8\x97\xAB", + "\xF2\xC7" => "\xE8\x97\xB1", + "\xF2\xC8" => "\xE8\x97\xAD", + "\xF2\xC9" => "\xE8\x97\x99", + "\xF2\xCA" => "\xE8\x97\xA1", + "\xF2\xCB" => "\xE8\x97\xA8", + "\xF2\xCC" => "\xE8\x97\x9A", + "\xF2\xCD" => "\xE8\x97\x97", + "\xF2\xCE" => "\xE8\x97\xAC", + "\xF2\xCF" => "\xE8\x97\xB2", + "\xF2\xD0" => "\xE8\x97\xB8", + "\xF2\xD1" => "\xE8\x97\x98", + "\xF2\xD2" => "\xE8\x97\x9F", + "\xF2\xD3" => "\xE8\x97\xA3", + "\xF2\xD4" => "\xE8\x97\x9C", + "\xF2\xD5" => "\xE8\x97\x91", + "\xF2\xD6" => "\xE8\x97\xB0", + "\xF2\xD7" => "\xE8\x97\xA6", + "\xF2\xD8" => "\xE8\x97\xAF", + "\xF2\xD9" => "\xE8\x97\x9E", + "\xF2\xDA" => "\xE8\x97\xA2", + "\xF2\xDB" => "\xE8\xA0\x80", + "\xF2\xDC" => "\xE8\x9F\xBA", + "\xF2\xDD" => "\xE8\xA0\x83", + "\xF2\xDE" => "\xE8\x9F\xB6", + "\xF2\xDF" => "\xE8\x9F\xB7", + "\xF2\xE0" => "\xE8\xA0\x89", + "\xF2\xE1" => "\xE8\xA0\x8C", + "\xF2\xE2" => "\xE8\xA0\x8B", + "\xF2\xE3" => "\xE8\xA0\x86", + "\xF2\xE4" => "\xE8\x9F\xBC", + "\xF2\xE5" => "\xE8\xA0\x88", + "\xF2\xE6" => "\xE8\x9F\xBF", + "\xF2\xE7" => "\xE8\xA0\x8A", + "\xF2\xE8" => "\xE8\xA0\x82", + "\xF2\xE9" => "\xE8\xA5\xA2", + "\xF2\xEA" => "\xE8\xA5\x9A", + "\xF2\xEB" => "\xE8\xA5\x9B", + "\xF2\xEC" => "\xE8\xA5\x97", + "\xF2\xED" => "\xE8\xA5\xA1", + "\xF2\xEE" => "\xE8\xA5\x9C", + "\xF2\xEF" => "\xE8\xA5\x98", + "\xF2\xF0" => "\xE8\xA5\x9D", + "\xF2\xF1" => "\xE8\xA5\x99", + "\xF2\xF2" => "\xE8\xA6\x88", + "\xF2\xF3" => "\xE8\xA6\xB7", + "\xF2\xF4" => "\xE8\xA6\xB6", + "\xF2\xF5" => "\xE8\xA7\xB6", + "\xF2\xF6" => "\xE8\xAD\x90", + "\xF2\xF7" => "\xE8\xAD\x88", + "\xF2\xF8" => "\xE8\xAD\x8A", + "\xF2\xF9" => "\xE8\xAD\x80", + "\xF2\xFA" => "\xE8\xAD\x93", + "\xF2\xFB" => "\xE8\xAD\x96", + "\xF2\xFC" => "\xE8\xAD\x94", + "\xF2\xFD" => "\xE8\xAD\x8B", + "\xF2\xFE" => "\xE8\xAD\x95", + "\xF3\x40" => "\xE8\xAD\x91", + "\xF3\x41" => "\xE8\xAD\x82", + "\xF3\x42" => "\xE8\xAD\x92", + "\xF3\x43" => "\xE8\xAD\x97", + "\xF3\x44" => "\xE8\xB1\x83", + "\xF3\x45" => "\xE8\xB1\xB7", + "\xF3\x46" => "\xE8\xB1\xB6", + "\xF3\x47" => "\xE8\xB2\x9A", + "\xF3\x48" => "\xE8\xB4\x86", + "\xF3\x49" => "\xE8\xB4\x87", + "\xF3\x4A" => "\xE8\xB4\x89", + "\xF3\x4B" => "\xE8\xB6\xAC", + "\xF3\x4C" => "\xE8\xB6\xAA", + "\xF3\x4D" => "\xE8\xB6\xAD", + "\xF3\x4E" => "\xE8\xB6\xAB", + "\xF3\x4F" => "\xE8\xB9\xAD", + "\xF3\x50" => "\xE8\xB9\xB8", + "\xF3\x51" => "\xE8\xB9\xB3", + "\xF3\x52" => "\xE8\xB9\xAA", + "\xF3\x53" => "\xE8\xB9\xAF", + "\xF3\x54" => "\xE8\xB9\xBB", + "\xF3\x55" => "\xE8\xBB\x82", + "\xF3\x56" => "\xE8\xBD\x92", + "\xF3\x57" => "\xE8\xBD\x91", + "\xF3\x58" => "\xE8\xBD\x8F", + "\xF3\x59" => "\xE8\xBD\x90", + "\xF3\x5A" => "\xE8\xBD\x93", + "\xF3\x5B" => "\xE8\xBE\xB4", + "\xF3\x5C" => "\xE9\x85\x80", + "\xF3\x5D" => "\xE9\x84\xBF", + "\xF3\x5E" => "\xE9\x86\xB0", + "\xF3\x5F" => "\xE9\x86\xAD", + "\xF3\x60" => "\xE9\x8F\x9E", + "\xF3\x61" => "\xE9\x8F\x87", + "\xF3\x62" => "\xE9\x8F\x8F", + "\xF3\x63" => "\xE9\x8F\x82", + "\xF3\x64" => "\xE9\x8F\x9A", + "\xF3\x65" => "\xE9\x8F\x90", + "\xF3\x66" => "\xE9\x8F\xB9", + "\xF3\x67" => "\xE9\x8F\xAC", + "\xF3\x68" => "\xE9\x8F\x8C", + "\xF3\x69" => "\xE9\x8F\x99", + "\xF3\x6A" => "\xE9\x8E\xA9", + "\xF3\x6B" => "\xE9\x8F\xA6", + "\xF3\x6C" => "\xE9\x8F\x8A", + "\xF3\x6D" => "\xE9\x8F\x94", + "\xF3\x6E" => "\xE9\x8F\xAE", + "\xF3\x6F" => "\xE9\x8F\xA3", + "\xF3\x70" => "\xE9\x8F\x95", + "\xF3\x71" => "\xE9\x8F\x84", + "\xF3\x72" => "\xE9\x8F\x8E", + "\xF3\x73" => "\xE9\x8F\x80", + "\xF3\x74" => "\xE9\x8F\x92", + "\xF3\x75" => "\xE9\x8F\xA7", + "\xF3\x76" => "\xE9\x95\xBD", + "\xF3\x77" => "\xE9\x97\x9A", + "\xF3\x78" => "\xE9\x97\x9B", + "\xF3\x79" => "\xE9\x9B\xA1", + "\xF3\x7A" => "\xE9\x9C\xA9", + "\xF3\x7B" => "\xE9\x9C\xAB", + "\xF3\x7C" => "\xE9\x9C\xAC", + "\xF3\x7D" => "\xE9\x9C\xA8", + "\xF3\x7E" => "\xE9\x9C\xA6", + "\xF3\xA1" => "\xE9\x9E\xB3", + "\xF3\xA2" => "\xE9\x9E\xB7", + "\xF3\xA3" => "\xE9\x9E\xB6", + "\xF3\xA4" => "\xE9\x9F\x9D", + "\xF3\xA5" => "\xE9\x9F\x9E", + "\xF3\xA6" => "\xE9\x9F\x9F", + "\xF3\xA7" => "\xE9\xA1\x9C", + "\xF3\xA8" => "\xE9\xA1\x99", + "\xF3\xA9" => "\xE9\xA1\x9D", + "\xF3\xAA" => "\xE9\xA1\x97", + "\xF3\xAB" => "\xE9\xA2\xBF", + "\xF3\xAC" => "\xE9\xA2\xBD", + "\xF3\xAD" => "\xE9\xA2\xBB", + "\xF3\xAE" => "\xE9\xA2\xBE", + "\xF3\xAF" => "\xE9\xA5\x88", + "\xF3\xB0" => "\xE9\xA5\x87", + "\xF3\xB1" => "\xE9\xA5\x83", + "\xF3\xB2" => "\xE9\xA6\xA6", + "\xF3\xB3" => "\xE9\xA6\xA7", + "\xF3\xB4" => "\xE9\xA8\x9A", + "\xF3\xB5" => "\xE9\xA8\x95", + "\xF3\xB6" => "\xE9\xA8\xA5", + "\xF3\xB7" => "\xE9\xA8\x9D", + "\xF3\xB8" => "\xE9\xA8\xA4", + "\xF3\xB9" => "\xE9\xA8\x9B", + "\xF3\xBA" => "\xE9\xA8\xA2", + "\xF3\xBB" => "\xE9\xA8\xA0", + "\xF3\xBC" => "\xE9\xA8\xA7", + "\xF3\xBD" => "\xE9\xA8\xA3", + "\xF3\xBE" => "\xE9\xA8\x9E", + "\xF3\xBF" => "\xE9\xA8\x9C", + "\xF3\xC0" => "\xE9\xA8\x94", + "\xF3\xC1" => "\xE9\xAB\x82", + "\xF3\xC2" => "\xE9\xAC\x8B", + "\xF3\xC3" => "\xE9\xAC\x8A", + "\xF3\xC4" => "\xE9\xAC\x8E", + "\xF3\xC5" => "\xE9\xAC\x8C", + "\xF3\xC6" => "\xE9\xAC\xB7", + "\xF3\xC7" => "\xE9\xAF\xAA", + "\xF3\xC8" => "\xE9\xAF\xAB", + "\xF3\xC9" => "\xE9\xAF\xA0", + "\xF3\xCA" => "\xE9\xAF\x9E", + "\xF3\xCB" => "\xE9\xAF\xA4", + "\xF3\xCC" => "\xE9\xAF\xA6", + "\xF3\xCD" => "\xE9\xAF\xA2", + "\xF3\xCE" => "\xE9\xAF\xB0", + "\xF3\xCF" => "\xE9\xAF\x94", + "\xF3\xD0" => "\xE9\xAF\x97", + "\xF3\xD1" => "\xE9\xAF\xAC", + "\xF3\xD2" => "\xE9\xAF\x9C", + "\xF3\xD3" => "\xE9\xAF\x99", + "\xF3\xD4" => "\xE9\xAF\xA5", + "\xF3\xD5" => "\xE9\xAF\x95", + "\xF3\xD6" => "\xE9\xAF\xA1", + "\xF3\xD7" => "\xE9\xAF\x9A", + "\xF3\xD8" => "\xE9\xB5\xB7", + "\xF3\xD9" => "\xE9\xB6\x81", + "\xF3\xDA" => "\xE9\xB6\x8A", + "\xF3\xDB" => "\xE9\xB6\x84", + "\xF3\xDC" => "\xE9\xB6\x88", + "\xF3\xDD" => "\xE9\xB5\xB1", + "\xF3\xDE" => "\xE9\xB6\x80", + "\xF3\xDF" => "\xE9\xB5\xB8", + "\xF3\xE0" => "\xE9\xB6\x86", + "\xF3\xE1" => "\xE9\xB6\x8B", + "\xF3\xE2" => "\xE9\xB6\x8C", + "\xF3\xE3" => "\xE9\xB5\xBD", + "\xF3\xE4" => "\xE9\xB5\xAB", + "\xF3\xE5" => "\xE9\xB5\xB4", + "\xF3\xE6" => "\xE9\xB5\xB5", + "\xF3\xE7" => "\xE9\xB5\xB0", + "\xF3\xE8" => "\xE9\xB5\xA9", + "\xF3\xE9" => "\xE9\xB6\x85", + "\xF3\xEA" => "\xE9\xB5\xB3", + "\xF3\xEB" => "\xE9\xB5\xBB", + "\xF3\xEC" => "\xE9\xB6\x82", + "\xF3\xED" => "\xE9\xB5\xAF", + "\xF3\xEE" => "\xE9\xB5\xB9", + "\xF3\xEF" => "\xE9\xB5\xBF", + "\xF3\xF0" => "\xE9\xB6\x87", + "\xF3\xF1" => "\xE9\xB5\xA8", + "\xF3\xF2" => "\xE9\xBA\x94", + "\xF3\xF3" => "\xE9\xBA\x91", + "\xF3\xF4" => "\xE9\xBB\x80", + "\xF3\xF5" => "\xE9\xBB\xBC", + "\xF3\xF6" => "\xE9\xBC\xAD", + "\xF3\xF7" => "\xE9\xBD\x80", + "\xF3\xF8" => "\xE9\xBD\x81", + "\xF3\xF9" => "\xE9\xBD\x8D", + "\xF3\xFA" => "\xE9\xBD\x96", + "\xF3\xFB" => "\xE9\xBD\x97", + "\xF3\xFC" => "\xE9\xBD\x98", + "\xF3\xFD" => "\xE5\x8C\xB7", + "\xF3\xFE" => "\xE5\x9A\xB2", + "\xF4\x40" => "\xE5\x9A\xB5", + "\xF4\x41" => "\xE5\x9A\xB3", + "\xF4\x42" => "\xE5\xA3\xA3", + "\xF4\x43" => "\xE5\xAD\x85", + "\xF4\x44" => "\xE5\xB7\x86", + "\xF4\x45" => "\xE5\xB7\x87", + "\xF4\x46" => "\xE5\xBB\xAE", + "\xF4\x47" => "\xE5\xBB\xAF", + "\xF4\x48" => "\xE5\xBF\x80", + "\xF4\x49" => "\xE5\xBF\x81", + "\xF4\x4A" => "\xE6\x87\xB9", + "\xF4\x4B" => "\xE6\x94\x97", + "\xF4\x4C" => "\xE6\x94\x96", + "\xF4\x4D" => "\xE6\x94\x95", + "\xF4\x4E" => "\xE6\x94\x93", + "\xF4\x4F" => "\xE6\x97\x9F", + "\xF4\x50" => "\xE6\x9B\xA8", + "\xF4\x51" => "\xE6\x9B\xA3", + "\xF4\x52" => "\xE6\x9B\xA4", + "\xF4\x53" => "\xE6\xAB\xB3", + "\xF4\x54" => "\xE6\xAB\xB0", + "\xF4\x55" => "\xE6\xAB\xAA", + "\xF4\x56" => "\xE6\xAB\xA8", + "\xF4\x57" => "\xE6\xAB\xB9", + "\xF4\x58" => "\xE6\xAB\xB1", + "\xF4\x59" => "\xE6\xAB\xAE", + "\xF4\x5A" => "\xE6\xAB\xAF", + "\xF4\x5B" => "\xE7\x80\xBC", + "\xF4\x5C" => "\xE7\x80\xB5", + "\xF4\x5D" => "\xE7\x80\xAF", + "\xF4\x5E" => "\xE7\x80\xB7", + "\xF4\x5F" => "\xE7\x80\xB4", + "\xF4\x60" => "\xE7\x80\xB1", + "\xF4\x61" => "\xE7\x81\x82", + "\xF4\x62" => "\xE7\x80\xB8", + "\xF4\x63" => "\xE7\x80\xBF", + "\xF4\x64" => "\xE7\x80\xBA", + "\xF4\x65" => "\xE7\x80\xB9", + "\xF4\x66" => "\xE7\x81\x80", + "\xF4\x67" => "\xE7\x80\xBB", + "\xF4\x68" => "\xE7\x80\xB3", + "\xF4\x69" => "\xE7\x81\x81", + "\xF4\x6A" => "\xE7\x88\x93", + "\xF4\x6B" => "\xE7\x88\x94", + "\xF4\x6C" => "\xE7\x8A\xA8", + "\xF4\x6D" => "\xE7\x8D\xBD", + "\xF4\x6E" => "\xE7\x8D\xBC", + "\xF4\x6F" => "\xE7\x92\xBA", + "\xF4\x70" => "\xE7\x9A\xAB", + "\xF4\x71" => "\xE7\x9A\xAA", + "\xF4\x72" => "\xE7\x9A\xBE", + "\xF4\x73" => "\xE7\x9B\xAD", + "\xF4\x74" => "\xE7\x9F\x8C", + "\xF4\x75" => "\xE7\x9F\x8E", + "\xF4\x76" => "\xE7\x9F\x8F", + "\xF4\x77" => "\xE7\x9F\x8D", + "\xF4\x78" => "\xE7\x9F\xB2", + "\xF4\x79" => "\xE7\xA4\xA5", + "\xF4\x7A" => "\xE7\xA4\xA3", + "\xF4\x7B" => "\xE7\xA4\xA7", + "\xF4\x7C" => "\xE7\xA4\xA8", + "\xF4\x7D" => "\xE7\xA4\xA4", + "\xF4\x7E" => "\xE7\xA4\xA9", + "\xF4\xA1" => "\xE7\xA6\xB2", + "\xF4\xA2" => "\xE7\xA9\xAE", + "\xF4\xA3" => "\xE7\xA9\xAC", + "\xF4\xA4" => "\xE7\xA9\xAD", + "\xF4\xA5" => "\xE7\xAB\xB7", + "\xF4\xA6" => "\xE7\xB1\x89", + "\xF4\xA7" => "\xE7\xB1\x88", + "\xF4\xA8" => "\xE7\xB1\x8A", + "\xF4\xA9" => "\xE7\xB1\x87", + "\xF4\xAA" => "\xE7\xB1\x85", + "\xF4\xAB" => "\xE7\xB3\xAE", + "\xF4\xAC" => "\xE7\xB9\xBB", + "\xF4\xAD" => "\xE7\xB9\xBE", + "\xF4\xAE" => "\xE7\xBA\x81", + "\xF4\xAF" => "\xE7\xBA\x80", + "\xF4\xB0" => "\xE7\xBE\xBA", + "\xF4\xB1" => "\xE7\xBF\xBF", + "\xF4\xB2" => "\xE8\x81\xB9", + "\xF4\xB3" => "\xE8\x87\x9B", + "\xF4\xB4" => "\xE8\x87\x99", + "\xF4\xB5" => "\xE8\x88\x8B", + "\xF4\xB6" => "\xE8\x89\xA8", + "\xF4\xB7" => "\xE8\x89\xA9", + "\xF4\xB8" => "\xE8\x98\xA2", + "\xF4\xB9" => "\xE8\x97\xBF", + "\xF4\xBA" => "\xE8\x98\x81", + "\xF4\xBB" => "\xE8\x97\xBE", + "\xF4\xBC" => "\xE8\x98\x9B", + "\xF4\xBD" => "\xE8\x98\x80", + "\xF4\xBE" => "\xE8\x97\xB6", + "\xF4\xBF" => "\xE8\x98\x84", + "\xF4\xC0" => "\xE8\x98\x89", + "\xF4\xC1" => "\xE8\x98\x85", + "\xF4\xC2" => "\xE8\x98\x8C", + "\xF4\xC3" => "\xE8\x97\xBD", + "\xF4\xC4" => "\xE8\xA0\x99", + "\xF4\xC5" => "\xE8\xA0\x90", + "\xF4\xC6" => "\xE8\xA0\x91", + "\xF4\xC7" => "\xE8\xA0\x97", + "\xF4\xC8" => "\xE8\xA0\x93", + "\xF4\xC9" => "\xE8\xA0\x96", + "\xF4\xCA" => "\xE8\xA5\xA3", + "\xF4\xCB" => "\xE8\xA5\xA6", + "\xF4\xCC" => "\xE8\xA6\xB9", + "\xF4\xCD" => "\xE8\xA7\xB7", + "\xF4\xCE" => "\xE8\xAD\xA0", + "\xF4\xCF" => "\xE8\xAD\xAA", + "\xF4\xD0" => "\xE8\xAD\x9D", + "\xF4\xD1" => "\xE8\xAD\xA8", + "\xF4\xD2" => "\xE8\xAD\xA3", + "\xF4\xD3" => "\xE8\xAD\xA5", + "\xF4\xD4" => "\xE8\xAD\xA7", + "\xF4\xD5" => "\xE8\xAD\xAD", + "\xF4\xD6" => "\xE8\xB6\xAE", + "\xF4\xD7" => "\xE8\xBA\x86", + "\xF4\xD8" => "\xE8\xBA\x88", + "\xF4\xD9" => "\xE8\xBA\x84", + "\xF4\xDA" => "\xE8\xBD\x99", + "\xF4\xDB" => "\xE8\xBD\x96", + "\xF4\xDC" => "\xE8\xBD\x97", + "\xF4\xDD" => "\xE8\xBD\x95", + "\xF4\xDE" => "\xE8\xBD\x98", + "\xF4\xDF" => "\xE8\xBD\x9A", + "\xF4\xE0" => "\xE9\x82\x8D", + "\xF4\xE1" => "\xE9\x85\x83", + "\xF4\xE2" => "\xE9\x85\x81", + "\xF4\xE3" => "\xE9\x86\xB7", + "\xF4\xE4" => "\xE9\x86\xB5", + "\xF4\xE5" => "\xE9\x86\xB2", + "\xF4\xE6" => "\xE9\x86\xB3", + "\xF4\xE7" => "\xE9\x90\x8B", + "\xF4\xE8" => "\xE9\x90\x93", + "\xF4\xE9" => "\xE9\x8F\xBB", + "\xF4\xEA" => "\xE9\x90\xA0", + "\xF4\xEB" => "\xE9\x90\x8F", + "\xF4\xEC" => "\xE9\x90\x94", + "\xF4\xED" => "\xE9\x8F\xBE", + "\xF4\xEE" => "\xE9\x90\x95", + "\xF4\xEF" => "\xE9\x90\x90", + "\xF4\xF0" => "\xE9\x90\xA8", + "\xF4\xF1" => "\xE9\x90\x99", + "\xF4\xF2" => "\xE9\x90\x8D", + "\xF4\xF3" => "\xE9\x8F\xB5", + "\xF4\xF4" => "\xE9\x90\x80", + "\xF4\xF5" => "\xE9\x8F\xB7", + "\xF4\xF6" => "\xE9\x90\x87", + "\xF4\xF7" => "\xE9\x90\x8E", + "\xF4\xF8" => "\xE9\x90\x96", + "\xF4\xF9" => "\xE9\x90\x92", + "\xF4\xFA" => "\xE9\x8F\xBA", + "\xF4\xFB" => "\xE9\x90\x89", + "\xF4\xFC" => "\xE9\x8F\xB8", + "\xF4\xFD" => "\xE9\x90\x8A", + "\xF4\xFE" => "\xE9\x8F\xBF", + "\xF5\x40" => "\xE9\x8F\xBC", + "\xF5\x41" => "\xE9\x90\x8C", + "\xF5\x42" => "\xE9\x8F\xB6", + "\xF5\x43" => "\xE9\x90\x91", + "\xF5\x44" => "\xE9\x90\x86", + "\xF5\x45" => "\xE9\x97\x9E", + "\xF5\x46" => "\xE9\x97\xA0", + "\xF5\x47" => "\xE9\x97\x9F", + "\xF5\x48" => "\xE9\x9C\xAE", + "\xF5\x49" => "\xE9\x9C\xAF", + "\xF5\x4A" => "\xE9\x9E\xB9", + "\xF5\x4B" => "\xE9\x9E\xBB", + "\xF5\x4C" => "\xE9\x9F\xBD", + "\xF5\x4D" => "\xE9\x9F\xBE", + "\xF5\x4E" => "\xE9\xA1\xA0", + "\xF5\x4F" => "\xE9\xA1\xA2", + "\xF5\x50" => "\xE9\xA1\xA3", + "\xF5\x51" => "\xE9\xA1\x9F", + "\xF5\x52" => "\xE9\xA3\x81", + "\xF5\x53" => "\xE9\xA3\x82", + "\xF5\x54" => "\xE9\xA5\x90", + "\xF5\x55" => "\xE9\xA5\x8E", + "\xF5\x56" => "\xE9\xA5\x99", + "\xF5\x57" => "\xE9\xA5\x8C", + "\xF5\x58" => "\xE9\xA5\x8B", + "\xF5\x59" => "\xE9\xA5\x93", + "\xF5\x5A" => "\xE9\xA8\xB2", + "\xF5\x5B" => "\xE9\xA8\xB4", + "\xF5\x5C" => "\xE9\xA8\xB1", + "\xF5\x5D" => "\xE9\xA8\xAC", + "\xF5\x5E" => "\xE9\xA8\xAA", + "\xF5\x5F" => "\xE9\xA8\xB6", + "\xF5\x60" => "\xE9\xA8\xA9", + "\xF5\x61" => "\xE9\xA8\xAE", + "\xF5\x62" => "\xE9\xA8\xB8", + "\xF5\x63" => "\xE9\xA8\xAD", + "\xF5\x64" => "\xE9\xAB\x87", + "\xF5\x65" => "\xE9\xAB\x8A", + "\xF5\x66" => "\xE9\xAB\x86", + "\xF5\x67" => "\xE9\xAC\x90", + "\xF5\x68" => "\xE9\xAC\x92", + "\xF5\x69" => "\xE9\xAC\x91", + "\xF5\x6A" => "\xE9\xB0\x8B", + "\xF5\x6B" => "\xE9\xB0\x88", + "\xF5\x6C" => "\xE9\xAF\xB7", + "\xF5\x6D" => "\xE9\xB0\x85", + "\xF5\x6E" => "\xE9\xB0\x92", + "\xF5\x6F" => "\xE9\xAF\xB8", + "\xF5\x70" => "\xE9\xB1\x80", + "\xF5\x71" => "\xE9\xB0\x87", + "\xF5\x72" => "\xE9\xB0\x8E", + "\xF5\x73" => "\xE9\xB0\x86", + "\xF5\x74" => "\xE9\xB0\x97", + "\xF5\x75" => "\xE9\xB0\x94", + "\xF5\x76" => "\xE9\xB0\x89", + "\xF5\x77" => "\xE9\xB6\x9F", + "\xF5\x78" => "\xE9\xB6\x99", + "\xF5\x79" => "\xE9\xB6\xA4", + "\xF5\x7A" => "\xE9\xB6\x9D", + "\xF5\x7B" => "\xE9\xB6\x92", + "\xF5\x7C" => "\xE9\xB6\x98", + "\xF5\x7D" => "\xE9\xB6\x90", + "\xF5\x7E" => "\xE9\xB6\x9B", + "\xF5\xA1" => "\xE9\xB6\xA0", + "\xF5\xA2" => "\xE9\xB6\x94", + "\xF5\xA3" => "\xE9\xB6\x9C", + "\xF5\xA4" => "\xE9\xB6\xAA", + "\xF5\xA5" => "\xE9\xB6\x97", + "\xF5\xA6" => "\xE9\xB6\xA1", + "\xF5\xA7" => "\xE9\xB6\x9A", + "\xF5\xA8" => "\xE9\xB6\xA2", + "\xF5\xA9" => "\xE9\xB6\xA8", + "\xF5\xAA" => "\xE9\xB6\x9E", + "\xF5\xAB" => "\xE9\xB6\xA3", + "\xF5\xAC" => "\xE9\xB6\xBF", + "\xF5\xAD" => "\xE9\xB6\xA9", + "\xF5\xAE" => "\xE9\xB6\x96", + "\xF5\xAF" => "\xE9\xB6\xA6", + "\xF5\xB0" => "\xE9\xB6\xA7", + "\xF5\xB1" => "\xE9\xBA\x99", + "\xF5\xB2" => "\xE9\xBA\x9B", + "\xF5\xB3" => "\xE9\xBA\x9A", + "\xF5\xB4" => "\xE9\xBB\xA5", + "\xF5\xB5" => "\xE9\xBB\xA4", + "\xF5\xB6" => "\xE9\xBB\xA7", + "\xF5\xB7" => "\xE9\xBB\xA6", + "\xF5\xB8" => "\xE9\xBC\xB0", + "\xF5\xB9" => "\xE9\xBC\xAE", + "\xF5\xBA" => "\xE9\xBD\x9B", + "\xF5\xBB" => "\xE9\xBD\xA0", + "\xF5\xBC" => "\xE9\xBD\x9E", + "\xF5\xBD" => "\xE9\xBD\x9D", + "\xF5\xBE" => "\xE9\xBD\x99", + "\xF5\xBF" => "\xE9\xBE\x91", + "\xF5\xC0" => "\xE5\x84\xBA", + "\xF5\xC1" => "\xE5\x84\xB9", + "\xF5\xC2" => "\xE5\x8A\x98", + "\xF5\xC3" => "\xE5\x8A\x97", + "\xF5\xC4" => "\xE5\x9B\x83", + "\xF5\xC5" => "\xE5\x9A\xBD", + "\xF5\xC6" => "\xE5\x9A\xBE", + "\xF5\xC7" => "\xE5\xAD\x88", + "\xF5\xC8" => "\xE5\xAD\x87", + "\xF5\xC9" => "\xE5\xB7\x8B", + "\xF5\xCA" => "\xE5\xB7\x8F", + "\xF5\xCB" => "\xE5\xBB\xB1", + "\xF5\xCC" => "\xE6\x87\xBD", + "\xF5\xCD" => "\xE6\x94\x9B", + "\xF5\xCE" => "\xE6\xAC\x82", + "\xF5\xCF" => "\xE6\xAB\xBC", + "\xF5\xD0" => "\xE6\xAC\x83", + "\xF5\xD1" => "\xE6\xAB\xB8", + "\xF5\xD2" => "\xE6\xAC\x80", + "\xF5\xD3" => "\xE7\x81\x83", + "\xF5\xD4" => "\xE7\x81\x84", + "\xF5\xD5" => "\xE7\x81\x8A", + "\xF5\xD6" => "\xE7\x81\x88", + "\xF5\xD7" => "\xE7\x81\x89", + "\xF5\xD8" => "\xE7\x81\x85", + "\xF5\xD9" => "\xE7\x81\x86", + "\xF5\xDA" => "\xE7\x88\x9D", + "\xF5\xDB" => "\xE7\x88\x9A", + "\xF5\xDC" => "\xE7\x88\x99", + "\xF5\xDD" => "\xE7\x8D\xBE", + "\xF5\xDE" => "\xE7\x94\x97", + "\xF5\xDF" => "\xE7\x99\xAA", + "\xF5\xE0" => "\xE7\x9F\x90", + "\xF5\xE1" => "\xE7\xA4\xAD", + "\xF5\xE2" => "\xE7\xA4\xB1", + "\xF5\xE3" => "\xE7\xA4\xAF", + "\xF5\xE4" => "\xE7\xB1\x94", + "\xF5\xE5" => "\xE7\xB1\x93", + "\xF5\xE6" => "\xE7\xB3\xB2", + "\xF5\xE7" => "\xE7\xBA\x8A", + "\xF5\xE8" => "\xE7\xBA\x87", + "\xF5\xE9" => "\xE7\xBA\x88", + "\xF5\xEA" => "\xE7\xBA\x8B", + "\xF5\xEB" => "\xE7\xBA\x86", + "\xF5\xEC" => "\xE7\xBA\x8D", + "\xF5\xED" => "\xE7\xBD\x8D", + "\xF5\xEE" => "\xE7\xBE\xBB", + "\xF5\xEF" => "\xE8\x80\xB0", + "\xF5\xF0" => "\xE8\x87\x9D", + "\xF5\xF1" => "\xE8\x98\x98", + "\xF5\xF2" => "\xE8\x98\xAA", + "\xF5\xF3" => "\xE8\x98\xA6", + "\xF5\xF4" => "\xE8\x98\x9F", + "\xF5\xF5" => "\xE8\x98\xA3", + "\xF5\xF6" => "\xE8\x98\x9C", + "\xF5\xF7" => "\xE8\x98\x99", + "\xF5\xF8" => "\xE8\x98\xA7", + "\xF5\xF9" => "\xE8\x98\xAE", + "\xF5\xFA" => "\xE8\x98\xA1", + "\xF5\xFB" => "\xE8\x98\xA0", + "\xF5\xFC" => "\xE8\x98\xA9", + "\xF5\xFD" => "\xE8\x98\x9E", + "\xF5\xFE" => "\xE8\x98\xA5", + "\xF6\x40" => "\xE8\xA0\xA9", + "\xF6\x41" => "\xE8\xA0\x9D", + "\xF6\x42" => "\xE8\xA0\x9B", + "\xF6\x43" => "\xE8\xA0\xA0", + "\xF6\x44" => "\xE8\xA0\xA4", + "\xF6\x45" => "\xE8\xA0\x9C", + "\xF6\x46" => "\xE8\xA0\xAB", + "\xF6\x47" => "\xE8\xA1\x8A", + "\xF6\x48" => "\xE8\xA5\xAD", + "\xF6\x49" => "\xE8\xA5\xA9", + "\xF6\x4A" => "\xE8\xA5\xAE", + "\xF6\x4B" => "\xE8\xA5\xAB", + "\xF6\x4C" => "\xE8\xA7\xBA", + "\xF6\x4D" => "\xE8\xAD\xB9", + "\xF6\x4E" => "\xE8\xAD\xB8", + "\xF6\x4F" => "\xE8\xAD\x85", + "\xF6\x50" => "\xE8\xAD\xBA", + "\xF6\x51" => "\xE8\xAD\xBB", + "\xF6\x52" => "\xE8\xB4\x90", + "\xF6\x53" => "\xE8\xB4\x94", + "\xF6\x54" => "\xE8\xB6\xAF", + "\xF6\x55" => "\xE8\xBA\x8E", + "\xF6\x56" => "\xE8\xBA\x8C", + "\xF6\x57" => "\xE8\xBD\x9E", + "\xF6\x58" => "\xE8\xBD\x9B", + "\xF6\x59" => "\xE8\xBD\x9D", + "\xF6\x5A" => "\xE9\x85\x86", + "\xF6\x5B" => "\xE9\x85\x84", + "\xF6\x5C" => "\xE9\x85\x85", + "\xF6\x5D" => "\xE9\x86\xB9", + "\xF6\x5E" => "\xE9\x90\xBF", + "\xF6\x5F" => "\xE9\x90\xBB", + "\xF6\x60" => "\xE9\x90\xB6", + "\xF6\x61" => "\xE9\x90\xA9", + "\xF6\x62" => "\xE9\x90\xBD", + "\xF6\x63" => "\xE9\x90\xBC", + "\xF6\x64" => "\xE9\x90\xB0", + "\xF6\x65" => "\xE9\x90\xB9", + "\xF6\x66" => "\xE9\x90\xAA", + "\xF6\x67" => "\xE9\x90\xB7", + "\xF6\x68" => "\xE9\x90\xAC", + "\xF6\x69" => "\xE9\x91\x80", + "\xF6\x6A" => "\xE9\x90\xB1", + "\xF6\x6B" => "\xE9\x97\xA5", + "\xF6\x6C" => "\xE9\x97\xA4", + "\xF6\x6D" => "\xE9\x97\xA3", + "\xF6\x6E" => "\xE9\x9C\xB5", + "\xF6\x6F" => "\xE9\x9C\xBA", + "\xF6\x70" => "\xE9\x9E\xBF", + "\xF6\x71" => "\xE9\x9F\xA1", + "\xF6\x72" => "\xE9\xA1\xA4", + "\xF6\x73" => "\xE9\xA3\x89", + "\xF6\x74" => "\xE9\xA3\x86", + "\xF6\x75" => "\xE9\xA3\x80", + "\xF6\x76" => "\xE9\xA5\x98", + "\xF6\x77" => "\xE9\xA5\x96", + "\xF6\x78" => "\xE9\xA8\xB9", + "\xF6\x79" => "\xE9\xA8\xBD", + "\xF6\x7A" => "\xE9\xA9\x86", + "\xF6\x7B" => "\xE9\xA9\x84", + "\xF6\x7C" => "\xE9\xA9\x82", + "\xF6\x7D" => "\xE9\xA9\x81", + "\xF6\x7E" => "\xE9\xA8\xBA", + "\xF6\xA1" => "\xE9\xA8\xBF", + "\xF6\xA2" => "\xE9\xAB\x8D", + "\xF6\xA3" => "\xE9\xAC\x95", + "\xF6\xA4" => "\xE9\xAC\x97", + "\xF6\xA5" => "\xE9\xAC\x98", + "\xF6\xA6" => "\xE9\xAC\x96", + "\xF6\xA7" => "\xE9\xAC\xBA", + "\xF6\xA8" => "\xE9\xAD\x92", + "\xF6\xA9" => "\xE9\xB0\xAB", + "\xF6\xAA" => "\xE9\xB0\x9D", + "\xF6\xAB" => "\xE9\xB0\x9C", + "\xF6\xAC" => "\xE9\xB0\xAC", + "\xF6\xAD" => "\xE9\xB0\xA3", + "\xF6\xAE" => "\xE9\xB0\xA8", + "\xF6\xAF" => "\xE9\xB0\xA9", + "\xF6\xB0" => "\xE9\xB0\xA4", + "\xF6\xB1" => "\xE9\xB0\xA1", + "\xF6\xB2" => "\xE9\xB6\xB7", + "\xF6\xB3" => "\xE9\xB6\xB6", + "\xF6\xB4" => "\xE9\xB6\xBC", + "\xF6\xB5" => "\xE9\xB7\x81", + "\xF6\xB6" => "\xE9\xB7\x87", + "\xF6\xB7" => "\xE9\xB7\x8A", + "\xF6\xB8" => "\xE9\xB7\x8F", + "\xF6\xB9" => "\xE9\xB6\xBE", + "\xF6\xBA" => "\xE9\xB7\x85", + "\xF6\xBB" => "\xE9\xB7\x83", + "\xF6\xBC" => "\xE9\xB6\xBB", + "\xF6\xBD" => "\xE9\xB6\xB5", + "\xF6\xBE" => "\xE9\xB7\x8E", + "\xF6\xBF" => "\xE9\xB6\xB9", + "\xF6\xC0" => "\xE9\xB6\xBA", + "\xF6\xC1" => "\xE9\xB6\xAC", + "\xF6\xC2" => "\xE9\xB7\x88", + "\xF6\xC3" => "\xE9\xB6\xB1", + "\xF6\xC4" => "\xE9\xB6\xAD", + "\xF6\xC5" => "\xE9\xB7\x8C", + "\xF6\xC6" => "\xE9\xB6\xB3", + "\xF6\xC7" => "\xE9\xB7\x8D", + "\xF6\xC8" => "\xE9\xB6\xB2", + "\xF6\xC9" => "\xE9\xB9\xBA", + "\xF6\xCA" => "\xE9\xBA\x9C", + "\xF6\xCB" => "\xE9\xBB\xAB", + "\xF6\xCC" => "\xE9\xBB\xAE", + "\xF6\xCD" => "\xE9\xBB\xAD", + "\xF6\xCE" => "\xE9\xBC\x9B", + "\xF6\xCF" => "\xE9\xBC\x98", + "\xF6\xD0" => "\xE9\xBC\x9A", + "\xF6\xD1" => "\xE9\xBC\xB1", + "\xF6\xD2" => "\xE9\xBD\x8E", + "\xF6\xD3" => "\xE9\xBD\xA5", + "\xF6\xD4" => "\xE9\xBD\xA4", + "\xF6\xD5" => "\xE9\xBE\x92", + "\xF6\xD6" => "\xE4\xBA\xB9", + "\xF6\xD7" => "\xE5\x9B\x86", + "\xF6\xD8" => "\xE5\x9B\x85", + "\xF6\xD9" => "\xE5\x9B\x8B", + "\xF6\xDA" => "\xE5\xA5\xB1", + "\xF6\xDB" => "\xE5\xAD\x8B", + "\xF6\xDC" => "\xE5\xAD\x8C", + "\xF6\xDD" => "\xE5\xB7\x95", + "\xF6\xDE" => "\xE5\xB7\x91", + "\xF6\xDF" => "\xE5\xBB\xB2", + "\xF6\xE0" => "\xE6\x94\xA1", + "\xF6\xE1" => "\xE6\x94\xA0", + "\xF6\xE2" => "\xE6\x94\xA6", + "\xF6\xE3" => "\xE6\x94\xA2", + "\xF6\xE4" => "\xE6\xAC\x8B", + "\xF6\xE5" => "\xE6\xAC\x88", + "\xF6\xE6" => "\xE6\xAC\x89", + "\xF6\xE7" => "\xE6\xB0\x8D", + "\xF6\xE8" => "\xE7\x81\x95", + "\xF6\xE9" => "\xE7\x81\x96", + "\xF6\xEA" => "\xE7\x81\x97", + "\xF6\xEB" => "\xE7\x81\x92", + "\xF6\xEC" => "\xE7\x88\x9E", + "\xF6\xED" => "\xE7\x88\x9F", + "\xF6\xEE" => "\xE7\x8A\xA9", + "\xF6\xEF" => "\xE7\x8D\xBF", + "\xF6\xF0" => "\xE7\x93\x98", + "\xF6\xF1" => "\xE7\x93\x95", + "\xF6\xF2" => "\xE7\x93\x99", + "\xF6\xF3" => "\xE7\x93\x97", + "\xF6\xF4" => "\xE7\x99\xAD", + "\xF6\xF5" => "\xE7\x9A\xAD", + "\xF6\xF6" => "\xE7\xA4\xB5", + "\xF6\xF7" => "\xE7\xA6\xB4", + "\xF6\xF8" => "\xE7\xA9\xB0", + "\xF6\xF9" => "\xE7\xA9\xB1", + "\xF6\xFA" => "\xE7\xB1\x97", + "\xF6\xFB" => "\xE7\xB1\x9C", + "\xF6\xFC" => "\xE7\xB1\x99", + "\xF6\xFD" => "\xE7\xB1\x9B", + "\xF6\xFE" => "\xE7\xB1\x9A", + "\xF7\x40" => "\xE7\xB3\xB4", + "\xF7\x41" => "\xE7\xB3\xB1", + "\xF7\x42" => "\xE7\xBA\x91", + "\xF7\x43" => "\xE7\xBD\x8F", + "\xF7\x44" => "\xE7\xBE\x87", + "\xF7\x45" => "\xE8\x87\x9E", + "\xF7\x46" => "\xE8\x89\xAB", + "\xF7\x47" => "\xE8\x98\xB4", + "\xF7\x48" => "\xE8\x98\xB5", + "\xF7\x49" => "\xE8\x98\xB3", + "\xF7\x4A" => "\xE8\x98\xAC", + "\xF7\x4B" => "\xE8\x98\xB2", + "\xF7\x4C" => "\xE8\x98\xB6", + "\xF7\x4D" => "\xE8\xA0\xAC", + "\xF7\x4E" => "\xE8\xA0\xA8", + "\xF7\x4F" => "\xE8\xA0\xA6", + "\xF7\x50" => "\xE8\xA0\xAA", + "\xF7\x51" => "\xE8\xA0\xA5", + "\xF7\x52" => "\xE8\xA5\xB1", + "\xF7\x53" => "\xE8\xA6\xBF", + "\xF7\x54" => "\xE8\xA6\xBE", + "\xF7\x55" => "\xE8\xA7\xBB", + "\xF7\x56" => "\xE8\xAD\xBE", + "\xF7\x57" => "\xE8\xAE\x84", + "\xF7\x58" => "\xE8\xAE\x82", + "\xF7\x59" => "\xE8\xAE\x86", + "\xF7\x5A" => "\xE8\xAE\x85", + "\xF7\x5B" => "\xE8\xAD\xBF", + "\xF7\x5C" => "\xE8\xB4\x95", + "\xF7\x5D" => "\xE8\xBA\x95", + "\xF7\x5E" => "\xE8\xBA\x94", + "\xF7\x5F" => "\xE8\xBA\x9A", + "\xF7\x60" => "\xE8\xBA\x92", + "\xF7\x61" => "\xE8\xBA\x90", + "\xF7\x62" => "\xE8\xBA\x96", + "\xF7\x63" => "\xE8\xBA\x97", + "\xF7\x64" => "\xE8\xBD\xA0", + "\xF7\x65" => "\xE8\xBD\xA2", + "\xF7\x66" => "\xE9\x85\x87", + "\xF7\x67" => "\xE9\x91\x8C", + "\xF7\x68" => "\xE9\x91\x90", + "\xF7\x69" => "\xE9\x91\x8A", + "\xF7\x6A" => "\xE9\x91\x8B", + "\xF7\x6B" => "\xE9\x91\x8F", + "\xF7\x6C" => "\xE9\x91\x87", + "\xF7\x6D" => "\xE9\x91\x85", + "\xF7\x6E" => "\xE9\x91\x88", + "\xF7\x6F" => "\xE9\x91\x89", + "\xF7\x70" => "\xE9\x91\x86", + "\xF7\x71" => "\xE9\x9C\xBF", + "\xF7\x72" => "\xE9\x9F\xA3", + "\xF7\x73" => "\xE9\xA1\xAA", + "\xF7\x74" => "\xE9\xA1\xA9", + "\xF7\x75" => "\xE9\xA3\x8B", + "\xF7\x76" => "\xE9\xA5\x94", + "\xF7\x77" => "\xE9\xA5\x9B", + "\xF7\x78" => "\xE9\xA9\x8E", + "\xF7\x79" => "\xE9\xA9\x93", + "\xF7\x7A" => "\xE9\xA9\x94", + "\xF7\x7B" => "\xE9\xA9\x8C", + "\xF7\x7C" => "\xE9\xA9\x8F", + "\xF7\x7D" => "\xE9\xA9\x88", + "\xF7\x7E" => "\xE9\xA9\x8A", + "\xF7\xA1" => "\xE9\xA9\x89", + "\xF7\xA2" => "\xE9\xA9\x92", + "\xF7\xA3" => "\xE9\xA9\x90", + "\xF7\xA4" => "\xE9\xAB\x90", + "\xF7\xA5" => "\xE9\xAC\x99", + "\xF7\xA6" => "\xE9\xAC\xAB", + "\xF7\xA7" => "\xE9\xAC\xBB", + "\xF7\xA8" => "\xE9\xAD\x96", + "\xF7\xA9" => "\xE9\xAD\x95", + "\xF7\xAA" => "\xE9\xB1\x86", + "\xF7\xAB" => "\xE9\xB1\x88", + "\xF7\xAC" => "\xE9\xB0\xBF", + "\xF7\xAD" => "\xE9\xB1\x84", + "\xF7\xAE" => "\xE9\xB0\xB9", + "\xF7\xAF" => "\xE9\xB0\xB3", + "\xF7\xB0" => "\xE9\xB1\x81", + "\xF7\xB1" => "\xE9\xB0\xBC", + "\xF7\xB2" => "\xE9\xB0\xB7", + "\xF7\xB3" => "\xE9\xB0\xB4", + "\xF7\xB4" => "\xE9\xB0\xB2", + "\xF7\xB5" => "\xE9\xB0\xBD", + "\xF7\xB6" => "\xE9\xB0\xB6", + "\xF7\xB7" => "\xE9\xB7\x9B", + "\xF7\xB8" => "\xE9\xB7\x92", + "\xF7\xB9" => "\xE9\xB7\x9E", + "\xF7\xBA" => "\xE9\xB7\x9A", + "\xF7\xBB" => "\xE9\xB7\x8B", + "\xF7\xBC" => "\xE9\xB7\x90", + "\xF7\xBD" => "\xE9\xB7\x9C", + "\xF7\xBE" => "\xE9\xB7\x91", + "\xF7\xBF" => "\xE9\xB7\x9F", + "\xF7\xC0" => "\xE9\xB7\xA9", + "\xF7\xC1" => "\xE9\xB7\x99", + "\xF7\xC2" => "\xE9\xB7\x98", + "\xF7\xC3" => "\xE9\xB7\x96", + "\xF7\xC4" => "\xE9\xB7\xB5", + "\xF7\xC5" => "\xE9\xB7\x95", + "\xF7\xC6" => "\xE9\xB7\x9D", + "\xF7\xC7" => "\xE9\xBA\xB6", + "\xF7\xC8" => "\xE9\xBB\xB0", + "\xF7\xC9" => "\xE9\xBC\xB5", + "\xF7\xCA" => "\xE9\xBC\xB3", + "\xF7\xCB" => "\xE9\xBC\xB2", + "\xF7\xCC" => "\xE9\xBD\x82", + "\xF7\xCD" => "\xE9\xBD\xAB", + "\xF7\xCE" => "\xE9\xBE\x95", + "\xF7\xCF" => "\xE9\xBE\xA2", + "\xF7\xD0" => "\xE5\x84\xBD", + "\xF7\xD1" => "\xE5\x8A\x99", + "\xF7\xD2" => "\xE5\xA3\xA8", + "\xF7\xD3" => "\xE5\xA3\xA7", + "\xF7\xD4" => "\xE5\xA5\xB2", + "\xF7\xD5" => "\xE5\xAD\x8D", + "\xF7\xD6" => "\xE5\xB7\x98", + "\xF7\xD7" => "\xE8\xA0\xAF", + "\xF7\xD8" => "\xE5\xBD\x8F", + "\xF7\xD9" => "\xE6\x88\x81", + "\xF7\xDA" => "\xE6\x88\x83", + "\xF7\xDB" => "\xE6\x88\x84", + "\xF7\xDC" => "\xE6\x94\xA9", + "\xF7\xDD" => "\xE6\x94\xA5", + "\xF7\xDE" => "\xE6\x96\x96", + "\xF7\xDF" => "\xE6\x9B\xAB", + "\xF7\xE0" => "\xE6\xAC\x91", + "\xF7\xE1" => "\xE6\xAC\x92", + "\xF7\xE2" => "\xE6\xAC\x8F", + "\xF7\xE3" => "\xE6\xAF\x8A", + "\xF7\xE4" => "\xE7\x81\x9B", + "\xF7\xE5" => "\xE7\x81\x9A", + "\xF7\xE6" => "\xE7\x88\xA2", + "\xF7\xE7" => "\xE7\x8E\x82", + "\xF7\xE8" => "\xE7\x8E\x81", + "\xF7\xE9" => "\xE7\x8E\x83", + "\xF7\xEA" => "\xE7\x99\xB0", + "\xF7\xEB" => "\xE7\x9F\x94", + "\xF7\xEC" => "\xE7\xB1\xA7", + "\xF7\xED" => "\xE7\xB1\xA6", + "\xF7\xEE" => "\xE7\xBA\x95", + "\xF7\xEF" => "\xE8\x89\xAC", + "\xF7\xF0" => "\xE8\x98\xBA", + "\xF7\xF1" => "\xE8\x99\x80", + "\xF7\xF2" => "\xE8\x98\xB9", + "\xF7\xF3" => "\xE8\x98\xBC", + "\xF7\xF4" => "\xE8\x98\xB1", + "\xF7\xF5" => "\xE8\x98\xBB", + "\xF7\xF6" => "\xE8\x98\xBE", + "\xF7\xF7" => "\xE8\xA0\xB0", + "\xF7\xF8" => "\xE8\xA0\xB2", + "\xF7\xF9" => "\xE8\xA0\xAE", + "\xF7\xFA" => "\xE8\xA0\xB3", + "\xF7\xFB" => "\xE8\xA5\xB6", + "\xF7\xFC" => "\xE8\xA5\xB4", + "\xF7\xFD" => "\xE8\xA5\xB3", + "\xF7\xFE" => "\xE8\xA7\xBE", + "\xF8\x40" => "\xE8\xAE\x8C", + "\xF8\x41" => "\xE8\xAE\x8E", + "\xF8\x42" => "\xE8\xAE\x8B", + "\xF8\x43" => "\xE8\xAE\x88", + "\xF8\x44" => "\xE8\xB1\x85", + "\xF8\x45" => "\xE8\xB4\x99", + "\xF8\x46" => "\xE8\xBA\x98", + "\xF8\x47" => "\xE8\xBD\xA4", + "\xF8\x48" => "\xE8\xBD\xA3", + "\xF8\x49" => "\xE9\x86\xBC", + "\xF8\x4A" => "\xE9\x91\xA2", + "\xF8\x4B" => "\xE9\x91\x95", + "\xF8\x4C" => "\xE9\x91\x9D", + "\xF8\x4D" => "\xE9\x91\x97", + "\xF8\x4E" => "\xE9\x91\x9E", + "\xF8\x4F" => "\xE9\x9F\x84", + "\xF8\x50" => "\xE9\x9F\x85", + "\xF8\x51" => "\xE9\xA0\x80", + "\xF8\x52" => "\xE9\xA9\x96", + "\xF8\x53" => "\xE9\xA9\x99", + "\xF8\x54" => "\xE9\xAC\x9E", + "\xF8\x55" => "\xE9\xAC\x9F", + "\xF8\x56" => "\xE9\xAC\xA0", + "\xF8\x57" => "\xE9\xB1\x92", + "\xF8\x58" => "\xE9\xB1\x98", + "\xF8\x59" => "\xE9\xB1\x90", + "\xF8\x5A" => "\xE9\xB1\x8A", + "\xF8\x5B" => "\xE9\xB1\x8D", + "\xF8\x5C" => "\xE9\xB1\x8B", + "\xF8\x5D" => "\xE9\xB1\x95", + "\xF8\x5E" => "\xE9\xB1\x99", + "\xF8\x5F" => "\xE9\xB1\x8C", + "\xF8\x60" => "\xE9\xB1\x8E", + "\xF8\x61" => "\xE9\xB7\xBB", + "\xF8\x62" => "\xE9\xB7\xB7", + "\xF8\x63" => "\xE9\xB7\xAF", + "\xF8\x64" => "\xE9\xB7\xA3", + "\xF8\x65" => "\xE9\xB7\xAB", + "\xF8\x66" => "\xE9\xB7\xB8", + "\xF8\x67" => "\xE9\xB7\xA4", + "\xF8\x68" => "\xE9\xB7\xB6", + "\xF8\x69" => "\xE9\xB7\xA1", + "\xF8\x6A" => "\xE9\xB7\xAE", + "\xF8\x6B" => "\xE9\xB7\xA6", + "\xF8\x6C" => "\xE9\xB7\xB2", + "\xF8\x6D" => "\xE9\xB7\xB0", + "\xF8\x6E" => "\xE9\xB7\xA2", + "\xF8\x6F" => "\xE9\xB7\xAC", + "\xF8\x70" => "\xE9\xB7\xB4", + "\xF8\x71" => "\xE9\xB7\xB3", + "\xF8\x72" => "\xE9\xB7\xA8", + "\xF8\x73" => "\xE9\xB7\xAD", + "\xF8\x74" => "\xE9\xBB\x82", + "\xF8\x75" => "\xE9\xBB\x90", + "\xF8\x76" => "\xE9\xBB\xB2", + "\xF8\x77" => "\xE9\xBB\xB3", + "\xF8\x78" => "\xE9\xBC\x86", + "\xF8\x79" => "\xE9\xBC\x9C", + "\xF8\x7A" => "\xE9\xBC\xB8", + "\xF8\x7B" => "\xE9\xBC\xB7", + "\xF8\x7C" => "\xE9\xBC\xB6", + "\xF8\x7D" => "\xE9\xBD\x83", + "\xF8\x7E" => "\xE9\xBD\x8F", + "\xF8\xA1" => "\xE9\xBD\xB1", + "\xF8\xA2" => "\xE9\xBD\xB0", + "\xF8\xA3" => "\xE9\xBD\xAE", + "\xF8\xA4" => "\xE9\xBD\xAF", + "\xF8\xA5" => "\xE5\x9B\x93", + "\xF8\xA6" => "\xE5\x9B\x8D", + "\xF8\xA7" => "\xE5\xAD\x8E", + "\xF8\xA8" => "\xE5\xB1\xAD", + "\xF8\xA9" => "\xE6\x94\xAD", + "\xF8\xAA" => "\xE6\x9B\xAD", + "\xF8\xAB" => "\xE6\x9B\xAE", + "\xF8\xAC" => "\xE6\xAC\x93", + "\xF8\xAD" => "\xE7\x81\x9F", + "\xF8\xAE" => "\xE7\x81\xA1", + "\xF8\xAF" => "\xE7\x81\x9D", + "\xF8\xB0" => "\xE7\x81\xA0", + "\xF8\xB1" => "\xE7\x88\xA3", + "\xF8\xB2" => "\xE7\x93\x9B", + "\xF8\xB3" => "\xE7\x93\xA5", + "\xF8\xB4" => "\xE7\x9F\x95", + "\xF8\xB5" => "\xE7\xA4\xB8", + "\xF8\xB6" => "\xE7\xA6\xB7", + "\xF8\xB7" => "\xE7\xA6\xB6", + "\xF8\xB8" => "\xE7\xB1\xAA", + "\xF8\xB9" => "\xE7\xBA\x97", + "\xF8\xBA" => "\xE7\xBE\x89", + "\xF8\xBB" => "\xE8\x89\xAD", + "\xF8\xBC" => "\xE8\x99\x83", + "\xF8\xBD" => "\xE8\xA0\xB8", + "\xF8\xBE" => "\xE8\xA0\xB7", + "\xF8\xBF" => "\xE8\xA0\xB5", + "\xF8\xC0" => "\xE8\xA1\x8B", + "\xF8\xC1" => "\xE8\xAE\x94", + "\xF8\xC2" => "\xE8\xAE\x95", + "\xF8\xC3" => "\xE8\xBA\x9E", + "\xF8\xC4" => "\xE8\xBA\x9F", + "\xF8\xC5" => "\xE8\xBA\xA0", + "\xF8\xC6" => "\xE8\xBA\x9D", + "\xF8\xC7" => "\xE9\x86\xBE", + "\xF8\xC8" => "\xE9\x86\xBD", + "\xF8\xC9" => "\xE9\x87\x82", + "\xF8\xCA" => "\xE9\x91\xAB", + "\xF8\xCB" => "\xE9\x91\xA8", + "\xF8\xCC" => "\xE9\x91\xA9", + "\xF8\xCD" => "\xE9\x9B\xA5", + "\xF8\xCE" => "\xE9\x9D\x86", + "\xF8\xCF" => "\xE9\x9D\x83", + "\xF8\xD0" => "\xE9\x9D\x87", + "\xF8\xD1" => "\xE9\x9F\x87", + "\xF8\xD2" => "\xE9\x9F\xA5", + "\xF8\xD3" => "\xE9\xA9\x9E", + "\xF8\xD4" => "\xE9\xAB\x95", + "\xF8\xD5" => "\xE9\xAD\x99", + "\xF8\xD6" => "\xE9\xB1\xA3", + "\xF8\xD7" => "\xE9\xB1\xA7", + "\xF8\xD8" => "\xE9\xB1\xA6", + "\xF8\xD9" => "\xE9\xB1\xA2", + "\xF8\xDA" => "\xE9\xB1\x9E", + "\xF8\xDB" => "\xE9\xB1\xA0", + "\xF8\xDC" => "\xE9\xB8\x82", + "\xF8\xDD" => "\xE9\xB7\xBE", + "\xF8\xDE" => "\xE9\xB8\x87", + "\xF8\xDF" => "\xE9\xB8\x83", + "\xF8\xE0" => "\xE9\xB8\x86", + "\xF8\xE1" => "\xE9\xB8\x85", + "\xF8\xE2" => "\xE9\xB8\x80", + "\xF8\xE3" => "\xE9\xB8\x81", + "\xF8\xE4" => "\xE9\xB8\x89", + "\xF8\xE5" => "\xE9\xB7\xBF", + "\xF8\xE6" => "\xE9\xB7\xBD", + "\xF8\xE7" => "\xE9\xB8\x84", + "\xF8\xE8" => "\xE9\xBA\xA0", + "\xF8\xE9" => "\xE9\xBC\x9E", + "\xF8\xEA" => "\xE9\xBD\x86", + "\xF8\xEB" => "\xE9\xBD\xB4", + "\xF8\xEC" => "\xE9\xBD\xB5", + "\xF8\xED" => "\xE9\xBD\xB6", + "\xF8\xEE" => "\xE5\x9B\x94", + "\xF8\xEF" => "\xE6\x94\xAE", + "\xF8\xF0" => "\xE6\x96\xB8", + "\xF8\xF1" => "\xE6\xAC\x98", + "\xF8\xF2" => "\xE6\xAC\x99", + "\xF8\xF3" => "\xE6\xAC\x97", + "\xF8\xF4" => "\xE6\xAC\x9A", + "\xF8\xF5" => "\xE7\x81\xA2", + "\xF8\xF6" => "\xE7\x88\xA6", + "\xF8\xF7" => "\xE7\x8A\xAA", + "\xF8\xF8" => "\xE7\x9F\x98", + "\xF8\xF9" => "\xE7\x9F\x99", + "\xF8\xFA" => "\xE7\xA4\xB9", + "\xF8\xFB" => "\xE7\xB1\xA9", + "\xF8\xFC" => "\xE7\xB1\xAB", + "\xF8\xFD" => "\xE7\xB3\xB6", + "\xF8\xFE" => "\xE7\xBA\x9A", + "\xF9\x40" => "\xE7\xBA\x98", + "\xF9\x41" => "\xE7\xBA\x9B", + "\xF9\x42" => "\xE7\xBA\x99", + "\xF9\x43" => "\xE8\x87\xA0", + "\xF9\x44" => "\xE8\x87\xA1", + "\xF9\x45" => "\xE8\x99\x86", + "\xF9\x46" => "\xE8\x99\x87", + "\xF9\x47" => "\xE8\x99\x88", + "\xF9\x48" => "\xE8\xA5\xB9", + "\xF9\x49" => "\xE8\xA5\xBA", + "\xF9\x4A" => "\xE8\xA5\xBC", + "\xF9\x4B" => "\xE8\xA5\xBB", + "\xF9\x4C" => "\xE8\xA7\xBF", + "\xF9\x4D" => "\xE8\xAE\x98", + "\xF9\x4E" => "\xE8\xAE\x99", + "\xF9\x4F" => "\xE8\xBA\xA5", + "\xF9\x50" => "\xE8\xBA\xA4", + "\xF9\x51" => "\xE8\xBA\xA3", + "\xF9\x52" => "\xE9\x91\xAE", + "\xF9\x53" => "\xE9\x91\xAD", + "\xF9\x54" => "\xE9\x91\xAF", + "\xF9\x55" => "\xE9\x91\xB1", + "\xF9\x56" => "\xE9\x91\xB3", + "\xF9\x57" => "\xE9\x9D\x89", + "\xF9\x58" => "\xE9\xA1\xB2", + "\xF9\x59" => "\xE9\xA5\x9F", + "\xF9\x5A" => "\xE9\xB1\xA8", + "\xF9\x5B" => "\xE9\xB1\xAE", + "\xF9\x5C" => "\xE9\xB1\xAD", + "\xF9\x5D" => "\xE9\xB8\x8B", + "\xF9\x5E" => "\xE9\xB8\x8D", + "\xF9\x5F" => "\xE9\xB8\x90", + "\xF9\x60" => "\xE9\xB8\x8F", + "\xF9\x61" => "\xE9\xB8\x92", + "\xF9\x62" => "\xE9\xB8\x91", + "\xF9\x63" => "\xE9\xBA\xA1", + "\xF9\x64" => "\xE9\xBB\xB5", + "\xF9\x65" => "\xE9\xBC\x89", + "\xF9\x66" => "\xE9\xBD\x87", + "\xF9\x67" => "\xE9\xBD\xB8", + "\xF9\x68" => "\xE9\xBD\xBB", + "\xF9\x69" => "\xE9\xBD\xBA", + "\xF9\x6A" => "\xE9\xBD\xB9", + "\xF9\x6B" => "\xE5\x9C\x9E", + "\xF9\x6C" => "\xE7\x81\xA6", + "\xF9\x6D" => "\xE7\xB1\xAF", + "\xF9\x6E" => "\xE8\xA0\xBC", + "\xF9\x6F" => "\xE8\xB6\xB2", + "\xF9\x70" => "\xE8\xBA\xA6", + "\xF9\x71" => "\xE9\x87\x83", + "\xF9\x72" => "\xE9\x91\xB4", + "\xF9\x73" => "\xE9\x91\xB8", + "\xF9\x74" => "\xE9\x91\xB6", + "\xF9\x75" => "\xE9\x91\xB5", + "\xF9\x76" => "\xE9\xA9\xA0", + "\xF9\x77" => "\xE9\xB1\xB4", + "\xF9\x78" => "\xE9\xB1\xB3", + "\xF9\x79" => "\xE9\xB1\xB1", + "\xF9\x7A" => "\xE9\xB1\xB5", + "\xF9\x7B" => "\xE9\xB8\x94", + "\xF9\x7C" => "\xE9\xB8\x93", + "\xF9\x7D" => "\xE9\xBB\xB6", + "\xF9\x7E" => "\xE9\xBC\x8A", + "\xF9\xA1" => "\xE9\xBE\xA4", + "\xF9\xA2" => "\xE7\x81\xA8", + "\xF9\xA3" => "\xE7\x81\xA5", + "\xF9\xA4" => "\xE7\xB3\xB7", + "\xF9\xA5" => "\xE8\x99\xAA", + "\xF9\xA6" => "\xE8\xA0\xBE", + "\xF9\xA7" => "\xE8\xA0\xBD", + "\xF9\xA8" => "\xE8\xA0\xBF", + "\xF9\xA9" => "\xE8\xAE\x9E", + "\xF9\xAA" => "\xE8\xB2\x9C", + "\xF9\xAB" => "\xE8\xBA\xA9", + "\xF9\xAC" => "\xE8\xBB\x89", + "\xF9\xAD" => "\xE9\x9D\x8B", + "\xF9\xAE" => "\xE9\xA1\xB3", + "\xF9\xAF" => "\xE9\xA1\xB4", + "\xF9\xB0" => "\xE9\xA3\x8C", + "\xF9\xB1" => "\xE9\xA5\xA1", + "\xF9\xB2" => "\xE9\xA6\xAB", + "\xF9\xB3" => "\xE9\xA9\xA4", + "\xF9\xB4" => "\xE9\xA9\xA6", + "\xF9\xB5" => "\xE9\xA9\xA7", + "\xF9\xB6" => "\xE9\xAC\xA4", + "\xF9\xB7" => "\xE9\xB8\x95", + "\xF9\xB8" => "\xE9\xB8\x97", + "\xF9\xB9" => "\xE9\xBD\x88", + "\xF9\xBA" => "\xE6\x88\x87", + "\xF9\xBB" => "\xE6\xAC\x9E", + "\xF9\xBC" => "\xE7\x88\xA7", + "\xF9\xBD" => "\xE8\x99\x8C", + "\xF9\xBE" => "\xE8\xBA\xA8", + "\xF9\xBF" => "\xE9\x92\x82", + "\xF9\xC0" => "\xE9\x92\x80", + "\xF9\xC1" => "\xE9\x92\x81", + "\xF9\xC2" => "\xE9\xA9\xA9", + "\xF9\xC3" => "\xE9\xA9\xA8", + "\xF9\xC4" => "\xE9\xAC\xAE", + "\xF9\xC5" => "\xE9\xB8\x99", + "\xF9\xC6" => "\xE7\x88\xA9", + "\xF9\xC7" => "\xE8\x99\x8B", + "\xF9\xC8" => "\xE8\xAE\x9F", + "\xF9\xC9" => "\xE9\x92\x83", + "\xF9\xCA" => "\xE9\xB1\xB9", + "\xF9\xCB" => "\xE9\xBA\xB7", + "\xF9\xCC" => "\xE7\x99\xB5", + "\xF9\xCD" => "\xE9\xA9\xAB", + "\xF9\xCE" => "\xE9\xB1\xBA", + "\xF9\xCF" => "\xE9\xB8\x9D", + "\xF9\xD0" => "\xE7\x81\xA9", + "\xF9\xD1" => "\xE7\x81\xAA", + "\xF9\xD2" => "\xE9\xBA\xA4", + "\xF9\xD3" => "\xE9\xBD\xBE", + "\xF9\xD4" => "\xE9\xBD\x89", + "\xF9\xD5" => "\xE9\xBE\x98", + ); + return strtr($string, $transform); +} + +?>
\ 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 new file mode 100644 index 0000000000..3304b18cdd --- /dev/null +++ b/phpBB/includes/utf/data/search_indexer_0.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..6173117ffc --- /dev/null +++ b/phpBB/includes/utf/data/search_indexer_1.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..e26f7d81a0 --- /dev/null +++ b/phpBB/includes/utf/data/search_indexer_19.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..751226ed22 --- /dev/null +++ b/phpBB/includes/utf/data/search_indexer_2.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..caab3c540b --- /dev/null +++ b/phpBB/includes/utf/data/search_indexer_20.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..7fc3e4dc09 --- /dev/null +++ b/phpBB/includes/utf/data/search_indexer_21.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..b8718bd608 --- /dev/null +++ b/phpBB/includes/utf/data/search_indexer_26.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..41798c9e86 --- /dev/null +++ b/phpBB/includes/utf/data/search_indexer_3.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..191365a313 --- /dev/null +++ b/phpBB/includes/utf/data/search_indexer_31.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..73ed2924ab --- /dev/null +++ b/phpBB/includes/utf/data/search_indexer_32.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..4e8762a646 --- /dev/null +++ b/phpBB/includes/utf/data/search_indexer_33.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..8bf908e514 --- /dev/null +++ b/phpBB/includes/utf/data/search_indexer_36.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..51acbff1c2 --- /dev/null +++ b/phpBB/includes/utf/data/search_indexer_4.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..32ac28a549 --- /dev/null +++ b/phpBB/includes/utf/data/search_indexer_448.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..0f1228a394 --- /dev/null +++ b/phpBB/includes/utf/data/search_indexer_5.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..8902bc7995 --- /dev/null +++ b/phpBB/includes/utf/data/search_indexer_58.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..f6d2ac0665 --- /dev/null +++ b/phpBB/includes/utf/data/search_indexer_6.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..44d0beb624 --- /dev/null +++ b/phpBB/includes/utf/data/search_indexer_64.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..5c3f1d54b8 --- /dev/null +++ b/phpBB/includes/utf/data/search_indexer_84.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..bdf188291f --- /dev/null +++ b/phpBB/includes/utf/data/search_indexer_9.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..b0f8eed3aa --- /dev/null +++ b/phpBB/includes/utf/data/search_indexer_95.php @@ -0,0 +1 @@ +<?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 new file mode 100644 index 0000000000..a3ed3ee602 --- /dev/null +++ b/phpBB/includes/utf/data/utf_canonical_comp.php @@ -0,0 +1,2 @@ +<?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 new file mode 100644 index 0000000000..460a0cf323 --- /dev/null +++ b/phpBB/includes/utf/data/utf_canonical_decomp.php @@ -0,0 +1,2 @@ +<?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 new file mode 100644 index 0000000000..08a7a047a4 --- /dev/null +++ b/phpBB/includes/utf/data/utf_compatibility_decomp.php @@ -0,0 +1,2 @@ +<?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 new file mode 100644 index 0000000000..03031f8b6d --- /dev/null +++ b/phpBB/includes/utf/data/utf_nfc_qc.php @@ -0,0 +1,2 @@ +<?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 new file mode 100644 index 0000000000..da9a8a0e89 --- /dev/null +++ b/phpBB/includes/utf/data/utf_nfkc_qc.php @@ -0,0 +1,2 @@ +<?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 new file mode 100644 index 0000000000..befc17d410 --- /dev/null +++ b/phpBB/includes/utf/data/utf_normalizer_common.php @@ -0,0 +1,4 @@ +<?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 new file mode 100644 index 0000000000..a77952499a --- /dev/null +++ b/phpBB/includes/utf/utf_normalizer.php @@ -0,0 +1,1516 @@ +<?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; +} + +/** +* Some Unicode characters encoded in UTF-8 +* +* Preserved for compatibility +*/ +define('UTF8_REPLACEMENT', "\xEF\xBF\xBD"); +define('UTF8_MAX', "\xF4\x8F\xBF\xBF"); +define('UTF8_FFFE', "\xEF\xBF\xBE"); +define('UTF8_FFFF', "\xEF\xBF\xBF"); +define('UTF8_SURROGATE_FIRST', "\xED\xA0\x80"); +define('UTF8_SURROGATE_LAST', "\xED\xBF\xBF"); +define('UTF8_HANGUL_FIRST', "\xEA\xB0\x80"); +define('UTF8_HANGUL_LAST', "\xED\x9E\xA3"); + +define('UTF8_CJK_FIRST', "\xE4\xB8\x80"); +define('UTF8_CJK_LAST', "\xE9\xBE\xBB"); +define('UTF8_CJK_B_FIRST', "\xF0\xA0\x80\x80"); +define('UTF8_CJK_B_LAST', "\xF0\xAA\x9B\x96"); + +// 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']); + +// NFC_QC and NFKC_QC values +define('UNICODE_QC_MAYBE', 0); +define('UNICODE_QC_NO', 1); + +// Contains all the ASCII characters appearing in UTF-8, sorted by frequency +define('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 +define('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 +define('UNICODE_HANGUL_SBASE', 0xAC00); +define('UNICODE_HANGUL_LBASE', 0x1100); +define('UNICODE_HANGUL_VBASE', 0x1161); +define('UNICODE_HANGUL_TBASE', 0x11A7); +define('UNICODE_HANGUL_SCOUNT', 11172); +define('UNICODE_HANGUL_LCOUNT', 19); +define('UNICODE_HANGUL_VCOUNT', 21); +define('UNICODE_HANGUL_TCOUNT', 28); +define('UNICODE_HANGUL_NCOUNT', 588); +define('UNICODE_JAMO_L', 0); +define('UNICODE_JAMO_V', 1); +define('UNICODE_JAMO_T', 2); + +/** +* Unicode normalization routines +* +* @package utf +*/ +class utf_normalizer +{ + /** + * 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 + */ + function cleanup(&$str) + { + // The string below is the list of all autorized 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'])) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/utf/data/utf_nfc_qc.' . $phpEx); + } + + if (!isset($GLOBALS['utf_canonical_decomp'])) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/utf/data/utf_canonical_decomp.' . $phpEx); + } + + // 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 = utf_normalizer::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 + */ + function nfc(&$str) + { + $pos = strspn($str, UTF8_ASCII_RANGE); + $len = strlen($str); + + if ($pos == $len) + { + // ASCII strings return immediately + return; + } + + if (!isset($GLOBALS['utf_nfc_qc'])) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/utf/data/utf_nfc_qc.' . $phpEx); + } + + if (!isset($GLOBALS['utf_canonical_decomp'])) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/utf/data/utf_canonical_decomp.' . $phpEx); + } + + $str = utf_normalizer::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 + */ + function nfkc(&$str) + { + $pos = strspn($str, UTF8_ASCII_RANGE); + $len = strlen($str); + + if ($pos == $len) + { + // ASCII strings return immediately + return; + } + + if (!isset($GLOBALS['utf_nfkc_qc'])) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/utf/data/utf_nfkc_qc.' . $phpEx); + } + + if (!isset($GLOBALS['utf_compatibility_decomp'])) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/utf/data/utf_compatibility_decomp.' . $phpEx); + } + + $str = utf_normalizer::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 + */ + function nfd(&$str) + { + $pos = strspn($str, UTF8_ASCII_RANGE); + $len = strlen($str); + + if ($pos == $len) + { + // ASCII strings return immediately + return; + } + + if (!isset($GLOBALS['utf_canonical_decomp'])) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/utf/data/utf_canonical_decomp.' . $phpEx); + } + + $str = utf_normalizer::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 + */ + function nfkd(&$str) + { + $pos = strspn($str, UTF8_ASCII_RANGE); + $len = strlen($str); + + if ($pos == $len) + { + // ASCII strings return immediately + return; + } + + if (!isset($GLOBALS['utf_compatibility_decomp'])) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/utf/data/utf_compatibility_decomp.' . $phpEx); + } + + $str = utf_normalizer::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 + */ + 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)) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/utf/data/utf_normalizer_common.' . $phpEx); + } + + // Load the canonical composition table + if (!isset($utf_canonical_comp)) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/utf/data/utf_canonical_comp.' . $phpEx); + } + + // 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) . UTF8_REPLACEMENT; + $pos += strspn($str, 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) . 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) . 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) . 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) . 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) . 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 > 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) . UTF8_REPLACEMENT; + $pos += strspn($str, 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, UTF8_TRAILING_BYTES, $pos); + $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . str_repeat(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] == 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 + // Note: the two commented lines below can be enabled under PHP5 for a very small performance gain in most cases +// 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] == UNICODE_JAMO_L && $utf_jamo_type[$utf_char] == 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]] == 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, 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 + */ + function decompose($str, $pos, $len, &$decomp_map) + { + global $utf_combining_class; + + // Load some commonly-used tables + if (!isset($utf_combining_class)) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/utf/data/utf_normalizer_common.' . $phpEx); + } + + // 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, 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(UTF8_REPLACEMENT, $spn); + $dump = $sort = 0; + } + else + { + $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . str_repeat(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 < UTF8_HANGUL_FIRST || $utf_char > 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, UTF8_TRAILING_BYTES, ++$pos); + $tmp .= str_repeat(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 .= 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 .= 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 .= 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 .= 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 .= UTF8_REPLACEMENT; + $dump = $sort = 0; + + $tmp_pos = $starter_pos = $pos; + continue 2; + } + break; + + default: + if ($utf_char > 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 .= 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)) - 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 % 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 / UNICODE_HANGUL_NCOUNT)); + $utf_char[5] = chr(0xA1 + (int) (($idx % UNICODE_HANGUL_NCOUNT) / 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, UTF8_ASCII_RANGE, $pos); + } + else + { + $pos += strspn($str, 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 new file mode 100644 index 0000000000..6f3ac93305 --- /dev/null +++ b/phpBB/includes/utf/utf_tools.php @@ -0,0 +1,1995 @@ +<?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 strtolower + * @ignore + */ + function utf8_strtolower($str) + { + return mb_strtolower($str); + } + + /** + * UTF-8 aware alternative to strtoupper + * @ignore + */ + function utf8_strtoupper($str) + { + return mb_strtoupper($str); + } + + /** + * 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 strtolower + * Make a string lowercase + * Note: The concept of a characters "case" only exists is some alphabets + * such as Latin, Greek, Cyrillic, Armenian and archaic Georgian - it does + * not exist in the Chinese alphabet, for example. See Unicode Standard + * Annex #21: Case Mappings + * + * @param string + * @return string string in lowercase + */ + function utf8_strtolower($string) + { + static $utf8_upper_to_lower = array( + "\xC3\x80" => "\xC3\xA0", "\xC3\x81" => "\xC3\xA1", + "\xC3\x82" => "\xC3\xA2", "\xC3\x83" => "\xC3\xA3", "\xC3\x84" => "\xC3\xA4", "\xC3\x85" => "\xC3\xA5", + "\xC3\x86" => "\xC3\xA6", "\xC3\x87" => "\xC3\xA7", "\xC3\x88" => "\xC3\xA8", "\xC3\x89" => "\xC3\xA9", + "\xC3\x8A" => "\xC3\xAA", "\xC3\x8B" => "\xC3\xAB", "\xC3\x8C" => "\xC3\xAC", "\xC3\x8D" => "\xC3\xAD", + "\xC3\x8E" => "\xC3\xAE", "\xC3\x8F" => "\xC3\xAF", "\xC3\x90" => "\xC3\xB0", "\xC3\x91" => "\xC3\xB1", + "\xC3\x92" => "\xC3\xB2", "\xC3\x93" => "\xC3\xB3", "\xC3\x94" => "\xC3\xB4", "\xC3\x95" => "\xC3\xB5", + "\xC3\x96" => "\xC3\xB6", "\xC3\x98" => "\xC3\xB8", "\xC3\x99" => "\xC3\xB9", "\xC3\x9A" => "\xC3\xBA", + "\xC3\x9B" => "\xC3\xBB", "\xC3\x9C" => "\xC3\xBC", "\xC3\x9D" => "\xC3\xBD", "\xC3\x9E" => "\xC3\xBE", + "\xC4\x80" => "\xC4\x81", "\xC4\x82" => "\xC4\x83", "\xC4\x84" => "\xC4\x85", "\xC4\x86" => "\xC4\x87", + "\xC4\x88" => "\xC4\x89", "\xC4\x8A" => "\xC4\x8B", "\xC4\x8C" => "\xC4\x8D", "\xC4\x8E" => "\xC4\x8F", + "\xC4\x90" => "\xC4\x91", "\xC4\x92" => "\xC4\x93", "\xC4\x96" => "\xC4\x97", "\xC4\x98" => "\xC4\x99", + "\xC4\x9A" => "\xC4\x9B", "\xC4\x9C" => "\xC4\x9D", "\xC4\x9E" => "\xC4\x9F", "\xC4\xA0" => "\xC4\xA1", + "\xC4\xA2" => "\xC4\xA3", "\xC4\xA4" => "\xC4\xA5", "\xC4\xA6" => "\xC4\xA7", "\xC4\xA8" => "\xC4\xA9", + "\xC4\xAA" => "\xC4\xAB", "\xC4\xAE" => "\xC4\xAF", "\xC4\xB4" => "\xC4\xB5", "\xC4\xB6" => "\xC4\xB7", + "\xC4\xB9" => "\xC4\xBA", "\xC4\xBB" => "\xC4\xBC", "\xC4\xBD" => "\xC4\xBE", "\xC5\x81" => "\xC5\x82", + "\xC5\x83" => "\xC5\x84", "\xC5\x85" => "\xC5\x86", "\xC5\x87" => "\xC5\x88", "\xC5\x8A" => "\xC5\x8B", + "\xC5\x8C" => "\xC5\x8D", "\xC5\x90" => "\xC5\x91", "\xC5\x94" => "\xC5\x95", "\xC5\x96" => "\xC5\x97", + "\xC5\x98" => "\xC5\x99", "\xC5\x9A" => "\xC5\x9B", "\xC5\x9C" => "\xC5\x9D", "\xC5\x9E" => "\xC5\x9F", + "\xC5\xA0" => "\xC5\xA1", "\xC5\xA2" => "\xC5\xA3", "\xC5\xA4" => "\xC5\xA5", "\xC5\xA6" => "\xC5\xA7", + "\xC5\xA8" => "\xC5\xA9", "\xC5\xAA" => "\xC5\xAB", "\xC5\xAC" => "\xC5\xAD", "\xC5\xAE" => "\xC5\xAF", + "\xC5\xB0" => "\xC5\xB1", "\xC5\xB2" => "\xC5\xB3", "\xC5\xB4" => "\xC5\xB5", "\xC5\xB6" => "\xC5\xB7", + "\xC5\xB8" => "\xC3\xBF", "\xC5\xB9" => "\xC5\xBA", "\xC5\xBB" => "\xC5\xBC", "\xC5\xBD" => "\xC5\xBE", + "\xC6\xA0" => "\xC6\xA1", "\xC6\xAF" => "\xC6\xB0", "\xC8\x98" => "\xC8\x99", "\xC8\x9A" => "\xC8\x9B", + "\xCE\x86" => "\xCE\xAC", "\xCE\x88" => "\xCE\xAD", "\xCE\x89" => "\xCE\xAE", "\xCE\x8A" => "\xCE\xAF", + "\xCE\x8C" => "\xCF\x8C", "\xCE\x8E" => "\xCF\x8D", "\xCE\x8F" => "\xCF\x8E", "\xCE\x91" => "\xCE\xB1", + "\xCE\x92" => "\xCE\xB2", "\xCE\x93" => "\xCE\xB3", "\xCE\x94" => "\xCE\xB4", "\xCE\x95" => "\xCE\xB5", + "\xCE\x96" => "\xCE\xB6", "\xCE\x97" => "\xCE\xB7", "\xCE\x98" => "\xCE\xB8", "\xCE\x99" => "\xCE\xB9", + "\xCE\x9A" => "\xCE\xBA", "\xCE\x9B" => "\xCE\xBB", "\xCE\x9C" => "\xCE\xBC", "\xCE\x9D" => "\xCE\xBD", + "\xCE\x9E" => "\xCE\xBE", "\xCE\x9F" => "\xCE\xBF", "\xCE\xA0" => "\xCF\x80", "\xCE\xA1" => "\xCF\x81", + "\xCE\xA3" => "\xCF\x83", "\xCE\xA4" => "\xCF\x84", "\xCE\xA5" => "\xCF\x85", "\xCE\xA6" => "\xCF\x86", + "\xCE\xA7" => "\xCF\x87", "\xCE\xA8" => "\xCF\x88", "\xCE\xA9" => "\xCF\x89", "\xCE\xAA" => "\xCF\x8A", + "\xCE\xAB" => "\xCF\x8B", "\xD0\x81" => "\xD1\x91", "\xD0\x82" => "\xD1\x92", "\xD0\x83" => "\xD1\x93", + "\xD0\x84" => "\xD1\x94", "\xD0\x85" => "\xD1\x95", "\xD0\x86" => "\xD1\x96", "\xD0\x87" => "\xD1\x97", + "\xD0\x88" => "\xD1\x98", "\xD0\x89" => "\xD1\x99", "\xD0\x8A" => "\xD1\x9A", "\xD0\x8B" => "\xD1\x9B", + "\xD0\x8C" => "\xD1\x9C", "\xD0\x8E" => "\xD1\x9E", "\xD0\x8F" => "\xD1\x9F", "\xD0\x90" => "\xD0\xB0", + "\xD0\x91" => "\xD0\xB1", "\xD0\x92" => "\xD0\xB2", "\xD0\x93" => "\xD0\xB3", "\xD0\x94" => "\xD0\xB4", + "\xD0\x95" => "\xD0\xB5", "\xD0\x96" => "\xD0\xB6", "\xD0\x97" => "\xD0\xB7", "\xD0\x98" => "\xD0\xB8", + "\xD0\x99" => "\xD0\xB9", "\xD0\x9A" => "\xD0\xBA", "\xD0\x9B" => "\xD0\xBB", "\xD0\x9C" => "\xD0\xBC", + "\xD0\x9D" => "\xD0\xBD", "\xD0\x9E" => "\xD0\xBE", "\xD0\x9F" => "\xD0\xBF", "\xD0\xA0" => "\xD1\x80", + "\xD0\xA1" => "\xD1\x81", "\xD0\xA2" => "\xD1\x82", "\xD0\xA3" => "\xD1\x83", "\xD0\xA4" => "\xD1\x84", + "\xD0\xA5" => "\xD1\x85", "\xD0\xA6" => "\xD1\x86", "\xD0\xA7" => "\xD1\x87", "\xD0\xA8" => "\xD1\x88", + "\xD0\xA9" => "\xD1\x89", "\xD0\xAA" => "\xD1\x8A", "\xD0\xAB" => "\xD1\x8B", "\xD0\xAC" => "\xD1\x8C", + "\xD0\xAD" => "\xD1\x8D", "\xD0\xAE" => "\xD1\x8E", "\xD0\xAF" => "\xD1\x8F", "\xD2\x90" => "\xD2\x91", + "\xE1\xB8\x82" => "\xE1\xB8\x83", "\xE1\xB8\x8A" => "\xE1\xB8\x8B", "\xE1\xB8\x9E" => "\xE1\xB8\x9F", "\xE1\xB9\x80" => "\xE1\xB9\x81", + "\xE1\xB9\x96" => "\xE1\xB9\x97", "\xE1\xB9\xA0" => "\xE1\xB9\xA1", "\xE1\xB9\xAA" => "\xE1\xB9\xAB", "\xE1\xBA\x80" => "\xE1\xBA\x81", + "\xE1\xBA\x82" => "\xE1\xBA\x83", "\xE1\xBA\x84" => "\xE1\xBA\x85", "\xE1\xBB\xB2" => "\xE1\xBB\xB3" + ); + + return strtr(strtolower($string), $utf8_upper_to_lower); + } + + /** + * UTF-8 aware alternative to strtoupper + * Make a string uppercase + * Note: The concept of a characters "case" only exists is some alphabets + * such as Latin, Greek, Cyrillic, Armenian and archaic Georgian - it does + * not exist in the Chinese alphabet, for example. See Unicode Standard + * Annex #21: Case Mappings + * + * @param string + * @return string string in uppercase + */ + function utf8_strtoupper($string) + { + static $utf8_lower_to_upper = array( + "\xC3\xA0" => "\xC3\x80", "\xC3\xA1" => "\xC3\x81", + "\xC3\xA2" => "\xC3\x82", "\xC3\xA3" => "\xC3\x83", "\xC3\xA4" => "\xC3\x84", "\xC3\xA5" => "\xC3\x85", + "\xC3\xA6" => "\xC3\x86", "\xC3\xA7" => "\xC3\x87", "\xC3\xA8" => "\xC3\x88", "\xC3\xA9" => "\xC3\x89", + "\xC3\xAA" => "\xC3\x8A", "\xC3\xAB" => "\xC3\x8B", "\xC3\xAC" => "\xC3\x8C", "\xC3\xAD" => "\xC3\x8D", + "\xC3\xAE" => "\xC3\x8E", "\xC3\xAF" => "\xC3\x8F", "\xC3\xB0" => "\xC3\x90", "\xC3\xB1" => "\xC3\x91", + "\xC3\xB2" => "\xC3\x92", "\xC3\xB3" => "\xC3\x93", "\xC3\xB4" => "\xC3\x94", "\xC3\xB5" => "\xC3\x95", + "\xC3\xB6" => "\xC3\x96", "\xC3\xB8" => "\xC3\x98", "\xC3\xB9" => "\xC3\x99", "\xC3\xBA" => "\xC3\x9A", + "\xC3\xBB" => "\xC3\x9B", "\xC3\xBC" => "\xC3\x9C", "\xC3\xBD" => "\xC3\x9D", "\xC3\xBE" => "\xC3\x9E", + "\xC3\xBF" => "\xC5\xB8", "\xC4\x81" => "\xC4\x80", "\xC4\x83" => "\xC4\x82", "\xC4\x85" => "\xC4\x84", + "\xC4\x87" => "\xC4\x86", "\xC4\x89" => "\xC4\x88", "\xC4\x8B" => "\xC4\x8A", "\xC4\x8D" => "\xC4\x8C", + "\xC4\x8F" => "\xC4\x8E", "\xC4\x91" => "\xC4\x90", "\xC4\x93" => "\xC4\x92", "\xC4\x97" => "\xC4\x96", + "\xC4\x99" => "\xC4\x98", "\xC4\x9B" => "\xC4\x9A", "\xC4\x9D" => "\xC4\x9C", "\xC4\x9F" => "\xC4\x9E", + "\xC4\xA1" => "\xC4\xA0", "\xC4\xA3" => "\xC4\xA2", "\xC4\xA5" => "\xC4\xA4", "\xC4\xA7" => "\xC4\xA6", + "\xC4\xA9" => "\xC4\xA8", "\xC4\xAB" => "\xC4\xAA", "\xC4\xAF" => "\xC4\xAE", "\xC4\xB5" => "\xC4\xB4", + "\xC4\xB7" => "\xC4\xB6", "\xC4\xBA" => "\xC4\xB9", "\xC4\xBC" => "\xC4\xBB", "\xC4\xBE" => "\xC4\xBD", + "\xC5\x82" => "\xC5\x81", "\xC5\x84" => "\xC5\x83", "\xC5\x86" => "\xC5\x85", "\xC5\x88" => "\xC5\x87", + "\xC5\x8B" => "\xC5\x8A", "\xC5\x8D" => "\xC5\x8C", "\xC5\x91" => "\xC5\x90", "\xC5\x95" => "\xC5\x94", + "\xC5\x97" => "\xC5\x96", "\xC5\x99" => "\xC5\x98", "\xC5\x9B" => "\xC5\x9A", "\xC5\x9D" => "\xC5\x9C", + "\xC5\x9F" => "\xC5\x9E", "\xC5\xA1" => "\xC5\xA0", "\xC5\xA3" => "\xC5\xA2", "\xC5\xA5" => "\xC5\xA4", + "\xC5\xA7" => "\xC5\xA6", "\xC5\xA9" => "\xC5\xA8", "\xC5\xAB" => "\xC5\xAA", "\xC5\xAD" => "\xC5\xAC", + "\xC5\xAF" => "\xC5\xAE", "\xC5\xB1" => "\xC5\xB0", "\xC5\xB3" => "\xC5\xB2", "\xC5\xB5" => "\xC5\xB4", + "\xC5\xB7" => "\xC5\xB6", "\xC5\xBA" => "\xC5\xB9", "\xC5\xBC" => "\xC5\xBB", "\xC5\xBE" => "\xC5\xBD", + "\xC6\xA1" => "\xC6\xA0", "\xC6\xB0" => "\xC6\xAF", "\xC8\x99" => "\xC8\x98", "\xC8\x9B" => "\xC8\x9A", + "\xCE\xAC" => "\xCE\x86", "\xCE\xAD" => "\xCE\x88", "\xCE\xAE" => "\xCE\x89", "\xCE\xAF" => "\xCE\x8A", + "\xCE\xB1" => "\xCE\x91", "\xCE\xB2" => "\xCE\x92", "\xCE\xB3" => "\xCE\x93", "\xCE\xB4" => "\xCE\x94", + "\xCE\xB5" => "\xCE\x95", "\xCE\xB6" => "\xCE\x96", "\xCE\xB7" => "\xCE\x97", "\xCE\xB8" => "\xCE\x98", + "\xCE\xB9" => "\xCE\x99", "\xCE\xBA" => "\xCE\x9A", "\xCE\xBB" => "\xCE\x9B", "\xCE\xBC" => "\xCE\x9C", + "\xCE\xBD" => "\xCE\x9D", "\xCE\xBE" => "\xCE\x9E", "\xCE\xBF" => "\xCE\x9F", "\xCF\x80" => "\xCE\xA0", + "\xCF\x81" => "\xCE\xA1", "\xCF\x83" => "\xCE\xA3", "\xCF\x84" => "\xCE\xA4", "\xCF\x85" => "\xCE\xA5", + "\xCF\x86" => "\xCE\xA6", "\xCF\x87" => "\xCE\xA7", "\xCF\x88" => "\xCE\xA8", "\xCF\x89" => "\xCE\xA9", + "\xCF\x8A" => "\xCE\xAA", "\xCF\x8B" => "\xCE\xAB", "\xCF\x8C" => "\xCE\x8C", "\xCF\x8D" => "\xCE\x8E", + "\xCF\x8E" => "\xCE\x8F", "\xD0\xB0" => "\xD0\x90", "\xD0\xB1" => "\xD0\x91", "\xD0\xB2" => "\xD0\x92", + "\xD0\xB3" => "\xD0\x93", "\xD0\xB4" => "\xD0\x94", "\xD0\xB5" => "\xD0\x95", "\xD0\xB6" => "\xD0\x96", + "\xD0\xB7" => "\xD0\x97", "\xD0\xB8" => "\xD0\x98", "\xD0\xB9" => "\xD0\x99", "\xD0\xBA" => "\xD0\x9A", + "\xD0\xBB" => "\xD0\x9B", "\xD0\xBC" => "\xD0\x9C", "\xD0\xBD" => "\xD0\x9D", "\xD0\xBE" => "\xD0\x9E", + "\xD0\xBF" => "\xD0\x9F", "\xD1\x80" => "\xD0\xA0", "\xD1\x81" => "\xD0\xA1", "\xD1\x82" => "\xD0\xA2", + "\xD1\x83" => "\xD0\xA3", "\xD1\x84" => "\xD0\xA4", "\xD1\x85" => "\xD0\xA5", "\xD1\x86" => "\xD0\xA6", + "\xD1\x87" => "\xD0\xA7", "\xD1\x88" => "\xD0\xA8", "\xD1\x89" => "\xD0\xA9", "\xD1\x8A" => "\xD0\xAA", + "\xD1\x8B" => "\xD0\xAB", "\xD1\x8C" => "\xD0\xAC", "\xD1\x8D" => "\xD0\xAD", "\xD1\x8E" => "\xD0\xAE", + "\xD1\x8F" => "\xD0\xAF", "\xD1\x91" => "\xD0\x81", "\xD1\x92" => "\xD0\x82", "\xD1\x93" => "\xD0\x83", + "\xD1\x94" => "\xD0\x84", "\xD1\x95" => "\xD0\x85", "\xD1\x96" => "\xD0\x86", "\xD1\x97" => "\xD0\x87", + "\xD1\x98" => "\xD0\x88", "\xD1\x99" => "\xD0\x89", "\xD1\x9A" => "\xD0\x8A", "\xD1\x9B" => "\xD0\x8B", + "\xD1\x9C" => "\xD0\x8C", "\xD1\x9E" => "\xD0\x8E", "\xD1\x9F" => "\xD0\x8F", "\xD2\x91" => "\xD2\x90", + "\xE1\xB8\x83" => "\xE1\xB8\x82", "\xE1\xB8\x8B" => "\xE1\xB8\x8A", "\xE1\xB8\x9F" => "\xE1\xB8\x9E", "\xE1\xB9\x81" => "\xE1\xB9\x80", + "\xE1\xB9\x97" => "\xE1\xB9\x96", "\xE1\xB9\xA1" => "\xE1\xB9\xA0", "\xE1\xB9\xAB" => "\xE1\xB9\xAA", "\xE1\xBA\x81" => "\xE1\xBA\x80", + "\xE1\xBA\x83" => "\xE1\xBA\x82", "\xE1\xBA\x85" => "\xE1\xBA\x84", "\xE1\xBB\xB3" => "\xE1\xBB\xB2" + ); + + return strtr(strtoupper($string), $utf8_lower_to_upper); + } + + /** + * 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; +} + +/** +* UTF-8 aware alternative to ucfirst +* Make a string's first character uppercase +* +* @author Harry Fuecks +* @param string +* @return string with first character as upper case (if applicable) +*/ +function utf8_ucfirst($str) +{ + switch (utf8_strlen($str)) + { + case 0: + return ''; + break; + + case 1: + return utf8_strtoupper($str); + break; + + default: + preg_match('/^(.{1})(.*)$/us', $str, $matches); + return utf8_strtoupper($matches[1]) . $matches[2]; + break; + } +} + +/** +* Recode a string to UTF-8 +* +* If the encoding is not supported, the string is returned as-is +* +* @param string $string Original string +* @param string $encoding Original encoding (lowered) +* @return string The string, encoded in UTF-8 +*/ +function utf8_recode($string, $encoding) +{ + $encoding = strtolower($encoding); + + if ($encoding == 'utf-8' || !is_string($string) || empty($string)) + { + return $string; + } + + // we force iso-8859-1 to be cp1252 + if ($encoding == 'iso-8859-1') + { + $encoding = 'cp1252'; + } + // convert iso-8859-8-i to iso-8859-8 + else if ($encoding == 'iso-8859-8-i') + { + $encoding = 'iso-8859-8'; + $string = hebrev($string); + } + + // First, try iconv() + if (function_exists('iconv')) + { + $ret = @iconv($encoding, 'utf-8', $string); + + if (!empty($ret)) + { + return $ret; + } + } + + // Try the mb_string extension + if (function_exists('mb_convert_encoding')) + { + // mbstring is nasty on PHP4, we must make *sure* that we send a good encoding + switch ($encoding) + { + case 'iso-8859-1': + case 'iso-8859-2': + case 'iso-8859-4': + case 'iso-8859-7': + case 'iso-8859-9': + case 'iso-8859-15': + case 'windows-1251': + case 'windows-1252': + case 'cp1252': + case 'shift_jis': + case 'euc-kr': + case 'big5': + case 'gb2312': + $ret = @mb_convert_encoding($string, 'utf-8', $encoding); + + if (!empty($ret)) + { + return $ret; + } + } + } + + // Try the recode extension + if (function_exists('recode_string')) + { + $ret = @recode_string($encoding . '..utf-8', $string); + + if (!empty($ret)) + { + return $ret; + } + } + + // If nothing works, check if we have a custom transcoder available + if (!preg_match('#^[a-z0-9_ \\-]+$#', $encoding)) + { + // Make sure the encoding name is alphanumeric, we don't want it to be abused into loading arbitrary files + trigger_error('Unknown encoding: ' . $encoding, E_USER_ERROR); + } + + global $phpbb_root_path, $phpEx; + + // iso-8859-* character encoding + if (preg_match('/iso[_ -]?8859[_ -]?(\\d+)/', $encoding, $array)) + { + switch ($array[1]) + { + case '1': + case '2': + case '4': + case '7': + case '8': + case '9': + case '15': + if (!function_exists('iso_8859_' . $array[1])) + { + if (!file_exists($phpbb_root_path . 'includes/utf/data/recode_basic.' . $phpEx)) + { + trigger_error('Basic reencoder file is missing', E_USER_ERROR); + } + include($phpbb_root_path . 'includes/utf/data/recode_basic.' . $phpEx); + } + return call_user_func('iso_8859_' . $array[1], $string); + break; + + default: + trigger_error('Unknown encoding: ' . $encoding, E_USER_ERROR); + break; + } + } + + // CP/WIN character encoding + if (preg_match('/(?:cp|windows)[_\- ]?(\\d+)/', $encoding, $array)) + { + switch ($array[1]) + { + case '932': + break; + case '1250': + case '1251': + case '1252': + case '1254': + case '1255': + case '1256': + case '1257': + case '874': + if (!function_exists('cp' . $array[1])) + { + if (!file_exists($phpbb_root_path . 'includes/utf/data/recode_basic.' . $phpEx)) + { + trigger_error('Basic reencoder file is missing', E_USER_ERROR); + } + include($phpbb_root_path . 'includes/utf/data/recode_basic.' . $phpEx); + } + return call_user_func('cp' . $array[1], $string); + break; + + default: + trigger_error('Unknown encoding: ' . $encoding, E_USER_ERROR); + break; + } + } + + // TIS-620 + if (preg_match('/tis[_ -]?620/', $encoding)) + { + if (!function_exists('tis_620')) + { + if (!file_exists($phpbb_root_path . 'includes/utf/data/recode_basic.' . $phpEx)) + { + trigger_error('Basic reencoder file is missing', E_USER_ERROR); + } + include($phpbb_root_path . 'includes/utf/data/recode_basic.' . $phpEx); + } + return tis_620($string); + } + + // SJIS + if (preg_match('/sjis(?:[_ -]?win)?|(?:cp|ibm)[_ -]?932|shift[_ -]?jis/', $encoding)) + { + if (!function_exists('sjis')) + { + if (!file_exists($phpbb_root_path . 'includes/utf/data/recode_cjk.' . $phpEx)) + { + trigger_error('CJK reencoder file is missing', E_USER_ERROR); + } + include($phpbb_root_path . 'includes/utf/data/recode_cjk.' . $phpEx); + } + return sjis($string); + } + + // EUC_KR + if (preg_match('/euc[_ -]?kr/', $encoding)) + { + if (!function_exists('euc_kr')) + { + if (!file_exists($phpbb_root_path . 'includes/utf/data/recode_cjk.' . $phpEx)) + { + trigger_error('CJK reencoder file is missing', E_USER_ERROR); + } + include($phpbb_root_path . 'includes/utf/data/recode_cjk.' . $phpEx); + } + return euc_kr($string); + } + + // BIG-5 + if (preg_match('/big[_ -]?5/', $encoding)) + { + if (!function_exists('big5')) + { + if (!file_exists($phpbb_root_path . 'includes/utf/data/recode_cjk.' . $phpEx)) + { + trigger_error('CJK reencoder file is missing', E_USER_ERROR); + } + include($phpbb_root_path . 'includes/utf/data/recode_cjk.' . $phpEx); + } + return big5($string); + } + + // GB2312 + if (preg_match('/gb[_ -]?2312/', $encoding)) + { + if (!function_exists('gb2312')) + { + if (!file_exists($phpbb_root_path . 'includes/utf/data/recode_cjk.' . $phpEx)) + { + trigger_error('CJK reencoder file is missing', E_USER_ERROR); + } + include($phpbb_root_path . 'includes/utf/data/recode_cjk.' . $phpEx); + } + return gb2312($string); + } + + // Trigger an error?! Fow now just give bad data :-( + trigger_error('Unknown encoding: ' . $encoding, E_USER_ERROR); + //return $string; // use utf_normalizer::cleanup() ? +} + +/** +* 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(); + global $phpbb_root_path, $phpEx; + + // common is always set + if (!isset($uniarray['c'])) + { + $uniarray['c'] = include($phpbb_root_path . 'includes/utf/data/case_fold_c.' . $phpEx); + } + + // 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.' . $phpEx); + } + + // 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.' . $phpEx); + } + + // 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", + ); + global $phpbb_root_path, $phpEx; + + // do the case fold + $text = utf8_case_fold($text, $option); + + if (!class_exists('utf_normalizer')) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx); + } + + // 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", + ); + global $phpbb_root_path, $phpEx; + + // 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). +* +* @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')) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx); + } + + 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) +{ + global $phpbb_root_path, $phpEx; + + static $homographs = array(); + if (empty($homographs)) + { + $homographs = include($phpbb_root_path . 'includes/utf/data/confusables.' . $phpEx); + } + + $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_recode($message, 'ISO-8859-1')); +} + +/** +* 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); +} + +/** +* UTF8-safe basename() function +* +* basename() has some limitations and is dependent on the locale setting +* according to the PHP manual. Therefore we provide our own locale independant +* basename function. +* +* @param string $filename The filename basename() should be applied to +* @return string The basenamed filename +*/ +function utf8_basename($filename) +{ + // We always check for forward slash AND backward slash + // because they could be mixed or "sneaked" in. ;) + // You know, never trust user input... + if (strpos($filename, '/') !== false) + { + $filename = utf8_substr($filename, utf8_strrpos($filename, '/') + 1); + } + + if (strpos($filename, '\\') !== false) + { + $filename = utf8_substr($filename, utf8_strrpos($filename, '\\') + 1); + } + + return $filename; +} + +/** +* UTF8-safe str_replace() function +* +* @param string $search The value to search for +* @param string $replace The replacement string +* @param string $subject The target string +* @return string The resultant string +*/ +function utf8_str_replace($search, $replace, $subject) +{ + if (!is_array($search)) + { + $search = array($search); + if (is_array($replace)) + { + $replace = (string) $replace; + trigger_error('Array to string conversion', E_USER_NOTICE); + } + } + + $length = sizeof($search); + + if (!is_array($replace)) + { + $replace = array_fill(0, $length, $replace); + } + else + { + $replace = array_pad($replace, $length, ''); + } + + for ($i = 0; $i < $length; $i++) + { + $search_length = utf8_strlen($search[$i]); + $replace_length = utf8_strlen($replace[$i]); + + $offset = 0; + while (($start = utf8_strpos($subject, $search[$i], $offset)) !== false) + { + $subject = utf8_substr($subject, 0, $start) . $replace[$i] . utf8_substr($subject, $start + $search_length); + $offset = $start + $replace_length; + } + } + + return $subject; +} + +?>
\ No newline at end of file |