aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/includes
diff options
context:
space:
mode:
Diffstat (limited to 'phpBB/includes')
-rw-r--r--phpBB/includes/acm/acm_apc.php84
-rw-r--r--phpBB/includes/acm/acm_eaccelerator.php120
-rw-r--r--phpBB/includes/acm/acm_file.php720
-rw-r--r--phpBB/includes/acm/acm_memcache.php124
-rw-r--r--phpBB/includes/acm/acm_memory.php426
-rw-r--r--phpBB/includes/acm/acm_null.php156
-rw-r--r--phpBB/includes/acm/acm_xcache.php121
-rw-r--r--phpBB/includes/acp/acp_attachments.php1452
-rw-r--r--phpBB/includes/acp/acp_ban.php252
-rw-r--r--phpBB/includes/acp/acp_bbcodes.php443
-rw-r--r--phpBB/includes/acp/acp_board.php957
-rw-r--r--phpBB/includes/acp/acp_bots.php418
-rw-r--r--phpBB/includes/acp/acp_captcha.php147
-rw-r--r--phpBB/includes/acp/acp_database.php2348
-rw-r--r--phpBB/includes/acp/acp_disallow.php108
-rw-r--r--phpBB/includes/acp/acp_email.php262
-rw-r--r--phpBB/includes/acp/acp_forums.php1947
-rw-r--r--phpBB/includes/acp/acp_groups.php789
-rw-r--r--phpBB/includes/acp/acp_icons.php946
-rw-r--r--phpBB/includes/acp/acp_inactive.php306
-rw-r--r--phpBB/includes/acp/acp_jabber.php131
-rw-r--r--phpBB/includes/acp/acp_language.php1453
-rw-r--r--phpBB/includes/acp/acp_logs.php176
-rw-r--r--phpBB/includes/acp/acp_main.php609
-rw-r--r--phpBB/includes/acp/acp_modules.php1065
-rw-r--r--phpBB/includes/acp/acp_permission_roles.php571
-rw-r--r--phpBB/includes/acp/acp_permissions.php1315
-rw-r--r--phpBB/includes/acp/acp_php_info.php84
-rw-r--r--phpBB/includes/acp/acp_profile.php1617
-rw-r--r--phpBB/includes/acp/acp_prune.php466
-rw-r--r--phpBB/includes/acp/acp_ranks.php240
-rw-r--r--phpBB/includes/acp/acp_reasons.php374
-rw-r--r--phpBB/includes/acp/acp_search.php629
-rw-r--r--phpBB/includes/acp/acp_send_statistics.php90
-rw-r--r--phpBB/includes/acp/acp_styles.php3768
-rw-r--r--phpBB/includes/acp/acp_update.php83
-rw-r--r--phpBB/includes/acp/acp_users.php2358
-rw-r--r--phpBB/includes/acp/acp_words.php187
-rw-r--r--phpBB/includes/acp/auth.php1285
-rw-r--r--phpBB/includes/acp/info/acp_attachments.php40
-rw-r--r--phpBB/includes/acp/info/acp_ban.php39
-rw-r--r--phpBB/includes/acp/info/acp_bbcodes.php37
-rw-r--r--phpBB/includes/acp/info/acp_board.php52
-rw-r--r--phpBB/includes/acp/info/acp_bots.php38
-rw-r--r--phpBB/includes/acp/info/acp_captcha.php38
-rw-r--r--phpBB/includes/acp/info/acp_database.php38
-rw-r--r--phpBB/includes/acp/info/acp_disallow.php38
-rw-r--r--phpBB/includes/acp/info/acp_email.php38
-rw-r--r--phpBB/includes/acp/info/acp_forums.php37
-rw-r--r--phpBB/includes/acp/info/acp_groups.php37
-rw-r--r--phpBB/includes/acp/info/acp_icons.php38
-rw-r--r--phpBB/includes/acp/info/acp_inactive.php37
-rw-r--r--phpBB/includes/acp/info/acp_jabber.php36
-rw-r--r--phpBB/includes/acp/info/acp_language.php37
-rw-r--r--phpBB/includes/acp/info/acp_logs.php40
-rw-r--r--phpBB/includes/acp/info/acp_main.php37
-rw-r--r--phpBB/includes/acp/info/acp_modules.php39
-rw-r--r--phpBB/includes/acp/info/acp_permission_roles.php40
-rw-r--r--phpBB/includes/acp/info/acp_permissions.php54
-rw-r--r--phpBB/includes/acp/info/acp_php_info.php37
-rw-r--r--phpBB/includes/acp/info/acp_profile.php37
-rw-r--r--phpBB/includes/acp/info/acp_prune.php38
-rw-r--r--phpBB/includes/acp/info/acp_ranks.php37
-rw-r--r--phpBB/includes/acp/info/acp_reasons.php37
-rw-r--r--phpBB/includes/acp/info/acp_search.php38
-rw-r--r--phpBB/includes/acp/info/acp_send_statistics.php37
-rw-r--r--phpBB/includes/acp/info/acp_styles.php40
-rw-r--r--phpBB/includes/acp/info/acp_update.php37
-rw-r--r--phpBB/includes/acp/info/acp_users.php47
-rw-r--r--phpBB/includes/acp/info/acp_words.php37
-rw-r--r--phpBB/includes/auth.php1046
-rw-r--r--phpBB/includes/auth/auth_apache.php249
-rw-r--r--phpBB/includes/auth/auth_db.php198
-rw-r--r--phpBB/includes/auth/auth_ldap.php349
-rw-r--r--phpBB/includes/auth/index.htm10
-rw-r--r--phpBB/includes/bbcode.php602
-rw-r--r--phpBB/includes/cache.php444
-rw-r--r--phpBB/includes/captcha/captcha_factory.php100
-rw-r--r--phpBB/includes/captcha/captcha_gd.php2640
-rw-r--r--phpBB/includes/captcha/captcha_gd_wave.php845
-rw-r--r--phpBB/includes/captcha/captcha_non_gd.php392
-rw-r--r--phpBB/includes/captcha/plugins/captcha_abstract.php375
-rw-r--r--phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php165
-rw-r--r--phpBB/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php83
-rw-r--r--phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php72
-rw-r--r--phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php945
-rw-r--r--phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php336
-rw-r--r--phpBB/includes/constants.php270
-rw-r--r--phpBB/includes/db/db_tools.php2032
-rw-r--r--phpBB/includes/db/dbal.php887
-rw-r--r--phpBB/includes/db/firebird.php512
-rw-r--r--phpBB/includes/db/index.htm10
-rw-r--r--phpBB/includes/db/mssql.php449
-rw-r--r--phpBB/includes/db/mssql_odbc.php426
-rw-r--r--phpBB/includes/db/mysql.php491
-rw-r--r--phpBB/includes/db/mysqli.php468
-rw-r--r--phpBB/includes/db/oracle.php752
-rw-r--r--phpBB/includes/db/postgres.php440
-rw-r--r--phpBB/includes/db/sqlite.php334
-rw-r--r--phpBB/includes/diff/diff.php1148
-rw-r--r--phpBB/includes/diff/engine.php554
-rw-r--r--phpBB/includes/diff/renderer.php860
-rw-r--r--phpBB/includes/functions.php4367
-rw-r--r--phpBB/includes/functions_admin.php3303
-rw-r--r--phpBB/includes/functions_compress.php723
-rw-r--r--phpBB/includes/functions_content.php1357
-rw-r--r--phpBB/includes/functions_convert.php2454
-rw-r--r--phpBB/includes/functions_display.php1277
-rw-r--r--phpBB/includes/functions_install.php540
-rw-r--r--phpBB/includes/functions_jabber.php872
-rw-r--r--phpBB/includes/functions_messenger.php1558
-rw-r--r--phpBB/includes/functions_module.php883
-rw-r--r--phpBB/includes/functions_posting.php2614
-rw-r--r--phpBB/includes/functions_privmsgs.php1981
-rw-r--r--phpBB/includes/functions_profile_fields.php1143
-rw-r--r--phpBB/includes/functions_template.php814
-rw-r--r--phpBB/includes/functions_transfer.php873
-rw-r--r--phpBB/includes/functions_upload.php988
-rw-r--r--phpBB/includes/functions_user.php3582
-rw-r--r--phpBB/includes/hooks/index.php250
-rw-r--r--phpBB/includes/index.htm10
-rw-r--r--phpBB/includes/mcp/info/mcp_ban.php39
-rw-r--r--phpBB/includes/mcp/info/mcp_logs.php39
-rw-r--r--phpBB/includes/mcp/info/mcp_main.php40
-rw-r--r--phpBB/includes/mcp/info/mcp_notes.php38
-rw-r--r--phpBB/includes/mcp/info/mcp_pm_reports.php39
-rw-r--r--phpBB/includes/mcp/info/mcp_queue.php39
-rw-r--r--phpBB/includes/mcp/info/mcp_reports.php39
-rw-r--r--phpBB/includes/mcp/info/mcp_warn.php40
-rw-r--r--phpBB/includes/mcp/mcp_ban.php219
-rw-r--r--phpBB/includes/mcp/mcp_forum.php447
-rw-r--r--phpBB/includes/mcp/mcp_front.php380
-rw-r--r--phpBB/includes/mcp/mcp_logs.php218
-rw-r--r--phpBB/includes/mcp/mcp_main.php1282
-rw-r--r--phpBB/includes/mcp/mcp_notes.php251
-rw-r--r--phpBB/includes/mcp/mcp_pm_reports.php323
-rw-r--r--phpBB/includes/mcp/mcp_post.php501
-rw-r--r--phpBB/includes/mcp/mcp_queue.php992
-rw-r--r--phpBB/includes/mcp/mcp_reports.php726
-rw-r--r--phpBB/includes/mcp/mcp_topic.php635
-rw-r--r--phpBB/includes/mcp/mcp_warn.php511
-rw-r--r--phpBB/includes/message_parser.php1685
-rw-r--r--phpBB/includes/questionnaire/questionnaire.php471
-rw-r--r--phpBB/includes/search/fulltext_mysql.php932
-rw-r--r--phpBB/includes/search/fulltext_native.php1742
-rw-r--r--phpBB/includes/search/index.htm10
-rw-r--r--phpBB/includes/search/search.php320
-rw-r--r--phpBB/includes/session.php2342
-rw-r--r--phpBB/includes/template.php668
-rw-r--r--phpBB/includes/ucp/info/ucp_attachments.php37
-rw-r--r--phpBB/includes/ucp/info/ucp_groups.php38
-rw-r--r--phpBB/includes/ucp/info/ucp_main.php40
-rw-r--r--phpBB/includes/ucp/info/ucp_pm.php40
-rw-r--r--phpBB/includes/ucp/info/ucp_prefs.php39
-rw-r--r--phpBB/includes/ucp/info/ucp_profile.php40
-rw-r--r--phpBB/includes/ucp/info/ucp_zebra.php38
-rw-r--r--phpBB/includes/ucp/ucp_activate.php143
-rw-r--r--phpBB/includes/ucp/ucp_attachments.php201
-rw-r--r--phpBB/includes/ucp/ucp_confirm.php50
-rw-r--r--phpBB/includes/ucp/ucp_groups.php1117
-rw-r--r--phpBB/includes/ucp/ucp_main.php835
-rw-r--r--phpBB/includes/ucp/ucp_pm.php416
-rw-r--r--phpBB/includes/ucp/ucp_pm_compose.php1290
-rw-r--r--phpBB/includes/ucp/ucp_pm_options.php836
-rw-r--r--phpBB/includes/ucp/ucp_pm_viewfolder.php509
-rw-r--r--phpBB/includes/ucp/ucp_pm_viewmessage.php320
-rw-r--r--phpBB/includes/ucp/ucp_prefs.php357
-rw-r--r--phpBB/includes/ucp/ucp_profile.php649
-rw-r--r--phpBB/includes/ucp/ucp_register.php503
-rw-r--r--phpBB/includes/ucp/ucp_remind.php125
-rw-r--r--phpBB/includes/ucp/ucp_resend.php170
-rw-r--r--phpBB/includes/ucp/ucp_zebra.php257
-rw-r--r--phpBB/includes/utf/data/case_fold_c.php1
-rw-r--r--phpBB/includes/utf/data/case_fold_f.php1
-rw-r--r--phpBB/includes/utf/data/case_fold_s.php1
-rw-r--r--phpBB/includes/utf/data/confusables.php1
-rw-r--r--phpBB/includes/utf/data/recode_basic.php1543
-rw-r--r--phpBB/includes/utf/data/recode_cjk.php45179
-rw-r--r--phpBB/includes/utf/data/search_indexer_0.php1
-rw-r--r--phpBB/includes/utf/data/search_indexer_1.php1
-rw-r--r--phpBB/includes/utf/data/search_indexer_19.php1
-rw-r--r--phpBB/includes/utf/data/search_indexer_2.php1
-rw-r--r--phpBB/includes/utf/data/search_indexer_20.php1
-rw-r--r--phpBB/includes/utf/data/search_indexer_21.php1
-rw-r--r--phpBB/includes/utf/data/search_indexer_26.php1
-rw-r--r--phpBB/includes/utf/data/search_indexer_3.php1
-rw-r--r--phpBB/includes/utf/data/search_indexer_31.php1
-rw-r--r--phpBB/includes/utf/data/search_indexer_32.php1
-rw-r--r--phpBB/includes/utf/data/search_indexer_33.php1
-rw-r--r--phpBB/includes/utf/data/search_indexer_36.php1
-rw-r--r--phpBB/includes/utf/data/search_indexer_4.php1
-rw-r--r--phpBB/includes/utf/data/search_indexer_448.php1
-rw-r--r--phpBB/includes/utf/data/search_indexer_5.php1
-rw-r--r--phpBB/includes/utf/data/search_indexer_58.php1
-rw-r--r--phpBB/includes/utf/data/search_indexer_6.php1
-rw-r--r--phpBB/includes/utf/data/search_indexer_64.php1
-rw-r--r--phpBB/includes/utf/data/search_indexer_84.php1
-rw-r--r--phpBB/includes/utf/data/search_indexer_9.php1
-rw-r--r--phpBB/includes/utf/data/search_indexer_95.php1
-rw-r--r--phpBB/includes/utf/data/utf_canonical_comp.php2
-rw-r--r--phpBB/includes/utf/data/utf_canonical_decomp.php2
-rw-r--r--phpBB/includes/utf/data/utf_compatibility_decomp.php2
-rw-r--r--phpBB/includes/utf/data/utf_nfc_qc.php2
-rw-r--r--phpBB/includes/utf/data/utf_nfkc_qc.php2
-rw-r--r--phpBB/includes/utf/data/utf_normalizer_common.php4
-rw-r--r--phpBB/includes/utf/utf_normalizer.php1516
-rw-r--r--phpBB/includes/utf/utf_tools.php1995
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' => '&nbsp;&nbsp;<span>[ <a href="' . $this->u_action . '&amp;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 . '&amp;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&amp;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 .= '&nbsp; &nbsp;';
+ $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 . "&amp;action=edit&amp;g={$row['group_id']}",
+ 'U_DELETE' => $this->u_action . "&amp;action=delete&amp;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&amp;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&amp;form=acp_ban&amp;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'] . ' -&gt; ');
+
+ $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 . '&amp;action=' . (($action == 'add') ? 'create' : 'modify') . (($bbcode_id) ? "&amp;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 . '&amp;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 . '&amp;action=edit&amp;bbcode=' . $row['bbcode_id'],
+ 'U_DELETE' => $this->u_action . '&amp;action=delete&amp;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\", '\"', '&#39;', '&#40;', '&#41;'), 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'] . '&nbsp;&nbsp;<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'] . '&nbsp;&nbsp;<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 . '" />&nbsp;<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 . "&amp;id=$bot_id&amp;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 . "&amp;id=$bot_id&amp;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 . "&amp;id=$bot_id&amp;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 . "&amp;id=$bot_id&amp;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 . "&amp;id={$row['bot_id']}&amp;action=$active_value",
+ 'L_ACTIVATE_DEACTIVATE' => $user->lang[$active_lang],
+ 'U_EDIT' => $this->u_action . "&amp;id={$row['bot_id']}&amp;action=edit",
+ 'U_DELETE' => $this->u_action . "&amp;id={$row['bot_id']}&amp;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 . '&amp;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 . '&amp;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&amp;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&amp;form=acp_email&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 = '&amp;mode=setting_forum_local&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . "&amp;parent_id={$this->parent_id}&amp;f=$forum_id&amp;action=sync&amp;start=$start&amp;topics_done=$topics_done&amp;total={$row['forum_topics_real']}";
+
+ meta_refresh(0, $url);
+
+ $template->assign_vars(array(
+ 'U_PROGRESS_BAR' => $this->u_action . "&amp;action=progress_bar&amp;start=$topics_done&amp;total={$row['forum_topics_real']}",
+ 'UA_PROGRESS_BAR' => addslashes($this->u_action . "&amp;action=progress_bar&amp;start=$topics_done&amp;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 . "&amp;parent_id={$this->parent_id}&amp;f=$forum_id&amp;action=sync_forum";
+ meta_refresh(0, $url);
+
+ $template->assign_vars(array(
+ 'U_PROGRESS_BAR' => $this->u_action . '&amp;action=progress_bar',
+ 'UA_PROGRESS_BAR' => addslashes($this->u_action . '&amp;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 . '&amp;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 . '&amp;parent_id=' . $this->parent_id,
+ 'U_EDIT_ACTION' => $this->u_action . "&amp;parent_id={$this->parent_id}&amp;action=$action&amp;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 . '&amp;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 . "&amp;parent_id={$parent_id}&amp;action=delete&amp;f=$forum_id",
+ 'U_BACK' => $this->u_action . '&amp;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 = '&amp;mode=setting_forum_local&amp;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 . '&amp;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 .= ' -&gt; ' . $row['forum_name'];
+ }
+ else
+ {
+ $navigation .= ' -&gt; <a href="' . $this->u_action . '&amp;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 . "&amp;parent_id=$this->parent_id&amp;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 . '&amp;parent_id=' . $row['forum_id'],
+ 'U_MOVE_UP' => $url . '&amp;action=move_up',
+ 'U_MOVE_DOWN' => $url . '&amp;action=move_down',
+ 'U_EDIT' => $url . '&amp;action=edit',
+ 'U_DELETE' => $url . '&amp;action=delete',
+ 'U_SYNC' => $url . '&amp;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 . '&amp;parent_id=' . $this->parent_id . '&amp;f=' . $row['forum_id'];
+
+ $template->assign_vars(array(
+ 'S_NO_FORUMS' => true,
+
+ 'U_EDIT' => $url . '&amp;action=edit',
+ 'U_DELETE' => $url . '&amp;action=delete',
+ 'U_SYNC' => $url . '&amp;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 . '&amp;parent_id=' . $this->parent_id,
+
+ 'U_PROGRESS_BAR' => $this->u_action . '&amp;action=progress_bar',
+ 'UA_PROGRESS_BAR' => addslashes($this->u_action . '&amp;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 . '&amp;' . $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 = '&amp;mode=setting_forum_local&amp;forum_id[]=' . $forum_data['forum_id'];
+ $action = append_sid($this->u_action . "&amp;parent_id={$this->parent_id}&amp;f={$forum_data['forum_id']}&amp;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 . '&amp;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 . '&amp;action=list&amp;g=' . $group_id));
+ }
+ else
+ {
+ trigger_error($user->lang[$error] . adm_back_link($this->u_action . '&amp;action=list&amp;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 . '&amp;action=list&amp;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 . '&amp;action=list&amp;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 . '&amp;action=list&amp;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 . '&amp;action=list&amp;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 . '&amp;action=list&amp;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&amp;mode=groups&amp;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&amp;name=group_colour'),
+ 'U_ACTION' => "{$this->u_action}&amp;action=$action&amp;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&amp;action=edit&amp;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 . "&amp;action=$action&amp;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 . "&amp;g=$group_id",
+ 'U_BACK' => $this->u_action,
+ 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=list&amp;field=usernames'),
+ 'U_DEFAULT_ALL' => "{$this->u_action}&amp;action=default&amp;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&amp;action=edit&amp;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}&amp;action=list&amp;g=$group_id",
+ 'U_EDIT' => "{$this->u_action}&amp;action=edit&amp;g=$group_id",
+ 'U_DELETE' => ($auth->acl_get('a_groupdel')) ? "{$this->u_action}&amp;action=delete&amp;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], ' -&gt; ' . $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], ' -&gt; ' . $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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;action=import',
+ 'U_EXPORT' => $this->u_action . '&amp;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 . '&amp;action=edit&amp;id=' . $row[$fields . '_id'],
+ 'U_DELETE' => $this->u_action . '&amp;action=delete&amp;id=' . $row[$fields . '_id'],
+ 'U_MOVE_UP' => $this->u_action . '&amp;action=move_up&amp;id=' . $row[$fields . '_id'] . '&amp;start=' . $pagination_start,
+ 'U_MOVE_DOWN' => $this->u_action . '&amp;action=move_down&amp;id=' . $row[$fields . '_id'] . '&amp;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 . "&amp;$u_sort_param&amp;start=$start";
+ $u_action .= ($per_page != $config['topics_per_page']) ? "&amp;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 . "&amp;$u_sort_param&amp;start=$start";
+ $u_action .= ($per_page != $config['topics_per_page']) ? "&amp;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&amp;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&amp;mode=overview&amp;u={$row['user_id']}"),
+ 'U_SEARCH_USER' => ($auth->acl_get('u_search')) ? append_sid("{$phpbb_root_path}search.$phpEx", "author_id={$row['user_id']}&amp;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 . "&amp;$u_sort_param&amp;users_per_page=$per_page", $inactive_count, $per_page, $start, true),
+ 'USERS_PER_PAGE' => $per_page,
+
+ 'U_ACTION' => $this->u_action . '&amp;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 . "&amp;id=$lang_id&amp;action=upload_data",
+ 'U_BACK' => $this->u_action . "&amp;id=$lang_id&amp;action=details&amp;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 . '&amp;action=details&amp;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 . '&amp;action=details&amp;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 . '&amp;action=details&amp;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 . '&amp;action=details&amp;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 . '&amp;id=' . $lang_id . '&amp;action=details&amp;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 . '&amp;action=details&amp;id=' . $lang_id . '&amp;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 . '&amp;action=details&amp;id=' . $lang_id . '&amp;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 . '&amp;action=details&amp;id=' . $lang_id . '&amp;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 . '&amp;action=details&amp;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 . '&amp;action=details&amp;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 . '&amp;action=details&amp;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 . '&amp;action=details&amp;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 . "&amp;action=details&amp;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 . "&amp;action=$action&amp;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 . "&amp;action=details&amp;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 . "&amp;action=$action&amp;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 . "&amp;action=details&amp;id={$row['lang_id']}",
+ 'U_DOWNLOAD' => $this->u_action . "&amp;action=download&amp;id={$row['lang_id']}",
+ 'U_DELETE' => $this->u_action . "&amp;action=delete&amp;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 . '&amp;action=install&amp;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') . '&nbsp; &nbsp;<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">&nbsp;</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) ? '&amp;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 . "&amp;$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&amp;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&amp;mode=admin'),
+ 'U_INACTIVE_USERS' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=inactive&amp;mode=list'),
+ 'U_VERSIONCHECK' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=update&amp;mode=version_check'),
+ 'U_VERSIONCHECK_FORCE' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=1&amp;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&amp;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&amp;mode=overview&amp;u={$row['user_id']}"),
+ 'U_SEARCH_USER' => ($auth->acl_get('u_search')) ? append_sid("{$phpbb_root_path}search.$phpEx", "author_id={$row['user_id']}&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;parent_id=' . $this->parent_id,
+ 'U_EDIT_ACTION' => $this->u_action . '&amp;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 .= ' -&gt; ' . $langname;
+ }
+ else
+ {
+ $navigation .= ' -&gt; <a href="' . $this->u_action . '&amp;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 . '&amp;parent_id=' . $this->parent_id . '&amp;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 . '&amp;parent_id=' . $row['module_id'],
+ 'U_MOVE_UP' => $url . '&amp;action=move_up',
+ 'U_MOVE_DOWN' => $url . '&amp;action=move_down',
+ 'U_EDIT' => $url . '&amp;action=edit',
+ 'U_DELETE' => $url . '&amp;action=delete',
+ 'U_ENABLE' => $url . '&amp;action=enable',
+ 'U_DISABLE' => $url . '&amp;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 . '&amp;parent_id=' . $this->parent_id . '&amp;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 . '&amp;action=edit',
+ 'U_DELETE' => $url . '&amp;action=delete',
+ 'U_ENABLE' => $url . '&amp;action=enable',
+ 'U_DISABLE' => $url . '&amp;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 . '">&nbsp; &nbsp;' . $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 . '&amp;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 . '&amp;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 .= '&nbsp; &nbsp;';
+ $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 . '&amp;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 . "&amp;action={$action}&amp;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 . '&amp;action=edit&amp;role_id=' . $row['role_id'],
+ 'U_REMOVE' => $this->u_action . '&amp;action=remove&amp;role_id=' . $row['role_id'],
+ 'U_MOVE_UP' => $this->u_action . '&amp;action=move_up&amp;order=' . $row['role_order'],
+ 'U_MOVE_DOWN' => $this->u_action . '&amp;action=move_down&amp;order=' . $row['role_order'],
+ 'U_DISPLAY_ITEMS' => ($row['role_id'] == $display_item) ? '' : $this->u_action . '&amp;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 . '&amp;type=' . $permission_type;
+ foreach ($forum_id as $fid)
+ {
+ $u_redirect .= '&amp;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&amp;form=select_victim&amp;field=username&amp;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&amp;form=add_user&amp;field=username&amp;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 . '&amp;forum_id[]=' . implode('&amp;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 . '&amp;forum_id[]=' . implode('&amp;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')) . "&amp;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 . "&amp;u=$user_id&amp;f=0&amp;auth=$permission&amp;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 . "&amp;action=$action&amp;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 . "&amp;action=$active_value&amp;field_id=$id",
+ 'U_EDIT' => $this->u_action . "&amp;action=edit&amp;field_id=$id",
+ 'U_TRANSLATE' => $this->u_action . "&amp;action=edit&amp;field_id=$id&amp;step=3",
+ 'U_DELETE' => $this->u_action . "&amp;action=delete&amp;field_id=$id",
+ 'U_MOVE_UP' => $this->u_action . "&amp;action=move_up&amp;order={$row['field_order']}",
+ 'U_MOVE_DOWN' => $this->u_action . "&amp;action=move_down&amp;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&amp;u=' . $user_id),
+ 'U_USER_ADMIN' => ($auth->acl_get('a_user')) ? append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&amp;mode=overview&amp;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&amp;form=acp_prune&amp;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 . '&amp;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 . '&amp;action=edit&amp;id=' . $row['rank_id'],
+ 'U_DELETE' => $this->u_action . '&amp;action=delete&amp;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 . "&amp;id=$reason_id&amp;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 . '&amp;action=edit&amp;id=' . $row['reason_id'],
+ 'U_DELETE' => (!$other_reason) ? $this->u_action . '&amp;action=delete&amp;id=' . $row['reason_id'] : '',
+ 'U_MOVE_UP' => $this->u_action . '&amp;action=move_up&amp;order=' . $row['reason_order'],
+ 'U_MOVE_DOWN' => $this->u_action . '&amp;action=move_down&amp;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&amp;mode=index') . '">&raquo; ' . $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 . '&amp;action=delete&amp;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 . '&amp;action=create&amp;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&amp;mode=$mode&amp;action=progress_bar"),
+ 'UA_PROGRESS_BAR' => addslashes(append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&amp;mode=$mode&amp;action=progress_bar")),
+ ));
+
+ if (isset($this->state[1]))
+ {
+ $template->assign_vars(array(
+ 'S_CONTINUE_INDEXING' => $this->state[1],
+ 'U_CONTINUE_INDEXING' => $this->u_action . '&amp;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 . "&amp;action=$option&amp;id=" . $row[$mode . '_id'] . '">' . $user->lang[strtoupper($option)] . '</a>';
+ }
+
+ $s_actions = array();
+ foreach ($actions as $option)
+ {
+ $s_actions[] = '<a href="' . $this->u_action . "&amp;action=$option&amp;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 . '&amp;action=' . (($mode == 'style') ? 'details' : 'edit') . '&amp;id=' . $row[$mode . '_id'],
+ 'U_STYLE_ACT_DEACT' => $this->u_action . '&amp;action=' . $stylevis . '&amp;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 . '&amp;action=install&amp;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 . "&amp;action=edit&amp;id=$template_id&amp;text_rows=$text_rows&amp;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 . "&amp;action=edit&amp;id=$template_id&amp;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 . "&amp;action=cache&amp;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>', '', '', '&#91;', '&#93;', '&#46;', '&#58;');
+
+ $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('#([^ ;])&nbsp;([^ &])#', '$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 . "&amp;action=cache&amp;id=$template_id&amp;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 . "&amp;action=cache&amp;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 . "&amp;action=edit&amp;id=$theme_id&amp;template_file=$theme_file&amp;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 . "&amp;action=edit&amp;id=$theme_id&amp;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 . "&amp;action=edit&amp;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 . "&amp;action=delete&amp;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 . '&amp;action=export&amp;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 . '&amp;action=details&amp;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 . "&amp;action=install&amp;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 . '&amp;action=add&amp;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, '&amp;') === false) ? str_replace('&', '&amp;', $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 . '&amp;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&amp;form=select_user&amp;field=username&amp;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&amp;u=$user_id"),
+ 'U_ACTION' => $this->u_action . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;u=' . $user_id), E_USER_WARNING);
+ }
+
+ if (!check_form_key($form_name))
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&amp;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 . '&amp;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 . '&amp;u=' . $user_id), E_USER_WARNING);
+ }
+
+ if (!check_form_key($form_name))
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;u=' . $user_id), E_USER_WARNING);
+ }
+
+ if (!check_form_key($form_name))
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;u=' . $user_id));
+
+ break;
+
+ case 'delsig':
+
+ if (!check_form_key($form_name))
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&amp;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 . '&amp;u=' . $user_id));
+
+ break;
+
+ case 'delavatar':
+
+ if (!check_form_key($form_name))
+ {
+ trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . "&amp;action=$action&amp;u=$user_id",
+ 'U_BACK' => $this->u_action . "&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . "&amp;u=$user_id&amp;ip=" . (($ip == 'ip') ? 'hostname' : 'ip'),
+ 'U_WHOIS' => $this->u_action . "&amp;action=whois&amp;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&amp;u={$user_row['user_id']}&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . "&amp;u=$user_id&amp;$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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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&amp;p={$row['post_msg_id']}");
+ }
+ else
+ {
+ $view_topic = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "t={$row['topic_id']}&amp;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&amp;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 . "&amp;u=$user_id&amp;sk=$sort_key&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;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 . '&amp;u=' . $user_id), E_USER_WARNING);
+ }
+
+ if (!$group_id)
+ {
+ trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action . '&amp;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 . '&amp;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&amp;mode=manage&amp;action=edit&amp;u=$user_id&amp;g={$data['group_id']}&amp;back_link=acp_users_groups"),
+ 'U_DEFAULT' => $this->u_action . "&amp;action=default&amp;u=$user_id&amp;g=" . $data['group_id'],
+ 'U_DEMOTE_PROMOTE' => $this->u_action . '&amp;action=' . (($data['group_leader']) ? 'demote' : 'promote') . "&amp;u=$user_id&amp;g=" . $data['group_id'],
+ 'U_DELETE' => $this->u_action . "&amp;action=delete&amp;u=$user_id&amp;g=" . $data['group_id'],
+ 'U_APPROVE' => ($group_type == 'pending') ? $this->u_action . "&amp;action=approve&amp;u=$user_id&amp;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 . '&amp;u=' . $user_id,
+ 'U_USER_PERMISSIONS' => append_sid("{$phpbb_admin_path}index.$phpEx" ,'i=permissions&amp;mode=setting_user_global&amp;user_id[]=' . $user_id),
+ 'U_USER_FORUM_PERMISSIONS' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=permissions&amp;mode=setting_user_local&amp;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 . '&amp;action=edit&amp;id=' . $row['word_id'],
+ 'U_DELETE' => $this->u_action . '&amp;action=delete&amp;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&amp;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&amp;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&amp;mode=trace&amp;u=$ug_id&amp;f=$forum_id&amp;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&amp;mode=trace&amp;u=$ug_id&amp;f=$forum_id&amp;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('&#58;', '&#46;'), 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(?:=&quot;(.*?)&quot;)?:$uid\]((?!\[quote(?:=&quot;.*?&quot;)?:$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", '&nbsp; &nbsp;', $code);
+ $code = str_replace(' ', '&nbsp; ', $code);
+ $code = str_replace(' ', ' &nbsp;', $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&amp;confirm_id=' . $this->confirm_id . '&amp;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 .= '&amp;' . 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&amp;mode=visual&amp;i=' . $id . '&amp;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 . "&amp;configure=1&amp;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 . "&amp;question_id={$row['question_id']}&amp;configure=1&amp;select_captcha=" . $this->get_class_name() . '&amp;';
+
+ $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 &copy; 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)) : '&nbsp;') . '</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 : '&nbsp;') . '</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('&lt;', '&gt;'), $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('&lt;', '&gt;'), $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">&nbsp;</span> ' . $user->lang['LINE_UNMODIFIED'] . '
+ <span class="added">&nbsp;</span> ' . $user->lang['LINE_ADDED'] . '
+ <span class="modified">&nbsp;</span> ' . $user->lang['LINE_MODIFIED'] . '
+ <span class="removed">&nbsp;</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 : '&nbsp;') . '<br /></pre></td>
+ <td><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '<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">&nbsp;</td><td class="added"><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '<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 : '&nbsp;') . '<br /></pre></td><td class="removed_empty">&nbsp;</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">&nbsp;</td>';
+ }
+ else
+ {
+ $output .= '<td class="unmodified">&nbsp;</td>';
+ }
+
+ if (!empty($right))
+ {
+ $output .= '<td class="modified"><pre>' . $right . '<br /></pre></td>';
+ }
+ else if ($row < $newsize)
+ {
+ $output .= '<td class="modified">&nbsp;</td>';
+ }
+ else
+ {
+ $output .= '<td class="unmodified">&nbsp;</td>';
+ }
+
+ $output .= '</tr>';
+ break;
+ }
+ }
+
+ if (!empty($current_context))
+ {
+ $line = $current_context;
+ $current_context = '';
+
+ $output .= '<tr class="unmodified"><td><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '<br /></pre></td>';
+ $output .= '<td><pre>' . ((strlen($line)) ? $line : '&nbsp;') . '<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) ? '' : '&amp;');
+
+ $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>&nbsp;&nbsp;' . $page_string;
+ }
+
+ if ($on_page != $total_pages)
+ {
+ $page_string .= '&nbsp;&nbsp;<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 &amp; (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&amp;f=2");
+* append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=1&amp;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) ? '&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) ? '&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 &amp;'s are in, this will break the redirect
+ $url = str_replace('&amp;', '&', $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('&', '&amp;', $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('&', '&amp;', $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('/(\?)?(&amp;|&)?sid=[a-z0-9]+/', '', $url);
+ // if the sid was the first param, make the old second as first ones
+ $url = preg_replace("/$phpEx(&amp;|&)+?/", "$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('&', '&amp;', $redirect);
+ }
+
+ return $phpbb_root_path . str_replace('&', '&amp;', $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('&', '&amp;', $url);
+
+ // For XHTML compatibility we change back & to &amp;
+ $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 &amp; for user->page (user->page is always using &)
+ $use_page = ($u_action) ? $phpbb_root_path . $u_action : $phpbb_root_path . str_replace('&', '&amp;', $user->page['page']);
+ $u_action = reapply_sid($use_page);
+ $u_action .= ((strpos($u_action, '?') === false) ? '?' : '&amp;') . '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\'\.\-_\+\|]++|&amp;)+@[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="(.*?)(?:(&amp;|\?)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 &copy; 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&amp;folder=inbox'),
+ 'U_RETURN_INBOX' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=inbox'),
+ 'U_POPUP_PM' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;mode=popup'),
+ 'UA_POPUP_PM' => addslashes(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;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') . '&amp;redirect=' . urlencode(str_replace('&amp;', '&', build_url())) : append_sid("index.$phpEx", false, true, $user->session_id) . '&amp;redirect=' . urlencode(str_replace('&amp;', '&', 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'] . '&amp;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() . '&amp;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 .= '&nbsp; &nbsp;';
+ $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&amp;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']] . '&amp;t=' . $row['topic_id']) : false;
+ $log[$key]['viewlogs'] = (isset($is_mod[$row['topic_id']])) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=logs&amp;mode=topic_logs&amp;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)) ? '&amp;' : '') . "{$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('&lt;', '&gt;', '&#91;', '&#93;', '&#46;', '&#58;', '&#058;');
+ $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\*\+\-]+(?:=(?:&quot;.*&quot;|[^\]]*))?(?::[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 .= '&amp;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'] . '&amp;t=1');
+ $download_link .= '&amp;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 . '&amp;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 &quot;quote&quot;' (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 &amp;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&amp;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 . '&amp;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'] . '&amp;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&amp;mode=unapproved_topics&amp;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') . '&amp;f=' . $root_data['forum_id'] . '&amp;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 . '&amp;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&amp;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('&amp;', '&quot;', "'", '&lt;', '&gt;'), 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') ? '&amp;f' : '&amp;f=' . $forum_id . '&amp;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&amp;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&amp;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&amp;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&amp;" . (($is_watching) ? 'unwatch' : 'watch') . "=$mode&amp;start=$start&amp;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) ? '&amp;icat=' . $icat : '') . "&amp;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) ? '&amp;icat=' . $icat : '') . "&amp;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.: &amp;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) ? '?' : '&amp;';
+
+ $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']) ? '&amp;icat=' . $current_id : '') . '&amp;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&amp;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&amp;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&amp;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 . '&amp;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 . '&amp;t=' . $draft['topic_id'] . '&amp;mode=reply&amp;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'] . '&amp;mode=post&amp;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&amp;mode=compose&amp;d={$draft['draft_id']}" . (($pm_action) ? "&amp;action=$pm_action" : '') . (($msg_id) ? "&amp;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&amp;t=$topic_id&amp;p={$row['post_id']}&amp;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&amp;mode=post_details&amp;f=' . $forum_id . '&amp;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 .= '&amp;t=' . $data['topic_id'];
+
+ if ($mode != 'post')
+ {
+ $params .= '&amp;p=' . $data['post_id'];
+ $add_anchor = '#p' . $data['post_id'];
+ }
+ }
+ else if ($mode != 'post' && $post_mode != 'edit_first_post' && $post_mode != 'edit_topic')
+ {
+ $params .= '&amp;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&amp;folder=' . $f_id) : append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;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&amp;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&amp;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&amp;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&amp;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') . '&amp;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&amp;f=$folder_id&amp;p=" . $row['msg_id'],
+ 'U_QUOTE' => (!$in_post_mode && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&amp;mode=compose&amp;action=quote&amp;f=" . $folder_id . "&amp;p=" . $row['msg_id'] : '',
+ 'U_POST_REPLY_PM' => ($author_id != $user->data['user_id'] && $author_id != ANONYMOUS && $auth->acl_get('u_sendpm')) ? "$url&amp;mode=compose&amp;action=reply&amp;f=$folder_id&amp;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&amp;p=" . $next_history_pm : '',
+ 'U_VIEW_PREVIOUS_HISTORY' => ($previous_history_pm) ? "$url&amp;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&amp;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, '&quot;') !== 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 . '">&laquo; ' . $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 . '">&laquo; ' . $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'] . ' -&gt; ');
+
+ $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&amp;form=mcp_ban&amp;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) ? "&amp;f=$forum_id" : '';
+ $url_extra .= ($GLOBALS['topic_id']) ? '&amp;t=' . $GLOBALS['topic_id'] : '';
+ $url_extra .= ($GLOBALS['post_id']) ? '&amp;p=' . $GLOBALS['post_id'] : '';
+ $url_extra .= ($GLOBALS['user_id']) ? '&amp;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 .= '&amp;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 .= '&amp;topic_id_list[' . $num . ']=' . $topic_id;
+ }
+ }
+
+ make_jumpbox($url . "&amp;i=$id&amp;action=$action&amp;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&amp;mode=forum_logs&amp;f=' . $forum_id) : '',
+
+ 'S_MCP_ACTION' => $url . "&amp;i=$id&amp;forum_action=$action&amp;mode=$mode&amp;start=$start" . (($merge_select) ? $selected_ids : ''),
+
+ 'PAGINATION' => generate_pagination($url . "&amp;i=$id&amp;action=$action&amp;mode=$mode&amp;sd=$sort_dir&amp;sk=$sort_key&amp;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 . "&amp;i=$id&amp;action=$action&amp;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 . '&amp;i=queue&amp;mode=' . (($topic_unapproved) ? 'approve_details' : 'unapproved_posts') . '&amp;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&amp;f=$forum_id&amp;topic_id_list[]={$row['topic_id']}&amp;mode=forum_view&amp;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 . "&amp;i=$id&amp;mode=forum_view&amp;action=$action&amp;to_topic_id=" . $row['topic_id'] . $selected_ids;
+ }
+ else
+ {
+ $u_select_topic = $url . "&amp;i=$id&amp;mode=topic_view&amp;action=merge&amp;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&amp;f=$forum_id&amp;t={$row['topic_id']}&amp;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&amp;mode=topic_view&amp;t=' . $row['topic_id'] . '&amp;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 . '&amp;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&amp;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&amp;mode=approve_details&amp;f=' . $row['forum_id'] . '&amp;p=' . $row['post_id']),
+ 'U_MCP_FORUM' => (!$global_topic) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&amp;mode=forum_view&amp;f=' . $row['forum_id']) : '',
+ 'U_MCP_TOPIC' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&amp;mode=topic_view&amp;f=' . $row['forum_id'] . '&amp;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'] . '&amp;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) ? '&amp;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'] . '&amp;p=' . $row['post_id'] . "&amp;i=reports&amp;mode=report_details"),
+ 'U_MCP_FORUM' => (!$global_topic) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'f=' . $row['forum_id'] . "&amp;i=$id&amp;mode=forum_view") : '',
+ 'U_MCP_TOPIC' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'f=' . $row['forum_id'] . '&amp;t=' . $row['topic_id'] . "&amp;i=$id&amp;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'] . '&amp;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'] . "&amp;i=pm_reports&amp;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&amp;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) ? '&amp;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 . "&amp;$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&amp;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&amp;form=mcp&amp;field=username&amp;select_single=true'),
+ 'U_POST_ACTION' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&amp;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, "&amp;u=$user_id") === false)
+ {
+ $this->p_master->adjust_url('&amp;u=' . $user_id);
+ $this->u_action .= "&amp;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 . '&amp;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) ? '&amp;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 . "&amp;$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&amp;mode=pm_report_details&amp;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&amp;mode=pm_report_details&amp;r=' . $report_id),
+ 'U_MCP_REPORTER_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&amp;mode=user_notes&amp;u=' . $report['user_id']),
+ 'U_MCP_USER_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&amp;mode=user_notes&amp;u=' . $pm_info['author_id']),
+ 'U_MCP_WARN_REPORTER' => ($auth->acl_get('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&amp;mode=warn_user&amp;u=' . $report['user_id']) : '',
+ 'U_MCP_WARN_USER' => ($auth->acl_get('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&amp;mode=warn_user&amp;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']) ? '&amp;mode=pm_reports' : '&amp;mode=pm_reports_closed') . '&amp;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 . '&amp;r=' . $report_id . '&amp;pm=' . $pm_id . '&amp;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&amp;mode=pm_report_details&amp;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 . "&amp;st=$sort_days&amp;sk=$sort_key&amp;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&amp;mode=$mode&amp;p=$post_id") . '">', '</a>'),
+ 'U_RETURN_POST' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&amp;mode=$mode&amp;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&amp;i=main&amp;quickmod=1", // Use this for mode paramaters
+ 'U_POST_ACTION' => "$url&amp;i=$id&amp;mode=post_details", // Use this for action parameters
+ 'U_APPROVE_ACTION' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=queue&amp;p=$post_id&amp;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&amp;f={$post_info['forum_id']}&amp;p={$post_info['post_id']}") : '',
+ 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=mcp_chgposter&amp;field=username&amp;select_single=true'),
+ 'U_MCP_APPROVE' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&amp;mode=approve_details&amp;f=' . $post_info['forum_id'] . '&amp;p=' . $post_id),
+ 'U_MCP_REPORT' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&amp;mode=report_details&amp;f=' . $post_info['forum_id'] . '&amp;p=' . $post_id),
+ 'U_MCP_USER_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&amp;mode=user_notes&amp;u=' . $post_info['user_id']),
+ 'U_MCP_WARN_USER' => ($auth->acl_get('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&amp;mode=warn_user&amp;u=' . $post_info['user_id']) : '',
+ 'U_VIEW_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&amp;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'] . '&amp;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']}&amp;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']}&amp;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&amp;i=$id&amp;mode=$mode&amp;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&amp;mode=$mode&amp;action=whois&amp;p=$post_id&amp;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&amp;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&amp;i=main&amp;mode=post_details&amp;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&amp;u=' . $user_id),
+ 'U_SEARCHPOSTS' => append_sid("{$phpbb_root_path}search.$phpEx", 'author_id=' . $user_id . '&amp;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&amp;i=$id&amp;mode=post_details&amp;rdns={$row['poster_ip']}#ip",
+ 'U_WHOIS' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&amp;mode=$mode&amp;action=whois&amp;p=$post_id&amp;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'] . '&amp;p=' . $post_info['post_id'] . '#p' . $post_info['post_id']);
+ $topic_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&amp;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&amp;p=$post_id&amp;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&amp;f={$post_info['forum_id']}&amp;p={$post_info['post_id']}") : '',
+ 'U_MCP_APPROVE' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&amp;mode=approve_details&amp;f=' . $post_info['forum_id'] . '&amp;p=' . $post_id),
+ 'U_MCP_REPORT' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&amp;mode=report_details&amp;f=' . $post_info['forum_id'] . '&amp;p=' . $post_id),
+ 'U_MCP_USER_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&amp;mode=user_notes&amp;u=' . $post_info['user_id']),
+ 'U_MCP_WARN_USER' => ($auth->acl_get('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&amp;mode=warn_user&amp;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) ? '&amp;mode=unapproved_topics' : '&amp;mode=unapproved_posts')) . "&amp;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&amp;mode=approve_details&amp;f=' . $post_info['forum_id'] . '&amp;p=' . $post_id . '&amp;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('&nbsp; &nbsp;', $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'] . '&amp;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'] . '&amp;p=' . $row['post_id']) . (($mode == 'unapproved_posts') ? '#p' . $row['post_id'] : ''),
+ 'U_VIEW_DETAILS' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=queue&amp;start=$start&amp;mode=approve_details&amp;f={$row['forum_id']}&amp;p={$row['post_id']}" . (($mode == 'unapproved_topics') ? "&amp;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 . "&amp;f=$forum_id&amp;st=$sort_days&amp;sk=$sort_key&amp;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']}&amp;t={$post_data['topic_id']}&amp;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')) . "&amp;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&amp;mode=report_details&amp;f=' . $post_info['forum_id'] . '&amp;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&amp;f={$post_info['forum_id']}&amp;p={$post_info['post_id']}") : '',
+ 'U_MCP_APPROVE' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&amp;mode=approve_details&amp;f=' . $post_info['forum_id'] . '&amp;p=' . $post_id),
+ 'U_MCP_REPORT' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&amp;mode=report_details&amp;f=' . $post_info['forum_id'] . '&amp;p=' . $post_id),
+ 'U_MCP_REPORTER_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&amp;mode=user_notes&amp;u=' . $report['user_id']),
+ 'U_MCP_USER_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&amp;mode=user_notes&amp;u=' . $post_info['user_id']),
+ 'U_MCP_WARN_REPORTER' => ($auth->acl_get('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&amp;mode=warn_user&amp;u=' . $report['user_id']) : '',
+ 'U_MCP_WARN_USER' => ($auth->acl_get('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&amp;mode=warn_user&amp;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'] . '&amp;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'] . '&amp;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']) ? '&amp;mode=reports' : '&amp;mode=reports_closed') . '&amp;start=' . $start . '&amp;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 . '&amp;r=' . $report_id . '&amp;p=' . $post_id . '&amp;f=' . $forum_id . '&amp;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('&nbsp; &nbsp;', $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'] . '&amp;p=' . $row['post_id']) . '#p' . $row['post_id'],
+ 'U_VIEW_DETAILS' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=reports&amp;start=$start&amp;mode=report_details&amp;f={$row['forum_id']}&amp;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 . "&amp;f=$forum_id&amp;t=$topic_id&amp;st=$sort_days&amp;sk=$sort_key&amp;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')) . '&amp;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')) . '&amp;mode=pm_reports');
+ }
+ else if ($action == 'close' && !request_var('r', 0))
+ {
+ $redirect = request_var('redirect', build_url(array('mode', 'p', 'quickmod')) . '&amp;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) . '&amp;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 . "&amp;i=$id&amp;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&amp;i=$id&amp;p={$row['post_id']}&amp;mode=post_details" . (($forum_id) ? "&amp;f=$forum_id" : ''),
+ 'U_MCP_APPROVE' => ($auth->acl_get('m_approve', $topic_info['forum_id'])) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&amp;mode=approve_details&amp;f=' . $topic_info['forum_id'] . '&amp;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&amp;mode=report_details&amp;f=' . $topic_info['forum_id'] . '&amp;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'] . '&amp;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'] . '&amp;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&amp;i=$id&amp;mode=$mode&amp;action=$action&amp;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&amp;i=$id&amp;mode=forum_view&amp;action=merge_select" . (($forum_id) ? "&amp;f=$forum_id" : ''),
+
+ 'RETURN_TOPIC' => sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f={$topic_info['forum_id']}&amp;t={$topic_info['topic_id']}&amp;start=$start") . '">', '</a>'),
+ 'RETURN_FORUM' => sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", "f={$topic_info['forum_id']}&amp;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&amp;t={$topic_info['topic_id']}&amp;mode=$mode&amp;action=$action&amp;to_topic_id=$to_topic_id&amp;posts_per_page=$posts_per_page&amp;st=$sort_days&amp;sk=$sort_key&amp;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'] . '&amp;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 . '&amp;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&amp;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'] . '&amp;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 . '&amp;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&amp;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&amp;form=mcp&amp;field=username&amp;select_single=true'),
+ 'U_POST_ACTION' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&amp;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&amp;mode=user_notes&amp;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&amp;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&amp;mode=user_notes&amp;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&amp;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&amp;mode=user_notes&amp;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&amp;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&amp;mode=list&amp;st=$st&amp;sk=$sk&amp;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, "&amp;f=$forum_id&amp;p=$post_id") === false)
+ {
+ $this->p_master->adjust_url("&amp;f=$forum_id&amp;p=$post_id");
+ $this->u_action .= "&amp;f=$forum_id&amp;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&amp;mode=user_notes&amp;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&amp;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, "&amp;u=$user_id") === false)
+ {
+ $this->p_master->adjust_url('&amp;u=' . $user_id);
+ $this->u_action .= "&amp;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&amp;mode=user_notes&amp;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(=&quot;.*?&quot;)?\]\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(?:=&quot;(.*?)&quot;)?\](.+)\[/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('&lt;', '&gt;', '&#91;', '&#93;', '&#46;', '&#58;');
+
+ 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('&lt;', '&gt;', '&#91;', '&#93;', '&#46;', '&#58;', '&#058;');
+ $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>', '', '', '&#91;', '&#93;', '&#46;', '&#58;');
+
+ if ($remove_tags)
+ {
+ $str_from[] = '<span class="syntaxdefault">&lt;?php </span>';
+ $str_to[] = '';
+ $str_from[] = '<span class="syntaxdefault">&lt;?php&nbsp;';
+ $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]+">)?\?&gt;(</span>)#', '$1&nbsp;$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++|&nbsp;)*+</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=&quot;(.*?)&quot;\]#ie', "'quote=&quot;' . str_replace(array('[', ']', '\\\"'), array('&#91;', '&#93;', '\"'), '\$1') . '&quot;]'", $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(?:=&quot;(.*?)&quot;)?$#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('&#91;', '&#93;'), array('[', ']'), $m[1]);
+ $username = preg_replace('#\[(?!b|i|u|color|url|email|/b|/i|/u|/color|/url|/email)#iU', '&#91;$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=&quot;' . $username . '&quot;:' . $this->bbcode_uid . ']';
+ }
+ else
+ {
+ $out .= 'quote:' . $this->bbcode_uid . ']';
+ }
+
+ $tok = '[';
+ $buffer = '';
+ }
+ else if (preg_match('#^quote=&quot;(.*?)#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('/(&amp;|\?)sid=[0-9a-f]{32}&amp;/', '\1', $url);
+ $url = preg_replace('/(&amp;|\?)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&#058;");
+ $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 .= '&amp;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&amp;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&amp;p={$row['post_msg_id']}");
+ }
+ else
+ {
+ $view_topic = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "t={$row['topic_id']}&amp;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 . "&amp;sk=$sort_key&amp;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 . "&amp;sk=a&amp;sd=" . (($sort_key == 'a' && $sort_dir == 'a') ? 'd' : 'a'),
+ 'U_SORT_FILE_COMMENT' => $this->u_action . "&amp;sk=b&amp;sd=" . (($sort_key == 'b' && $sort_dir == 'a') ? 'd' : 'a'),
+ 'U_SORT_EXTENSION' => $this->u_action . "&amp;sk=c&amp;sd=" . (($sort_key == 'c' && $sort_dir == 'a') ? 'd' : 'a'),
+ 'U_SORT_FILESIZE' => $this->u_action . "&amp;sk=d&amp;sd=" . (($sort_key == 'd' && $sort_dir == 'a') ? 'd' : 'a'),
+ 'U_SORT_DOWNLOADS' => $this->u_action . "&amp;sk=e&amp;sd=" . (($sort_key == 'e' && $sort_dir == 'a') ? 'd' : 'a'),
+ 'U_SORT_POST_TIME' => $this->u_action . "&amp;sk=f&amp;sd=" . (($sort_key == 'f' && $sort_dir == 'a') ? 'd' : 'a'),
+ 'U_SORT_TOPIC_TITLE' => $this->u_action . "&amp;sk=g&amp;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&amp;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&amp;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&amp;name=group_colour'),
+ 'S_UCP_ACTION' => $this->u_action . "&amp;action=$action&amp;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 . "&amp;action=$action&amp;g=$group_id", $total_members, $config['topics_per_page'], $start),
+
+ 'U_ACTION' => $this->u_action . "&amp;g=$group_id",
+ 'S_UCP_ACTION' => $this->u_action . "&amp;g=$group_id",
+ 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=ucp&amp;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 . '&amp;action=list&amp;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 . '&amp;action=list&amp;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 . '&amp;action=list&amp;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 . '&amp;action=list&amp;g=' . $group_id . '">', '</a>'));
+ }
+
+ trigger_error($user->lang['GROUP_USERS_REMOVE'] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $this->u_action . '&amp;action=list&amp;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 . '&amp;action=list&amp;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 . '&amp;action=list&amp;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 . '&amp;action=list&amp;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 . "&amp;action=list&amp;g={$value['group_id']}",
+ 'U_EDIT' => $this->u_action . "&amp;action=edit&amp;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&amp;t=$topic_id&amp;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&amp;t=$topic_id&amp;view=unread") . '#unread',
+ 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$g_forum_id&amp;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'] . '&amp;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&amp;mode=subscribed") . '">', '</a>');
+ meta_refresh(3, append_sid("{$phpbb_root_path}ucp.$phpEx", "i=$id&amp;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&amp;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'] . '&amp;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'] . '&amp;t=' . $draft['topic_id'] . '&amp;mode=reply&amp;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'] . '&amp;mode=post&amp;d=' . $draft['draft_id']);
+ }
+ else if ($pm_drafts)
+ {
+ $link_pm = true;
+ $insert_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=$id&amp;mode=compose&amp;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 . '&amp;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&amp;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) . "&amp;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 . '&amp;view=unread') . '#unread',
+ 'U_LAST_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params . '&amp;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&amp;folder=inbox') . '" onclick="jump_to_inbox(this.href); return false;">', '</a>'),
+ 'U_INBOX' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;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 . '&amp;folder=' . $folder_id . '&amp;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 . '&amp;action=view_folder',
+ 'S_PM_ACTION' => $this->u_action . '&amp;action=' . $action,
+
+ 'U_INBOX' => $this->u_action . '&amp;folder=inbox',
+ 'U_OUTBOX' => $this->u_action . '&amp;folder=outbox',
+ 'U_SENTBOX' => $this->u_action . '&amp;folder=sentbox',
+ 'U_CREATE_FOLDER' => $this->u_action . '&amp;mode=options',
+ 'U_CURRENT_FOLDER' => $this->u_action . '&amp;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)) ? "&amp;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&amp;mode=view&amp;action=view_message&amp;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&amp;form=postform&amp;field=username_list&amp;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&amp;mode=$mode&amp;action=$action", true, $user->session_id);
+ $s_action .= ($msg_id) ? "&amp;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&amp;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&amp;mode=compose"
+ confirm_box(false, 'DELETE_MESSAGE', build_hidden_fields($s_hidden_fields));
+ }
+
+ redirect(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;mode=view&amp;action=view_message&amp;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&amp;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&amp;mode=view&amp;p=' . $msg_id);
+ $return_folder_url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;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=&quot;' . $quote_username . '&quot;]' . 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&amp;u={$post['author_id']}]{$quote_username}[/url]";
+ }
+ else
+ {
+ $quote_username_text = $quote_username . ' (' . generate_board_url() . "/memberlist.$phpEx?mode=viewprofile&amp;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=&quot;{$quote_username}&quot;]\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&amp;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&amp;mode=popup'),
+ 'UA_PROGRESS_BAR' => addslashes(append_sid("{$phpbb_root_path}posting.$phpEx", 'f=0&amp;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&amp;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&amp;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&amp;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&amp;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&amp;form=ucp&amp;field=rule_string&amp;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&amp;mode=view&amp;f=$folder_id&amp;p=$message_id");
+ $remove_message_url = append_sid("{$phpbb_root_path}ucp.$phpEx", "i=$id&amp;mode=compose&amp;action=delete&amp;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&amp;mode=view&amp;action=view_folder&amp;f=$folder_id&amp;$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&amp;mode=compose') : '',
+ 'S_PM_ACTION' => append_sid("{$phpbb_root_path}ucp.$phpEx", "i=pm&amp;mode=view&amp;action=view_folder&amp;f=$folder_id" . (($start !== 0) ? "&amp;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&amp;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&amp;mode=compose&amp;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&amp;action=aim&amp;u=' . $author_id) : '',
+ 'U_YIM' => ($user_info['user_yim']) ? 'http://edit.yahoo.com/config/send_webmesg?.target=' . urlencode($user_info['user_yim']) . '&amp;.src=pg' : '',
+ 'U_MSN' => ($user_info['user_msnm'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&amp;action=msnm&amp;u=' . $author_id) : '',
+ 'U_JABBER' => ($user_info['user_jabber'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&amp;action=jabber&amp;u=' . $author_id) : '',
+
+ 'U_DELETE' => ($auth->acl_get('u_pm_delete')) ? "$url&amp;mode=compose&amp;action=delete&amp;f=$folder_id&amp;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&amp;mode=compose&amp;action=quote&amp;f=$folder_id&amp;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&amp;mode=compose&amp;action=edit&amp;f=$folder_id&amp;p=" . $message_row['msg_id'] : '',
+ 'U_POST_REPLY_PM' => ($auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&amp;mode=compose&amp;action=reply&amp;f=$folder_id&amp;p=" . $message_row['msg_id'] : '',
+ 'U_POST_REPLY_ALL' => ($auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&amp;mode=compose&amp;action=reply&amp;f=$folder_id&amp;reply_to_all=1&amp;p=" . $message_row['msg_id'] : '',
+ 'U_PREVIOUS_PM' => "$url&amp;f=$folder_id&amp;p=" . $message_row['msg_id'] . "&amp;view=previous",
+ 'U_NEXT_PM' => "$url&amp;f=$folder_id&amp;p=" . $message_row['msg_id'] . "&amp;view=next",
+
+ 'U_PM_ACTION' => $url . '&amp;mode=compose&amp;f=' . $folder_id . '&amp;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&amp;f=$folder_id&amp;p=" . $message_row['msg_id'] . "&amp;view=print" : '',
+ 'U_FORWARD_PM' => ($config['forward_pm'] && $auth->acl_get('u_sendpm') && $auth->acl_get('u_pm_forward')) ? "$url&amp;mode=compose&amp;action=forward&amp;f=$folder_id&amp;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&amp;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&amp;mode=avatar&amp;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) ? '&amp;change_lang=' . urlencode($change_lang) : '';
+ $add_coppa = ($coppa !== false) ? '&amp;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&amp;coppa=0' . $add_lang),
+ 'U_COPPA_YES' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=register&amp;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&amp;form=ucp&amp;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;#38; it will return &#38;
+* - 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