diff options
| author | Nils Adermann <naderman@naderman.de> | 2010-03-02 01:05:33 +0100 |
|---|---|---|
| committer | Nils Adermann <naderman@naderman.de> | 2010-03-02 01:05:33 +0100 |
| commit | ee82970d96e0a6772b24c48aab8ebd1888ec5216 (patch) | |
| tree | 2f284a1671eb3667a4b280b252ecd6e930b5920c /phpBB/includes | |
| parent | c9f68f0b5c339cf7c0126eef8e7c533a0107bd66 (diff) | |
| parent | 108312d52a447e3ad5a2e8d1682f0439e5443cf0 (diff) | |
| download | forums-ee82970d96e0a6772b24c48aab8ebd1888ec5216.tar forums-ee82970d96e0a6772b24c48aab8ebd1888ec5216.tar.gz forums-ee82970d96e0a6772b24c48aab8ebd1888ec5216.tar.bz2 forums-ee82970d96e0a6772b24c48aab8ebd1888ec5216.tar.xz forums-ee82970d96e0a6772b24c48aab8ebd1888ec5216.zip | |
Merge commit 'release-3.0-B2'
Diffstat (limited to 'phpBB/includes')
115 files changed, 8788 insertions, 3188 deletions
diff --git a/phpBB/includes/acm/acm_file.php b/phpBB/includes/acm/acm_file.php index fadef07ac3..175ef0ad81 100644 --- a/phpBB/includes/acm/acm_file.php +++ b/phpBB/includes/acm/acm_file.php @@ -19,6 +19,7 @@ class acm var $is_modified = false; var $sql_rowset = array(); + var $sql_row_pointer = array(); /** * Set cache path @@ -56,6 +57,7 @@ class acm unset($this->vars); unset($this->var_expires); unset($this->sql_rowset); + unset($this->sql_row_pointer); } /** @@ -69,7 +71,7 @@ class acm } global $phpEx; - $file = '<?php $this->vars=' . $this->format_array($this->vars) . ";\n\$this->var_expires=" . $this->format_array($this->var_expires) . ' ?>'; + $file = "<?php\n\$this->vars = " . $this->format_array($this->vars) . ";\n\n\$this->var_expires = " . $this->format_array($this->var_expires) . "\n?>"; if ($fp = @fopen($this->cache_dir . 'data_global.' . $phpEx, 'wb')) { @@ -255,26 +257,28 @@ class acm /** * Format an array to be stored on filesystem */ - function format_array($array) + function format_array($array, $tab = '') { + $tab .= "\t"; + $lines = array(); foreach ($array as $k => $v) { if (is_array($v)) { - $lines[] = "\n'$k' => " . $this->format_array($v); + $lines[] = "\n{$tab}'$k' => " . $this->format_array($v, $tab); } else if (is_int($v)) { - $lines[] = "\n'$k' => $v"; + $lines[] = "\n{$tab}'$k' => $v"; } else if (is_bool($v)) { - $lines[] = "\n'$k' => " . (($v) ? 'true' : 'false'); + $lines[] = "\n{$tab}'$k' => " . (($v) ? 'true' : 'false'); } else { - $lines[] = "\n'$k' => '" . str_replace("'", "\\'", str_replace('\\', '\\\\', $v)) . "'"; + $lines[] = "\n{$tab}'$k' => '" . str_replace("'", "\\'", str_replace('\\', '\\\\', $v)) . "'"; } } @@ -309,6 +313,8 @@ class acm return false; } + $this->sql_row_pointer[$query_id] = 0; + return $query_id; } @@ -329,6 +335,7 @@ class acm $lines = array(); $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)) { @@ -359,7 +366,63 @@ class acm */ function sql_fetchrow($query_id) { - return array_shift($this->sql_rowset[$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 the number of rows from cache (database) + */ + function sql_numrows($query_id) + { + return sizeof($this->sql_rowset[$query_id]); + } + + /** + * 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($query_id, $rownum) + { + 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; } } diff --git a/phpBB/includes/acp/acp_attachments.php b/phpBB/includes/acp/acp_attachments.php index 85480756ca..1089a06152 100644 --- a/phpBB/includes/acp/acp_attachments.php +++ b/phpBB/includes/acp/acp_attachments.php @@ -78,7 +78,7 @@ class acp_attachments } $db->sql_freeresult($result); - $l_legend_cat_images = $user->lang['SETTINGS_CAT_IMAGES'] . ' [' . $user->lang['ASSIGNED_GROUP'] . ': ' . ((sizeof($s_assigned_groups[ATTACHMENT_CATEGORY_IMAGE])) ? implode(', ', $s_assigned_groups[ATTACHMENT_CATEGORY_IMAGE]) : $user->lang['NONE']) . ']'; + $l_legend_cat_images = $user->lang['SETTINGS_CAT_IMAGES'] . ' [' . $user->lang['ASSIGNED_GROUP'] . ': ' . ((sizeof($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', @@ -97,7 +97,7 @@ class acp_attachments 'max_attachments_pm' => array('lang' => 'MAX_ATTACHMENTS_PM', 'type' => 'text:3:3', 'explain' => false), 'secure_downloads' => array('lang' => 'SECURE_DOWNLOADS', 'type' => 'radio:yes_no', 'explain' => true), 'secure_allow_deny' => array('lang' => 'SECURE_ALLOW_DENY', 'type' => 'custom', 'method' => 'select_allow_deny', 'explain' => true), - 'secure_allow_empty_referer' => array('lang' => 'SECURE_EMPTY_REFERER', 'type' => 'radio:yes_no', 'explain' => true), + 'secure_allow_empty_referer' => array('lang' => 'SECURE_EMPTY_REFERRER', 'type' => 'radio:yes_no', 'explain' => true), 'legend2' => $l_legend_cat_images, 'img_display_inlined' => array('lang' => 'DISPLAY_INLINED', 'type' => 'radio:yes_no', 'explain' => true), @@ -294,7 +294,7 @@ class acp_attachments { $sql = 'SELECT extension FROM ' . EXTENSIONS_TABLE . ' - WHERE extension_id IN (' . implode(', ', $extension_id_list) . ')'; + WHERE ' . $db->sql_in_set('extension_id', $extension_id_list); $result = $db->sql_query($sql); $extension_list = ''; @@ -306,7 +306,7 @@ class acp_attachments $sql = 'DELETE FROM ' . EXTENSIONS_TABLE . ' - WHERE extension_id IN (' . implode(', ', $extension_id_list) . ')'; + WHERE ' . $db->sql_in_set('extension_id', $extension_id_list); $db->sql_query($sql); add_log('admin', 'LOG_ATTACH_EXT_DEL', $extension_list); @@ -508,7 +508,7 @@ class acp_attachments { $sql = 'UPDATE ' . EXTENSIONS_TABLE . " SET group_id = $group_id - WHERE extension_id IN (" . implode(', ', $extension_list) . ")"; + WHERE " . $db->sql_in_set('extension_id', $extension_list); $db->sql_query($sql); } @@ -521,7 +521,7 @@ class acp_attachments } $cat_lang = array( - ATTACHMENT_CATEGORY_NONE => $user->lang['NONE'], + 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'] @@ -631,25 +631,30 @@ class acp_attachments $img_path = $config['upload_icons_path']; - $imglist = filelist($phpbb_root_path . $img_path); - $imglist = array_values($imglist); - $imglist = $imglist[0]; - $filename_list = ''; $no_image_select = false; - foreach ($imglist as $key => $img) + + $imglist = filelist($phpbb_root_path . $img_path); + + if (sizeof($imglist)) { - if (!$ext_group_row['upload_icon']) - { - $no_image_select = true; - $selected = ''; - } - else + $imglist = array_values($imglist); + $imglist = $imglist[0]; + + foreach ($imglist as $key => $img) { - $selected = ($ext_group_row['upload_icon'] == $img) ? ' selected="selected"' : ''; - } + if (!$ext_group_row['upload_icon']) + { + $no_image_select = true; + $selected = ''; + } + else + { + $selected = ($ext_group_row['upload_icon'] == $img) ? ' selected="selected"' : ''; + } - $filename_list .= '<option value="' . htmlspecialchars($img) . '"' . $selected . '>' . htmlspecialchars($img) . '</option>'; + $filename_list .= '<option value="' . htmlspecialchars($img) . '"' . $selected . '>' . htmlspecialchars($img) . '</option>'; + } } $i = 0; @@ -701,7 +706,7 @@ class acp_attachments $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); + $result = $db->sql_query($sql, 600); $right = $cat_right = $padding_inc = 0; $padding = $forum_list = $holding = ''; @@ -860,7 +865,7 @@ class acp_attachments $sql = 'SELECT forum_id, topic_id, post_id FROM ' . POSTS_TABLE . ' - WHERE post_id IN (' . implode(', ', array_keys($upload_list)) . ')'; + WHERE ' . $db->sql_in_set('post_id', array_keys($upload_list)); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -954,7 +959,7 @@ class acp_attachments global $db, $user; $types = array( - ATTACHMENT_CATEGORY_NONE => $user->lang['NONE'], + 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'] @@ -1097,7 +1102,7 @@ class acp_attachments 'in_message' => 0, 'physical_filename' => $filedata['physical_filename'], 'real_filename' => $filedata['real_filename'], - 'comment' => $message_parser->filename_data['filecomment'], + 'attach_comment' => $message_parser->filename_data['filecomment'], 'extension' => $filedata['extension'], 'mimetype' => $filedata['mimetype'], 'filesize' => $filedata['filesize'], @@ -1145,7 +1150,7 @@ class acp_attachments { $imagick = ''; - $exe = ((defined('PHP_OS')) && (preg_match('#win#i', PHP_OS))) ? '.exe' : ''; + $exe = ((defined('PHP_OS')) && (preg_match('#^win#i', PHP_OS))) ? '.exe' : ''; $magic_home = getenv('MAGICK_HOME'); @@ -1368,16 +1373,16 @@ class acp_attachments } else if (isset($_POST['unsecuresubmit'])) { - $unip_sql = implode(', ', array_map('intval', $_POST['unip'])); + $unip_sql = array_map('intval', $_POST['unip']); - if ($unip_sql != '') + 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 site_id IN ($unip_sql)"; + FROM ' . SITELIST_TABLE . ' + WHERE ' . $db->sql_in_set('site_id', $unip_sql); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -1386,8 +1391,8 @@ class acp_attachments } $db->sql_freeresult($result); - $sql = 'DELETE FROM ' . SITELIST_TABLE . " - WHERE site_id IN ($unip_sql)"; + $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); diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php index edc8a594da..cdfe8e42eb 100644 --- a/phpBB/includes/acp/acp_bbcodes.php +++ b/phpBB/includes/acp/acp_bbcodes.php @@ -33,12 +33,12 @@ class acp_bbcodes switch ($action) { case 'add': - $bbcode_match = $bbcode_tpl = ''; + $bbcode_match = $bbcode_tpl = $bbcode_helpline = ''; $display_on_posting = 0; break; case 'edit': - $sql = 'SELECT bbcode_match, bbcode_tpl, display_on_posting + $sql = 'SELECT bbcode_match, bbcode_tpl, display_on_posting, bbcode_helpline FROM ' . BBCODES_TABLE . ' WHERE bbcode_id = ' . $bbcode_id; $result = $db->sql_query($sql); @@ -53,6 +53,7 @@ class acp_bbcodes $bbcode_match = $row['bbcode_match']; $bbcode_tpl = htmlspecialchars($row['bbcode_tpl']); $display_on_posting = $row['display_on_posting']; + $bbcode_helpline = html_entity_decode($row['bbcode_helpline']); break; case 'modify': @@ -75,6 +76,7 @@ class acp_bbcodes $bbcode_match = request_var('bbcode_match', ''); $bbcode_tpl = html_entity_decode(request_var('bbcode_tpl', '')); + $bbcode_helpline = htmlspecialchars(request_var('bbcode_helpline', '')); break; } @@ -89,8 +91,10 @@ class acp_bbcodes 'U_BACK' => $this->u_action, 'U_ACTION' => $this->u_action . '&action=' . (($action == 'add') ? 'create' : 'modify') . (($bbcode_id) ? "&bbcode=$bbcode_id" : ''), + 'L_BBCODE_USAGE_EXPLAIN'=> sprintf($user->lang['BBCODE_USAGE_EXPLAIN'], '<a href="#down">', '</a>'), 'BBCODE_MATCH' => $bbcode_match, 'BBCODE_TPL' => $bbcode_tpl, + 'BBCODE_HELPLINE' => $bbcode_helpline, 'DISPLAY_ON_POSTING' => $display_on_posting) ); @@ -134,6 +138,7 @@ class acp_bbcodes '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'], @@ -163,7 +168,7 @@ class acp_bbcodes $bbcode_id = NUM_CORE_BBCODES + 1; } - if ($bbcode_id > 31) + if ($bbcode_id > 1511) { trigger_error('TOO_MANY_BBCODES'); } @@ -278,8 +283,8 @@ class acp_bbcodes { $token_type = $m[1][$n]; - reset($tokens[$token_type]); - list($match, $replace) = each($tokens[$token_type]); + 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)) @@ -337,7 +342,7 @@ class acp_bbcodes } // Lowercase tags - $bbcode_tag = preg_replace('/.*?\[([a-z]+=?).*/i', '$1', $bbcode_match); + $bbcode_tag = preg_replace('/.*?\[([a-z0-9_-]+=?).*/i', '$1', $bbcode_match); $fp_match = preg_replace('#\[/?' . $bbcode_tag . '#ie', "strtolower('\$0')", $fp_match); $fp_replace = preg_replace('#\[/?' . $bbcode_tag . '#ie', "strtolower('\$0')", $fp_replace); $sp_match = preg_replace('#\[/?' . $bbcode_tag . '#ie', "strtolower('\$0')", $sp_match); diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index da424d1131..49e4b1eb1c 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -40,9 +40,9 @@ class acp_board 'board_disable_msg' => false, 'default_lang' => array('lang' => 'DEFAULT_LANGUAGE', 'type' => 'select', 'function' => 'language_select', 'params' => array('{CONFIG_VALUE}'), 'explain' => false), 'default_dateformat' => array('lang' => 'DEFAULT_DATE_FORMAT', 'type' => 'custom', 'method' => 'dateformat_select', 'explain' => true), - 'board_timezone' => array('lang' => 'SYSTEM_TIMEZONE', 'type' => 'select', 'function' => 'tz_select', 'params' => array('{CONFIG_VALUE}'), 'explain' => false), + 'board_timezone' => array('lang' => 'SYSTEM_TIMEZONE', 'type' => 'select', 'function' => 'tz_select', 'params' => array('{CONFIG_VALUE}', 1), 'explain' => false), 'board_dst' => array('lang' => 'SYSTEM_DST', 'type' => 'radio:yes_no', 'explain' => false), - 'default_style' => array('lang' => 'DEFAULT_STYLE', 'type' => 'select', 'function' => 'style_select', 'params' => array('{CONFIG_VALUE}', true), 'explain' => false), + 'default_style' => array('lang' => 'DEFAULT_STYLE', 'type' => 'select', 'function' => 'style_select', 'params' => array('{CONFIG_VALUE}', 1), 'explain' => false), 'override_user_style' => array('lang' => 'OVERRIDE_STYLE', 'type' => 'radio:yes_no', 'explain' => true), 'legend2' => 'WARNINGS', @@ -71,6 +71,14 @@ class acp_board 'allow_sig_smilies' => array('lang' => 'ALLOW_SIG_SMILIES', 'type' => 'radio:yes_no', 'explain' => false), 'allow_nocensors' => array('lang' => 'ALLOW_NO_CENSORS', 'type' => 'radio:yes_no', 'explain' => true), 'allow_bookmarks' => array('lang' => 'ALLOW_BOOKMARKS', 'type' => 'radio:yes_no', 'explain' => true), + + 'legend2' => 'ACP_LOAD_SETTINGS', + 'load_birthdays' => array('lang' => 'YES_BIRTHDAYS', 'type' => 'radio:yes_no', 'explain' => false), + 'load_moderators' => array('lang' => 'YES_MODERATORS', 'type' => 'radio:yes_no', 'explain' => false), + 'load_jumpbox' => array('lang' => 'YES_JUMPBOX', 'type' => 'radio:yes_no', 'explain' => false), + 'load_cpf_memberlist' => array('lang' => 'LOAD_CPF_MEMBERLIST', 'type' => 'radio:yes_no', 'explain' => false), + 'load_cpf_viewprofile' => array('lang' => 'LOAD_CPF_VIEWPROFILE', 'type' => 'radio:yes_no', 'explain' => false), + 'load_cpf_viewtopic' => array('lang' => 'LOAD_CPF_VIEWTOPIC', 'type' => 'radio:yes_no', 'explain' => false), ) ); break; @@ -104,14 +112,13 @@ class acp_board 'pm_max_boxes' => array('lang' => 'BOXES_MAX', 'type' => 'text:4:4', 'explain' => true), 'pm_max_msgs' => array('lang' => 'BOXES_LIMIT', 'type' => 'text:4:4', 'explain' => true), 'full_folder_action' => array('lang' => 'FULL_FOLDER_ACTION', 'type' => 'select', 'method' => 'full_folder_select', 'explain' => true), - 'pm_edit_time' => array('lang' => 'PM_EDIT_TIME', 'type' => 'text:3:3', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']), + 'pm_edit_time' => array('lang' => 'PM_EDIT_TIME', 'type' => 'text:3:3', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']), 'legend2' => 'GENERAL_OPTIONS', 'allow_mass_pm' => array('lang' => 'ALLOW_MASS_PM', 'type' => 'radio:yes_no', 'explain' => false), 'auth_bbcode_pm' => array('lang' => 'ALLOW_BBCODE_PM', 'type' => 'radio:yes_no', 'explain' => false), 'auth_smilies_pm' => array('lang' => 'ALLOW_SMILIES_PM', 'type' => 'radio:yes_no', 'explain' => false), 'allow_pm_attach' => array('lang' => 'ALLOW_PM_ATTACHMENTS', 'type' => 'radio:yes_no', 'explain' => false), - 'auth_download_pm' => array('lang' => 'ALLOW_DOWNLOAD_PM', 'type' => 'radio:yes_no', 'explain' => false), 'allow_sig_pm' => array('lang' => 'ALLOW_SIG_PM', 'type' => 'radio:yes_no', 'explain' => false), 'print_pm' => array('lang' => 'ALLOW_PRINT_PM', 'type' => 'radio:yes_no', 'explain' => false), 'forward_pm' => array('lang' => 'ALLOW_FORWARD_PM', 'type' => 'radio:yes_no', 'explain' => false), @@ -137,7 +144,7 @@ class acp_board 'legend2' => 'POSTING', 'bump_type' => false, - 'edit_time' => array('lang' => 'EDIT_TIME', 'type' => 'text:3:3', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']), + 'edit_time' => array('lang' => 'EDIT_TIME', 'type' => 'text:3:3', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']), 'display_last_edited' => array('lang' => 'DISPLAY_LAST_EDITED', 'type' => 'radio:yes_no', 'explain' => true), 'flood_interval' => array('lang' => 'FLOOD_INTERVAL', 'type' => 'text:3:4', 'explain' => true), 'bump_interval' => array('lang' => 'BUMP_INTERVAL', 'type' => 'custom', 'method' => 'bump_interval', 'explain' => true), @@ -204,33 +211,6 @@ class acp_board 'coppa_enable' => array('lang' => 'ENABLE_COPPA', 'type' => 'radio:yes_no', 'explain' => true), 'coppa_mail' => array('lang' => 'COPPA_MAIL', 'type' => 'textarea:5:40', 'explain' => true), 'coppa_fax' => array('lang' => 'COPPA_FAX', 'type' => 'text:25:100', 'explain' => false), - 'coppa_hide_groups' => array('lang' => 'COPPA_HIDE_GROUPS', 'type' => 'radio:yes_no', 'explain' => true), - ) - ); - break; - - case 'visual': - $display_vars = array( - 'title' => 'ACP_VC_SETTINGS', - 'vars' => array( - 'legend1' => 'GENERAL_OPTIONS', - 'enable_confirm' => array('lang' => 'VISUAL_CONFIRM_REG', 'type' => 'radio:yes_no', 'explain' => true), - 'enable_post_confirm' => array('lang' => 'VISUAL_CONFIRM_POST', 'type' => 'radio:yes_no', 'explain' => true), - - 'legend2' => 'CAPTCHA_OPTIONS', - 'policy_overlap' => array('lang' => 'CAPTCHA_OVERLAP', 'type' => 'radio:yes_no', 'explain' => false), - 'policy_overlap_noise_pixel' => array('lang' => 'OVERLAP_NOISE_PIXEL', 'type' => 'select', 'method' => 'captcha_pixel_noise_select', 'explain' => false), - 'policy_overlap_noise_line' => array('lang' => 'OVERLAP_NOISE_LINE', 'type' => 'radio:yes_no', 'explain' => false), - 'policy_entropy' => array('lang' => 'CAPTCHA_ENTROPY', 'type' => 'radio:yes_no', 'explain' => false), - 'policy_entropy_noise_pixel' => array('lang' => 'ENTROPY_NOISE_PIXEL', 'type' => 'select', 'method' => 'captcha_pixel_noise_select', 'explain' => false), - 'policy_entropy_noise_line' => array('lang' => 'ENTROPY_NOISE_LINE', 'type' => 'radio:yes_no', 'explain' => false), - 'policy_shape' => array('lang' => 'CAPTCHA_SHAPE', 'type' => 'radio:yes_no', 'explain' => false), - 'policy_shape_noise_pixel' => array('lang' => 'SHAPE_NOISE_PIXEL', 'type' => 'select', 'method' => 'captcha_pixel_noise_select', 'explain' => false), - 'policy_shape_noise_line' => array('lang' => 'SHAPE_NOISE_LINE', 'type' => 'radio:yes_no', 'explain' => false), - 'policy_3dbitmap' => array('lang' => 'CAPTCHA_3DBITMAP', 'type' => 'radio:yes_no', 'explain' => false), - 'policy_cells' => array('lang' => 'CAPTCHA_CELLS', 'type' => 'radio:yes_no', 'explain' => false), - 'policy_stencil' => array('lang' => 'CAPTCHA_STENCIL', 'type' => 'radio:yes_no', 'explain' => false), - 'policy_composite' => array('lang' => 'CAPTCHA_COMPOSITE', 'type' => 'radio:yes_no', 'explain' => false), ) ); break; @@ -259,16 +239,17 @@ class acp_board 'load_online_time' => array('lang' => 'ONLINE_LENGTH', 'type' => 'text:4:3', 'explain' => true), 'legend2' => 'GENERAL_OPTIONS', - 'load_db_track' => array('lang' => 'YES_POST_MARKING', 'type' => 'radio:yes_no', 'explain' => true), - 'load_db_lastread' => array('lang' => 'YES_READ_MARKING', 'type' => 'radio:yes_no', 'explain' => true), - 'load_online' => array('lang' => 'YES_ONLINE', 'type' => 'radio:yes_no', 'explain' => true), - 'load_online_guests' => array('lang' => 'YES_ONLINE_GUESTS', 'type' => 'radio:yes_no', 'explain' => true), - 'load_onlinetrack' => array('lang' => 'YES_ONLINE_TRACK', 'type' => 'radio:yes_no', 'explain' => true), - 'load_birthdays' => array('lang' => 'YES_BIRTHDAYS', 'type' => 'radio:yes_no', 'explain' => false), - 'load_moderators' => array('lang' => 'YES_MODERATORS', 'type' => 'radio:yes_no', 'explain' => false), - 'load_jumpbox' => array('lang' => 'YES_JUMPBOX', 'type' => 'radio:yes_no', 'explain' => false), - 'load_user_activity' => array('lang' => 'LOAD_USER_ACTIVITY','type' => 'radio:yes_no', 'explain' => true), - 'load_tplcompile' => array('lang' => 'RECOMPILE_TEMPLATES', 'type' => 'radio:yes_no', 'explain' => true), + 'load_db_track' => array('lang' => 'YES_POST_MARKING', 'type' => 'radio:yes_no', 'explain' => true), + 'load_db_lastread' => array('lang' => 'YES_READ_MARKING', 'type' => 'radio:yes_no', 'explain' => true), + 'load_anon_lastread' => array('lang' => 'YES_ANON_READ_MARKING', 'type' => 'radio:yes_no', 'explain' => true), + 'load_online' => array('lang' => 'YES_ONLINE', 'type' => 'radio:yes_no', 'explain' => true), + 'load_online_guests' => array('lang' => 'YES_ONLINE_GUESTS', 'type' => 'radio:yes_no', 'explain' => true), + 'load_onlinetrack' => array('lang' => 'YES_ONLINE_TRACK', 'type' => 'radio:yes_no', 'explain' => true), + 'load_birthdays' => array('lang' => 'YES_BIRTHDAYS', 'type' => 'radio:yes_no', 'explain' => false), + 'load_moderators' => array('lang' => 'YES_MODERATORS', 'type' => 'radio:yes_no', 'explain' => false), + 'load_jumpbox' => array('lang' => 'YES_JUMPBOX', 'type' => 'radio:yes_no', 'explain' => false), + 'load_user_activity' => array('lang' => 'LOAD_USER_ACTIVITY', 'type' => 'radio:yes_no', 'explain' => true), + 'load_tplcompile' => array('lang' => 'RECOMPILE_TEMPLATES', 'type' => 'radio:yes_no', 'explain' => true), 'legend3' => 'CUSTOM_PROFILE_FIELDS', 'load_cpf_memberlist' => array('lang' => 'LOAD_CPF_MEMBERLIST', 'type' => 'radio:yes_no', 'explain' => false), @@ -316,14 +297,14 @@ class acp_board 'title' => 'ACP_SECURITY_SETTINGS', 'vars' => array( 'legend1' => 'ACP_SECURITY_SETTINGS', - 'allow_autologin' => array('lang' => 'ALLOW_AUTOLOGIN', 'type' => 'radio:yes_no', 'explain' => true), - 'max_autologin_time' => array('lang' => 'AUTOLOGIN_LENGTH', 'type' => 'text:5:5', 'explain' => true), - 'ip_check' => array('lang' => 'IP_VALID', 'type' => 'custom', 'method' => 'select_ip_check', 'explain' => true), - 'browser_check' => array('lang' => 'BROWSER_VALID', 'type' => 'radio:yes_no', 'explain' => true), - 'pass_complex' => array('lang' => 'PASSWORD_TYPE', 'type' => 'select', 'method' => 'select_password_chars', 'explain' => true), - 'chg_passforce' => array('lang' => 'FORCE_PASS_CHANGE', 'type' => 'text:3:3', 'explain' => true), - 'max_login_attempts' => array('lang' => 'MAX_LOGIN_ATTEMPTS','type' => 'text:3:3', 'explain' => true), - 'tpl_allow_php' => array('lang' => 'TPL_ALLOW_PHP', 'type' => 'radio:yes_no', 'explain' => true), + 'allow_autologin' => array('lang' => 'ALLOW_AUTOLOGIN', 'type' => 'radio:yes_no', 'explain' => true), + 'max_autologin_time' => array('lang' => 'AUTOLOGIN_LENGTH', 'type' => 'text:5:5', 'explain' => true), + 'ip_check' => array('lang' => 'IP_VALID', 'type' => 'custom', 'method' => 'select_ip_check', 'explain' => true), + 'browser_check' => array('lang' => 'BROWSER_VALID', 'type' => 'radio:yes_no', 'explain' => true), + 'pass_complex' => array('lang' => 'PASSWORD_TYPE', 'type' => 'select', 'method' => 'select_password_chars', 'explain' => true), + 'chg_passforce' => array('lang' => 'FORCE_PASS_CHANGE', 'type' => 'text:3:3', 'explain' => true), + 'max_login_attempts' => array('lang' => 'MAX_LOGIN_ATTEMPTS', 'type' => 'text:3:3', 'explain' => true), + 'tpl_allow_php' => array('lang' => 'TPL_ALLOW_PHP', 'type' => 'radio:yes_no', 'explain' => true), ) ); break; @@ -363,7 +344,7 @@ class acp_board } $this->new_config = $config; - $cfg_array = (isset($_REQUEST['config'])) ? request_var('config', array('' => '')) : $this->new_config; + $cfg_array = (isset($_REQUEST['config'])) ? request_var('config', array('' => ''), true) : $this->new_config; // 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) @@ -417,7 +398,7 @@ class acp_board { include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx); - $method = 'admin_' . $method; + $method = 'acp_' . $method; if (function_exists($method)) { if ($fields = $method($this->new_config)) @@ -545,7 +526,7 @@ class acp_board { if ($method && file_exists($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx)) { - $method = 'admin_' . $method; + $method = 'acp_' . $method; if (function_exists($method)) { $fields = $method($this->new_config); @@ -622,21 +603,11 @@ class acp_board } /** - * Select captcha pixel noise - */ - function captcha_pixel_noise_select($value, $key = '') - { - global $user; - - return '<option value="0"' . (($value == 0) ? ' selected="selected"' : '') . '>' . $user->lang['NONE'] . '</option><option value="1"' . (($value == 1) ? ' selected="selected"' : '') . '>' . $user->lang['LIGHT'] . '</option><option value="2"' . (($value == 2) ? ' selected="selected"' : '') . '>' . $user->lang['MEDIUM'] . '</option><option value="3"' . (($value == 3) ? ' selected="selected"' : '') . '>' . $user->lang['HEAVY'] . '</option>'; - } - - /** * Select ip validation */ function select_ip_check($value, $key = '') { - $radio_ary = array(4 => 'ALL', 3 => 'CLASS_C', 2 => 'CLASS_B', 0 => 'NONE'); + $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); } diff --git a/phpBB/includes/acp/acp_bots.php b/phpBB/includes/acp/acp_bots.php index a57283e3ea..f24a6b7b12 100644 --- a/phpBB/includes/acp/acp_bots.php +++ b/phpBB/includes/acp/acp_bots.php @@ -96,7 +96,7 @@ class acp_bots foreach ($_tables as $table) { $sql = "DELETE FROM $table - WHERE user_id IN (" . implode(', ', $user_id_ary) . ')'; + WHERE " . $db->sql_in_set('user_id', $user_id_ary); $db->sql_query($sql); } diff --git a/phpBB/includes/acp/acp_captcha.php b/phpBB/includes/acp/acp_captcha.php new file mode 100644 index 0000000000..3ac354004a --- /dev/null +++ b/phpBB/includes/acp/acp_captcha.php @@ -0,0 +1,113 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +*/ + +/** +* @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'); + + $config_vars = array('enable_confirm' => 'REG_ENABLE', + 'enable_post_confirm' => 'POST_ENABLE', + 'policy_overlap' => 'OVERLAP_ENABLE', + 'policy_overlap_noise_pixel' => 'OVERLAP_NOISE_PIXEL', + 'policy_overlap_noise_line' => 'OVERLAP_NOISE_LINE_ENABLE', + 'policy_entropy' => 'ENTROPY_ENABLE', + 'policy_entropy_noise_pixel' => 'ENTROPY_NOISE_PIXEL', + 'policy_entropy_noise_line' => 'ENTROPY_NOISE_LINE_ENABLE', + 'policy_shape' => 'SHAPE_ENABLE', + 'policy_shape_noise_pixel' => 'SHAPE_NOISE_PIXEL', + 'policy_shape_noise_line' => 'SHAPE_NOISE_LINE_ENABLE', + 'policy_3dbitmap' => 'THREEDBITMAP_ENABLE', + 'policy_cells' => 'CELLS_ENABLE', + 'policy_stencil' => 'STENCIL_ENABLE', + 'policy_composite' => 'COMPOSITE_ENABLE' + ); + + $policy_modules = array('policy_entropy', 'policy_3dbitmap', 'policy_overlap', 'policy_shape', 'policy_cells', 'policy_stencil', 'policy_composite'); + + switch ($mode) + { + case 'visual': + $this->tpl_name = 'acp_captcha'; + $this->page_title = 'ACP_VC_SETTINGS'; + $submit = request_var('submit', ''); + if ($submit) + { + $config_vars = array_keys($config_vars); + foreach ($config_vars as $config_var) + { + set_config($config_var, request_var($config_var, '')); + } + trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); + } + else + { + $array = array(); + + foreach ($config_vars as $config_var => $template_var) + { + $array[$template_var] = $config[$config_var]; + } + $template->assign_vars($array); + + + if (@extension_loaded('gd')) + { + $template->assign_var('GD', true); + foreach ($policy_modules as $module_name) + { + $template->assign_var('U_' . strtoupper($module_name), sprintf($user->lang['CAPTCHA_EXPLAIN'], '<a href="' . append_sid("{$phpbb_root_path}adm/index.$phpEx", 'i=captcha&mode=img&policy=' . $module_name) . '" target="_blank">', '</a>')); + } + if (function_exists('imagettfbbox') && function_exists('imagettftext')) + { + $template->assign_var('TTF', true); + } + } + } + break; + + case 'img': + $policy = request_var('policy', ''); + + if (!@extension_loaded('gd')) + { + trigger_error($user->lang['NO_GD']); + } + + if (!($policy === 'policy_entropy' || $policy === 'policy_3dbitmap') && (!function_exists('imagettfbbox') || !function_exists('imagettftext'))) + { + trigger_error($user->lang['NO_TTF']); + } + + if (!in_array($policy, $policy_modules)) + { + trigger_error($user->lang['BAD_POLICY']); + } + + $user->add_lang('ucp'); + + include($phpbb_root_path . 'includes/captcha/captcha_gd.' . $phpEx); + + $captcha = new captcha(); + $captcha->execute(gen_rand_string(), $policy); + break; + } + } +} + +?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php index 3cdb09bb5e..59ccb342fd 100644 --- a/phpBB/includes/acp/acp_database.php +++ b/phpBB/includes/acp/acp_database.php @@ -68,7 +68,7 @@ class acp_database @set_time_limit(1200); - $filename = time(); + $filename = 'backup_' . time(); // We set up the info needed for our on-the-fly creation :D switch ($format) @@ -135,6 +135,7 @@ class acp_database { case 'sqlite': $sql_data .= "BEGIN TRANSACTION;\n"; + $sqlite_version = sqlite_libversion(); break; case 'postgres': @@ -143,7 +144,8 @@ class acp_database case 'mssql': case 'mssql_odbc': - $sql_data .= "BEGIN TRANSACTION\nGO\n"; + $sql_data .= "BEGIN TRANSACTION\n"; + $sql_data .= "GO\n"; break; } @@ -157,14 +159,26 @@ class acp_database case 'mysqli': case 'mysql4': case 'mysql': - case 'sqlite': $sql_data .= '# Table: ' . $table_name . "\n"; $sql_data .= "DROP TABLE IF EXISTS $table_name;\n"; break; case 'oracle': $sql_data .= '# Table: ' . $table_name . "\n"; - $sql_data .= "DROP TABLE $table_name;\n\\\n"; + $sql_data .= "DROP TABLE $table_name;\n"; + $sql_data .= '\\' . "\n"; + break; + + case 'sqlite': + $sql_data .= '# Table: ' . $table_name . "\n"; + if (version_compare($sqlite_version, '3.0') == -1) + { + $sql_data .= "DROP TABLE $table_name;\n"; + } + else + { + $sql_data .= "DROP TABLE IF EXISTS $table_name;\n"; + } break; case 'postgres': @@ -177,11 +191,33 @@ class acp_database case 'mssql_odbc': $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;\nGO\n"; + $sql_data .= "DROP TABLE $table_name;\n"; + $sql_data .= "GO\n"; break; } $sql_data .= $this->get_table_structure($table_name); } + // We might wanna empty out all that junk :D + else + { + switch (SQL_LAYER) + { + case 'mysqli': + case 'mysql4': + case 'mysql': + case 'mssql': + case 'mssql_odbc': + case 'oracle': + case 'postgres': + case 'firebird': + $sql_data .= 'TRUNCATE TABLE ' . $table_name . ";\n"; + break; + + case 'sqlite': + $sql_data .= 'DELETE FROM ' . $table_name . ";\n"; + break; + } + } // Now write the data for the first time. :) if ($store == true) { @@ -211,7 +247,8 @@ class acp_database { case 'mysqli': - $sql = "SELECT * FROM $table_name"; + $sql = "SELECT * + FROM $table_name"; $result = mysqli_query($db->db_connect_id, $sql, MYSQLI_USE_RESULT); if ($result != false) { @@ -278,7 +315,8 @@ class acp_database case 'mysql4': case 'mysql': - $sql = "SELECT * FROM $table_name"; + $sql = "SELECT * + FROM $table_name"; $result = mysql_unbuffered_query($sql, $db->db_connect_id); if ($result != false) @@ -347,12 +385,48 @@ class acp_database break; case 'sqlite': + // This is *not* my fault. The PHP guys forgot a call to finalize when they wrote this function. This forces all the tables to stay locked... + // They finally fixed it in 5.1.3 but 5.1.2 and under still have this so instead, we go and grab the column types by smashing open the sqlite_master table + // and grope around for things that remind us of datatypes... + if (version_compare(phpversion(), '5.1.3', '>=')) + { + $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); + + $column_list = array(); + $table_cols = explode(',', trim($matches[1])); + foreach($table_cols as $declaration) + { + $entities = preg_split('#\s+#', trim($declaration)); + $column_name = preg_replace('/"?([^"]+)"?/', '\1', $entities[0]); - $col_types = sqlite_fetch_column_types($table_name, $db->db_connect_id); - $sql = "SELECT * FROM $table_name"; - $result = $db->sql_query($sql); + // Hit a primary key, those are not what we need :D + if (empty($entities[1])) + { + continue; + } + $col_types[$column_name] = $entities[1]; + } + } - while ($row = $db->sql_fetchrow($result)) + // Unbueffered query and the foreach make this ultra fast, we wait for nothing. + $sql = "SELECT * + FROM $table_name"; + $result = sqlite_unbuffered_query($db->db_connect_id, $sql); + $rows = sqlite_fetch_all($result, SQLITE_ASSOC); + + foreach ($rows as $row) { $names = $data = array(); foreach ($row as $row_name => $row_data) @@ -405,7 +479,7 @@ class acp_database // Grab all of the data from current table. $sql = "SELECT * - FROM {$table_name}"; + FROM $table_name"; $result = $db->sql_query($sql); $i_num_fields = pg_num_fields($result); @@ -421,14 +495,14 @@ class acp_database FROM pg_attrdef d, pg_class c WHERE (c.relname = '{$table_name}') AND (c.oid = d.adrelid) - AND d.adnum = " . strval($i+1); + 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) + 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"; + $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"; } } } @@ -476,7 +550,7 @@ class acp_database // 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"; + $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\n"; if ($store == true) { @@ -526,7 +600,7 @@ class acp_database // Grab all of the data from current table. $sql = "SELECT * - FROM {$table_name}"; + FROM $table_name"; $result = $db->sql_query($sql); $retrieved_data = odbc_num_rows($result); @@ -534,8 +608,8 @@ class acp_database if ($retrieved_data) { $sql = "SELECT 1 as has_identity - FROM INFORMATION_SCHEMA.COLUMNS - WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1"; + 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'])) @@ -597,7 +671,7 @@ class acp_database // 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"; + $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\n"; if ($store == true) { @@ -637,7 +711,7 @@ class acp_database // Grab all of the data from current table. $sql = "SELECT * - FROM {$table_name}"; + FROM $table_name"; $result = $db->sql_query($sql); $retrieved_data = mssql_num_rows($result); @@ -653,8 +727,8 @@ class acp_database if ($retrieved_data) { $sql = "SELECT 1 as has_identity - FROM INFORMATION_SCHEMA.COLUMNS - WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1"; + 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'])) @@ -708,7 +782,7 @@ class acp_database // 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"; + $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\n"; if ($store == true) { @@ -748,7 +822,7 @@ class acp_database // Grab all of the data from current table. $sql = "SELECT * - FROM {$table_name}"; + FROM $table_name"; $result = $db->sql_query($sql); $i_num_fields = ibase_num_fields($result); @@ -803,7 +877,7 @@ class acp_database // 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"; + $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\n"; if ($store == true) { @@ -833,7 +907,7 @@ class acp_database // Grab all of the data from current table. $sql = "SELECT * - FROM {$table_name}"; + FROM $table_name"; $result = $db->sql_query($sql); $i_num_fields = ocinumcols($result); @@ -887,7 +961,7 @@ class acp_database // 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"; + $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\n"; if ($store == true) { @@ -987,9 +1061,9 @@ class acp_database break; case 'postgres': - $sql = "SELECT relname + $sql = 'SELECT relname FROM pg_stat_user_tables - ORDER BY relname;"; + ORDER BY relname'; $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) { @@ -1088,7 +1162,7 @@ class acp_database $delete = request_var('delete', ''); $file = request_var('file', ''); - preg_match('#^(\d{10})\.(sql(?:\.(?:gz|bz2))?)$#', $file, $matches); + preg_match('#^(backup_\d{10,})\.(sql(?:\.(?:gz|bz2))?)$#', $file, $matches); $file_name = $phpbb_root_path . 'store/' . $matches[0]; if (!(file_exists($file_name) && is_readable($file_name))) @@ -1144,39 +1218,47 @@ class acp_database { // Strip out sql comments... remove_remarks($data); - switch (SQL_LAYER) - { - case 'firebird': - $delim = ';;'; - break; - case 'mysql': - case 'mysql4': - case 'mysqli': - case 'sqlite': - case 'postgres': - $delim = ';'; - break; + // SQLite gets improved performance when you shove all of these disk write queries at once :D + if (SQL_LAYER == 'sqlite') + { + $db->sql_query($data); + } + else + { + switch (SQL_LAYER) + { + case 'firebird': + $delim = ';;'; + break; - case 'oracle': - $delim = '/'; - break; + case 'mysql': + case 'mysql4': + case 'mysqli': + case 'postgres': + $delim = ';'; + break; - case 'mssql': - case 'mssql-odbc': - $delim = 'GO'; - break; - } - $pieces = split_sql_file($data, $delim); + case 'oracle': + $delim = '/'; + break; - $sql_count = count($pieces); - for($i = 0; $i < $sql_count; $i++) - { - $sql = trim($pieces[$i]); + case 'mssql': + case 'mssql-odbc': + $delim = 'GO'; + break; + } + $pieces = split_sql_file($data, $delim); - if (!empty($sql) && $sql[0] != '#') + $sql_count = count($pieces); + for($i = 0; $i < $sql_count; $i++) { - $db->sql_query($sql); + $sql = trim($pieces[$i]); + + if (!empty($sql) && $sql[0] != '#') + { + $db->sql_query($sql); + } } } } @@ -1202,7 +1284,7 @@ class acp_database $dh = opendir($dir); while (($file = readdir($dh)) !== false) { - if (preg_match('#^(\d{10})\.(sql(?:\.(?:gz|bz2))?)$#', $file, $matches)) + if (preg_match('#^backup_(\d{10,})\.(sql(?:\.(?:gz|bz2))?)$#', $file, $matches)) { $supported = in_array($matches[2], $methods); @@ -1278,7 +1360,10 @@ class acp_database } $db->sql_freeresult($result); - $result = $db->sql_query("SHOW KEYS FROM $table_name"); + $sql = "SHOW KEYS + FROM $table_name"; + + $result = $db->sql_query($sql); $index = array(); while ($row = $db->sql_fetchrow($result)) @@ -1403,11 +1488,12 @@ class acp_database // 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 + $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 @@ -1477,7 +1563,7 @@ class acp_database // 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 + $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) @@ -1486,7 +1572,8 @@ class acp_database 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 "; + ORDER BY index_name, tab_name, column_name"; + $result = $db->sql_query($sql_pri_keys); $index_create = $index_rows = $primary_key = array(); @@ -1599,7 +1686,7 @@ class acp_database if ($row['COLUMN_DEFAULT']) { - $line .= ' CONSTRAINT [DF_' . $table_name . '_' . $row['COLUMN_NAME'] . '] DEFAULT ' . $row['COLUMN_DEFAULT']; + $line .= ' DEFAULT ' . $row['COLUMN_DEFAULT']; } $rows[] = $line; @@ -1666,7 +1753,7 @@ class acp_database $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 + $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 @@ -1727,7 +1814,7 @@ class acp_database $db->sql_freeresult($result); - $sql = 'SELECT I.RDB$INDEX_NAME AS INAME, I.RDB$UNIQUE_FLAG AS UFLAG, S.RDB$FIELD_NAME AS FNAME + $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 @@ -1771,7 +1858,7 @@ class acp_database $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 + $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) @@ -1800,7 +1887,9 @@ class acp_database case 'oracle': $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}'"; + $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(); diff --git a/phpBB/includes/acp/acp_email.php b/phpBB/includes/acp/acp_email.php index 62a86eed19..c20640bd54 100644 --- a/phpBB/includes/acp/acp_email.php +++ b/phpBB/includes/acp/acp_email.php @@ -55,13 +55,11 @@ class acp_email { if ($usernames) { - $usernames = implode(', ', preg_replace('#^[\s]*?(.*?)[\s]*?$#e', "\"'\" . \$db->sql_escape('\\1') . \"'\"", explode("\n", $usernames))); - $sql = 'SELECT username, user_email, user_jabber, user_notify_type, user_lang - FROM ' . USERS_TABLE . " - WHERE username IN ($usernames) + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('username', explode("\n", $usernames)) . ' AND user_allow_massemail = 1 - ORDER BY user_lang, user_notify_type"; // , SUBSTRING(user_email FROM INSTR(user_email, '@')) + ORDER BY user_lang, user_notify_type'; // , SUBSTRING(user_email FROM INSTR(user_email, '@')) } else { @@ -85,10 +83,10 @@ class acp_email } $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); if (!$row) { + $db->sql_freeresult($result); trigger_error($user->lang['NO_USER'] . adm_back_link($this->u_action)); } @@ -121,7 +119,7 @@ class acp_email $email_list[$j][$i]['jabber'] = $row['user_jabber']; $i++; } - } + } while ($row = $db->sql_fetchrow($result)); $db->sql_freeresult($result); @@ -159,6 +157,7 @@ class acp_email $messenger->assign_vars(array( 'SITENAME' => $config['sitename'], 'CONTACT_EMAIL' => $config['board_contact'], + 'EMAIL_SIG' => str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']), 'MESSAGE' => html_entity_decode($message)) ); diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php index ac4112a773..5964a285e7 100644 --- a/phpBB/includes/acp/acp_forums.php +++ b/phpBB/includes/acp/acp_forums.php @@ -99,10 +99,12 @@ class acp_forums 'forum_link_track' => request_var('forum_link_track', false), 'forum_desc' => request_var('forum_desc', '', true), 'forum_desc_uid' => '', - 'forum_desc_bitfield' => 0, + 'forum_desc_options' => 0, + 'forum_desc_bitfield' => '', 'forum_rules' => request_var('forum_rules', '', true), 'forum_rules_uid' => '', - 'forum_rules_bitfield' => 0, + 'forum_rules_options' => 0, + 'forum_rules_bitfield' => '', 'forum_rules_link' => request_var('forum_rules_link', ''), 'forum_image' => request_var('forum_image', ''), 'forum_style' => request_var('forum_style', 0), @@ -111,6 +113,7 @@ class acp_forums '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), 'prune_days' => request_var('prune_days', 7), 'prune_viewed' => request_var('prune_viewed', 7), 'prune_freq' => request_var('prune_freq', 1), @@ -126,13 +129,13 @@ class acp_forums // 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'], request_var('rules_parse_bbcode', false), request_var('rules_parse_urls', false), request_var('rules_parse_smilies', false)); + 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'], request_var('desc_parse_bbcode', false), request_var('desc_parse_urls', false), request_var('desc_parse_smilies', false)); + 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); @@ -142,8 +145,20 @@ class acp_forums $forum_perm_from = request_var('forum_perm_from', 0); // Copy permissions? - if ($forum_perm_from && $action == 'add') + if ($forum_perm_from) { + // if we edit a forum delete current permissions first + if ($action == 'edit') + { + $sql = 'DELETE FROM ' . ACL_USERS_TABLE . ' + WHERE forum_id = ' . (int) $forum_data['forum_id']; + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . ' + WHERE forum_id = ' . (int) $forum_data['forum_id']; + $db->sql_query($sql); + } + // 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" @@ -281,7 +296,7 @@ class acp_forums trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); } - $sql = 'SELECT forum_name + $sql = 'SELECT forum_name, forum_type FROM ' . FORUMS_TABLE . " WHERE forum_id = $forum_id"; $result = $db->sql_query($sql); @@ -306,12 +321,13 @@ class acp_forums if ($update) { - $forum_data['forum_flags'] = 0; - $forum_data['forum_flags'] += (request_var('forum_link_track', false)) ? 1 : 0; - $forum_data['forum_flags'] += (request_var('prune_old_polls', false)) ? 2 : 0; - $forum_data['forum_flags'] += (request_var('prune_announce', false)) ? 4 : 0; - $forum_data['forum_flags'] += (request_var('prune_sticky', false)) ? 8 : 0; - $forum_data['forum_flags'] += ($forum_data['show_active']) ? 16 : 0; + $forum_data['forum_flags'] = 0; + $forum_data['forum_flags'] += (request_var('forum_link_track', false)) ? 1 : 0; + $forum_data['forum_flags'] += (request_var('prune_old_polls', false)) ? 2 : 0; + $forum_data['forum_flags'] += (request_var('prune_announce', false)) ? 4 : 0; + $forum_data['forum_flags'] += (request_var('prune_sticky', false)) ? 8 : 0; + $forum_data['forum_flags'] += ($forum_data['show_active']) ? 16 : 0; + $forum_data['forum_flags'] += (request_var('enable_post_review', true)) ? 32 : 0; } // Show form to create/modify a forum @@ -326,7 +342,20 @@ class acp_forums $forum_data = $row; } - $parents_list = make_forum_select($forum_data['parent_id'], $forum_id, false, false, false); + // Make sure there is no forum displayed for parents_list having the current forum id as a parent... + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE . ' + WHERE parent_id = ' . $forum_id; + $result = $db->sql_query($sql); + + $exclude_forums = array($forum_id); + while ($row = $db->sql_fetchrow($result)) + { + $exclude_forums[] = $row['forum_id']; + } + $db->sql_freeresult($result); + + $parents_list = make_forum_select($forum_data['parent_id'], $exclude_forums, false, false, false); $forum_data['forum_password_confirm'] = $forum_data['forum_password']; } @@ -390,16 +419,17 @@ class acp_forums { // 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'] = 0; + $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'], request_var('rules_allow_bbcode', false), request_var('rules_allow_urls', false), request_var('rules_allow_smiliess', false)); + 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_smiliess', 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_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_bitfield']); + $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 @@ -409,13 +439,14 @@ class acp_forums { // 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'] = 0; + $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'], request_var('desc_allow_bbcode', false), request_var('desc_allow_urls', false), request_var('desc_allow_smiliess', false)); + 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_smiliess', false)); } // decode... - $forum_desc_data = generate_text_for_edit($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield']); + $forum_desc_data = generate_text_for_edit($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_options']); } $forum_type_options = ''; @@ -468,8 +499,9 @@ class acp_forums 'U_BACK' => $this->u_action . '&parent_id=' . $this->parent_id, 'U_EDIT_ACTION' => $this->u_action . "&parent_id={$this->parent_id}&action=$action&f=$forum_id", - 'L_TITLE' => $user->lang[$this->page_title], - 'ERROR_MSG' => (sizeof($errors)) ? implode('<br />', $errors) : '', + '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'], @@ -501,21 +533,22 @@ class acp_forums 'S_STATUS_OPTIONS' => $statuslist, 'S_PARENT_OPTIONS' => $parents_list, 'S_STYLES_OPTIONS' => $styles_list, - 'S_FORUM_OPTIONS' => make_forum_select(false, false, false), + 'S_FORUM_OPTIONS' => make_forum_select(($action == 'add') ? $forum_data['parent_id'] : false, 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_LINK' => ($forum_data['forum_type'] == FORUM_LINK) ? true : false, 'S_FORUM_CAT' => ($forum_data['forum_type'] == FORUM_CAT) ? true : false, - 'S_FORUM_LINK_TRACK' => ($forum_data['forum_flags'] & 1) ? true : false, 'S_ENABLE_INDEXING' => ($forum_data['enable_indexing']) ? true : false, 'S_TOPIC_ICONS' => ($forum_data['enable_icons']) ? 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'] & 1) ? true : false, 'S_PRUNE_OLD_POLLS' => ($forum_data['forum_flags'] & 2) ? true : false, 'S_PRUNE_ANNOUNCE' => ($forum_data['forum_flags'] & 4) ? true : false, 'S_PRUNE_STICKY' => ($forum_data['forum_flags'] & 8) ? true : false, 'S_DISPLAY_ACTIVE_TOPICS' => ($forum_data['forum_flags'] & 16) ? true : false, + 'S_ENABLE_POST_REVIEW' => ($forum_data['forum_flags'] & 32) ? true : false, ) ); @@ -645,7 +678,7 @@ class acp_forums $template->assign_block_vars('forums', array( 'FOLDER_IMAGE' => $folder_image, 'FORUM_NAME' => $row['forum_name'], - 'FORUM_DESCRIPTION' => generate_text_for_display($row['forum_desc'], $row['forum_desc_uid'], $row['forum_desc_bitfield']), + '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'], @@ -744,12 +777,14 @@ class acp_forums // 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']) ? 1 : 0; $forum_data['forum_flags'] += ($forum_data['prune_old_polls']) ? 2 : 0; $forum_data['forum_flags'] += ($forum_data['prune_announce']) ? 4 : 0; $forum_data['forum_flags'] += ($forum_data['prune_sticky']) ? 8 : 0; $forum_data['forum_flags'] += ($forum_data['show_active']) ? 16 : 0; + $forum_data['forum_flags'] += ($forum_data['enable_post_review']) ? 32 : 0; // Unset data that are not database fields $forum_data_sql = $forum_data; @@ -759,6 +794,7 @@ class acp_forums 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['forum_password_confirm']); // What are we going to do tonight Brain? The same thing we do everynight, @@ -935,14 +971,14 @@ class acp_forums $sql = 'UPDATE ' . FORUMS_TABLE . " SET right_id = right_id + $diff, forum_parents = '' WHERE " . $to_data['right_id'] . ' BETWEEN left_id AND right_id - AND forum_id NOT IN (' . implode(', ', $moved_ids) . ')'; + 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 forum_id NOT IN (' . implode(', ', $moved_ids) . ')'; + AND ' . $db->sql_in_set('forum_id', $moved_ids, true); $db->sql_query($sql); // Resync moved branch @@ -961,7 +997,7 @@ class acp_forums { $sql = 'SELECT MAX(right_id) AS right_id FROM ' . FORUMS_TABLE . ' - WHERE forum_id NOT IN (' . implode(', ', $moved_ids) . ')'; + WHERE ' . $db->sql_in_set('forum_id', $moved_ids, true); $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); @@ -971,7 +1007,7 @@ class acp_forums $sql = 'UPDATE ' . FORUMS_TABLE . " SET left_id = left_id $diff, right_id = right_id $diff, forum_parents = '' - WHERE forum_id IN (" . implode(', ', $moved_ids) . ')'; + WHERE " . $db->sql_in_set('forum_id', $moved_ids); $db->sql_query($sql); } @@ -982,7 +1018,7 @@ class acp_forums { global $db; - $table_ary = array(LOG_TABLE, POSTS_TABLE, TOPICS_TABLE, DRAFTS_TABLE, TOPICS_TRACK_TABLE); + $table_ary = array(ACL_GROUPS_TABLE, ACL_USERS_TABLE, LOG_TABLE, POSTS_TABLE, TOPICS_TABLE, DRAFTS_TABLE, TOPICS_TRACK_TABLE); foreach ($table_ary as $table) { @@ -1023,6 +1059,7 @@ class acp_forums $errors = array(); $log_action_posts = $log_action_forums = $posts_to_name = $subforums_to_name = ''; + $forum_ids = array($forum_id); if ($action_posts == 'delete') { @@ -1066,8 +1103,6 @@ class acp_forums if ($action_subforums == 'delete') { $log_action_forums = 'FORUMS'; - - $forum_ids = array($forum_id); $rows = get_forum_branch($forum_id, 'children', 'descending', false); foreach ($rows as $row) @@ -1084,7 +1119,7 @@ class acp_forums $diff = sizeof($forum_ids) * 2; $sql = 'DELETE FROM ' . FORUMS_TABLE . ' - WHERE forum_id IN (' . implode(', ', $forum_ids) . ')'; + WHERE ' . $db->sql_in_set('forum_id', $forum_ids); $db->sql_query($sql); } else if ($action_subforums == 'move') @@ -1159,11 +1194,6 @@ class acp_forums WHERE left_id > {$forum_data['right_id']}"; $db->sql_query($sql); - if (!isset($forum_ids) || !is_array($forum_ids)) - { - $forum_ids = array($forum_id); - } - // Delete forum ids from extension groups table $sql = 'SELECT group_id, allowed_forums FROM ' . EXTENSION_GROUPS_TABLE; @@ -1332,11 +1362,10 @@ class acp_forums if (sizeof($ids)) { $start += sizeof($ids); - $id_list = implode(', ', $ids); foreach ($tables as $table) { - $db->sql_query("DELETE FROM $table WHERE $field IN ($id_list)"); + $db->sql_query("DELETE FROM $table WHERE " . $db->sql_in_set($field, $id_list)); } } } @@ -1364,6 +1393,43 @@ class acp_forums $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', (int) $row['stat'], true); + + add_log('admin', 'LOG_RESYNC_STATS'); + return array(); } diff --git a/phpBB/includes/acp/acp_groups.php b/phpBB/includes/acp/acp_groups.php index 5aee176524..9f7e68bfe5 100644 --- a/phpBB/includes/acp/acp_groups.php +++ b/phpBB/includes/acp/acp_groups.php @@ -85,7 +85,7 @@ class acp_groups break; } - trigger_error($user->lang[$message] . adm_back_link($this->u_action)); + trigger_error($user->lang[$message] . adm_back_link($this->u_action . '&action=list&g=' . $group_id)); break; case 'default': @@ -134,7 +134,7 @@ class acp_groups group_user_attributes('default', $group_id, $mark_ary, false, $group_row['group_name'], $group_row); } - trigger_error($user->lang['GROUP_DEFS_UPDATED'] . adm_back_link($this->u_action)); + trigger_error($user->lang['GROUP_DEFS_UPDATED'] . adm_back_link($this->u_action . '&action=list&g=' . $group_id)); } else { @@ -176,13 +176,15 @@ class acp_groups break; } + $back_link = ($action == 'delete') ? $this->u_action : $this->u_action . '&action=list&g=' . $group_id; + if ($error) { - trigger_error($user->lang[$error] . adm_back_link($this->u_action)); + trigger_error($user->lang[$error] . adm_back_link($back_link)); } $message = ($action == 'delete') ? 'GROUP_DELETED' : 'GROUP_USERS_REMOVE'; - trigger_error($user->lang[$message] . adm_back_link($this->u_action)); + trigger_error($user->lang[$message] . adm_back_link($back_link)); } else { @@ -204,7 +206,7 @@ class acp_groups if (!$name_ary) { - trigger_error($user->lang['NO_USERS'] . adm_back_link($this->u_action)); + trigger_error($user->lang['NO_USERS'] . adm_back_link($this->u_action . '&action=list&g=' . $group_id)); } $name_ary = array_unique(explode("\n", $name_ary)); @@ -212,11 +214,11 @@ class acp_groups // Add user/s to group if ($error = group_user_add($group_id, false, $name_ary, $group_row['group_name'], $default, $leader, 0, $group_row)) { - trigger_error($user->lang[$error] . adm_back_link($this->u_action)); + trigger_error($user->lang[$error] . adm_back_link($this->u_action . '&action=list&g=' . $group_id)); } $message = ($action == 'addleaders') ? 'GROUP_MODS_ADDED' : 'GROUP_USERS_ADDED'; - trigger_error($user->lang[$message] . adm_back_link($this->u_action)); + trigger_error($user->lang[$message] . adm_back_link($this->u_action . '&action=list&g=' . $group_id)); break; case 'edit': @@ -418,7 +420,7 @@ class acp_groups 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_bitfield']); + $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']; } @@ -607,10 +609,12 @@ class acp_groups 'S_ON_PAGE' => on_page($total_members, $config['topics_per_page'], $start), 'PAGINATION' => generate_pagination($this->u_action . "&action=$action&g=$group_id", $total_members, $config['topics_per_page'], $start, true), + 'GROUP_NAME' => ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'], 'U_ACTION' => $this->u_action . "&g=$group_id", 'U_BACK' => $this->u_action, - 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=list&field=usernames')) + 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=list&field=usernames'), + 'U_DEFAULT_ALL' => "{$this->u_action}&action=default&g=$group_id") ); foreach ($group_data['leader'] as $row) @@ -701,7 +705,6 @@ class acp_groups $template->assign_block_vars('groups', array( 'U_LIST' => "{$this->u_action}&action=list&g=$group_id", - 'U_DEFAULT' => "{$this->u_action}&action=default&g=$group_id", 'U_EDIT' => "{$this->u_action}&action=edit&g=$group_id", 'U_DELETE' => ($auth->acl_get('a_groupdel')) ? "{$this->u_action}&action=delete&g=$group_id" : '', diff --git a/phpBB/includes/acp/acp_icons.php b/phpBB/includes/acp/acp_icons.php index b74e5f8b4f..66aec3a90d 100644 --- a/phpBB/includes/acp/acp_icons.php +++ b/phpBB/includes/acp/acp_icons.php @@ -108,44 +108,41 @@ class acp_icons ORDER BY {$fields}_order " . (($icon_id || $action == 'add') ? 'DESC' : 'ASC'); $result = $db->sql_query($sql); - if ($row = $db->sql_fetchrow($result)) + while ($row = $db->sql_fetchrow($result)) { - do + if ($action == 'add') { - if ($action == 'add') - { - unset($_images[$row[$fields . '_url']]); - } + unset($_images[$row[$fields . '_url']]); + } - if ($row[$fields . '_id'] == $icon_id) + if ($row[$fields . '_id'] == $icon_id) + { + $after = true; + $data[$row[$fields . '_url']] = $row; + } + else + { + if ($action == 'edit' && !$icon_id) { - $after = true; $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; - } - $after_txt = ($mode == 'smilies') ? $row['code'] : $row['icons_url']; - $order_list = '<option value="' . ($row[$fields . '_order']) . '"' . $selected . '>' . sprintf($user->lang['AFTER_' . $lang], ' -> ' . htmlspecialchars($after_txt)) . '</option>' . $order_list; + $selected = ''; + if (!empty($after)) + { + $selected = ' selected="selected"'; + $after = false; } + + $after_txt = ($mode == 'smilies') ? $row['code'] : $row['icons_url']; + $order_list = '<option value="' . ($row[$fields . '_order']) . '"' . $selected . '>' . sprintf($user->lang['AFTER_' . $lang], ' -> ' . htmlspecialchars($after_txt)) . '</option>' . $order_list; } - while ($row = $db->sql_fetchrow($result)); } $db->sql_freeresult($result); $order_list = '<option value="1"' . ((!isset($after)) ? ' selected="selected"' : '') . '>' . $user->lang['FIRST'] . '</option>' . $order_list; + $data = array(); if ($action == 'add') { $data = $_images; @@ -231,20 +228,20 @@ class acp_icons } $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, + $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]) + 'emotion' => $image_emotion[$image], + 'code' => $image_code[$image]) ); } - + if (!empty($image_order[$image])) { $img_sql = array_merge($img_sql, array( @@ -351,7 +348,10 @@ class acp_icons $cur_img = array(); $field_sql = ($mode == 'smilies') ? 'code' : 'icons_url'; - $result = $db->sql_query("SELECT $field_sql FROM $table"); + + $sql = "SELECT $field_sql + FROM $table"; + $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) { @@ -371,8 +371,8 @@ class acp_icons $data = array(); if (preg_match_all("#'(.*?)', #", $pak_entry, $data)) { - if ((sizeof($data[1]) != 3 && $mode == 'icons') || - (sizeof($data[1]) != 5 && $mode == 'smilies')) + 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)); } @@ -381,11 +381,12 @@ class acp_icons $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][3]) && isset($data[1][4])) + if (isset($data[1][4]) && isset($data[1][5])) { - $emotion = stripslashes($data[1][3]); - $code = stripslashes($data[1][4]); + $emotion = stripslashes($data[1][4]); + $code = stripslashes($data[1][5]); } if ($current == 'replace' && @@ -394,15 +395,16 @@ class acp_icons { $replace_sql = ($mode == 'smilies') ? $code : $img; $sql = array( - $fields . '_url' => $img, - $fields . '_height' => (int) $height, - $fields . '_width' => (int) $width, + $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 + 'emotion' => $emotion, )); } @@ -415,17 +417,18 @@ class acp_icons ++$order; $sql = array( - $fields . '_url' => $img, - $fields . '_height' => (int) $height, - $fields . '_width' => (int) $width, - $fields . '_order' => (int) $order, + $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 + 'code' => $code, + 'emotion' => $emotion, )); } $db->sql_query("INSERT INTO $table " . $db->sql_build_array('INSERT', $sql)); @@ -435,7 +438,7 @@ class acp_icons $cache->destroy('icons'); $cache->destroy('sql', $table); - + trigger_error($user->lang[$lang . '_IMPORT_SUCCESS'] . adm_back_link($this->u_action)); } else @@ -476,7 +479,7 @@ class acp_icons ); return; - + break; case 'send': @@ -492,6 +495,7 @@ class acp_icons $pak .= "'" . addslashes($row[$fields . '_url']) . "', "; $pak .= "'" . addslashes($row[$fields . '_width']) . "', "; $pak .= "'" . addslashes($row[$fields . '_height']) . "', "; + $pak .= "'" . addslashes($row['display_on_posting']) . "', "; if ($mode == 'smilies') { @@ -505,7 +509,7 @@ class acp_icons if ($pak != '') { - $db->sql_close(); + garbage_collection(); header('Pragma: public'); @@ -519,15 +523,16 @@ class acp_icons } else { - trigger_error($user->lang['NO_' . $fields . '_EXPORT'] . adm_back_link($this->u_action)); + trigger_error($user->lang['NO_' . strtoupper($fields) . '_EXPORT'] . adm_back_link($this->u_action)); } break; case 'delete': - $db->sql_query("DELETE FROM $table - WHERE {$fields}_id = $icon_id"); + $sql = "DELETE FROM $table + WHERE {$fields}_id = $icon_id"; + $db->sql_query($sql); switch ($mode) { @@ -549,6 +554,9 @@ class acp_icons $notice = $user->lang[$lang . '_DELETED']; + $cache->destroy('icons'); + $cache->destroy('sql', $table); + break; case 'move_up': diff --git a/phpBB/includes/acp/acp_language.php b/phpBB/includes/acp/acp_language.php index 668422a90b..29aabe240f 100644 --- a/phpBB/includes/acp/acp_language.php +++ b/phpBB/includes/acp/acp_language.php @@ -71,6 +71,10 @@ class acp_language $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']); } @@ -97,23 +101,13 @@ class acp_language )); } - $entry = $_POST['entry']; - foreach ($entry as $key => $value) - { - if (is_array($value)) - { - foreach ($value as $key2 => $data) - { - $entry[$key][$key2] = htmlentities($data); - } - } - else - { - $entry[$key] = htmlentities($value); - } - } - - $hidden_data = build_hidden_fields(array('file' => $this->language_file, 'dir' => $this->language_directory, 'method' => $method, 'entry' => $entry)); + $hidden_data = build_hidden_fields(array( + 'file' => $this->language_file, + 'dir' => $this->language_directory, + 'method' => $method, + 'entry' => $_POST['entry']), + true + ); $template->assign_vars(array( 'S_UPLOAD' => true, @@ -133,7 +127,8 @@ class acp_language trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action)); } - $sql = 'SELECT * FROM ' . LANG_TABLE . " + $sql = 'SELECT * + FROM ' . LANG_TABLE . " WHERE lang_id = $lang_id"; $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); @@ -168,7 +163,8 @@ class acp_language trigger_error($user->lang['NO_FILE_SELECTED'] . adm_back_link($this->u_action)); } - $sql = 'SELECT * FROM ' . LANG_TABLE . " + $sql = 'SELECT * + FROM ' . LANG_TABLE . " WHERE lang_id = $lang_id"; $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); @@ -210,8 +206,7 @@ class acp_language if ($this->language_directory == 'email') { // Email Template - $entry = (STRIP) ? stripslashes($_POST['entry']) : $_POST['entry']; - $entry = preg_replace('#&(\#[0-9]+;)#', '&\1', $entry); + $entry = $this->prepare_lang_entry($_POST['entry'], false); fwrite($fp, $entry); } else @@ -229,23 +224,19 @@ class acp_language { if (!is_array($value)) { + continue; } - else - { - $entry = "\tarray(\n"; + + $entry = "\tarray(\n"; - foreach ($value as $_key => $_value) - { - $_value = (STRIP) ? stripslashes($_value) : $_value; - $_value = preg_replace('#&(\#[0-9]+;)#', '&\1', $_value); - $entry .= "\t\t" . (int) $_key . "\t=> '" . str_replace("'", "\\'", $_value) . "',\n"; - } - - $entry .= "\t),\n"; + foreach ($value as $_key => $_value) + { + $entry .= "\t\t" . (int) $_key . "\t=> '" . $this->prepare_lang_entry($_value) . "',\n"; } - + + $entry .= "\t),\n"; fwrite($fp, $entry); - } + } } else { @@ -255,32 +246,13 @@ class acp_language foreach ($_POST['entry'] as $key => $value) { - if (!is_array($value)) - { - $value = (STRIP) ? stripslashes($value) : $value; - $value = preg_replace('#&(\#[0-9]+;)#', '&\1', $value); - $entry = "\t'" . $key . "'\t=> '" . str_replace("'", "\\'", $value) . "',\n"; - } - else - { - $entry = "\n\t'" . $key . "'\t=> array(\n"; - - foreach ($value as $_key => $_value) - { - $_value = (STRIP) ? stripslashes($_value) : $_value; - $_value = preg_replace('#&(\#[0-9]+;)#', '&\1', $_value); - $entry .= "\t\t'" . $_key . "'\t=> '" . str_replace("'", "\\'", $_value) . "',\n"; - } - - $entry .= "\t),\n\n"; - } - + $entry = $this->format_lang_array($key, $value); fwrite($fp, $entry); - } + } } $footer = "));\n\n?>"; - fwrite($fp, $footer); + fwrite($fp, $footer); } fclose($fp); @@ -302,7 +274,8 @@ class acp_language } else if ($action == 'upload_data') { - $sql = 'SELECT lang_iso FROM ' . LANG_TABLE . " + $sql = 'SELECT lang_iso + FROM ' . LANG_TABLE . " WHERE lang_id = $lang_id"; $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); @@ -322,6 +295,11 @@ class acp_language 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']); } @@ -335,6 +313,9 @@ class acp_language $transfer->copy_file('store/' . $lang_path . $file, $lang_path . $file); $transfer->close_session(); + // Remove from storage folder + @unlink($phpbb_root_path . 'store/' . $lang_path . $file); + add_log('admin', 'LOG_LANGUAGE_FILE_REPLACED', $file); trigger_error($user->lang['UPLOAD_COMPLETED']); @@ -353,7 +334,8 @@ class acp_language $this->page_title = 'LANGUAGE_PACK_DETAILS'; - $sql = 'SELECT * FROM ' . LANG_TABLE . ' + $sql = 'SELECT * + FROM ' . LANG_TABLE . ' WHERE lang_id = ' . $lang_id; $result = $db->sql_query($sql); $lang_entries = $db->sql_fetchrow($result); @@ -665,7 +647,8 @@ class acp_language trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action)); } - $sql = 'SELECT * FROM ' . LANG_TABLE . ' + $sql = 'SELECT * + FROM ' . LANG_TABLE . ' WHERE lang_id = ' . $lang_id; $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); @@ -707,7 +690,8 @@ class acp_language ); unset($file); - $sql = 'SELECT lang_iso FROM ' . LANG_TABLE . " + $sql = 'SELECT lang_iso + FROM ' . LANG_TABLE . " WHERE lang_iso = '" . $db->sql_escape($lang_iso) . "'"; $result = $db->sql_query($sql); @@ -746,7 +730,8 @@ class acp_language trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action)); } - $sql = 'SELECT * FROM ' . LANG_TABLE . ' + $sql = 'SELECT * + FROM ' . LANG_TABLE . ' WHERE lang_id = ' . $lang_id; $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); @@ -794,7 +779,7 @@ class acp_language include_once($phpbb_root_path . 'includes/functions_compress.' . $phpEx); - if ($use_method == 'zip') + if ($use_method == '.zip') { $compress = new compress_zip('w', $phpbb_root_path . 'store/lang_' . $row['lang_iso'] . $use_method); } @@ -818,6 +803,17 @@ class acp_language // 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'); @@ -862,7 +858,8 @@ class acp_language $db->sql_freeresult($result); $sql = 'SELECT * - FROM ' . LANG_TABLE; + FROM ' . LANG_TABLE . ' + ORDER BY lang_english_name'; $result = $db->sql_query($sql); $installed = array(); @@ -975,8 +972,7 @@ $lang = array_merge($lang, array( '; // Language files in language root directory - $this->main_files = array("common.$phpEx", "groups.$phpEx", "mcp.$phpEx", "memberlist.$phpEx", "posting.$phpEx", "search.$phpEx", "ucp.$phpEx", "viewforum.$phpEx", "viewtopic.$phpEx", "help_bbcode.$phpEx", "help_faq.$phpEx"); - + $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"); } /** @@ -1041,22 +1037,52 @@ $lang = array_merge($lang, array( foreach ($value as $_key => $_value) { - $tpl .= ' - <tr> - <td class="row1" style="white-space: nowrap;">' . $key_prefix . '<b>' . $_key . '</b></td> - <td class="row2">'; - - if ($input_field) + if (is_array($_value)) { - $tpl .= '<input type="text" name="entry[' . $key . '][' . $_key . ']" value="' . htmlspecialchars($_value) . '" size="50" />'; + $tpl .= ' + <tr> + <td class="row3" colspan="2">' . $key_prefix . ' <b>' . $_key . '</b></td> + </tr>'; + + foreach ($_value as $__key => $__value) + { + $tpl .= ' + <tr> + <td class="row1" style="white-space: nowrap;">' . $key_prefix . '<b>' . $__key . '</b></td> + <td class="row2">'; + + if ($input_field) + { + $tpl .= '<input type="text" name="entry[' . $key . '][' . $_key . '][' . $__key . ']" value="' . htmlspecialchars($__value) . '" size="50" />'; + } + else + { + $tpl .= '<b>' . htmlspecialchars($__value) . '</b>'; + } + + $tpl .= '</td> + </tr>'; + } } else { - $tpl .= '<b>' . htmlspecialchars($_value) . '</b>'; + $tpl .= ' + <tr> + <td class="row1" style="white-space: nowrap;">' . $key_prefix . '<b>' . $_key . '</b></td> + <td class="row2">'; + + if ($input_field) + { + $tpl .= '<input type="text" name="entry[' . $key . '][' . $_key . ']" value="' . htmlspecialchars($_value) . '" size="50" />'; + } + else + { + $tpl .= '<b>' . htmlspecialchars($_value) . '</b>'; + } + + $tpl .= '</td> + </tr>'; } - - $tpl .= '</td> - </tr>'; } $tpl .= ' @@ -1191,6 +1217,49 @@ $lang = array_merge($lang, array( 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}'{$key}'\t=> '" . $this->prepare_lang_entry($value) . "',\n"; + } + else + { + $_tabs = $tabs . "\t"; + $entry .= "\n{$tabs}'{$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 index 3f1a2436cf..d233d7c885 100644 --- a/phpBB/includes/acp/acp_logs.php +++ b/phpBB/includes/acp/acp_logs.php @@ -42,14 +42,15 @@ class acp_logs if (($deletemark || $deleteall) && $auth->acl_get('a_clearlogs')) { $where_sql = ''; - if ($deletemark && $marked) + + if ($deletemark && sizeof($marked)) { $sql_in = array(); foreach ($marked as $mark) { $sql_in[] = $mark; } - $where_sql = ' AND log_id IN (' . implode(', ', $sql_in) . ')'; + $where_sql = ' AND ' . $db->sql_in_set('log_id', $sql_in); unset($sql_in); } @@ -67,7 +68,7 @@ class acp_logs // 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' => 'l.user_id', 't' => 'l.log_time', 'i' => 'l.log_ip', 'o' => 'l.log_operation'); + $sort_by_sql = array('u' => 'u.username', '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); diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index 0e1e4fe793..bab08bc0ff 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -21,9 +21,9 @@ class acp_main global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix; $action = request_var('action', ''); - $mark = (isset($_REQUEST['mark'])) ? implode(', ', request_var('mark', array(0))) : ''; + $mark = (isset($_REQUEST['mark'])) ? request_var('mark', array(0)) : array(); - if ($mark) + if (sizeof($mark)) { switch ($action) { @@ -36,8 +36,8 @@ class acp_main } $sql = 'SELECT username - FROM ' . USERS_TABLE . " - WHERE user_id IN ($mark)"; + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', $mark); $result = $db->sql_query($sql); $user_affected = array(); @@ -50,14 +50,13 @@ class acp_main if ($action == 'activate') { include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); - $mark_ary = explode(', ', $mark); - foreach ($mark_ary as $user_id) + foreach ($mark as $user_id) { user_active_flip($user_id, USER_INACTIVE); } - set_config('num_users', $config['num_users'] + sizeof($mark_ary), true); + set_config('num_users', $config['num_users'] + sizeof($mark), true); // Update latest username update_last_username(); @@ -69,9 +68,9 @@ class acp_main trigger_error($user->lang['NO_ADMIN']); } - $sql = 'DELETE FROM ' . USER_GROUP_TABLE . " WHERE user_id IN ($mark)"; + $sql = 'DELETE FROM ' . USER_GROUP_TABLE . ' WHERE ' . $db->sql_in_set('user_id', $mark); $db->sql_query($sql); - $sql = 'DELETE FROM ' . USERS_TABLE . " WHERE user_id IN ($mark)"; + $sql = 'DELETE FROM ' . USERS_TABLE . ' WHERE ' . $db->sql_in_set('user_id', $mark); $db->sql_query($sql); add_log('admin', 'LOG_INDEX_' . strtoupper($action), implode(', ', $user_affected)); @@ -91,8 +90,8 @@ class acp_main } $sql = 'SELECT user_id, username, user_email, user_lang, user_jabber, user_notify_type, user_regdate, user_actkey - FROM ' . USERS_TABLE . " - WHERE user_id IN ($mark)"; + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', $mark); $result = $db->sql_query($sql); if ($row = $db->sql_fetchrow($result)) @@ -209,39 +208,20 @@ class acp_main trigger_error($user->lang['NO_ADMIN']); } - $post_count_ary = $auth->acl_getf('f_postcount'); - $forum_read_ary = $auth->acl_getf('f_read'); - - $forum_ary = array(); - foreach ($post_count_ary as $forum_id => $allowed) - { - if ($allowed['f_postcount'] && $forum_read_ary[$forum_id]['f_read']) - { - $forum_ary[] = $forum_id; - } - } + $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); - if (!sizeof($forum_ary)) + while ($row = $db->sql_fetchrow($result)) { - $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_posts = 0'); - } - else - { - $sql = 'SELECT COUNT(post_id) AS num_posts, poster_id - FROM ' . POSTS_TABLE . ' - WHERE poster_id <> ' . ANONYMOUS . ' - AND forum_id IN (' . implode(', ', $forum_ary) . ') - 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); + $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_posts = {$row['num_posts']} WHERE user_id = {$row['poster_id']}"); } + $db->sql_freeresult($result); add_log('admin', 'LOG_RESYNC_POSTCOUNTS'); + break; case 'date': @@ -412,8 +392,10 @@ class acp_main 'DBSIZE' => $dbsize, 'UPLOAD_DIR_SIZE' => $upload_dir_size, 'GZIP_COMPRESSION' => ($config['gzip_compress']) ? $user->lang['ON'] : $user->lang['OFF'], + 'DATABASE_INFO' => $db->sql_server_info(), 'U_ACTION' => append_sid("{$phpbb_admin_path}index.$phpEx"), + 'U_ADMIN_LOG' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=logs&mode=admin'), 'S_ACTION_OPTIONS' => ($auth->acl_get('a_board')) ? $s_action_options : '', ) @@ -439,7 +421,7 @@ class acp_main if ($auth->acl_get('a_user')) { - $sql = 'SELECT user_id, username, user_regdate + $sql = 'SELECT user_id, username, user_regdate, user_lastvisit FROM ' . USERS_TABLE . ' WHERE user_type = ' . USER_INACTIVE . ' ORDER BY user_regdate ASC'; @@ -449,6 +431,7 @@ class acp_main { $template->assign_block_vars('inactive', array( 'DATE' => $user->format_date($row['user_regdate']), + 'LAST_VISIT' => (!$row['user_lastvisit']) ? ' - ' : $user->format_date($row['user_lastvisit']), 'USER_ID' => $row['user_id'], 'USERNAME' => $row['username'], 'U_USER_ADMIN' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=users&mode=overview&u={$row['user_id']}")) @@ -473,6 +456,12 @@ class acp_main $template->assign_var('S_DEBUG_EXTRA', true); } + // Warn if install is still present + if (file_exists($phpbb_root_path . 'install')) + { + $template->assign_var('S_REMOVE_INSTALL', true); + } + $this->tpl_name = 'acp_main'; $this->page_title = 'ACP_MAIN'; } diff --git a/phpBB/includes/acp/acp_modules.php b/phpBB/includes/acp/acp_modules.php index ce14694adf..7c72a1ca6b 100644 --- a/phpBB/includes/acp/acp_modules.php +++ b/phpBB/includes/acp/acp_modules.php @@ -144,16 +144,16 @@ class acp_modules break; } - list($module_name, $module_mode) = explode('::', $quick_install); + list($module_basename, $module_mode) = explode('::', $quick_install); // Check if module name and mode exist... - $fileinfo = $this->get_module_infos($module_name); - $fileinfo = $fileinfo[$module_name]; + $fileinfo = $this->get_module_infos($module_basename); + $fileinfo = $fileinfo[$module_basename]; if (isset($fileinfo['modes'][$module_mode])) { $module_data = array( - 'module_name' => $module_name, + 'module_basename' => $module_basename, 'module_enabled' => 0, 'module_display' => (isset($fileinfo['modes'][$module_mode]['display'])) ? $fileinfo['modes'][$module_mode]['display'] : 1, 'parent_id' => $parent_id, @@ -202,7 +202,7 @@ class acp_modules if ($action == 'add') { $module_row = array( - 'module_name' => '', + 'module_basename' => '', 'module_enabled' => 0, 'module_display' => 1, 'parent_id' => 0, @@ -214,7 +214,7 @@ class acp_modules $module_data = array(); - $module_data['module_name'] = request_var('module_name', (string) $module_row['module_name']); + $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']); @@ -235,7 +235,7 @@ class acp_modules if ($module_type == 'category') { - $module_data['module_name'] = $module_data['module_mode'] = $module_data['module_auth'] = ''; + $module_data['module_basename'] = $module_data['module_mode'] = $module_data['module_auth'] = ''; $module_data['module_display'] = 1; } @@ -245,10 +245,10 @@ class acp_modules } // Adjust auth row - if ($module_data['module_name'] && $module_data['module_mode']) + if ($module_data['module_basename'] && $module_data['module_mode']) { - $fileinfo = $this->get_module_infos($module_data['module_name']); - $module_data['module_auth'] = $fileinfo[$module_data['module_name']]['modes'][$module_data['module_mode']]['auth']; + $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); @@ -262,7 +262,7 @@ class acp_modules } // Category/not category? - $is_cat = (!$module_data['module_name']) ? true : false; + $is_cat = (!$module_data['module_basename']) ? true : false; // Get module informations $module_infos = $this->get_module_infos(); @@ -271,20 +271,20 @@ class acp_modules $s_name_options = $s_mode_options = ''; foreach ($module_infos as $option => $values) { - if (!$module_data['module_name']) + if (!$module_data['module_basename']) { - $module_data['module_name'] = $option; + $module_data['module_basename'] = $option; } // Name options - $s_name_options .= '<option value="' . $option . '"' . (($option == $module_data['module_name']) ? ' selected="selected"' : '') . '>' . $this->lang_name($values['title']) . ' [' . $this->module_class . '_' . $option . ']</option>'; + $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)); // Build module modes foreach ($values['modes'] as $m_mode => $m_values) { - if ($option == $module_data['module_name']) + 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>'; } @@ -387,7 +387,7 @@ class acp_modules } else { - $module_image = (!$row['module_name'] || $row['left_id'] + 1 != $row['right_id']) ? '<img src="images/icon_subfolder.gif" width="46" height="25" alt="' . $user->lang['CATEGORY'] . '" />' : '<img src="images/icon_folder.gif" width="46" height="25" alt="' . $user->lang['MODULE'] . '" />'; + $module_image = (!$row['module_basename'] || $row['left_id'] + 1 != $row['right_id']) ? '<img src="images/icon_subfolder.gif" width="46" height="25" alt="' . $user->lang['CATEGORY'] . '" />' : '<img src="images/icon_folder.gif" width="46" height="25" alt="' . $user->lang['MODULE'] . '" />'; } $url = $this->u_action . '&parent_id=' . $parent_id . '&m=' . $row['module_id']; @@ -551,22 +551,10 @@ class acp_modules { global $db, $user, $auth, $config; - switch (SQL_LAYER) - { - case 'firebird': - $sql = 'SELECT module_id, module_enabled, "module_name", 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"; - break; - - default: - $sql = 'SELECT module_id, module_enabled, module_name, 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"; - break; - } + $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; @@ -607,13 +595,13 @@ class acp_modules } // empty category - if (!$row['module_name'] && ($row['left_id'] + 1 == $row['right_id']) && $ignore_emptycat) + if (!$row['module_basename'] && ($row['left_id'] + 1 == $row['right_id']) && $ignore_emptycat) { continue; } // ignore non-category? - if ($row['module_name'] && $ignore_noncat) + if ($row['module_basename'] && $ignore_noncat) { continue; } @@ -723,8 +711,10 @@ class acp_modules WHERE module_class = '" . $db->sql_escape($this->module_class) . "' AND module_id = {$module_data['parent_id']}"; $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); - if (!$row = $db->sql_fetchrow($result)) + if (!$row) { if ($run_inline) { @@ -733,7 +723,6 @@ class acp_modules trigger_error($user->lang['PARENT_NO_EXIST']); } - $db->sql_freeresult($result); $sql = 'UPDATE ' . MODULES_TABLE . " SET left_id = left_id + 2, right_id = right_id + 2 @@ -777,7 +766,7 @@ class acp_modules { $row = $this->get_module_row($module_data['module_id']); - if ($module_data['module_name'] && !$row['module_name']) + 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); @@ -792,9 +781,12 @@ class acp_modules { $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', $module_data) . " + SET ' . $db->sql_build_array('UPDATE', $update_ary) . " WHERE module_class = '" . $db->sql_escape($this->module_class) . "' AND module_id = {$module_data['module_id']}"; $db->sql_query($sql); @@ -849,7 +841,7 @@ class acp_modules SET right_id = right_id + $diff WHERE module_class = '" . $db->sql_escape($this->module_class) . "' AND " . $to_data['right_id'] . ' BETWEEN left_id AND right_id - AND module_id NOT IN (' . implode(', ', $moved_ids) . ')'; + AND ' . $db->sql_in_set('module_id', $moved_ids, true); $db->sql_query($sql); // Resync the righthand side of the tree @@ -857,7 +849,7 @@ class acp_modules SET left_id = left_id + $diff, right_id = right_id + $diff WHERE module_class = '" . $db->sql_escape($this->module_class) . "' AND left_id > " . $to_data['right_id'] . ' - AND module_id NOT IN (' . implode(', ', $moved_ids) . ')'; + AND ' . $db->sql_in_set('module_id', $moved_ids, true); $db->sql_query($sql); // Resync moved branch @@ -876,7 +868,7 @@ class acp_modules $sql = 'SELECT MAX(right_id) AS right_id FROM ' . MODULES_TABLE . " WHERE module_class = '" . $db->sql_escape($this->module_class) . "' - AND module_id NOT IN (" . implode(', ', $moved_ids) . ')'; + AND " . $db->sql_in_set('module_id', $moved_ids, true); $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); @@ -887,7 +879,7 @@ class acp_modules $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 module_id IN (" . implode(', ', $moved_ids) . ')'; + AND " . $db->sql_in_set('module_id', $moved_ids); $db->sql_query($sql); } diff --git a/phpBB/includes/acp/acp_permission_roles.php b/phpBB/includes/acp/acp_permission_roles.php index 1681986a36..2026aebaf0 100644 --- a/phpBB/includes/acp/acp_permission_roles.php +++ b/phpBB/includes/acp/acp_permission_roles.php @@ -239,7 +239,7 @@ class acp_permission_roles $auth_options = array(); while ($row = $db->sql_fetchrow($result)) { - $auth_options[$row['auth_option']] = ACL_UNSET; + $auth_options[$row['auth_option']] = ACL_NO; } $db->sql_freeresult($result); } @@ -294,7 +294,7 @@ class acp_permission_roles ) ); - // We need to fill the auth options array with ACL_UNSET options ;) + // 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 LIKE '{$permission_type}%' @@ -306,7 +306,7 @@ class acp_permission_roles { if (!isset($auth_options[$row['auth_option']])) { - $auth_options[$row['auth_option']] = ACL_UNSET; + $auth_options[$row['auth_option']] = ACL_NO; } } $db->sql_freeresult($result); @@ -447,17 +447,17 @@ class acp_permission_roles $template->assign_block_vars('auth', array( 'CAT_NAME' => $user->lang['permission_cat'][$cat], - 'S_YES' => ($cat_array['S_YES'] && !$cat_array['S_NO'] && !$cat_array['S_UNSET']) ? true : false, - 'S_NO' => ($cat_array['S_NO'] && !$cat_array['S_YES'] && !$cat_array['S_UNSET']) ? true : false, - 'S_UNSET' => ($cat_array['S_UNSET'] && !$cat_array['S_NO'] && !$cat_array['S_YES']) ? true : false) + '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, - 'S_UNSET' => ($allowed == ACL_UNSET) ? true : false, 'FIELD_NAME' => $permission, 'PERMISSION' => $user->lang['acl_' . $permission]['lang']) @@ -484,7 +484,7 @@ class acp_permission_roles $auth_settings = array(); while ($row = $db->sql_fetchrow($result)) { - $auth_settings[$row['auth_option']] = ACL_UNSET; + $auth_settings[$row['auth_option']] = ACL_NO; } $db->sql_freeresult($result); diff --git a/phpBB/includes/acp/acp_permissions.php b/phpBB/includes/acp/acp_permissions.php index 277281497b..ee4b2a1ade 100644 --- a/phpBB/includes/acp/acp_permissions.php +++ b/phpBB/includes/acp/acp_permissions.php @@ -59,8 +59,8 @@ class acp_permissions $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); + $username = request_var('username', array('')); + $usernames = request_var('usernames', ''); $user_id = request_var('user_id', array(0)); $group_id = request_var('group_id', array(0)); @@ -70,7 +70,7 @@ class acp_permissions if ($select_all_groups) { // Add default groups to selection - $sql_and = ($config['coppa_hide_groups']) ? " AND group_name NOT IN ('INACTIVE_COPPA', 'REGISTERED_COPPA')" : ''; + $sql_and = (!$config['coppa_enable']) ? " AND group_name NOT IN ('INACTIVE_COPPA', 'REGISTERED_COPPA')" : ''; $sql = 'SELECT group_id FROM ' . GROUPS_TABLE . ' @@ -213,7 +213,32 @@ class acp_permissions switch ($action) { case 'delete': - $this->remove_permissions($mode, $permission_type, $auth_admin, $user_id, $group_id, $forum_id); + // 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)); + } break; case 'apply_permissions': @@ -273,7 +298,7 @@ class acp_permissions continue 2; } - $forum_list = make_forum_select(false, false, true, false, false, true); + $forum_list = make_forum_select(false, false, true, false, false, false, true); // Build forum options $s_forum_options = ''; @@ -343,99 +368,30 @@ class acp_permissions continue 2; } - $sql_forum_id = ($permission_scope == 'global') ? 'AND a.forum_id = 0' : ((sizeof($forum_id)) ? 'AND a.forum_id IN (' . implode(', ', $forum_id) . ')' : 'AND a.forum_id <> 0'); - $sql_permission_option = "AND o.auth_option LIKE '" . $db->sql_escape($permission_type) . "%'"; - - $sql = $db->sql_build_query('SELECT_DISTINCT', array( - 'SELECT' => 'u.username, u.user_regdate, u.user_id', - - 'FROM' => array( - USERS_TABLE => 'u', - ACL_OPTIONS_TABLE => 'o', - ACL_USERS_TABLE => 'a' - ), - - 'LEFT_JOIN' => array( - array( - 'FROM' => array(ACL_ROLES_DATA_TABLE => 'r'), - 'ON' => 'a.auth_role_id = r.role_id' - ) - ), - - 'WHERE' => "(a.auth_option_id = o.auth_option_id OR r.auth_option_id = o.auth_option_id) - $sql_permission_option - $sql_forum_id - AND u.user_id = a.user_id", - - 'ORDER_BY' => 'u.username, 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 = $db->sql_build_query('SELECT_DISTINCT', array( - 'SELECT' => 'g.group_type, g.group_name, g.group_id', - - 'FROM' => array( - GROUPS_TABLE => 'g', - ACL_OPTIONS_TABLE => 'o', - ACL_GROUPS_TABLE => 'a' - ), - - 'LEFT_JOIN' => array( - array( - 'FROM' => array(ACL_ROLES_DATA_TABLE => 'r'), - 'ON' => 'a.auth_role_id = r.role_id' - ) - ), - - 'WHERE' => "(a.auth_option_id = o.auth_option_id OR r.auth_option_id = o.auth_option_id) - $sql_permission_option - $sql_forum_id - AND g.group_id = a.group_id", - - '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); + $items = $this->retrieve_defined_user_groups($permission_scope, $forum_id, $permission_type); // Now we check the users... because the "all"-selection is different here (all defined users/groups) $all_users = (isset($_POST['all_users'])) ? true : false; $all_groups = (isset($_POST['all_groups'])) ? true : false; - if ($all_users && sizeof($defined_user_ids)) + if ($all_users && sizeof($items['user_ids'])) { - $user_id = $defined_user_ids; + $user_id = $items['user_ids']; continue 2; } - if ($all_groups && sizeof($defined_group_ids)) + if ($all_groups && sizeof($items['group_ids'])) { - $group_id = $defined_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' => $s_defined_user_options, - 'S_DEFINED_GROUP_OPTIONS' => $s_defined_group_options, - 'S_ADD_GROUP_OPTIONS' => group_select_options(false, $defined_group_ids), + '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']), 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=add_user&field=username')) ); @@ -457,7 +413,7 @@ class acp_permissions { $sql = 'SELECT forum_name FROM ' . FORUMS_TABLE . ' - WHERE forum_id IN (' . implode(', ', $forum_id) . ') + WHERE ' . $db->sql_in_set('forum_id', $forum_id) . ' ORDER BY forum_name ASC'; $result = $db->sql_query($sql); @@ -497,7 +453,7 @@ class acp_permissions '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_UNSET); + $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 @@ -506,7 +462,7 @@ class acp_permissions '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_NO); + $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)); } } @@ -598,7 +554,7 @@ class acp_permissions $sql = "SELECT $sql_id FROM $table - WHERE $sql_id IN (" . implode(', ', $ids) . ')'; + WHERE " . $db->sql_in_set($sql_id, $ids); $result = $db->sql_query($sql); $ids = array(); @@ -783,10 +739,10 @@ class acp_permissions } $db->sql_freeresult($result); - // We need to add any ACL_UNSET setting from auth_settings to compare correctly + // We need to add any ACL_NO setting from auth_settings to compare correctly foreach ($auth_settings as $option => $setting) { - if ($setting == ACL_UNSET) + if ($setting == ACL_NO) { $test_auth_settings[$option] = $setting; } @@ -847,8 +803,8 @@ class acp_permissions } // Logging ... first grab user or groupnames ... - $sql = ($ug_type == 'group') ? 'SELECT group_name as name, group_type FROM ' . GROUPS_TABLE . ' WHERE group_id' : 'SELECT username as name FROM ' . USERS_TABLE . ' WHERE user_id'; - $sql .= ' IN (' . implode(', ', array_map('intval', $ug_id)) . ')'; + $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 = ''; @@ -869,7 +825,7 @@ class acp_permissions // Grab the forum details if non-zero forum_id $sql = 'SELECT forum_name FROM ' . FORUMS_TABLE . ' - WHERE forum_id IN (' . implode(', ', $forum_id) . ')'; + WHERE ' . $db->sql_in_set('forum_id', $forum_id); $result = $db->sql_query($sql); $l_forum_list = ''; @@ -902,7 +858,7 @@ class acp_permissions if (sizeof($perms)) { $sql = 'DELETE FROM ' . ZEBRA_TABLE . ' - WHERE zebra_id IN (' . implode(', ', array_unique($perms)) . ') + WHERE ' . $db->sql_in_set('zebra_id', array_unique($perms)) . ' AND foe = 1'; $db->sql_query($sql); } @@ -960,8 +916,8 @@ class acp_permissions 'WHO' => $user->lang['DEFAULT'], 'INFORMATION' => $user->lang['TRACE_DEFAULT'], - 'S_SETTING_UNSET' => true, - 'S_TOTAL_UNSET' => true) + 'S_SETTING_NO' => true, + 'S_TOTAL_NO' => true) ); $sql = 'SELECT DISTINCT g.group_name, g.group_id, g.group_type @@ -976,12 +932,13 @@ class acp_permissions while ($row = $db->sql_fetchrow($result)) { $groups[$row['group_id']] = array( - 'auth_setting' => ACL_UNSET, + '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; if (sizeof($groups)) { // Get group auth settings @@ -993,23 +950,22 @@ class acp_permissions } unset($hold_ary); - $total = ACL_UNSET; foreach ($groups as $id => $row) { switch ($row['auth_setting']) { - case ACL_UNSET: - $information = $user->lang['TRACE_GROUP_UNSET']; + case ACL_NO: + $information = $user->lang['TRACE_GROUP_NO']; break; case ACL_YES: - $information = ($total == ACL_YES) ? $user->lang['TRACE_GROUP_YES_TOTAL_YES'] : (($total == ACL_NO) ? $user->lang['TRACE_GROUP_YES_TOTAL_NO'] : $user->lang['TRACE_GROUP_YES_TOTAL_UNSET']); - $total = ($total == ACL_UNSET) ? ACL_YES : $total; + $information = ($total == ACL_YES) ? $user->lang['TRACE_GROUP_YES_TOTAL_YES'] : (($total == ACL_NEVER) ? $user->lang['TRACE_GROUP_YES_TOTAL_NEVER'] : $user->lang['TRACE_GROUP_YES_TOTAL_NO']); + $total = ($total == ACL_NO) ? ACL_YES : $total; break; - case ACL_NO: - $information = ($total == ACL_YES) ? $user->lang['TRACE_GROUP_NO_TOTAL_YES'] : (($total == ACL_NO) ? $user->lang['TRACE_GROUP_NO_TOTAL_NO'] : $user->lang['TRACE_GROUP_NO_TOTAL_UNSET']); - $total = ACL_NO; + case ACL_NEVER: + $information = ($total == ACL_YES) ? $user->lang['TRACE_GROUP_NEVER_TOTAL_YES'] : (($total == ACL_NEVER) ? $user->lang['TRACE_GROUP_NEVER_TOTAL_NEVER'] : $user->lang['TRACE_GROUP_NEVER_TOTAL_NO']); + $total = ACL_NEVER; break; } @@ -1017,35 +973,35 @@ class acp_permissions 'WHO' => $row['group_name'], 'INFORMATION' => $information, - 'S_SETTING_UNSET' => ($row['auth_setting'] == ACL_UNSET) ? true : false, - 'S_SETTING_YES' => ($row['auth_setting'] == ACL_YES) ? true : false, 'S_SETTING_NO' => ($row['auth_setting'] == ACL_NO) ? true : false, - 'S_TOTAL_UNSET' => ($total == ACL_UNSET) ? 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_NO' => ($total == ACL_NO) ? true : false) + 'S_TOTAL_NEVER' => ($total == ACL_NEVER) ? true : false) ); } } // Get user specific permission... $hold_ary = $auth->acl_user_raw_data($user_id, $permission, $forum_id); - $auth_setting = (!sizeof($hold_ary)) ? ACL_UNSET : $hold_ary[$user_id][$forum_id][$permission]; + $auth_setting = (!sizeof($hold_ary)) ? ACL_NO : $hold_ary[$user_id][$forum_id][$permission]; switch ($auth_setting) { - case ACL_UNSET: - $information = ($total == ACL_UNSET) ? $user->lang['TRACE_USER_UNSET_TOTAL_UNSET'] : $user->lang['TRACE_USER_KEPT']; - $total = ($total == ACL_UNSET) ? ACL_NO : $total; + case ACL_NO: + $information = ($total == ACL_NO) ? $user->lang['TRACE_USER_NO_TOTAL_NO'] : $user->lang['TRACE_USER_KEPT']; + $total = ($total == ACL_NO) ? ACL_NEVER : $total; break; case ACL_YES: - $information = ($total == ACL_YES) ? $user->lang['TRACE_USER_YES_TOTAL_YES'] : (($total == ACL_NO) ? $user->lang['TRACE_USER_YES_TOTAL_NO'] : $user->lang['TRACE_USER_YES_TOTAL_UNSET']); - $total = ($total == ACL_UNSET) ? ACL_YES : $total; + $information = ($total == ACL_YES) ? $user->lang['TRACE_USER_YES_TOTAL_YES'] : (($total == ACL_NEVER) ? $user->lang['TRACE_USER_YES_TOTAL_NEVER'] : $user->lang['TRACE_USER_YES_TOTAL_NO']); + $total = ($total == ACL_NO) ? ACL_YES : $total; break; - case ACL_NO: - $information = ($total == ACL_YES) ? $user->lang['TRACE_USER_NO_TOTAL_YES'] : (($total == ACL_NO) ? $user->lang['TRACE_USER_NO_TOTAL_NO'] : $user->lang['TRACE_USER_NO_TOTAL_UNSET']); - $total = ACL_NO; + case ACL_NEVER: + $information = ($total == ACL_YES) ? $user->lang['TRACE_USER_NEVER_TOTAL_YES'] : (($total == ACL_NEVER) ? $user->lang['TRACE_USER_NEVER_TOTAL_NEVER'] : $user->lang['TRACE_USER_NEVER_TOTAL_NO']); + $total = ACL_NEVER; break; } @@ -1053,12 +1009,12 @@ class acp_permissions 'WHO' => $userdata['username'], 'INFORMATION' => $information, - 'S_SETTING_UNSET' => ($auth_setting == ACL_UNSET) ? true : false, - 'S_SETTING_YES' => ($auth_setting == ACL_YES) ? true : false, 'S_SETTING_NO' => ($auth_setting == ACL_NO) ? true : false, - 'S_TOTAL_UNSET' => 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_NO' => ($total == ACL_NO) ? true : false) + 'S_TOTAL_NEVER' => ($total == ACL_NEVER) ? true : false) ); // global permission might overwrite local permission @@ -1077,24 +1033,24 @@ class acp_permissions if ($auth_setting) { - $information = ($total == ACL_YES) ? $user->lang['TRACE_USER_GLOBAL_YES_TOTAL_YES'] : $user->lang['TRACE_USER_GLOBAL_YES_TOTAL_NO']; + $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_NO_TOTAL_KEPT']; + $information = $user->lang['TRACE_USER_GLOBAL_NEVER_TOTAL_KEPT']; } $template->assign_block_vars('trace', array( 'WHO' => sprintf($user->lang['TRACE_GLOBAL_SETTING'], $userdata['username']), 'INFORMATION' => sprintf($information, '<a href="' . $this->u_action . "&u=$user_id&f=0&auth=$permission&back=$forum_id\">", '</a>'), - 'S_SETTING_UNSET' => false, + 'S_SETTING_NO' => false, 'S_SETTING_YES' => $auth_setting, - 'S_SETTING_NO' => !$auth_setting, - 'S_TOTAL_UNSET' => false, + 'S_SETTING_NEVER' => !$auth_setting, + 'S_TOTAL_NO' => false, 'S_TOTAL_YES' => ($total == ACL_YES) ? true : false, - 'S_TOTAL_NO' => ($total == ACL_NO) ? true : false) + 'S_TOTAL_NEVER' => ($total == ACL_NEVER) ? true : false) ); } @@ -1105,15 +1061,101 @@ class acp_permissions 'WHO' => $userdata['username'], 'INFORMATION' => $user->lang['TRACE_USER_FOUNDER'], - 'S_SETTING_UNSET' => ($auth_setting == ACL_UNSET) ? true : false, - 'S_SETTING_YES' => ($auth_setting == ACL_YES) ? true : false, 'S_SETTING_NO' => ($auth_setting == ACL_NO) ? true : false, - 'S_TOTAL_UNSET' => 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_NO' => false) + 'S_TOTAL_NEVER' => 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'); + $sql_permission_option = "AND o.auth_option LIKE '" . $db->sql_escape($permission_type) . "%'"; + + $sql = $db->sql_build_query('SELECT_DISTINCT', array( + 'SELECT' => 'u.username, u.user_regdate, u.user_id', + + 'FROM' => array( + USERS_TABLE => 'u', + ACL_OPTIONS_TABLE => 'o', + ACL_USERS_TABLE => 'a' + ), + + 'LEFT_JOIN' => array( + array( + 'FROM' => array(ACL_ROLES_DATA_TABLE => 'r'), + 'ON' => 'a.auth_role_id = r.role_id' + ) + ), + + 'WHERE' => "(a.auth_option_id = o.auth_option_id OR r.auth_option_id = o.auth_option_id) + $sql_permission_option + $sql_forum_id + AND u.user_id = a.user_id", + + 'ORDER_BY' => 'u.username, 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 = $db->sql_build_query('SELECT_DISTINCT', array( + 'SELECT' => 'g.group_type, g.group_name, g.group_id', + + 'FROM' => array( + GROUPS_TABLE => 'g', + ACL_OPTIONS_TABLE => 'o', + ACL_GROUPS_TABLE => 'a' + ), + + 'LEFT_JOIN' => array( + array( + 'FROM' => array(ACL_ROLES_DATA_TABLE => 'r'), + 'ON' => 'a.auth_role_id = r.role_id' + ) + ), + + 'WHERE' => "(a.auth_option_id = o.auth_option_id OR r.auth_option_id = o.auth_option_id) + $sql_permission_option + $sql_forum_id + AND g.group_id = a.group_id", + + '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_profile.php b/phpBB/includes/acp/acp_profile.php index 0e70327585..c361c47c2e 100644 --- a/phpBB/includes/acp/acp_profile.php +++ b/phpBB/includes/acp/acp_profile.php @@ -50,7 +50,8 @@ class acp_profile $lang_defs = array(); $sql = 'SELECT lang_id, lang_iso - FROM ' . LANG_TABLE; + FROM ' . LANG_TABLE . ' + ORDER BY lang_english_name'; $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -63,7 +64,7 @@ class acp_profile $sql = 'SELECT field_id, lang_id FROM ' . PROFILE_LANG_TABLE . ' - ORDER BY lang_id'; + ORDER BY lang_id'; $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -119,19 +120,19 @@ class acp_profile $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(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 = $matches[1]; + $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+#', $declaration); - if ($entities[0] !== $field_ident) + $entities = preg_split('#\s+#', trim($declaration)); + if ($entities[0] !== '_' . $field_ident) { $column_list[] = $entities[0]; } @@ -139,7 +140,7 @@ class acp_profile $columns = implode(',', $column_list); - $new_table_cols = preg_replace('/' . $field_ident . '[^,]+,/', '', $new_table_cols); + $new_table_cols = preg_replace('/' . '_' . $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 . ');'); @@ -148,7 +149,7 @@ class acp_profile break; default: - $db->sql_query('ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " DROP $field_ident"); + $db->sql_query('ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " DROP _$field_ident"); } $order = 0; @@ -293,16 +294,17 @@ class acp_profile $field_type = $field_row['field_type']; // Get language entries - $sql = 'SELECT * FROM ' . PROFILE_FIELDS_LANG_TABLE . ' + $sql = 'SELECT * + FROM ' . PROFILE_FIELDS_LANG_TABLE . ' WHERE lang_id = ' . $lang_defs['iso'][$config['default_lang']] . " AND field_id = $field_id - ORDER BY option_id ASC"; + 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['value']; + $lang_options[$row['option_id']] = $row['lang_value']; } $db->sql_freeresult($result); @@ -474,7 +476,8 @@ class acp_profile if ($action == 'edit') { // Get language entries - $sql = 'SELECT * FROM ' . PROFILE_FIELDS_LANG_TABLE . ' + $sql = 'SELECT * + FROM ' . PROFILE_FIELDS_LANG_TABLE . ' WHERE lang_id <> ' . $lang_defs['iso'][$config['default_lang']] . " AND field_id = $field_id ORDER BY option_id ASC"; @@ -483,12 +486,13 @@ class acp_profile $l_lang_options = array(); while ($row = $db->sql_fetchrow($result)) { - $l_lang_options[$row['lang_id']][$row['option_id']] = $row['value']; + $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 . ' + $sql = 'SELECT lang_id, lang_name, lang_explain, lang_default_value + FROM ' . PROFILE_LANG_TABLE . ' WHERE lang_id <> ' . $lang_defs['iso'][$config['default_lang']] . " AND field_id = $field_id ORDER BY lang_id ASC"; @@ -536,7 +540,7 @@ class acp_profile if ($cp->vars['lang_name'] == '') { - $error[] = $user->lang['EMPTY_USER_FIELD_IDENT']; + $error[] = $user->lang['EMPTY_USER_FIELD_NAME']; } if ($field_type == FIELD_BOOL || $field_type == FIELD_DROPDOWN) @@ -545,7 +549,7 @@ class acp_profile { $error[] = $user->lang['NO_FIELD_ENTRIES']; } - } + } } $step = (isset($_REQUEST['next'])) ? $step + 1 : ((isset($_REQUEST['prev'])) ? $step - 1 : $step); @@ -769,7 +773,8 @@ class acp_profile $sql = 'SELECT lang_id, lang_iso FROM ' . LANG_TABLE . " - WHERE lang_iso <> '" . $config['default_lang'] . "'"; + WHERE lang_iso <> '" . $config['default_lang'] . "' + ORDER BY lang_english_name"; $result = $db->sql_query($sql); $languages = array(); @@ -928,278 +933,28 @@ class acp_profile 'field_active' => 1 ); - $db->sql_query('INSERT INTO ' . PROFILE_FIELDS_TABLE . ' ' . $db->sql_build_array('INSERT', $profile_fields)); + $sql = 'INSERT INTO ' . PROFILE_FIELDS_TABLE . ' ' . $db->sql_build_array('INSERT', $profile_fields); + $db->sql_query($sql); $field_id = $db->sql_nextid(); } else { - $db->sql_query('UPDATE ' . PROFILE_FIELDS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $profile_fields) . " - WHERE field_id = $field_id"); + $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') { - switch (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 = $matches[1]; - $old_table_cols = explode(',', $new_table_cols); - $column_list = array(); - foreach($old_table_cols as $declaration) - { - $entities = preg_split('#\s+#', $declaration); - $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 $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; - } - - $profile_sql[] = $sql; + $field_ident = '_' . $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_name' => $cp->vars['lang_name'], + 'lang_explain' => $cp->vars['lang_explain'], 'lang_default_value' => $cp->vars['lang_default_value'] ); @@ -1272,7 +1027,7 @@ class acp_profile { $sql_ary = array( 'field_type' => (int) $field_type, - 'value' => $value + 'lang_value' => $value ); if ($action == 'create') @@ -1286,9 +1041,9 @@ class acp_profile 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) + 'field_id' => $field_id, + 'lang_id' => (int) $default_lang_id, + 'option_id' => (int) $option_id) ); } } @@ -1327,7 +1082,7 @@ class acp_profile 'lang_id' => (int) $lang_id, 'option_id' => (int) $option_id, 'field_type' => (int) $field_type, - 'value' => $value + 'lang_value' => $value ); } } @@ -1380,6 +1135,7 @@ class acp_profile } } + $db->sql_transaction('begin'); if ($action == 'create') @@ -1399,7 +1155,7 @@ class acp_profile } else { - add_log('admin', 'LOG_PROFILE_FIELD_CREATE', $field_ident . ':' . $cp->vars['lang_name']); + add_log('admin', 'LOG_PROFILE_FIELD_CREATE', substr($field_ident, 1) . ':' . $cp->vars['lang_name']); trigger_error($user->lang['ADDED_PROFILE_FIELD'] . adm_back_link($this->u_action)); } } @@ -1451,6 +1207,276 @@ class acp_profile } } } + + /** + * 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 (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 == '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 \"$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; + } } ?>
\ No newline at end of file diff --git a/phpBB/includes/acp/acp_prune.php b/phpBB/includes/acp/acp_prune.php index 56bd735de0..4752e7bafe 100644 --- a/phpBB/includes/acp/acp_prune.php +++ b/phpBB/includes/acp/acp_prune.php @@ -68,7 +68,7 @@ class acp_prune 'S_PRUNED' => true) ); - $sql_forum = (sizeof($forum_id)) ? ' AND forum_id IN (' . implode(', ', $forum_id) . ')' : ''; + $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 @@ -148,7 +148,7 @@ class acp_prune { $sql = 'SELECT forum_id, forum_name FROM ' . FORUMS_TABLE . ' - WHERE forum_id IN (' . implode(', ', $forum_id) . ')'; + WHERE ' . $db->sql_in_set('forum_id', $forum_id); $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); @@ -202,19 +202,11 @@ class acp_prune if ($users) { - $users = explode("\n", $users); - - $where_sql = ''; - - foreach ($users as $username) - { - $where_sql .= (($where_sql != '') ? ', ' : '') . "'" . $db->sql_escape($username) . "'"; - } - $where_sql = " AND username IN ($where_sql)"; + $where_sql = ' AND ' . $db->sql_in_set('username', explode("\n", $users)); } else { - $username = request_var('username', '', true); + $username = request_var('username', ''); $email = request_var('email', ''); $joined_select = request_var('joined_select', 'lt'); @@ -317,7 +309,7 @@ class acp_prune 'prune' => 1, 'users' => request_var('users', ''), - 'username' => request_var('username', '', true), + 'username' => request_var('username', ''), 'email' => request_var('email', ''), 'joined_select' => request_var('joined_select', ''), 'joined' => request_var('joined', ''), diff --git a/phpBB/includes/acp/acp_ranks.php b/phpBB/includes/acp/acp_ranks.php index f5ec4bae30..59505c34c2 100644 --- a/phpBB/includes/acp/acp_ranks.php +++ b/phpBB/includes/acp/acp_ranks.php @@ -37,7 +37,7 @@ class acp_ranks $rank_title = request_var('title', '', true); $special_rank = request_var('special_rank', 0); - $min_posts = ($special_rank) ? -1 : request_var('min_posts', 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 @@ -130,7 +130,7 @@ class acp_ranks { foreach ($img_ary as $img) { - $img = substr($path, 1) . (($path != '') ? '/' : '') . $img; + $img = $path . $img; if (!in_array($img, $existing_imgs) || $action == 'edit') { diff --git a/phpBB/includes/acp/acp_reasons.php b/phpBB/includes/acp/acp_reasons.php index d6e15435ee..402663ad90 100644 --- a/phpBB/includes/acp/acp_reasons.php +++ b/phpBB/includes/acp/acp_reasons.php @@ -76,7 +76,7 @@ class acp_reasons { $sql = 'SELECT reason_id FROM ' . REPORTS_REASONS_TABLE . " - WHERE LOWER(reason_title) = '" . strtolower($reason_row['reason_title']) . "'"; + WHERE LOWER(reason_title) = '" . strtolower($db->sql_escape($reason_row['reason_title'])) . "'"; $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); @@ -198,10 +198,38 @@ class acp_reasons $other_reason_id = (int) $db->sql_fetchfield('reason_id'); $db->sql_freeresult($result); - // 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"; + switch (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; + + // Nearly standard, not quite + case 'mssql': + case 'mssql_odbc': + // 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; + + // 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); diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index cafb3c795d..b7c37772ed 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -267,23 +267,24 @@ class acp_search } else { - $sql = 'SELECT post_id, poster_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 = array(); - while (false !== ($row = $db->sql_fetchrow($result))) + while ($row = $db->sql_fetchrow($result)) { $ids[] = $row['post_id']; $posters[] = $row['poster_id']; + $forum_ids[] = $row['forum_id']; } $db->sql_freeresult($result); if (sizeof($ids)) { - $this->search->index_remove($ids, $posters); + $this->search->index_remove($ids, $posters, $forum_ids); } $post_counter += $this->batch_size; @@ -318,15 +319,15 @@ class acp_search } else { - $sql = 'SELECT post_id, post_subject, post_text, poster_id + $sql = 'SELECT post_id, post_subject, post_text, post_encoding, 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 (false !== ($row = $db->sql_fetchrow($result))) + while ($row = $db->sql_fetchrow($result)) { - $this->search->index('post', $row['post_id'], $row['post_text'], $row['post_subject'], $row['poster_id']); + $this->search->index('post', $row['post_id'], $row['post_text'], $row['post_subject'], $row['post_encoding'], $row['poster_id'], $row['forum_id']); } $db->sql_freeresult($result); @@ -523,6 +524,12 @@ class acp_search 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); diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php index b11145a6b2..48277dc487 100644 --- a/phpBB/includes/acp/acp_styles.php +++ b/phpBB/includes/acp/acp_styles.php @@ -27,7 +27,14 @@ class acp_styles global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; // Hardcoded template bitfield to add for new templates - define('TEMPLATE_BITFIELD', 6921); + $bitfield = new bitfield(); + $bitfield->set(0); + $bitfield->set(3); + $bitfield->set(8); + $bitfield->set(9); + $bitfield->set(11); + $bitfield->set(12); + define('TEMPLATE_BITFIELD', $bitfield->get_base64()); $user->add_lang('acp/styles'); @@ -82,7 +89,32 @@ parse_css_file = {PARSE_CSS_FILE} pagination_sep = \'{PAGINATION_SEP}\' '; - $this->imageset_keys = 'site_logo, btn_post, btn_post_pm, btn_reply, btn_reply_pm, btn_locked, btn_profile, btn_pm, btn_delete, btn_info, btn_quote, btn_search, btn_edit, btn_report, btn_email, btn_www, btn_icq, btn_aim, btn_yim, btn_msnm, btn_jabber, btn_online, btn_offline, btn_friend, btn_foe, icon_unapproved, icon_reported, icon_attach, icon_post, icon_post_new, icon_post_latest, icon_post_newest, forum, forum_new, forum_locked, forum_link, sub_forum, sub_forum_new, folder, folder_moved, folder_posted, folder_new, folder_new_posted, folder_hot, folder_hot_posted, folder_hot_new, folder_hot_new_posted, folder_locked, folder_locked_posted, folder_locked_new, folder_locked_new_posted, folder_sticky, folder_sticky_posted, folder_sticky_new, folder_sticky_new_posted, folder_announce, folder_announce_posted, folder_announce_new, folder_announce_new_posted, folder_global, folder_global_posted, folder_global_new, folder_global_new_posted, poll_left, poll_center, poll_right, attach_progress_bar, user_icon1, user_icon2, user_icon3, user_icon4, user_icon5, user_icon6, user_icon7, user_icon8, user_icon9, user_icon10'; + $this->imageset_keys = array( + 'logos' => array( + 'site_logo', + ), + 'buttons' => array( + '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', + ), + '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) @@ -183,7 +215,7 @@ pagination_sep = \'{PAGINATION_SEP}\' break; } - $this->frontend('style', array('details', 'export', 'delete')); + $this->frontend('style', array('details'), array('export', 'delete')); break; case 'template': @@ -260,7 +292,7 @@ pagination_sep = \'{PAGINATION_SEP}\' break; } - $this->frontend('template', array('cache', 'details', 'refresh', 'edit', 'export', 'delete')); + $this->frontend('template', array('edit', 'cache', 'details'), array('refresh', 'export', 'delete')); break; case 'theme': @@ -303,6 +335,7 @@ pagination_sep = \'{PAGINATION_SEP}\' $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)); } } @@ -318,11 +351,74 @@ pagination_sep = \'{PAGINATION_SEP}\' break; } - $this->frontend('theme', array('details', 'refresh', 'edit', 'export', 'delete')); + $this->frontend('theme', array('edit', 'details'), array('refresh', 'export', 'delete')); break; case 'imageset': - $this->frontend('imageset', array('details', 'edit', 'delete', 'export')); + + 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)); + } + + if (confirm_box(true)) + { + $sql_ary = array(); + + $cfg_data = parse_cfg_file("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/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($key, 'img_') === 0) + { + $key = substr($key, 4); + if (in_array($key, $imageset_definitions)) + { + $sql_ary[$key] = str_replace('{PATH}', "styles/{$imageset_row['imageset_path']}/imageset/", trim($value)); + } + } + } + unset($cfg_data); + + $sql = 'UPDATE ' . STYLES_IMAGESET_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE imageset_id = $style_id"; + $db->sql_query($sql); + + $cache->destroy('sql', STYLES_IMAGESET_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; } } @@ -330,7 +426,7 @@ pagination_sep = \'{PAGINATION_SEP}\' /** * Build Frontend with supplied options */ - function frontend($mode, $options) + function frontend($mode, $options, $actions) { global $user, $template, $db, $config, $phpbb_root_path, $phpEx; @@ -408,12 +504,19 @@ pagination_sep = \'{PAGINATION_SEP}\' $s_options[] = '<a href="' . $this->u_action . "&action=$option&id=" . $row[$mode . '_id'] . '">' . $user->lang[strtoupper($option)] . '</a>'; } + $s_actions = array(); + foreach ($actions as $option) + { + $s_actions[] = '<a href="' . $this->u_action . "&action=$option&id=" . $row[$mode . '_id'] . '">' . $user->lang[strtoupper($option)] . '</a>'; + } + $template->assign_block_vars('installed', array( 'S_DEFAULT_STYLE' => ($mode == 'style' && $row['style_id'] == $config['default_style']) ? true : false, 'U_EDIT' => $this->u_action . '&action=' . (($mode == 'style') ? 'details' : 'edit') . '&id=' . $row[$mode . '_id'], 'U_STYLE_ACT_DEACT' => $this->u_action . '&action=' . $stylevis . '&id=' . $row[$mode . '_id'], 'L_STYLE_ACT_DEACT' => $user->lang['STYLE_' . strtoupper($stylevis)], 'S_OPTIONS' => implode(' | ', $s_options), + 'S_ACTIONS' => implode(' | ', $s_actions), 'U_PREVIEW' => ($mode == 'style') ? append_sid("{$phpbb_root_path}index.$phpEx", "$mode=" . $row[$mode . '_id']) : '', 'NAME' => $row[$mode . '_name'], @@ -483,16 +586,17 @@ pagination_sep = \'{PAGINATION_SEP}\' $filelist = $filelist_cats = array(); - $template_data = (!empty($_POST['template_data'])) ? ((STRIP) ? stripslashes($_POST['template_data']) : $_POST['template_data']) : ''; + // we want newlines no carriage returns! + $_POST['template_data'] = (isset($_POST['template_data']) && !empty($_POST['template_data'])) ? str_replace(array("\r\n", "\r"), array("\n", "\n"), $_POST['template_data']) : ''; + + $template_data = (STRIP) ? stripslashes($_POST['template_data']) : $_POST['template_data']; $template_file = request_var('template_file', ''); $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); - // we want newlines no carriage returns! - $template_data = str_replace(array("\n\r", "\r"), array("\n", "\n"), $template_data); - + // Retrieve some information about the template $sql = 'SELECT template_storedb, template_path, template_name FROM ' . STYLES_TEMPLATE_TABLE . " @@ -728,7 +832,7 @@ pagination_sep = \'{PAGINATION_SEP}\' 'FILENAME' => str_replace('.', '/', $source) . '.html') ); - $code = str_replace(array("\n\r", "\r"), array("\n", "\n"), file_get_contents("{$phpbb_root_path}cache/{$cache_prefix}_$source.html.$phpEx")); + $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) @@ -815,20 +919,20 @@ pagination_sep = \'{PAGINATION_SEP}\' $this->page_title = 'EDIT_THEME'; + // we want newlines no carriage returns! + $_POST['css_data'] = (isset($_POST['css_data']) && !empty($_POST['css_data'])) ? str_replace(array("\r\n", "\r"), array("\n", "\n"), $_POST['css_data']) : ''; + // get user input $text_rows = max(5, min(999, request_var('text_rows', 20))); $hide_css = request_var('hidecss', false); $show_css = !$hide_css && request_var('showcss', false); $edit_class = request_var('css_class', ''); $custom_class = request_var('custom_class', ''); - $css_data = (!empty($_POST['css_data'])) ? ((STRIP) ? stripslashes($_POST['css_data']) : $_POST['css_data']) : ''; + $css_data = (STRIP) ? stripslashes($_POST['css_data']) : $_POST['css_data']; $submit = isset($_POST['submit']) ? true : false; $add_custom = isset($_POST['add_custom']) ? true : false; $matches = array(); - // we want newlines no carriage returns! - $css_data = str_replace(array("\n\r", "\r"), array("\n", "\n"), $css_data); - // Retrieve some information about the theme $sql = 'SELECT theme_storedb, theme_path, theme_name, theme_data FROM ' . STYLES_THEME_TABLE . " @@ -943,7 +1047,7 @@ pagination_sep = \'{PAGINATION_SEP}\' $css_elements = array_diff(array_map('trim', explode("\n", preg_replace("#;[\n]*#s", "\n", $css_data))), array('')); // Grab list of potential images for the "images" type - $imglist = filelist($phpbb_root_path . 'styles/' . $theme_info['theme_name'] . '/theme'); + $img_filelist = filelist($phpbb_root_path . 'styles/' . $theme_info['theme_name'] . '/theme'); foreach ($match_elements as $type => $match_ary) { @@ -1009,7 +1113,7 @@ pagination_sep = \'{PAGINATION_SEP}\' $selected = ($unit_option == $unit) ? ' selected="selected"' : ''; $s_units .= "<option value=\"$unit_option\"$selected>$unit_option</option>"; } - $s_units = '<option value=""' . (($unit == '') ? ' selected="selected"' : '') . '>' . $user->lang['NONE'] . '</option>' . $s_units; + $s_units = '<option value=""' . (($unit == '') ? ' selected="selected"' : '') . '>' . $user->lang['NO_UNIT'] . '</option>' . $s_units; $template->assign_vars(array( strtoupper($var) => $value, @@ -1020,7 +1124,7 @@ pagination_sep = \'{PAGINATION_SEP}\' case 'images': // generate a list of images for this setting $s_imglist = ''; - foreach ($imglist as $path => $img_ary) + foreach ($img_filelist as $path => $img_ary) { foreach ($img_ary as $img) { @@ -1030,7 +1134,7 @@ pagination_sep = \'{PAGINATION_SEP}\' $s_imglist .= "<option value=\"$img\"$selected>$img</option>"; } } - $s_imglist = '<option value=""' . (($value == '') ? ' selected="selected"' : '') . '>' . $user->lang['NONE'] . '</option>' . $s_imglist; + $s_imglist = '<option value=""' . (($value == '') ? ' selected="selected"' : '') . '>' . $user->lang['NO_IMAGE'] . '</option>' . $s_imglist; $template->assign_vars(array( 'S_' . strtoupper($var) => $s_imglist) @@ -1065,7 +1169,7 @@ pagination_sep = \'{PAGINATION_SEP}\' $s_hidden_fields['cssother'] = implode(' ;; ', $css_elements); } - unset($imglist, $css_elements); + unset($img_filelist, $css_elements); } // else if we are showing raw css or the user submitted data from the simple view // then we need to turn the given information into raw css @@ -1257,24 +1361,8 @@ pagination_sep = \'{PAGINATION_SEP}\' // Check to see whether the selected image exists in the table $valid_name = ($update) ? false : true; - $imglist = array( - 'logos' => array( - 'site_logo', - ), - 'buttons' => array( - 'btn_post', 'btn_reply', 'btn_locked', 'btn_quote', 'btn_edit', 'btn_delete', 'btn_report', 'btn_post_pm', 'btn_reply_pm', 'btn_profile', 'btn_pm', 'btn_info', 'btn_search', 'btn_email', 'btn_www', 'btn_icq', 'btn_aim', 'btn_yim', 'btn_msnm', 'btn_jabber', 'btn_online', 'btn_offline', - ), - 'icons' => array( - 'icon_unapproved', 'icon_reported', 'icon_attach', 'icon_post', 'icon_post_new', 'icon_post_latest', 'icon_post_newest',), - 'forums' => array( - 'forum', 'forum_new', 'forum_locked', 'forum_link', 'sub_forum', 'sub_forum_new',), - 'folders' => array( - 'folder', 'folder_posted', 'folder_new', 'folder_new_posted', 'folder_hot', 'folder_hot_posted', 'folder_hot_new', 'folder_hot_new_posted', 'folder_locked', 'folder_locked_posted', 'folder_locked_new', 'folder_locked_new_posted', 'folder_sticky', 'folder_sticky_posted', 'folder_sticky_new', 'folder_sticky_new_posted', 'folder_announce', 'folder_announce_posted', 'folder_announce_new', 'folder_announce_new_posted',), - 'polls' => array( - 'poll_left', 'poll_center', 'poll_right',), - ); - foreach ($imglist as $category => $img_ary) + foreach ($this->imageset_keys as $category => $img_ary) { if (in_array($imgname, $img_ary)) { @@ -1317,11 +1405,12 @@ pagination_sep = \'{PAGINATION_SEP}\' // Generate list of image options $img_options = ''; - foreach ($imglist as $category => $img_ary) + 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) { $template->assign_block_vars('category.images', array( @@ -1362,6 +1451,10 @@ pagination_sep = \'{PAGINATION_SEP}\' } closedir($dp); + // Make sure the list of possible images is sorted alphabetically + sort($imagesetlist['nolang']); + sort($imagesetlist['lang']); + $imagesetlist_options = ''; foreach ($imagesetlist as $type => $img_ary) { @@ -1395,7 +1488,7 @@ pagination_sep = \'{PAGINATION_SEP}\' 'IMAGE_OPTIONS' => $img_options, 'IMAGELIST_OPTIONS' => $imagesetlist_options, 'IMAGE_SIZE' => $imgsize_bool, - 'IMAGE_REQUEST' => (!empty($imgname)) ? '../styles/' . $imageset_path . '/imageset/' . str_replace('{LANG}', $imglang, $img_info[0]) : '', + 'IMAGE_REQUEST' => (!empty($img_info[0])) ? '../styles/' . $imageset_path . '/imageset/' . str_replace('{LANG}', $imglang, $img_info[0]) : '', 'U_ACTION' => $this->u_action . "&action=edit&id=$imageset_id", 'U_BACK' => $this->u_action, 'NAME' => $imageset_name, @@ -1408,7 +1501,7 @@ pagination_sep = \'{PAGINATION_SEP}\' */ function remove($mode, $style_id) { - global $db, $template, $user, $phpbb_root_path, $cache; + global $db, $template, $user, $phpbb_root_path, $cache, $config; $new_id = request_var('new_id', 0); $update = (isset($_POST['update'])) ? true : false; @@ -1489,6 +1582,11 @@ pagination_sep = \'{PAGINATION_SEP}\' 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 { @@ -1741,11 +1839,12 @@ pagination_sep = \'{PAGINATION_SEP}\' { $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_definitions = explode(', ', $this->imageset_keys); - - foreach ($imageset_definitions as $key) + foreach ($this->imageset_keys as $topic => $key_array) { - $imageset_cfg .= "\n" . $key . ' = ' . str_replace("styles/{$style_row['imageset_path']}/imageset/", '{PATH}', $style_row[$key]); + foreach ($key_array as $key) + { + $imageset_cfg .= "\n" . $key . ' = ' . str_replace("styles/{$style_row['imageset_path']}/imageset/", '{PATH}', $style_row[$key]); + } } $files[] = array( @@ -1794,7 +1893,14 @@ pagination_sep = \'{PAGINATION_SEP}\' { include($phpbb_root_path . 'includes/functions_compress.' . $phpEx); - $path = $style_row[$mode . '_path']; + if ($mode == 'style') + { + $path = preg_replace('#[^\w-]+#', '_', $style_row['style_name']); + } + else + { + $path = $style_row[$mode . '_path']; + } if ($format == 'zip') { @@ -2254,7 +2360,7 @@ pagination_sep = \'{PAGINATION_SEP}\' // heck of a lot of data ... $sql_ary = array( 'template_id' => $style_id, - 'template_filename' => "$template_pathfile$file", + 'template_filename' => "$pathfile$file", 'template_included' => (isset($includes[$file])) ? implode(':', $includes[$file]) . ':' : '', 'template_mtime' => filemtime("{$phpbb_root_path}styles/$template_path$pathfile$file"), 'template_data' => file_get_contents("{$phpbb_root_path}styles/$template_path$pathfile$file"), @@ -2581,7 +2687,7 @@ pagination_sep = \'{PAGINATION_SEP}\' { $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); + $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)) @@ -2867,40 +2973,54 @@ pagination_sep = \'{PAGINATION_SEP}\' $mode . '_path' => $path, ); - if ($mode != 'imageset') + switch ($mode) { - switch ($mode) - { - case 'template': - // We set a pre-defined bitfield here which we may use further in 3.2 - $sql_ary += array( - 'bbcode_bitfield' => TEMPLATE_BITFIELD, - 'template_storedb' => $store_db - ); - break; + case 'template': + // We set a pre-defined bitfield here which we may use further in 3.2 + $sql_ary += array( + 'bbcode_bitfield' => TEMPLATE_BITFIELD, + 'template_storedb' => $store_db + ); + break; - case 'theme': - $sql_ary += array( - 'theme_storedb' => $store_db, - 'theme_data' => ($store_db) ? (($root_path) ? $this->db_theme_data($sql_ary, false, $root_path) : '') : '', - 'theme_mtime' => filemtime("{$phpbb_root_path}styles/$path/theme/stylesheet.css") - ); - break; - } - } - else - { - $cfg_data = parse_cfg_file("$root_path$mode/imageset.cfg"); + case 'theme': + // We are only interested in the theme configuration for now + $theme_cfg = parse_cfg_file("{$phpbb_root_path}styles/$path/theme/theme.cfg"); - foreach ($cfg_data as $key => $value) - { - if (strpos($key, 'img_') === 0) + if (isset($theme_cfg['parse_css_file']) && $theme_cfg['parse_css_file']) { - $key = substr($key, 4); - $sql_ary[$key] = str_replace('{PATH}', "styles/$path/imageset/", trim($value)); + $store_db = 1; } - } - unset($cfg_data); + + $sql_ary += array( + 'theme_storedb' => $store_db, + 'theme_data' => ($store_db) ? $this->db_theme_data($sql_ary, false, $root_path) : '', + 'theme_mtime' => filemtime("{$phpbb_root_path}styles/$path/theme/stylesheet.css") + ); + break; + + case '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($key, 'img_') === 0) + { + $key = substr($key, 4); + if (in_array($key, $imageset_definitions)) + { + $sql_ary[$key] = str_replace('{PATH}', "styles/$path/imageset/", trim($value)); + } + } + } + unset($cfg_data); + break; } $db->sql_transaction('begin'); diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index a30078d7bf..e658609c5f 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -14,6 +14,12 @@ class acp_users { var $u_action; + var $p_master; + + function acp_users(&$p_master) + { + $this->p_master = &$p_master; + } function main($id, $mode) { @@ -28,7 +34,7 @@ class acp_users include($phpbb_root_path . 'includes/functions_profile_fields.' . $phpEx); $error = array(); - $username = request_var('username', '', true); + $username = request_var('username', ''); $user_id = request_var('u', 0); $action = request_var('action', ''); @@ -114,7 +120,7 @@ class acp_users foreach ($forms_ary['modes'] as $value => $ary) { - if (!$this->is_authed($ary['auth'])) + if (!$this->p_master->module_auth($ary['auth'])) { continue; } @@ -133,7 +139,7 @@ class acp_users // 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)); + trigger_error($user->lang['NOT_MANAGE_FOUNDER'] . adm_back_link($this->u_action . '&u=' . $user_id)); } switch ($mode) @@ -192,6 +198,12 @@ class acp_users case 'banuser': case 'banemail': case 'banip': + + if ($user_id == $user->data['user_id']) + { + trigger_error($user->lang['CANNOT_BAN_YOURSELF'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + $ban = array(); switch ($action) @@ -238,6 +250,11 @@ class acp_users case 'reactivate': + if ($user_id == $user->data['user_id']) + { + trigger_error($user->lang['CANNOT_FORCE_REACT_YOURSELF'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + if ($config['email_enable']) { include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); @@ -287,6 +304,12 @@ class acp_users case 'active': + if ($user_id == $user->data['user_id']) + { + // It is only deactivation since the user is already activated (else he would not have reached this page) + trigger_error($user->lang['CANNOT_DEACTIVATE_YOURSELF'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + user_active_flip($user_id, $user_row['user_type'], false, $user_row['username']); $message = ($user_row['user_type'] == USER_INACTIVE) ? 'USER_ADMIN_ACTIVATED' : 'USER_ADMIN_DEACTIVED'; @@ -376,7 +399,7 @@ class acp_users { $sql = 'SELECT topic_id, topic_replies, topic_replies_real FROM ' . TOPICS_TABLE . ' - WHERE topic_id IN (' . implode(', ', array_keys($topic_id_ary)) . ')'; + WHERE ' . $db->sql_in_set('topic_id', array_keys($topic_id_ary)); $result = $db->sql_query($sql); $del_topic_ary = array(); @@ -392,7 +415,7 @@ class acp_users if (sizeof($del_topic_ary)) { $sql = 'DELETE FROM ' . TOPICS_TABLE . ' - WHERE topic_id IN (' . implode(', ', $del_topic_ary) . ')'; + WHERE ' . $db->sql_in_set('topic_id', $del_topic_ary); $db->sql_query($sql); } } @@ -478,7 +501,7 @@ class acp_users { $sql = 'SELECT topic_id, forum_id, topic_title, topic_replies, topic_replies_real FROM ' . TOPICS_TABLE . ' - WHERE topic_id IN (' . implode(', ', array_keys($topic_id_ary)) . ')'; + WHERE ' . $db->sql_in_set('topic_id', array_keys($topic_id_ary)); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -601,8 +624,8 @@ class acp_users // Validation data $var_ary = array( - 'password_confirm' => array('string', true, $config['min_pass_chars'], $config['max_pass_chars']), 'user_password' => array('string', true, $config['min_pass_chars'], $config['max_pass_chars']), + 'password_confirm' => array('string', true, $config['min_pass_chars'], $config['max_pass_chars']), 'warnings' => array('num'), ); @@ -657,9 +680,34 @@ class acp_users $sql_ary['user_warnings'] = $data['warnings']; } - if (($user_row['user_type'] == USER_FOUNDER && !$data['user_founder']) || ($user_row['user_type'] != USER_FOUNDER && $data['user_founder'])) + // Only allow founders updating the founder status... + if ($user->data['user_type'] == USER_FOUNDER) { - $sql_ary['user_type'] = ($data['user_founder']) ? USER_FOUNDER : USER_NORMAL; + // Setting a normal member to be a founder + if ($data['user_founder'] && $user_row['user_type'] != USER_FOUNDER) + { + $sql_ary['user_type'] = USER_FOUNDER; + } + else if (!$data['user_founder'] && $user_row['user_type'] == USER_FOUNDER) + { + // Check if at least one founder is present + $sql = 'SELECT user_id + FROM ' . USERS_TABLE . ' + WHERE user_type = ' . USER_FOUNDER . ' + AND user_id <> ' . $user_id; + $result = $db->sql_query_limit($sql, 1); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + $sql_ary['user_type'] = USER_NORMAL; + } + else + { + trigger_error($user->lang['AT_LEAST_ONE_FOUNDER'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + } } } @@ -711,6 +759,9 @@ class acp_users user_update_name($user_row['username'], $update_username); } + // Let the users permissions being updated + $auth->acl_clear_prefetch($user_id); + add_log('admin', 'LOG_USER_USER_UPDATE', $data['username']); trigger_error($user->lang['USER_OVERVIEW_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); @@ -721,11 +772,19 @@ class acp_users } $user_char_ary = array('.*' => 'USERNAME_CHARS_ANY', '[\w]+' => 'USERNAME_ALPHA_ONLY', '[\w_\+\. \-\[\]]+' => 'USERNAME_ALPHA_SPACERS'); - $quick_tool_ary = array('banuser' => 'BAN_USER', 'banemail' => 'BAN_EMAIL', 'banip' => 'BAN_IP', 'active' => (($user_row['user_type'] == USER_INACTIVE) ? 'ACTIVATE' : 'DEACTIVATE'), 'delsig' => 'DEL_SIG', 'delavatar' => 'DEL_AVATAR', 'moveposts' => 'MOVE_POSTS', 'delposts' => 'DEL_POSTS', 'delattach' => 'DEL_ATTACH'); - - if ($config['email_enable']) + + if ($user_id == $user->data['user_id']) { - $quick_tool_ary['reactivate'] = 'FORCE'; + $quick_tool_ary = array('delsig' => 'DEL_SIG', 'delavatar' => 'DEL_AVATAR', 'moveposts' => 'MOVE_POSTS', 'delposts' => 'DEL_POSTS', 'delattach' => 'DEL_ATTACH'); + } + else + { + $quick_tool_ary = array('banuser' => 'BAN_USER', 'banemail' => 'BAN_EMAIL', 'banip' => 'BAN_IP', 'active' => (($user_row['user_type'] == USER_INACTIVE) ? 'ACTIVATE' : 'DEACTIVATE'), 'delsig' => 'DEL_SIG', 'delavatar' => 'DEL_AVATAR', 'moveposts' => 'MOVE_POSTS', 'delposts' => 'DEL_POSTS', 'delattach' => 'DEL_ATTACH'); + + if ($config['email_enable']) + { + $quick_tool_ary['reactivate'] = 'FORCE'; + } } $s_action_options = '<option class="sep" value="">' . $user->lang['SELECT_OPTION'] . '</option>'; @@ -743,6 +802,7 @@ class acp_users '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, 'U_SHOW_IP' => $this->u_action . "&u=$user_id&ip=" . (($ip == 'ip') ? 'hostname' : 'ip'), 'U_WHOIS' => $this->u_action . "&action=whois&user_ip={$user_row['user_ip']}", @@ -755,6 +815,7 @@ class acp_users 'USER_LASTACTIVE' => ($user_row['user_lastvisit']) ? $user->format_date($user_row['user_lastvisit']) : ' - ', 'USER_EMAIL' => $user_row['user_email'], 'USER_WARNINGS' => $user_row['user_warnings'], + 'USER_POSTS' => $user_row['user_posts'], ) ); @@ -787,7 +848,7 @@ class acp_users { $sql_in[] = $mark; } - $where_sql = ' AND log_id IN (' . implode(', ', $sql_in) . ')'; + $where_sql = ' AND ' . $db->sql_in_set('log_id', $sql_in); unset($sql_in); } @@ -813,7 +874,7 @@ class acp_users // 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' => 'l.user_id', 't' => 'l.log_time', 'i' => 'l.log_ip', 'o' => 'l.log_operation'); + $sort_by_sql = array('u' => 'l.username', '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); @@ -943,6 +1004,34 @@ class acp_users // Update Custom Fields if (sizeof($cp_data)) { + switch (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; + } + + foreach ($cp_data as $key => $value) + { + $cp_data[$right_delim . $key . $left_delim] = $value; + unset($cp_data[$key]); + } + $sql = 'UPDATE ' . PROFILE_FIELDS_DATA_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $cp_data) . " WHERE user_id = $user_id"; @@ -1077,7 +1166,7 @@ class acp_users $var_ary = array( 'dateformat' => array('string', false, 3, 30), - 'lang' => array('match', false, '#^[a-z_]{2,}$#i'), + 'lang' => array('match', false, '#^[a-z_\-]{2,}$#i'), 'tz' => array('num', false, -14, 14), 'topic_sk' => array('string', false, 1, 1), @@ -1252,7 +1341,7 @@ class acp_users 'S_LANG_OPTIONS' => language_select($lang), 'S_STYLE_OPTIONS' => style_select($style), - 'S_TZ_OPTIONS' => tz_select($tz), + 'S_TZ_OPTIONS' => tz_select($tz, true), ) ); @@ -1449,6 +1538,7 @@ class acp_users 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']) ? request_var('enable_bbcode', $this->optionget($user_row, 'bbcode')) : false; $enable_smilies = ($config['allow_sig_smilies']) ? request_var('enable_smilies', $this->optionget($user_row, 'smilies')) : false; @@ -1520,9 +1610,14 @@ class acp_users '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_SMILIES_ALLOWED' => $config['allow_sig_smilies'], + 'S_BBCODE_IMG' => ($config['allow_sig_img']) ? true : false, + 'S_BBCODE_FLASH' => ($config['allow_sig_flash']) ? true : false) ); + // Assigning custom bbcodes + display_custom_bbcodes(); + break; case 'attach': @@ -1541,7 +1636,7 @@ class acp_users { $sql = 'SELECT real_filename FROM ' . ATTACHMENTS_TABLE . ' - WHERE attach_id IN (' . implode(', ', $marked) . ')'; + WHERE ' . $db->sql_in_set('attach_id', $marked); $result = $db->sql_query($sql); $log_attachments = array(); @@ -1623,7 +1718,7 @@ class acp_users $template->assign_block_vars('attach', array( 'REAL_FILENAME' => $row['real_filename'], - 'COMMENT' => nl2br($row['comment']), + 'COMMENT' => nl2br($row['attach_comment']), 'EXTENSION' => $row['extension'], 'SIZE' => ($row['filesize'] >= 1048576) ? ($row['filesize'] >> 20) . ' ' . $user->lang['MB'] : (($row['filesize'] >= 1024) ? ($row['filesize'] >> 10) . ' ' . $user->lang['KB'] : $row['filesize'] . ' ' . $user->lang['BYTES']), 'DOWNLOAD_COUNT' => $row['download_count'], @@ -1745,14 +1840,14 @@ class acp_users // Select box for other groups $sql = 'SELECT group_id, group_name, group_type FROM ' . GROUPS_TABLE . ' - ' . ((sizeof($id_ary)) ? 'WHERE group_id NOT IN (' . implode(', ', $id_ary) . ')' : '') . ' + ' . ((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_hide_groups'] && in_array($row['group_name'], array('INACTIVE_COPPA', 'REGISTERED_COPPA'))) + if (!$config['coppa_enable'] && in_array($row['group_name'], array('INACTIVE_COPPA', 'REGISTERED_COPPA'))) { continue; } @@ -1809,28 +1904,40 @@ class acp_users // Select auth options $sql = 'SELECT auth_option, is_local, is_global FROM ' . ACL_OPTIONS_TABLE . " - WHERE auth_option LIKE '%\_' - AND is_global = 1 - ORDER BY auth_option"; + WHERE auth_option LIKE '%\_'"; + + if (SQL_LAYER == 'mssql' || SQL_LAYER == 'mssql_odbc') + { + $sql .= " ESCAPE '\\'"; + } + + $sql .= 'AND is_global = 1 + ORDER BY auth_option'; $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) { - $hold_ary = $auth_admin->get_mask('view', $user_id, false, false, $row['auth_option'], 'global', ACL_NO); + $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); $sql = 'SELECT auth_option, is_local, is_global FROM ' . ACL_OPTIONS_TABLE . " - WHERE auth_option LIKE '%\_' - AND is_local = 1 - ORDER BY is_global DESC, auth_option"; + WHERE auth_option LIKE '%\_'"; + + if (SQL_LAYER == 'mssql' || SQL_LAYER == 'mssql_odbc') + { + $sql .= " ESCAPE '\\'"; + } + + $sql .= '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, false, $row['auth_option'], 'local', ACL_NO); + $hold_ary = $auth_admin->get_mask('view', $user_id, false, false, $row['auth_option'], 'local', ACL_NEVER); $auth_admin->display_mask('view', $row['auth_option'], $hold_ary, 'user', true, false); } $db->sql_freeresult($result); @@ -1895,26 +2002,6 @@ class acp_users $var = ($data) ? $data : $user_row['user_options']; return ($var & 1 << $user->keyoptions[$key]) ? true : false; } - - /** - * Check if user is allowed to call this user mode - */ - function is_authed($module_auth) - { - global $config, $auth; - - $module_auth = trim($module_auth); - - if (!$module_auth) - { - return true; - } - - $is_auth = false; - eval('$is_auth = (int) (' . preg_replace(array('#acl_([a-z_]+)(,\$id)?#', '#\$id#', '#cfg_([a-z_]+)#'), array('(int) $auth->acl_get("\\1"\\2)', 'true', '(int) $config["\\1"]'), $module_auth) . ');'); - - return $is_auth; - } } ?>
\ No newline at end of file diff --git a/phpBB/includes/acp/auth.php b/phpBB/includes/acp/auth.php index db02e5dd97..71d17bd40d 100644 --- a/phpBB/includes/acp/auth.php +++ b/phpBB/includes/acp/auth.php @@ -81,9 +81,9 @@ class auth_admin extends auth * @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_NO|ACL_UNSET|ACL_YES $acl_fill defines the mode those permissions not set are getting filled with + * @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_NO) + 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; @@ -136,7 +136,7 @@ class auth_admin extends auth $sql = 'SELECT user_id, user_permissions, user_type FROM ' . USERS_TABLE . ' - WHERE user_id IN (' . implode(',', $ug_id) . ')'; + WHERE ' . $db->sql_in_set('user_id', $ug_id); $result = $db->sql_query($sql); while ($userdata = $db->sql_fetchrow($result)) @@ -292,14 +292,14 @@ class auth_admin extends auth { $sql = 'SELECT user_id as ug_id, username as ug_name FROM ' . USERS_TABLE . ' - WHERE user_id IN (' . implode(', ', array_keys($hold_ary)) . ') + WHERE ' . $db->sql_in_set('user_id', array_keys($hold_ary)) . ' ORDER BY username ASC'; } else { $sql = 'SELECT group_id as ug_id, group_name as ug_name, group_type FROM ' . GROUPS_TABLE . ' - WHERE group_id IN (' . implode(', ', array_keys($hold_ary)) . ') + WHERE ' . $db->sql_in_set('group_id', array_keys($hold_ary)) . ' ORDER BY group_type DESC, group_name ASC'; } $result = $db->sql_query($sql); @@ -322,7 +322,7 @@ class auth_admin extends auth $forum_names_ary = array(); if ($local) { - $forum_names_ary = make_forum_select(false, false, true, false, false, true); + $forum_names_ary = make_forum_select(false, false, true, false, false, false, true); } else { @@ -361,7 +361,7 @@ class auth_admin extends auth $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 r.role_id IN (' . implode(', ', array_keys($roles)) . ')'; + AND ' . $db->sql_in_set('r.role_id', array_keys($roles)); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -584,7 +584,7 @@ class auth_admin extends auth // Get forum names $sql = 'SELECT forum_id, forum_name FROM ' . FORUMS_TABLE . ' - WHERE forum_id IN (' . implode(', ', array_keys($hold_ary)) . ')'; + WHERE ' . $db->sql_in_set('forum_id', array_keys($hold_ary)); $result = $db->sql_query($sql); $forum_names = array(); @@ -605,7 +605,7 @@ class auth_admin extends auth { $sql = 'SELECT user_id, username FROM ' . USERS_TABLE . ' - WHERE user_id IN (' . implode(', ', $auth_ary['users']) . ') + WHERE ' . $db->sql_in_set('user_id', $auth_ary['users']) . ' ORDER BY username'; $result = $db->sql_query($sql); @@ -624,7 +624,7 @@ class auth_admin extends auth { $sql = 'SELECT group_id, group_name, group_type FROM ' . GROUPS_TABLE . ' - WHERE group_id IN (' . implode(', ', $auth_ary['groups']) . ') + WHERE ' . $db->sql_in_set('group_id', $auth_ary['groups']) . ' ORDER BY group_type ASC, group_name'; $result = $db->sql_query($sql); @@ -768,12 +768,12 @@ class auth_admin extends auth $ug_id = array($ug_id); } - $ug_id_sql = 'IN (' . implode(', ', array_map('intval', $ug_id)) . ')'; - $forum_sql = 'IN (' . implode(', ', array_map('intval', $forum_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'; + $id_field = $ug_type . '_id'; // Get any flags as required reset($auth); @@ -797,8 +797,8 @@ class auth_admin extends auth } $sql = "DELETE FROM $table - WHERE forum_id $forum_sql - AND $id_field $ug_id_sql + WHERE $forum_sql + AND $ug_id_sql AND auth_option_id IN ($any_option_id, " . implode(', ', $auth_option_ids) . ')'; $db->sql_query($sql); @@ -818,17 +818,17 @@ class auth_admin extends auth if (sizeof($role_ids)) { $sql = "DELETE FROM $table - WHERE forum_id $forum_sql - AND $id_field $ug_id_sql + WHERE $forum_sql + AND $ug_id_sql AND auth_option_id = 0 - AND auth_role_id IN (" . implode(', ', $role_ids) . ')'; + 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_NO)) + if ($setting == ACL_YES && (!isset($auth[$flag]) || $auth[$flag] == ACL_NEVER)) { $auth[$flag] = ACL_YES; } @@ -858,7 +858,7 @@ class auth_admin extends auth { $auth_option_id = (int) $this->option_ids[$auth_option]; - if ($setting != ACL_UNSET) + if ($setting != ACL_NO) { foreach ($ug_id as $id) { @@ -920,7 +920,7 @@ class auth_admin extends auth // Re-set any flag... foreach ($auth as $auth_option => $setting) { - if ($setting == ACL_YES && (!isset($auth[$flag]) || $auth[$flag] == ACL_NO)) + if ($setting == ACL_YES && (!isset($auth[$flag]) || $auth[$flag] == ACL_NEVER)) { $auth[$flag] = ACL_YES; } @@ -931,7 +931,7 @@ class auth_admin extends auth { $auth_option_id = (int) $this->option_ids[$auth_option]; - if ($setting != ACL_UNSET) + if ($setting != ACL_NO) { $sql_ary[] = array( 'role_id' => (int) $role_id, @@ -941,13 +941,13 @@ class auth_admin extends auth } } - // If no data is there, we set the any-flag to ACL_NO... + // 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' => $this->option_ids[$flag], - 'auth_setting' => ACL_NO + 'auth_setting' => ACL_NEVER ); } @@ -995,12 +995,12 @@ class auth_admin extends auth if ($forum_id !== false) { - $where_sql[] = (!is_array($forum_id)) ? 'forum_id = ' . (int) $forum_id : 'forum_id IN (' . implode(', ', array_map('intval', $forum_id)) . ')'; + $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 : $id_field . ' IN (' . implode(', ', array_map('intval', $ug_id)) . ')'; + $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 @@ -1016,7 +1016,7 @@ class auth_admin extends auth while ($row = $db->sql_fetchrow($result)) { $option_id_ary[] = $row['auth_option_id']; - $auth_id_ary[$row['auth_option']] = ACL_UNSET; + $auth_id_ary[$row['auth_option']] = ACL_NO; } $db->sql_freeresult($result); @@ -1043,7 +1043,7 @@ class auth_admin extends 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 rd.role_id IN (' . implode(', ', array_keys($cur_role_auth)) . ')'; + AND ' . $db->sql_in_set('rd.role_id', array_keys($cur_role_auth)); $result = $db->sql_query($sql); $auth_settings = array(); @@ -1072,7 +1072,7 @@ class auth_admin extends auth // Now, normally remove permissions... if ($permission_type !== false) { - $where_sql[] = 'auth_option_id IN (' . implode(', ', array_map('intval', $option_id_ary)) . ')'; + $where_sql[] = $db->sql_in_set('auth_option_id', array_map('intval', $option_id_ary)); } $sql = "DELETE FROM $table @@ -1093,9 +1093,9 @@ class auth_admin extends auth foreach ($category_array as $cat => $cat_array) { $template->assign_block_vars($tpl_cat, array( - 'S_YES' => ($cat_array['S_YES'] && !$cat_array['S_NO'] && !$cat_array['S_UNSET']) ? true : false, - 'S_NO' => ($cat_array['S_NO'] && !$cat_array['S_YES'] && !$cat_array['S_UNSET']) ? true : false, - 'S_UNSET' => ($cat_array['S_UNSET'] && !$cat_array['S_NO'] && !$cat_array['S_YES']) ? true : false, + '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]) ); @@ -1104,8 +1104,8 @@ class auth_admin extends auth { $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, - 'S_UNSET' => ($allowed == ACL_UNSET) ? true : false, 'UG_ID' => $ug_id, 'FORUM_ID' => $forum_id, @@ -1166,15 +1166,15 @@ class auth_admin extends auth { $content_array[$forum_id][$cat] = array( 'S_YES' => false, + 'S_NEVER' => false, 'S_NO' => false, - 'S_UNSET' => 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]['S_UNSET'] |= ($auth_setting == ACL_UNSET) ? true : false; $content_array[$forum_id][$cat]['permissions'][$permission] = $auth_setting; } @@ -1211,7 +1211,7 @@ class auth_admin extends auth { if (strpos($opt, 'a_') === 0) { - $hold_ary[0][$opt] = ACL_NO; + $hold_ary[0][$opt] = ACL_NEVER; } } diff --git a/phpBB/includes/acp/info/acp_board.php b/phpBB/includes/acp/info/acp_board.php index a8d6d5af51..e6a2372088 100644 --- a/phpBB/includes/acp/info/acp_board.php +++ b/phpBB/includes/acp/info/acp_board.php @@ -27,7 +27,6 @@ class acp_board_info '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')), 'registration' => array('title' => 'ACP_REGISTER_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), - 'visual' => array('title' => 'ACP_VC_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')), diff --git a/phpBB/includes/acp/info/acp_captcha.php b/phpBB/includes/acp/info/acp_captcha.php new file mode 100644 index 0000000000..82fbf997f4 --- /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_permission_roles.php b/phpBB/includes/acp/info/acp_permission_roles.php index 395e15193b..114d23f018 100644 --- a/phpBB/includes/acp/info/acp_permission_roles.php +++ b/phpBB/includes/acp/info/acp_permission_roles.php @@ -20,10 +20,10 @@ class acp_permission_roles_info 'title' => 'ACP_PERMISSION_ROLES', 'version' => '1.0.0', 'modes' => array( - 'admin_roles' => array('title' => 'ACP_ADMIN_ROLES', 'auth' => 'acl_a_roles', 'cat' => array('ACP_PERMISSION_ROLES')), - 'user_roles' => array('title' => 'ACP_USER_ROLES', 'auth' => 'acl_a_roles', 'cat' => array('ACP_PERMISSION_ROLES')), - 'mod_roles' => array('title' => 'ACP_MOD_ROLES', 'auth' => 'acl_a_roles', 'cat' => array('ACP_PERMISSION_ROLES')), - 'forum_roles' => array('title' => 'ACP_FORUM_ROLES', 'auth' => 'acl_a_roles', 'cat' => array('ACP_PERMISSION_ROLES')), + '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')), ), ); } diff --git a/phpBB/includes/auth.php b/phpBB/includes/auth.php index 884f58ef0a..4e6a8af1d8 100644 --- a/phpBB/includes/auth.php +++ b/phpBB/includes/auth.php @@ -161,7 +161,7 @@ class auth if (sizeof($this->acl)) { - $sql .= ' WHERE forum_id NOT IN (' . implode(', ', array_keys($this->acl)) . ')'; + $sql .= ' WHERE ' . $db->sql_in_set('forum_id', array_keys($this->acl), true); } $result = $db->sql_query($sql); @@ -378,14 +378,14 @@ class auth // 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[$opt] == ACL_YES && (!isset($bitstring[$this->acl_options[$ary_key][$option_key]]) || $bitstring[$this->acl_options[$ary_key][$option_key]] == ACL_NO)) + if ($auth_ary[$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_NO; + $bitstring[$id] = ACL_NEVER; } } @@ -418,7 +418,13 @@ class auth { global $db; - $where_sql = ($user_id !== false) ? ' WHERE user_id ' . ((is_array($user_id)) ? ' IN (' . implode(', ', array_map('intval', $user_id)) . ')' : " = $user_id") : ''; + $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 = '', @@ -440,8 +446,8 @@ class auth $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 a.$sql_id IN (" . implode(', ', $ug_id) . ')') : ''; - $sql_forum = ($forum_id !== false) ? ((!is_array($forum_id)) ? "AND a.forum_id = $forum_id" : 'AND a.forum_id IN (' . implode(', ', $forum_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 @@ -469,8 +475,8 @@ class auth { global $db; - $sql_user = ($user_id !== false) ? ((!is_array($user_id)) ? "user_id = $user_id" : 'user_id IN (' . implode(', ', $user_id) . ')') : ''; - $sql_forum = ($forum_id !== false) ? ((!is_array($forum_id)) ? "AND a.forum_id = $forum_id" : 'AND a.forum_id IN (' . implode(', ', $forum_id) . ')') : ''; + $sql_user = ($user_id !== false) ? ((!is_array($user_id)) ? "user_id = $user_id" : $db->sql_in_set('user_id', $user_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)) : ''; $sql_opts = ''; @@ -482,14 +488,14 @@ class auth } else { - $sql_opts = 'AND ao.auth_option IN (' . implode(', ', preg_replace('#^\s*(.*)\s*$#e', "\"'\" . \$db->sql_escape('\\1') . \"'\"", $opts)) . ')'; + $sql_opts = 'AND ' . $db->sql_in_set('ao.auth_option', $opts); } } $hold_ary = array(); // First grab user settings ... each user has only one setting for each - // option ... so we shouldn't need any ACL_NO checks ... he says ... + // option ... so we shouldn't need any ACL_NEVER checks ... he says ... // Grab assigned roles... $sql = $db->sql_build_query('SELECT', array( 'SELECT' => 'ao.auth_option, a.auth_role_id, r.auth_setting as role_auth_setting, a.user_id, a.forum_id, a.auth_setting', @@ -522,7 +528,7 @@ class auth } $db->sql_freeresult($result); - // Now grab group settings ... ACL_NO overrides ACL_YES so act appropriatley + // Now grab group settings ... ACL_NEVER overrides ACL_YES so act appropriatley $sql = $db->sql_build_query('SELECT', array( 'SELECT' => 'ug.user_id, ao.auth_option, a.forum_id, a.auth_setting, a.auth_role_id, r.auth_setting as role_auth_setting', @@ -552,13 +558,13 @@ class auth while ($row = $db->sql_fetchrow($result)) { - if (!isset($hold_ary[$row['user_id']][$row['forum_id']][$row['auth_option']]) || (isset($hold_ary[$row['user_id']][$row['forum_id']][$row['auth_option']]) && $hold_ary[$row['user_id']][$row['forum_id']][$row['auth_option']] != ACL_NO)) + if (!isset($hold_ary[$row['user_id']][$row['forum_id']][$row['auth_option']]) || (isset($hold_ary[$row['user_id']][$row['forum_id']][$row['auth_option']]) && $hold_ary[$row['user_id']][$row['forum_id']][$row['auth_option']] != ACL_NEVER)) { $setting = ($row['auth_role_id']) ? $row['role_auth_setting'] : $row['auth_setting']; $hold_ary[$row['user_id']][$row['forum_id']][$row['auth_option']] = $setting; - // Check for existence of ACL_YES if an option got set to NO - if ($setting == ACL_NO) + // Check for existence of ACL_YES if an option got set to ACL_NEVER + if ($setting == ACL_NEVER) { $flag = substr($row['auth_option'], 0, strpos($row['auth_option'], '_') + 1); @@ -586,8 +592,8 @@ class auth { global $db; - $sql_user = ($user_id !== false) ? ((!is_array($user_id)) ? "user_id = $user_id" : 'user_id IN (' . implode(', ', $user_id) . ')') : ''; - $sql_forum = ($forum_id !== false) ? ((!is_array($forum_id)) ? "AND a.forum_id = $forum_id" : 'AND a.forum_id IN (' . implode(', ', $forum_id) . ')') : ''; + $sql_user = ($user_id !== false) ? ((!is_array($user_id)) ? "user_id = $user_id" : $db->sql_in_set('user_id', $user_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)) : ''; $sql_opts = ''; @@ -599,7 +605,7 @@ class auth } else { - $sql_opts = 'AND ao.auth_option IN (' . implode(', ', preg_replace('#^\s*(.*)\s*$#e', "\"'\" . \$db->sql_escape('\\1') . \"'\"", $opts)) . ')'; + $sql_opts = 'AND ' . $db->sql_in_set('ao.auth_option', $opts); } } @@ -647,8 +653,8 @@ class auth { global $db; - $sql_group = ($group_id !== false) ? ((!is_array($group_id)) ? "group_id = $group_id" : 'group_id IN (' . implode(', ', $group_id) . ')') : ''; - $sql_forum = ($forum_id !== false) ? ((!is_array($forum_id)) ? "AND a.forum_id = $forum_id" : 'AND a.forum_id IN (' . implode(', ', $forum_id) . ')') : ''; + $sql_group = ($group_id !== false) ? ((!is_array($group_id)) ? "group_id = $group_id" : $db->sql_in_set('group_id', $group_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)) : ''; if ($opts !== false) { @@ -658,7 +664,7 @@ class auth } else { - $sql_opts = 'AND ao.auth_option IN (' . implode(', ', preg_replace('#^\s*(.*)\s*$#e', "\"'\" . \$db->sql_escape('\\1') . \"'\"", $opts)) . ')'; + $sql_opts = 'AND ' . $db->sql_in_set('ao.auth_option', $opts); } } @@ -707,40 +713,70 @@ class auth global $config, $db, $user, $phpbb_root_path, $phpEx; $method = trim(basename($config['auth_method'])); + include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx); - if (file_exists($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx)) + $method = 'login_' . $method; + if (function_exists($method)) { - include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx); + $login = $method($username, $password); - $method = 'login_' . $method; - if (function_exists($method)) + // 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) { - $login = $method($username, $password); + // 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_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); + } - // If login succeeded, we will log the user in... else we pass the login array through... - if ($login['status'] == LOGIN_SUCCESS) + 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 = '" . $db->sql_escape($username) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) { - $result = $user->session_create($login['user_row']['user_id'], $admin, $autologin, $viewonline); + return array( + 'status' => LOGIN_ERROR_EXTERNAL_AUTH, + 'error_msg' => 'AUTH_NO_PROFILE_CREATED', + 'user_row' => array('user_id' => ANONYMOUS), + ); + } - // Successful session creation - if ($result === true) - { - return array( - 'status' => LOGIN_SUCCESS, - 'error_msg' => false, - 'user_row' => $login['user_row'], - ); - } + $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) + { + $result = $user->session_create($login['user_row']['user_id'], $admin, $autologin, $viewonline); + + // Successful session creation + if ($result === true) + { return array( - 'status' => LOGIN_BREAK, - 'error_msg' => $result, + 'status' => LOGIN_SUCCESS, + 'error_msg' => false, 'user_row' => $login['user_row'], ); } - return $login; + return array( + 'status' => LOGIN_BREAK, + 'error_msg' => $result, + 'user_row' => $login['user_row'], + ); } + + return $login; } trigger_error('Authentication method not found', E_USER_ERROR); diff --git a/phpBB/includes/auth/auth_apache.php b/phpBB/includes/auth/auth_apache.php index 410bf1abdb..3ee0f1347f 100644 --- a/phpBB/includes/auth/auth_apache.php +++ b/phpBB/includes/auth/auth_apache.php @@ -4,13 +4,6 @@ * * Authentication plug-ins is largely down to Sergey Kanareykin, our thanks to him. * -* This is for initial authentication via Apaches basic realm authentication methods, -* user data is then obtained from the integrated user table -* -* You can do any kind of checking you like here ... the return data format is -* either the resulting row of user information, an integer zero (indicating an -* inactive user) or some error string -* * @package login * @version $Id$ * @copyright (c) 2005 phpBB Group @@ -19,17 +12,53 @@ */ /** +* 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; + 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) . "'"; @@ -57,11 +86,11 @@ function login_apache(&$username, &$password) ); } - // the user does not exist + // this is the user's first login so create an empty profile return array( - 'status' => LOGIN_ERROR_USERNAME, - 'error_msg' => 'LOGIN_ERROR_USERNAME', - 'user_row' => array('user_id' => ANONYMOUS), + 'status' => LOGIN_SUCCESS_CREATE_PROFILE, + 'error_msg' => false, + 'user_row' => user_row_apache($php_auth_user, $php_auth_pw), ); } @@ -82,11 +111,19 @@ 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'); + set_var($php_auth_pw, $php_auth_pw, 'string'); + $sql = 'SELECT * FROM ' . USERS_TABLE . " WHERE username = '" . $db->sql_escape($php_auth_user) . "'"; @@ -98,19 +135,73 @@ function autologin_apache() { return ($row['user_type'] == USER_INACTIVE || $row['user_type'] == USER_IGNORE) ? array() : $row; } + + // 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 = '" . $db->sql_escape($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' => $password, + 'user_email' => '', + 'group_id' => (int) $row['group_id'], + 'user_type' => USER_NORMAL, + 'user_ip' => $user->ip, + ); +} + +/** * The session validation function checks whether the user is still logged in * * @return boolean true if the given user is authenticated or false if the session should be closed */ function validate_session_apache(&$user) { - return ($_SERVER['PHP_AUTH_USER'] === $user['username']) ? true : false; + if (!isset($_SERVER['PHP_AUTH_USER'])) + { + return false; + } + + $php_auth_user = ''; + set_var($php_auth_user, $_SERVER['PHP_AUTH_USER'], 'string'); + + return ($php_auth_user === $user['username']) ? true : false; } ?>
\ No newline at end of file diff --git a/phpBB/includes/auth/auth_db.php b/phpBB/includes/auth/auth_db.php index 55465ab762..9477fd92c3 100644 --- a/phpBB/includes/auth/auth_db.php +++ b/phpBB/includes/auth/auth_db.php @@ -6,10 +6,6 @@ * * This is for authentication via the integrated user table * -* You can do any kind of checking you like here ... the return data format is -* either the resulting row of user information, an integer zero (indicating an -* inactive user) or some error string -* * @package login * @version $Id$ * @copyright (c) 2005 phpBB Group diff --git a/phpBB/includes/auth/auth_ldap.php b/phpBB/includes/auth/auth_ldap.php index e9b87bcf44..889f6d8661 100644 --- a/phpBB/includes/auth/auth_ldap.php +++ b/phpBB/includes/auth/auth_ldap.php @@ -5,13 +5,6 @@ * * Authentication plug-ins is largely down to Sergey Kanareykin, our thanks to him. * -* This is for initial authentication via an LDAP server, user information is then -* obtained from the integrated user table -* -* You can do any kind of checking you like here ... the return data format is -* either the resulting row of user information, an integer zero (indicating an -* inactive user) or some error string -* * @package login * @version $Id$ * @copyright (c) 2005 phpBB Group @@ -39,9 +32,17 @@ function init_ldap() } @ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3); + @ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0); // ldap_connect only checks whether the specified server is valid, so the connection might still fail - $search = @ldap_search($ldap, $config['ldap_base_dn'], $config['ldap_uid'] . '=' . $user->data['username'], array($config['ldap_uid'])); + $search = @ldap_search( + $ldap, + $config['ldap_base_dn'], + '(' . $config['ldap_uid'] . '=' . ldap_escape(html_entity_decode($user->data['username'])) . ')', + (empty($config['ldap_email'])) ? array($config['ldap_uid']) : array($config['ldap_uid'], $config['ldap_email']), + 0, + 1 + ); if ($search === false) { @@ -52,12 +53,18 @@ function init_ldap() @ldap_close($ldap); - if (is_array($result) && sizeof($result) > 1) + + if (!is_array($result) || sizeof($result) < 2) { - return false; + return sprintf($user->lang['LDAP_NO_IDENTITY'], $user->data['username']); } - return sprintf($user->lang['LDAP_NO_IDENTITY'], $user->data['username']); + if (!empty($config['ldap_email']) && !isset($result[0][$config['ldap_email']])) + { + return $user->lang['LDAP_NO_EMAIL']; + } + + return false; } /** @@ -65,7 +72,7 @@ function init_ldap() */ function login_ldap(&$username, &$password) { - global $db, $config; + global $db, $config, $user; if (!@extension_loaded('ldap')) { @@ -86,13 +93,22 @@ function login_ldap(&$username, &$password) } @ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3); + @ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0); + + $search = @ldap_search( + $ldap, + $config['ldap_base_dn'], + '(' . $config['ldap_uid'] . '=' . ldap_escape(html_entity_decode($username)) . ')', + (empty($config['ldap_email'])) ? array($config['ldap_uid']) : array($config['ldap_uid'], $config['ldap_email']), + 0, + 1 + ); - $search = @ldap_search($ldap, $config['ldap_base_dn'], $config['ldap_uid'] . '=' . $username, array($config['ldap_uid'])); - $result = @ldap_get_entries($ldap, $search); + $ldap_result = @ldap_get_entries($ldap, $search); - if (is_array($result) && sizeof($result) > 1) + if (is_array($ldap_result) && sizeof($ldap_result) > 1) { - if (@ldap_bind($ldap, $result[0]['dn'], $password)) + if (@ldap_bind($ldap, $ldap_result[0]['dn'], html_entity_decode($password))) { @ldap_close($ldap); @@ -105,6 +121,8 @@ function login_ldap(&$username, &$password) if ($row) { + unset($ldap_result); + // User inactive... if ($row['user_type'] == USER_INACTIVE || $row['user_type'] == USER_IGNORE) { @@ -122,9 +140,45 @@ function login_ldap(&$username, &$password) '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' => $password, + 'user_email' => (!empty($config['ldap_email'])) ? $ldap_result[0][$config['ldap_email']][0] : '', + 'group_id' => (int) $row['group_id'], + 'user_type' => USER_NORMAL, + 'user_ip' => $user->ip, + ); + + unset($ldap_result); + + // this is the user's first login so create an empty profile + return array( + 'status' => LOGIN_SUCCESS_CREATE_PROFILE, + 'error_msg' => false, + 'user_row' => $ldap_user_row, + ); + } } else { + unset($ldap_result); @ldap_close($ldap); // Give status about wrong password... @@ -146,17 +200,21 @@ function login_ldap(&$username, &$password) } /** +* 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 admin_ldap(&$new) +function acp_ldap(&$new) { global $user; - /** - * @todo Using same approach as with cfg_build_template? - */ - $tpl = ' <dl> @@ -171,27 +229,17 @@ function admin_ldap(&$new) <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_uid">' . $user->lang['LDAP_EMAIL'] . ':</label><br /><span>' . $user->lang['LDAP_EMAIL_EXPLAIN'] . '</span></dt> + <dd><input type="text" id="ldap_uid" size="40" name="config[ldap_email]" value="' . $new['ldap_email'] . '" /></dd> + </dl> '; // These are fields required in the config table return array( 'tpl' => $tpl, - 'config' => array('ldap_server', 'ldap_base_dn', 'ldap_uid') + 'config' => array('ldap_server', 'ldap_base_dn', 'ldap_uid', 'ldap_email') ); } -/** -* Would be nice to allow syncing of 'appropriate' data when user updates -* their username, password, etc. ... should be up to the plugin what data -* is updated. -* -* @todo implement this functionality (probably 3.2) -* -* @param new|update|delete $mode defining the action to take on user updates -*/ -function usercp_ldap($mode) -{ - global $db, $config; -} - ?>
\ No newline at end of file diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php index ea800e533b..7293f07dc9 100644 --- a/phpBB/includes/bbcode.php +++ b/phpBB/includes/bbcode.php @@ -15,7 +15,7 @@ class bbcode { var $bbcode_uid = ''; - var $bbcode_bitfield = 0; + var $bbcode_bitfield = ''; var $bbcode_cache = array(); var $bbcode_template = array(); @@ -28,7 +28,7 @@ class bbcode * Constructor * Init bbcode cache entries if bitfield is specified */ - function bbcode($bitfield = 0) + function bbcode($bitfield = '') { if ($bitfield) { @@ -69,32 +69,31 @@ class bbcode $str = array('search' => array(), 'replace' => array()); $preg = array('search' => array(), 'replace' => array()); - $bitlen = strlen(decbin($this->bbcode_bitfield)); - for ($bbcode_id = 0; $bbcode_id < $bitlen; ++$bbcode_id) + $bitfield = new bitfield($this->bbcode_bitfield); + $bbcodes_set = $bitfield->get_all_set(); + + foreach ($bbcodes_set as $bbcode_id) { - if ($this->bbcode_bitfield & (1 << $bbcode_id)) + if (!empty($this->bbcode_cache[$bbcode_id])) { - if (!empty($this->bbcode_cache[$bbcode_id])) + foreach ($this->bbcode_cache[$bbcode_id] as $type => $array) { - foreach ($this->bbcode_cache[$bbcode_id] as $type => $array) + foreach ($array as $search => $replace) { - foreach ($array as $search => $replace) - { - ${$type}['search'][] = str_replace('$uid', $this->bbcode_uid, $search); - ${$type}['replace'][] = $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($str['search'])) + { + $message = str_replace($str['search'], $str['replace'], $message); + $str = array('search' => array(), 'replace' => array()); + } - if (sizeof($preg['search'])) - { - $message = preg_replace($preg['search'], $preg['replace'], $message); - $preg = array('search' => array(), 'replace' => array()); - } + if (sizeof($preg['search'])) + { + $message = preg_replace($preg['search'], $preg['replace'], $message); + $preg = array('search' => array(), 'replace' => array()); } } } @@ -125,13 +124,14 @@ class bbcode } } - $sql = ''; - $bbcode_ids = $rowset = array(); - $bitlen = strlen(decbin($this->bbcode_bitfield)); + $bbcode_ids = $rowset = $sql = array(); - for ($bbcode_id = 0; $bbcode_id < $bitlen; ++$bbcode_id) + $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]) || !($this->bbcode_bitfield & (1 << $bbcode_id))) + if (isset($this->bbcode_cache[$bbcode_id])) { // do not try to re-cache it if it's already in continue; @@ -140,18 +140,18 @@ class bbcode if ($bbcode_id > NUM_CORE_BBCODES) { - $sql .= (($sql) ? ',' : '') . $bbcode_id; + $sql[] = $bbcode_id; } } - if ($sql) + if (sizeof($sql)) { global $db; $sql = 'SELECT * - FROM ' . BBCODES_TABLE . " - WHERE bbcode_id IN ($sql)"; - $result = $db->sql_query($sql); + FROM ' . BBCODES_TABLE . ' + WHERE ' . $db->sql_in_set('bbcode_id', $sql); + $result = $db->sql_query($sql, 3600); while ($row = $db->sql_fetchrow($result)) { @@ -232,7 +232,7 @@ class bbcode case 6: $this->bbcode_cache[$bbcode_id] = array( 'preg' => array( - '!\[color=(#[0-9A-F]{6}|[a-z\-]+):$uid\](.*?)\[/color:$uid\]!s' => $this->bbcode_tpl('color', $bbcode_id), + '!\[color=(#[0-9a-fA-F]{6}|[a-z\-]+):$uid\](.*?)\[/color:$uid\]!s' => $this->bbcode_tpl('color', $bbcode_id), ) ); break; @@ -312,9 +312,13 @@ class bbcode break; default: + if (!isset($template_bitfield)) + { + $template_bitfield = new bitfield($this->template_bitfield); + } if (isset($rowset[$bbcode_id])) { - if ($this->template_bitfield & (1 << $bbcode_id)) + if ($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)) @@ -390,9 +394,10 @@ class bbcode 'color' => '<span style="color: $1">$2</span>', 'email' => '<a href="mailto:$1">$2</a>' ); + $template_bitfield = new bitfield($this->template_bitfield); } - if ($bbcode_id != -1 && !($this->template_bitfield & (1 << $bbcode_id))) + if ($bbcode_id != -1 && !$template_bitfield->get($bbcode_id)) { return (isset($bbcode_hardtpl[$tpl_name])) ? $bbcode_hardtpl[$tpl_name] : false; } @@ -561,7 +566,7 @@ class bbcode $code = str_replace(' ', ' ', $code); // remove newline at the beginning - if ($code{0} == "\n") + if (!empty($code) && $code{0} == "\n") { $code = substr($code, 1); } diff --git a/phpBB/includes/captcha/captcha_gd.php b/phpBB/includes/captcha/captcha_gd.php index 05fb57c9c1..8a2bf70242 100644 --- a/phpBB/includes/captcha/captcha_gd.php +++ b/phpBB/includes/captcha/captcha_gd.php @@ -94,10 +94,10 @@ class captcha { if ($map & (1 << $x)) { - $char = hexdec(substr($seed, ($y * 4) + $x, 1)); + $char = hexdec(substr($seed, ($y << 2) + $x, 1)); if (!($char >> 2)) { - switch ($char % 4) + switch ($char & 3) { case 0: $shape = 'Circle'; @@ -124,21 +124,21 @@ class captcha $cells = array(); for ($i = 0; $i < 6; ++$i) { - $cells = hexdec(substr($seed, 20 + ($i * 2), 2)); - $x1 = $cells % 4; + $cells = hexdec(substr($seed, 20 + ($i << 1), 2)); + $x1 = $cells & 3; $cells = $cells >> 2; - $y1 = $cells % 4; + $y1 = $cells & 3; $cells = $cells >> 2; - $x2 = $cells % 4; + $x2 = $cells & 3; $cells = $cells >> 2; - $y2 = $cells % 4; + $y2 = $cells & 3; $x1_real = $x_min + (($x1 + 0.5) * $x_size); $y1_real = $y_min + (($y1 + 0.5) * $y_size); $x2_real = $x_min + (($x2 + 0.5) * $x_size); $y2_real = $y_min + (($y2 + 0.5) * $y_size); if ($thickness > 1) { - imagesetthickness($img,$thickness); + imagesetthickness($img, $thickness); } imageline($img, $x1_real, $y1_real, $x2_real, $y2_real, $colors[array_rand($colors)]); if ($thickness > 1) @@ -176,53 +176,77 @@ class captcha // Generate image $img_x = 800; $img_y = 250; - $img = imagecreate($img_x, $img_y); + $img = imagecreatetruecolor($img_x, $img_y); // Generate colors - $background = imagecolorallocate($img, mt_rand(155, 255), mt_rand(155, 255), mt_rand(155, 255)); - imagefill($img, 0, 0, $background); + $c = new color_manager($img, array( + 'random' => true, + 'min_saturation' => 70, + 'min_value' => 65, + )); + + $primaries = $c->color_scheme('background', 'tetradic', false); + + $noise = array_shift($primaries); + $noise = $c->mono_range($noise, 'value', 5, false); + $primaries = $c->mono_range($primaries, 'value', 5, false); - $random = array(); - $fontcolors = array(); - for ($i = 0; $i < 15; $i++) + // Generate code characters + $characters = array(); + $sizes = array(); + $bounding_boxes = array(); + $width_avail = $img_x; + $code_num = sizeof($code); + $char_class = $this->captcha_char('char_ttf'); + for ( $i = 0; $i < $code_num; ++$i ) { - $random[$i] = imagecolorallocate($img, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255)); - $fontcolors[$i] = imagecolorallocate($img, mt_rand(0, 120), mt_rand(0, 120), mt_rand(0, 120)); + $characters[$i] = new $char_class($code[$i]); + list($min, $max) = $characters[$i]->range(); + $sizes[$i] = mt_rand($min, $max / 2); + $box = $characters[$i]->dimensions($sizes[$i]); + $width_avail -= ($box[2] - $box[0]); + $bounding_boxes[$i] = $box; } - // Generate code characters - $code_num = sizeof($code); + // Redistribute leftover x-space + $offset = array(); + for ( $i = 0; $i < $code_num; ++$i ) + { + $denom = ($code_num - $i); + $denom = max(1.5, $denom); + $offset[$i] = mt_rand(0, (1.5 * $width_avail) / $denom); + $width_avail -= $offset[$i]; + } // Add some line noise if ($config['policy_shape_noise_line']) { - $this->noise_line($img, 0, 0, $img_x, $img_y, $background, $fontcolors, $random); + $this->noise_line($img, 0, 0, $img_x, $img_y, $c->r('background'), $primaries, $noise); } $real = mt_rand(0, 3); $patterns = array('', '', '', ''); for ($i = 32; $i > 0; --$i) { - $patterns[$i % 4] .= str_pad(dechex(mt_rand(0, 65535)), 4, '0', STR_PAD_LEFT); + $patterns[$i & 3] .= str_pad(dechex(mt_rand(0, 65535)), 4, '0', STR_PAD_LEFT); } - $char_class = $this->captcha_char('char_ttf'); for ($i = 0; $i < 4; ++$i) { - if ($i) + /*if ($i) { $y = 5 + ($i * 60); imageline($img, 550, $y, 650, $y, $fontcolors[0]); - } - $this->draw_pattern($patterns[$i], $img, 525, 10 + ($i * 60), 575, ($i + 1) * 60, $fontcolors); + }*/ + $this->draw_pattern($patterns[$i], $img, 525, 10 + ($i * 60), 575, ($i + 1) * 60, $primaries); if ($i == $real) { - $this->draw_pattern($patterns[$i], $img, 25, 25, 225, 225, $fontcolors, 3); + $this->draw_pattern($patterns[$i], $img, 25, 25, 225, 225, $primaries, 3); for ($j = 0; $j < $code_num; ++$j) { $character = new $char_class($code[$j]); - $character->drawchar(25, 600 + ($j * 25), 35 + ($i * 60), $img, $background, $fontcolors); + $character->drawchar(25, 600 + ($j * 25), 35 + ($i * 60), $img, $c->r('background'), $primaries); } } else @@ -231,20 +255,29 @@ class captcha for ($j = strlen($word) - 1; $j >= 0; --$j) { $character = new $char_class(substr($word, $j, 1)); - $character->drawchar(25, 600 + ($j * 25), 35 + ($i * 60), $img, $background, $fontcolors); + $character->drawchar(25, 600 + ($j * 25), 35 + ($i * 60), $img, $c->r('background'), $primaries); } } } - imagestring($img, 6, 250, 50, $user->lang['CAPTCHA_LINE_1'], $fontcolors[0]); - imagestring($img, 6, 250, 100, $user->lang['CAPTCHA_LINE_2'], $fontcolors[0]); - imagestring($img, 6, 250, 150, $user->lang['CAPTCHA_LINE_3'], $fontcolors[0]); - imagestring($img, 6, 250, 200, $user->lang['CAPTCHA_LINE_4'], $fontcolors[0]); + + $count = sizeof($user->lang['CAPTCHA']['shape']); + $line_height = $img_y / ($count + 1); + for ($i = 0; $i < $count; ++$i) + { + $text = $user->lang['CAPTCHA']['shape'][$i]; + $line_width = strlen($text) * 4.5; // ( / 2, * 9 ) + imagestring($img, 6, ($img_x / 2) - $line_width - 1, $line_height * ($i + 1) - 1, $text, $c->r('black')); + imagestring($img, 6, ($img_x / 2) - $line_width - 1, $line_height * ($i + 1) + 1, $text, $c->r('black')); + imagestring($img, 6, ($img_x / 2) - $line_width + 1, $line_height * ($i + 1) + 1, $text, $c->r('black')); + imagestring($img, 6, ($img_x / 2) - $line_width + 1, $line_height * ($i + 1) - 1, $text, $c->r('black')); + imagestring($img, 6, ($img_x / 2) - $line_width, $line_height * ($i + 1), $text, $c->r('white')); + } // Add some pixel noise if ($config['policy_shape_noise_pixel']) { - $this->noise_pixel($img, 0, 0, $img_x, $img_y, $background, $fontcolors, $random, $config['policy_shape_noise_pixel']); + $this->noise_pixel($img, 0, 0, $img_x, $img_y, $c->r('background'), $primaries, $noise, $config['policy_shape_noise_pixel']); } // Send image @@ -262,23 +295,23 @@ class captcha $fonts = captcha_load_ttf_fonts(); // Generate basic colors - $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)); - + $c = new color_manager($img, 'white'); + $c->allocate_named('primary', array( + 'random' => true, + 'min_saturation' => 50, + 'min_value' => 75, + )); + $bg_colors = $c->color_scheme('primary', 'triadic', false); + $text_colors = $c->mono_range('primary', 'saturation', 6); + $bg_colors = $c->mono_range($bg_colors, 'saturation', 6); + // Specificy image portion dimensions. $count = sizeof($code); $cellsize = $img_x / $count; $y_range = min($cellsize, $img_y); $y_max = $img_y - $y_range; $y_off = array(); // consecutive vertical offset of characters + $color = array(); // color of characters $y_off[0] = mt_rand(0, $y_max); for ($i = 1; $i < $count; ++$i) { @@ -293,108 +326,33 @@ class captcha $y_off[$i] = $y_off[$i - 1] * ((100 + $diff) / 100); } } + + $range = 0.075; - - $range = 0.1; - - $chars = array_merge(range('A', 'Z'), range('0', '9')); + $chars = array_merge(range('A', 'Z'), range('1', '9')); // draw some characters. if they're within the vector spec of the code character, color them differently - for ($i = 0; $i < 5000; ++$i) + for ($i = 0; $i < 8000; ++$i) { $degree = mt_rand(-30, 30); $x = mt_rand(0, $img_x - 1); $y = mt_rand(0, $img_y); - $c = $chars[array_rand($chars)]; + $text = $chars[array_rand($chars)]; $char = $x / $cellsize; $meta_x = ((($x % $cellsize) / $cellsize) * 1.5) - 0.25; $meta_y = (($img_y - $y) - $y_off[$char]) / $y_range; $font = $fonts[array_rand($fonts)]; + + $distance = vector_distance($map[$code[$char]], $meta_x, $meta_y, $range); - // distance check - $distance = 2; - $show = false; - foreach ($map[$code[$char]] AS $vector) - { - switch ($vector[0]) - { - case 'line': - - $c_theta = cos($vector[5]); - $s_theta = sin($vector[5]); - $bx = $meta_x - $vector[1]; - $by = $meta_y - $vector[2]; - $r = ($by * $c_theta) - ($bx * $s_theta); - if ($r < $range && $r > -$range) - { - if (abs($c_theta) > abs($s_theta)) - { - $s = (($bx + ($s_theta * $r)) / $c_theta); - } - else - { - $s = (($by + ($c_theta * $r)) / $s_theta); - } - if ($s > -$range) - { - if ($s < 0) - { - $distance = min($distance, sqrt(pow($s, 2) + pow($r, 2))); - } - elseif ($s < $vector[6]) - { - $distance = min($distance, $r); - } - elseif ($s < $vector[6] + $range) - { - $distance = min($distance, sqrt(pow($s - $vector[6], 2) + pow($r, 2))); - } - } - } - - break; - - case 'arc': - - $dx = $meta_x - $vector[1]; - $dy = -($meta_y - $vector[2]); // because our arcs are upside-down - if ( abs($dx) > abs($dy) ) - { - $phi = rad2deg(atan(($dy * $vector[3]) / ($dx * $vector[4]))); - $phi += ($dx < 0) ? 180 : 360; - $phi %= 360; - } - else - { - $phi = 90 - rad2deg(atan(($dx * $vector[4]) / ($dy * $vector[3]))); - $phi += ($dy < 0) ? 180 : 360; - $phi %= 360; - } - - $internal = $vector[6] > $vector[5]; // external wraps over the 360 point - $low = $phi >= $vector[5]; // phi is above our low range - $high = $phi <= $vector[6]; // phi is below our high range. - if ($internal ? ($low && $high) : ($low || $high)) // if it wraps, it can only be one or the other - { - $radphi = deg2rad($phi); - $px = cos($radphi) * 0.5 * $vector[3]; - $py = sin($radphi) * 0.5 * $vector[4]; - $distance = min($distance, sqrt(pow($px - $dx, 2) + pow($py - $dy, 2))); - } - - break; - } - } - - if ($distance <= $range) - { - imagettftext($img, 10, $degree, $x, $y, $black, $font, $c); - } - else - { - imagettftext($img, 10, $degree, $x, $y, $random[$char], $font, $c); - } - + $switch = !(rand() % 100); + + imagettftext($img, 10, $degree, $x, $y, + (($distance <= $range) xor $switch) ? + $c->r_rand($text_colors) : + $c->r_rand($bg_colors), + $font, $text); + } // Send image @@ -406,39 +364,44 @@ class captcha // Generate image $img_x = 800; $img_y = 250; - $img = imagecreate($img_x, $img_y); - $stencil = imagecreate($img_x, $img_y); + $img = imagecreatetruecolor($img_x, $img_y); + $stencil = imagecreatetruecolor($img_x, $img_y); $map = captcha_vectors(); $fonts = captcha_load_ttf_fonts(); // Generate colors - $white1 = imagecolorallocate($img, 255, 255, 255); - $black2 = imagecolorallocate($stencil, 0, 0, 0); - $black1 = imagecolorallocate($img, 0, 0, 0); - $white2 = imagecolorallocate($stencil, 255, 255, 255); - $channel = mt_rand(0,2); - $c1 = (!($channel % 3)) ? 255 : 0; - $c2 = (!(($channel + 1) % 3)) ? 255 : 0; - $c3 = (!(($channel + 2) % 3)) ? 255 : 0; - $primary = imagecolorallocate($img, $c1, $c2, $c3); - $second = imagecolorallocate($img, $c2, $c3, $c1); - $third = imagecolorallocate($img, $c3, $c1, $c2); - - imagefill($stencil, 0, 0, $black2); - imagefill($img, 0, 0, $white1); + $c = new color_manager($img, 'black'); + $cs = new color_manager($stencil, 'gray'); + + $c->allocate_named('primary', array( + 'random' => true, + 'min_saturation' => 75, + 'min_value' => 80, + )); + + $secondary = $c->color_scheme('primary', 'triadic', false); + + //imagefill($stencil, 0, 0, $black2); + //imagefill($img, 0, 0, $white1); $chars = array_merge(range('A', 'Z'), range('1', '9')); - - for ($i = 0; $i < 1000; ++$i) + $step = 20; + $density = 4; + for ($i = 0; $i < $img_x; $i += $step) { - $degree = mt_rand(-30, 30); - $x = mt_rand(0, $img_x - 1); - $y = mt_rand(0, $img_y); - $c = $chars[array_rand($chars)]; - $font = $fonts[array_rand($fonts)]; - - imagettftext($stencil, mt_rand(20, 30), $degree, $x, $y, $white2, $font, $c); + for ($j = 0; $j < $img_y; $j += $step) + { + for ($k = 0; $k < $density; ++$k) + { + $degree = mt_rand(-30, 30); + $x = mt_rand($i, $i + $step); + $y = mt_rand($j, $j + $step); + $char = $chars[array_rand($chars)]; + $font = $fonts[array_rand($fonts)]; + imagettftext($stencil, mt_rand(20, 30), $degree, $x, $y, $cs->r('black'), $font, $char); + } + } } for ($i = 0; $i < 3; ++$i) @@ -449,27 +412,62 @@ class captcha $x2 = mt_rand(0, $img_x - 1); $y1 = mt_rand(0, $img_y); $y2 = mt_rand(0, $img_y); - $c1 = $chars[array_rand($chars)]; - $c2 = $chars[array_rand($chars)]; + $char1 = $chars[array_rand($chars)]; + $char2 = $chars[array_rand($chars)]; $font1 = $fonts[array_rand($fonts)]; $font2 = $fonts[array_rand($fonts)]; - imagettftext($img, 150, $degree1, $x1, $y1, $second, $font1, $c1); - imagettftext($img, 150, $degree2, $x2, $y2, $third, $font2, $c2); + imagettftext($img, mt_rand(75, 100), $degree1, $x1, $y1, $secondary[0], $font1, $char1); + imagettftext($img, mt_rand(75, 100), $degree2, $x2, $y2, $secondary[1], $font2, $char2); } - $text = implode('', $code); - $font = $fonts[array_rand($fonts)]; - imagettftext($img, 150, mt_rand(-5, 5), mt_rand(0, $img_x / 4), mt_rand(150, $img_y), $primary, $font, $text); + $characters = array(); + $sizes = array(); + $bounding_boxes = array(); + $width_avail = $img_x; + $code_num = sizeof($code); + $char_class = $this->captcha_char('char_ttf'); + for ($i = 0; $i < $code_num; ++$i) + { + $characters[$i] = new $char_class($code[$i]); + $sizes[$i] = mt_rand(75, 100); + $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_num; ++$i) + { + $denom = ($code_num - $i); + $denom = max(1.5, $denom); + $offset[$i] = mt_rand(0, (1.5 * $width_avail) / $denom); + $width_avail -= $offset[$i]; + } + + // Draw the text + $xoffset = 0; + for ($i = 0; $i < $code_num; ++$i) + { + $characters[$i] = new $char_class($code[$i]); + $dimm = $bounding_boxes[$i]; + $xoffset += ($offset[$i] - $dimm[0]); + $yoffset = mt_rand(-$dimm[1], $img_y - $dimm[3]); + $characters[$i]->drawchar($sizes[$i], $xoffset, $yoffset, $img, $c->r('background'), array($c->r('primary'))); + $xoffset += $dimm[2]; + } for ($i = 0; $i < $img_x; ++$i) { for ($j = 0; $j < $img_y; ++$j) { - // if the stencil is black, set the pixel in the image black - if (!imagecolorat($stencil, $i, $j)) + // if the stencil is not black, set the pixel in the image to gray + if (imagecolorat($stencil, $i, $j)) { - imagesetpixel($img, $i, $j, $black1); + imagesetpixel($img, $i, $j, $c->r('gray')); } } } @@ -480,6 +478,7 @@ class captcha function policy_cells($code) { + global $user; // Generate image $img_x = 800; $img_y = 250; @@ -492,120 +491,137 @@ class captcha // // Generate colors // - $white = imagecolorallocate($img, 255, 255, 255); - $black = imagecolorallocate($img, 0, 0, 0); - $colors = array( - imagecolorallocate($img, 128, 0, 0), - imagecolorallocate($img, 0, 128, 0), - imagecolorallocate($img, 0, 0, 128), - imagecolorallocate($img, 90, 90, 90) - ); - - $red = mt_rand(0,3); - - imagefill($img, 10, 10, $white); - - $offset1 = 50; - $offset2 = 550; - - // draw the cell grid - for ($i = 0; $i < 4; ++$i) + $c = new color_manager($img, 'white'); + + $c->allocate_named('primary', array( + 'random' => true, + 'min_saturation' => 30, + 'min_value' => 65, + )); + $primaries = $c->color_scheme('primary', 'tetradic'); + $bg_colors = $c->mono_range($primaries, 'value', 4, false); + shuffle($primaries); + shuffle($bg_colors); + + // Randomize the characters on the right and the left + $left_characters = array(); + $right_characters = array(); + $chars = array_merge(range('A', 'Z'), range('1', '9')); + $chars_size = sizeof($chars) - 1; + $alpha = range('A', 'Z'); + $alpha_size = sizeof($alpha) - 1; + for ($i = 0; $i < 25; ++$i) { - imageline($img, $offset1 + 40 + ($i * 40), 25, $offset1 + 40 + ($i * 40), 225, $black); - imageline($img, $offset1, 65 + ($i * 40), $offset1 + 200, 65 + ($i * 40), $black); - imageline($img, $offset2 + 40 + ($i * 40), 25, $offset2 + 40 + ($i * 40), 225, $black); - imageline($img, $offset2, 65 + ($i * 40), $offset2 + 200, 65 + ($i * 40), $black); + $left_characters[$i] = $alpha[mt_rand(0, $alpha_size)]; + $right_characters[$i] = $chars[mt_rand(0, $chars_size)]; } - + + // Pick locations for our code, shuffle the rest into 3 separate queues $code_count = sizeof($code); - - $characters = array(); - $bitmap = array_fill(0, 25, 0); - $cellorder = array(); - $xs = array(); - $ys = array(); - - $chars = array_merge(range('A', 'Z'), range('1', '9')); - - for ($i = 0, $count = sizeof($chars) - 1; $i < 25; ++$i) + $code_order = range(0, 24); + shuffle($code_order); + $remaining = array_splice($code_order, $code_count); + $lineups = array($code_order, array(), array(), array()); + for ($i = sizeof($remaining) - 1; $i >= 0; --$i) { - // Put a character in this cell - $characters[$i] = $chars[array_rand($chars)]; - $xs[$i] = $offset1 + 20 + (($i % 5) * 40) + mt_rand(-13, 13); - $ys[$i] = 45 + (intval($i / 5) * 40) + mt_rand(-13, 13); - - // Generate a pastel color - $color = array(255, 255, 255); - for ($j = 0; $j < 3; ++$j) - { - $color[array_rand($color)] -= 25; - } - $bg = imagecolorallocate($img, $color[0], $color[1], $color[2]); - - // fill the cells with the background colors - imagefilledrectangle($img, $offset1 + 1 + (($i % 5) * 40), 26 + (intval($i / 5) * 40), $offset1 + 39 + (($i % 5) * 40), 64 + (intval($i / 5) * 40), $bg); - imagefilledrectangle($img, $offset2 + 1 + (($i % 5) * 40), 26 + (intval($i / 5) * 40), $offset2 + 39 + (($i % 5) * 40), 64 + (intval($i / 5) * 40), $bg); + $lineups[mt_rand(1, 3)][] = $remaining[$i]; } - - // assign the code to some cells - $cellorder = range(0, 24); - shuffle($cellorder); - array_splice($cellorder, $code_count); + + // overwrite the randomized left and right values with our code, where applicable for ($i = 0; $i < $code_count; ++$i) { - $bitmap[$cellorder[$i]] = $i + 1; - $characters[$cellorder[$i]] = $code[$i]; + $left_characters[$code_order[$i]] = $i + 1; + $right_characters[$code_order[$i]] = $code[$i]; } + + + $offset1 = 50; + $offset2 = 550; - // assign the remaning cells to three separate colors - $spares = array(array(), array(), array()); + // Draw the cells and right hand characters + $xs = $ys = array(); for ($i = 0; $i < 25; ++$i) { - if (!$bitmap[$i]) - { - $spares[array_rand($spares)][] = $i; - } - } - shuffle($spares[0]); - shuffle($spares[1]); - shuffle($spares[2]); + $xs[$i] = $offset1 + 20 + (($i % 5) * 40) + mt_rand(-13, 13); + $ys[$i] = 45 + (intval($i / 5) * 40) + mt_rand(-13, 13); - // draw circles and lines for our fake entries - for ($k = 0; $k < 3; ++$k ) + $bg = $c->r_rand($bg_colors); + + // fill the cells with the background colors + imagefilledrectangle($img, + $offset1 + 1 + (($i % 5) * 40), 26 + (intval($i / 5) * 40), + $offset1 + 39 + (($i % 5) * 40), 64 + (intval($i / 5) * 40), + $bg); + imagefilledrectangle($img, + $offset2 + 1 + (($i % 5) * 40), 26 + (intval($i / 5) * 40), + $offset2 + 39 + (($i % 5) * 40), 64 + (intval($i / 5) * 40), + $bg); + + $level = intval($i / 5); + $pos = $i % 5; + imagettftext($img, 12, 0, + $offset2 + 15 + ($pos * 40), 50 + ($level * 40), + $c->is_dark($bg) ? $c->r('white'): $c->r('black'), $fonts['genr102.ttf'], $right_characters[$i]); + } + + // draw the lines that appear between nodes (visual hint) + for ($k = 0; $k < 4; ++$k ) { - for ($i = 0, $size = sizeof($spares[$k]); $i < $size; ++$i ) + $lineup = $lineups[$k]; + for ($i = 1, $size = sizeof($lineup); $i < $size; ++$i ) { - imagefilledellipse($img, $xs[$spares[$k][$i]], $ys[$spares[$k][$i]], 20, 20, $colors[($red + $k + 1) % 4]); - if ($i) - { - imageline($img, $xs[$spares[$k][$i - 1]], $ys[$spares[$k][$i - 1]], $xs[$spares[$k][$i]], $ys[$spares[$k][$i]], $colors[($red + $k + 1) % 4]); - } + imageline($img, + $xs[$lineup[$i - 1]], $ys[$lineup[$i - 1]], + $xs[$lineup[$i]], $ys[$lineup[$i]], + $primaries[$k]); } } - - // draw lines for our real entries - for ($i = 1; $i < $code_count; ++$i ) + + // draw the actual nodes + $textcolor = $c->is_dark($primaries[0]) ? $c->r('white') : $c->r('black'); + for ($k = 0; $k < 4; ++$k ) { - imageline($img, $xs[$cellorder[$i - 1]], $ys[$cellorder[$i - 1]], $xs[$cellorder[$i]], $ys[$cellorder[$i]], $colors[$red]); - } - - // write characters into the text cells & put white dots (change this?) on our fake entry circles - for ($i = 0; $i < 25; ++$i) - { - if (!$bitmap[$i]) + for ($j = 0, $size = sizeof($lineups[$k]); $j < $size; ++$j ) { - imagefilledellipse($img, $xs[$i], $ys[$i], 9, 9, $white); + $i = $lineups[$k][$j]; + imagefilledellipse($img, + $xs[$i], $ys[$i], + 20, 20, + $primaries[$k]); + imagettftext($img, 12, 0, + $xs[$i] - 5, $ys[$i] + 5, + $textcolor, $fonts['genr102.ttf'], $left_characters[$i]); } - $level = intval($i / 5); - $pos = $i % 5; - imagettftext($img, 12, 0, $offset2 + 15 + ($pos * 40), 50 + ($level * 40), $black, $fonts[array_rand($fonts)], $characters[$i]); } - - // draw our real entries in - for ($i = 0; $i < $code_count; ++$i ) + + // Draw poly behind explain text + $points = mt_rand(3, 6); + $arc = 360 / $points; + $vertices = array(); + $c_x = $img_x / 2; + $c_y = $img_y / 2; + $radius = $img_y / 2.5; + $start = deg2rad(mt_rand(0, 360)); + for ($i = 0; $i < $points; ++$i) { - imagefilledellipse($img, $xs[$cellorder[$i]], $ys[$cellorder[$i]], 20, 20, $colors[$red]); - imagettftext($img, 12, 0, $xs[$cellorder[$i]] - 5, $ys[$cellorder[$i]] + 5, $white, $fonts[array_rand($fonts)], ($i + 1)); + $rad = $start + deg2rad(($arc * $i) + mt_rand(-10, 10)); + $vertices[] = $c_x + (cos($rad) * $radius); + $vertices[] = $c_y + (sin($rad) * $radius); + } + imagefilledpolygon($img, $vertices, $points, $primaries[mt_rand(0,3)]); + + // draw explain text + $count = sizeof($user->lang['CAPTCHA']['cells']); + $line_height = $img_y / ($count + 1); + for ($i = 0; $i < $count; ++$i) + { + $text = $user->lang['CAPTCHA']['cells'][$i]; + $line_width = strlen($text) * 4.5; // ( / 2, * 9 ) + imagestring($img, 6, ($img_x / 2) - $line_width - 1, $line_height * ($i + 1) - 1, $text, $c->r('black')); + imagestring($img, 6, ($img_x / 2) - $line_width - 1, $line_height * ($i + 1) + 1, $text, $c->r('black')); + imagestring($img, 6, ($img_x / 2) - $line_width + 1, $line_height * ($i + 1) + 1, $text, $c->r('black')); + imagestring($img, 6, ($img_x / 2) - $line_width + 1, $line_height * ($i + 1) - 1, $text, $c->r('black')); + imagestring($img, 6, ($img_x / 2) - $line_width, $line_height * ($i + 1), $text, $c->r('white')); } // Send image @@ -621,19 +637,18 @@ class captcha // Generate image $img_x = 800; $img_y = 250; - $img = imagecreate($img_x, $img_y); + $img = imagecreatetruecolor($img_x, $img_y); // Generate colors - $background = imagecolorallocate($img, mt_rand(155, 255), mt_rand(155, 255), mt_rand(155, 255)); - imagefill($img, 0, 0, $background); - - $random = $fontcolors = array(); + $c = new color_manager($img, array( + 'random' => true, + 'min_value' => 60, + ), 'hsv'); - for ($i = 0; $i < 15; $i++) - { - $random[$i] = imagecolorallocate($img, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255)); - $fontcolors[$i] = imagecolorallocate($img, mt_rand(0, 120), mt_rand(0, 120), mt_rand(0, 120)); - } + $scheme = $c->color_scheme('background', 'triadic', false); + $scheme = $c->mono_range($scheme, 'both', 10, false); + shuffle($scheme); + $bg_colors = array_splice($scheme, mt_rand(6, 12)); // Generate code characters $characters = $sizes = $bounding_boxes = array(); @@ -665,7 +680,7 @@ class captcha // Add some line noise if ($config['policy_entropy_noise_line']) { - $this->noise_line($img, 0, 0, $img_x, $img_y, $background, $fontcolors, $random); + $this->noise_line($img, 0, 0, $img_x, $img_y, $c->r('background'), $scheme, $bg_colors); } // Draw the text @@ -675,14 +690,14 @@ class captcha $dimm = $bounding_boxes[$i]; $xoffset += ($offset[$i] - $dimm[0]); $yoffset = mt_rand(-$dimm[1], $img_y - $dimm[3]); - $characters[$i]->drawchar($sizes[$i], $xoffset, $yoffset, $img, $background, $fontcolors); + $characters[$i]->drawchar($sizes[$i], $xoffset, $yoffset, $img, $c->r('background'), $scheme); $xoffset += $dimm[2]; } // Add some pixel noise if ($config['policy_entropy_noise_pixel']) { - $this->noise_pixel($img, 0, 0, $img_x, $img_y, $background, $fontcolors, $random, $config['policy_entropy_noise_pixel']); + $this->noise_pixel($img, 0, 0, $img_x, $img_y, $c->r('background'), $scheme, $bg_colors, $config['policy_entropy_noise_pixel']); } // Send image @@ -697,7 +712,7 @@ class captcha // Generate image $img_x = 700; $img_y = 225; - $img = imagecreate($img_x, $img_y); + $img = imagecreatetruecolor($img_x, $img_y); $x_grid = mt_rand(6, 10); $y_grid = mt_rand(6, 10); @@ -738,26 +753,36 @@ class captcha // we'll calculate the 4th point so that it forms a proper trapezoid $box[3][0] = $box[2][0] + $box[0][0] - $box[1][0]; $box[3][1] = $box[2][1] + $box[0][1] - $box[1][1]; - - // Generate colors (When we get a chance, come up with *better* colors. these ones suck) - $background = imagecolorallocate($img, mt_rand(155, 255), mt_rand(155, 255), mt_rand(155, 255)); - imagefill($img, 0, 0, $background); - + $c = new color_manager($img, array( + 'random' => true, + 'min_saturation' => 50, + 'min_value' => 65, + )); + + $r1 = $c->random_color(array( + 'min_value' => 20, + 'max_value' => 50, + )); + $r2 = $c->random_color(array( + 'min_value' => 70, + 'max_value' => 100, + )); + $rdata = mt_rand(0,1) ? array( + $c->colors[$r1], + $c->colors[$r2], + ) : array( + $c->colors[$r2], + $c->colors[$r1], + ); + $colors = array(); - - $minr = mt_rand(0, 8); - $ming = mt_rand(0, 8); - $minb = mt_rand(0, 8); - - $maxr = mt_rand(128, 220); - $maxg = mt_rand(128, 220); - $maxb = mt_rand(128, 220); - - for ($i = -30; $i <= 30; ++$i) + for ($i = 0; $i < 60; ++$i) { - $coeff1 = ($i + 30) / 60; - $coeff2 = 1 - $coeff1; - $colors[$i] = imagecolorallocate($img, ($coeff2 * $maxr) + ($coeff1 * $minr), ($coeff2 * $maxg) + ($coeff1 * $ming), ($coeff2 * $maxb) + ($coeff1 * $minb)); + $colors[$i - 30] = $c->allocate(array( + $rdata[0][0], + (($i * $rdata[0][1]) + ((60 - $i) * $rdata[1][1])) / 60, + (($i * $rdata[0][2]) + ((60 - $i) * $rdata[1][2])) / 60, + )); } // $img_buffer is the last row of 3-space positions (converted to img-space), cached @@ -794,7 +819,7 @@ class captcha { if ($map['data'][$letter][$y][$x]) { - $plane[$y + $plane_offset_y + (($c % 2) ? 1 : -1)][$x + $plane_offset_x] = true; + $plane[$y + $plane_offset_y + (($c & 1) ? 1 : -1)][$x + $plane_offset_x] = true; } } } @@ -817,8 +842,9 @@ class captcha { $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_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; @@ -827,25 +853,27 @@ class captcha for ($y = 1; $y <= $full_y; ++$y) { // swap buffers - $buffer_cur = $y % 2; + $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, $img_buffer[$buffer_prev][0][1] + $dyy + $offset); + $img_pos_cur = array($img_buffer[$buffer_prev][0][0] + $dyx, + $img_buffer[$buffer_prev][0][1] + $dyy + $offset); $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 + //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) + $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; @@ -869,7 +897,7 @@ class captcha $diag_up = (empty($plane[$y_index_old][$x_index_new]) == empty($plane[$y_index_new][$x_index_old])); // natural switching - $mode = ($x + $y) % 2; + $mode = ($x + $y) & 1; // override if it requires it if ($diag_down != $diag_up) @@ -915,20 +943,19 @@ class captcha // Generate image $img_x = 250; $img_y = 120; - $img = imagecreate($img_x, $img_y); + $img = imagecreatetruecolor($img_x, $img_y); // Generate colors - $background = imagecolorallocate($img, mt_rand(155, 255), mt_rand(155, 255), mt_rand(155, 255)); - imagefill($img, 0, 0, $background); - - $random = $fontcolors = array(); - - for ($i = 0; $i < 15; $i++) - { - $random[$i] = imagecolorallocate($img, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255)); - } - - $fontcolors[0] = imagecolorallocate($img, mt_rand(0, 120), mt_rand(0, 120), mt_rand(0, 120)); + $c = new color_manager($img, array( + 'random' => true, + 'min_saturation' => 70, + 'min_value' => 65, + )); + + $primaries = $c->color_scheme('background', 'triadic', false); + $text = mt_rand(0, 1); + $c->name_color('text', $primaries[$text]); + $noise = $c->mono_range($primaries[1 - $text], 'both', 6, false); // Generate code characters $characters = $bounding_boxes = array(); @@ -952,30 +979,44 @@ class captcha // Add some line noise if ($config['policy_overlap_noise_line']) { - $this->noise_line($img, 0, 0, $img_x, $img_y, $background, $fontcolors, $random); + $this->noise_line($img, 0, 0, $img_x, $img_y, $c->r('background'), array($c->r('text')), $noise); } // Draw the text - $min = -$bounding_boxes[0][1]; - $max = $img_y - $bounding_boxes[0][3]; + $min = 10 - $bounding_boxes[0][1]; + $max = ($img_y - 10) - $bounding_boxes[0][3]; $med = ($max + $min) / 2; - + $yoffset = mt_rand($med, $max); - - for ($i = 0; $i < $code_num; ++$i) + $char_num = sizeof($characters); + + imagesetthickness($img, 3); + for ($i = 0; $i < $char_num; ++$i) { + if ($i) + { + imageline($img, $old_x + mt_rand(-3, 3), $old_y - 70 + mt_rand(-3, 3), $offset + mt_rand(-3, 3), $yoffset - 70 + mt_rand(-3, 3), $c->r('text')); + imageline($img, $old_x + mt_rand(-3, 3), $old_y + 30 + mt_rand(-3, 3), $offset + mt_rand(-3, 3), $yoffset + 30 + mt_rand(-3, 3), $c->r('text')); + } + $dimm = $bounding_boxes[$i]; $offset -= $dimm[0]; - $characters[$i]->drawchar($char_size, $offset, $yoffset, $img, $background, $fontcolors); + $characters[$i]->drawchar($char_size, $offset, $yoffset, $img, $c->r('background'), array($c->r('text'))); + + $old_x = $offset; + $old_y = $yoffset; + $offset += $dimm[2]; $offset -= (($dimm[2] - $dimm[0]) * $overlap_factor); - $yoffset += ($i % 2) ? ((1 - $overlap_factor) * ($dimm[3] - $dimm[1])) : ((1 - $overlap_factor) * ($dimm[1] - $dimm[3])); + $yoffset += ($i & 1) ? ((1 - $overlap_factor) * ($dimm[3] - $dimm[1])) : ((1 - $overlap_factor) * ($dimm[1] - $dimm[3])); } + + imagesetthickness($img, 1); // Add some medium pixel noise if ($config['policy_overlap_noise_pixel']) { - $this->noise_pixel($img, 0, 0, $img_x, $img_y, $background, $fontcolors, $random, $config['policy_overlap_noise_pixel']); + $this->noise_pixel($img, 0, 0, $img_x, $img_y, $c->r('background'), array($c->r('text')), $noise, $config['policy_overlap_noise_pixel']); } // Send image @@ -1041,15 +1082,15 @@ class captcha case 'noise_pixel_heavy': - for ($x = $min_x; $x < $max_x; $x += mt_rand(9, 18)) + for ($x = $min_x; $x < $max_x; $x += mt_rand(4, 9)) { - for ($y = $min_y; $y < $max_y; $y += mt_rand(4, 9)) + for ($y = $min_y; $y < $max_y; $y++) { imagesetpixel($img, $x, $y, $non_font[array_rand($non_font)]); } } - for ($y = $min_y; $y < $max_y; $y++) + for ($y = $min_y; $y < $max_y; $y+= mt_rand(4, 9)) { for ($x = $min_x; $x < $max_x; $x++) { @@ -1066,6 +1107,7 @@ class captcha */ 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; @@ -1073,23 +1115,13 @@ class captcha do { - $line = array(); - - for ($j = mt_rand(30, 60); $j > 0; --$j) - { - $line[] = $non_font[array_rand($non_font)]; - } - - for ($j = mt_rand(30, 60); $j > 0; --$j) - { - $line[] = $bg; - } + $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); - for ($yp = -1; $yp <= 1; ++$yp) - { - imageline($img, $x1, $y1 + $yp, $x2, $y2 + $yp, IMG_COLOR_STYLED); - } + imageline($img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED); $y1 += mt_rand(12, 35); $y2 += mt_rand(12, 35); @@ -1103,28 +1135,19 @@ class captcha do { - $line = array(); - - for ($j = mt_rand(30, 60); $j > 0; --$j) - { - $line[] = $non_font[array_rand($non_font)]; - } - - for ($j = mt_rand(30, 60); $j > 0; --$j) - { - $line[] = $bg; - } + $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); - for ($xp = -1; $xp <= 1; ++$xp) - { - imageline($img, $x1 + $xp, $y1, $x2 + $xp, $y2, IMG_COLOR_STYLED); - } + imageline($img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED); $x1 += mt_rand(12, 35); $x2 += mt_rand(12, 35); } while ($x1 < $max_x && $x2 < $max_x); + imagesetthickness($img, 1); } /** @@ -1145,7 +1168,7 @@ class captcha $character_classes[] = 'char_ttf'; } } -//$character_classes = array('char_dots'); + // Use the module $override, else a random picked one... $class = ($override !== false && in_array($override, $character_classes)) ? $override : $character_classes[array_rand($character_classes)]; @@ -1179,7 +1202,8 @@ class char_dots $this->width_percent = (!empty($width_percent)) ? max(25, min(150, intval($width_percent))) : mt_rand(60, 90); $this->space = 10; - $this->radius = 1; + $this->radius = 3; + $this->density = 3; $this->letter = $letter; } @@ -1211,18 +1235,14 @@ class char_dots for ($i = 0; $i < $len; ++$i) { - $shift1 = mt_rand(-$this->radius, $this->radius); - $shift2 = mt_rand(-$this->radius, $this->radius); - - imagesetpixel($img, - $xoff + ($veclist[1] * $width) + (($i * $dx) / $len) + ($inv_dx * $shift1), - $yoff + ((1 - $veclist[2]) * $height) + (($i * $dy) / $len) + ($inv_dy * $shift1), - $color); - - imagesetpixel($img, - $xoff + ($veclist[1] * $width) + (($i * $dx) / $len) + ($inv_dx * $shift2), - $yoff + ((1 - $veclist[2]) * $height) + (($i * $dy) / $len) + ($inv_dy * $shift2), - $color); + for ($k = 0; $k <= $this->density; ++$k) + { + $shift = mt_rand(-$this->radius, $this->radius); + imagesetpixel($img, + $xoff + ($veclist[1] * $width) + (($i * $dx) / $len) + ($inv_dx * $shift), + $yoff + ((1 - $veclist[2]) * $height) + (($i * $dy) / $len) + ($inv_dy * $shift), + $color); + } } break; @@ -1243,22 +1263,20 @@ class char_dots for ($i = 0; $i < $arclengthdeg; $i += $increment) { $theta = deg2rad(($i + $veclist[5]) % 360); - $shift1 = mt_rand(-$this->radius, $this->radius); - $shift2 = mt_rand(-$this->radius, $this->radius); - $x_o1 = cos($theta) * (($veclist[3] * 0.5 * $width) + $shift1); - $y_o1 = sin($theta) * (($veclist[4] * 0.5 * $height) + $shift1); - $x_o2 = cos($theta) * (($veclist[3] * 0.5 * $width) + $shift2); - $y_o2 = sin($theta) * (($veclist[4] * 0.5 * $height) + $shift2); - - imagesetpixel($img, - $xoff + $x_c + $x_o1, - $yoff + $y_c + $y_o1, - $color); - - imagesetpixel($img, - $xoff + $x_c + $x_o2, - $yoff + $y_c + $y_o2, - $color); + $x_o = cos($theta); + $y_o = sin($theta); + $pre_width = ($veclist[3] * 0.5 * $width); + $pre_height = ($veclist[4] * 0.5 * $height); + for ($k = 0; $k <= $this->density; ++$k) + { + $shift = mt_rand(-$this->radius, $this->radius); + $x_o1 = $x_o * ($pre_width + $shift); + $y_o1 = $y_o * ($pre_height + $shift); + imagesetpixel($img, + $xoff + $x_c + $x_o1, + $yoff + $y_c + $y_o1, + $color); + } } break; @@ -1499,8 +1517,7 @@ class char_hatches for ($p = 0; $p <= $hatches; ++$p) { - // toss some crap at the hough transform, if people even get to that stage here - if (!mt_rand(0, 9) && ($hatches > 3) && !$p) + if (!$p && !mt_rand(0, 9) && ($hatches > 3)) { continue; } @@ -2699,4 +2716,712 @@ function captcha_vectors() ); } +class color_manager +{ + var $img; + var $mode; + var $colors; + var $named_colors; + var $named_rgb = array( + 'red' => array(0xff, 0x00, 0x00), + 'maroon' => array(0x80, 0x00, 0x00), + 'yellow' => array(0xff, 0xff, 0x00), + 'olive' => array(0x80, 0x80, 0x00), + 'lime' => array(0x00, 0xff, 0x00), + 'green' => array(0x00, 0x80, 0x00), + 'aqua' => array(0x00, 0xff, 0xff), + 'teal' => array(0x00, 0x80, 0x80), + 'blue' => array(0x00, 0x00, 0xff), + 'navy' => array(0x00, 0x00, 0x80), + 'fuchsia' => array(0xff, 0x00, 0xff), + 'purple' => array(0x80, 0x00, 0x80), + 'white' => array(0xff, 0xff, 0xff), + 'silver' => array(0xc0, 0xc0, 0xc0), + 'gray' => array(0x80, 0x80, 0x80), + 'black' => array(0x00, 0x00, 0x00), + ); + + /** + * Create the color manager, link it to + * the image resource + */ + function color_manager($img, $background = false, $mode = 'ahsv') + { + $this->img = $img; + $this->mode = $mode; + $this->colors = array(); + $this->named_colors = array(); + if ($background !== false) + { + $bg = $this->allocate_named('background', $background); + imagefill($this->img, 0, 0, $bg); + } + } + + /** + * Lookup a named color resource + */ + function r($named_color) + { + if (isset($this->named_colors[$named_color])) + { + return $this->named_colors[$named_color]; + } + if (isset($this->named_rgb[$named_color])) + { + return $this->allocate_named($named_color, $this->named_rgb[$named_color], 'rgb'); + } + return false; + } + + /** + * Assign a name to a color resource + */ + function name_color($name, $resource) + { + $this->named_colors[$name] = $resource; + } + + /** + * random color resource + */ + function r_rand($colors) + { + return $colors[array_rand($colors)]; + } + + /** + * names and allocates a color resource + */ + function allocate_named($name, $color, $mode = false) + { + $resource = $this->allocate($color, $mode); + if ($resource !== false) + { + $this->name_color($name, $resource); + } + return $resource; + } + + /** + * allocates a specified color into the image + */ + function allocate($color, $mode = false) + { + if ($mode === false) + { + $mode = $this->mode; + } + if (!is_array($color)) + { + if (isset($this->named_rgb[$color])) + { + return $this->allocate_named($color, $this->named_rgb[$color], 'rgb'); + } + if (!is_int($color)) + { + return false; + } + $mode = 'rgb'; + $color = array( + 255 & ($color >> 16), + 255 & ($color >> 8), + 255 & $color, + ); + } + + if (isset($color['mode'])) + { + $mode = $color['mode']; + unset($color['mode']); + } + if (isset($color['random'])) + { + unset($color['random']); + // everything else is params + return $this->random_color($color, $mode); + } + + $rgb = color_manager::model_convert($color, $mode, 'rgb'); + $store = ($this->mode == 'rgb') ? $rgb : color_manager::model_convert($color, $mode, $this->mode); + $resource = imagecolorallocate($this->img, $rgb[0], $rgb[1], $rgb[2]); + + $this->colors[$resource] = $store; + + return $resource; + } + + /** + * randomly generates a color, with optional params + */ + function random_color($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' => 100, // 0 - 100 + 'min_value' => 30, // 0 - 100 + 'max_value' => 100, // 0 - 100 + ); + + $alt = ($mode == 'ahsv'); + + $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 color_scheme($resource, $scheme, $include_original = true) + { + $mode = (in_array($this->mode, array('hsv', 'ahsv'), true) ? $this->mode : 'hsv'); + if (($pre = $this->r($resource)) !== false) + { + $resource = $pre; + } + $color = color_manager::model_convert($this->colors[$resource], $this->mode, $mode); + $results = $include_original ? array($resource) : array(); + + switch ($scheme) + { + case 'complement': + + $color2 = $color; + $color2[0] += 180; + $results[] = $this->allocate($color2, $mode); + + break; + + case 'triadic': + + $color2 = $color3 = $color; + $color2[0] += 120; + $color3[0] += 240; + $results[] = $this->allocate($color2, $mode); + $results[] = $this->allocate($color3, $mode); + + break; + + case 'tetradic': + + $color2 = $color3 = $color4 = $color; + $color2[0] += 30; + $color3[0] += 180; + $color4[0] += 210; + $results[] = $this->allocate($color2, $mode); + $results[] = $this->allocate($color3, $mode); + $results[] = $this->allocate($color4, $mode); + + break; + + case 'analogous': + + $color2 = $color3 = $color; + $color2[0] += 30; + $color3[0] += 330; + $results[] = $this->allocate($color2, $mode); + $results[] = $this->allocate($color3, $mode); + + break; + } + return $results; + } + + function mono_range($resource, $type = 'both', $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], $type, $count, $include_original)); + } + return $results; + } + $mode = (in_array($this->mode, array('hsv', 'ahsv'), true) ? $this->mode : 'ahsv'); + if (($pre = $this->r($resource)) !== false) + { + $resource = $pre; + } + $color = color_manager::model_convert($this->colors[$resource], $this->mode, $mode); + + $results = array(); + if ($include_original) + { + $results[] = $resource; + $count--; + } + + switch ($type) + { + case 'saturation': + + $pivot = $color[1]; + $num_below = intval(($pivot * $count) / 100); + $num_above = $count - $num_below; + + for ($i = $num_above; $i > 0; --$i) + { + $color[1] = (($i * 100) + (($num_above - $i) * $pivot)) / $num_above; + $results[] = $this->allocate($color, $mode); + } + + ++$num_below; + + for ($i = $num_below - 1; $i > 0; --$i) + { + $color[1] = ($i * $pivot) / $num_below;; + $results[] = $this->allocate($color, $mode); + } + + return $results; + + break; + + case 'value': + + $pivot = $color[2]; + $num_below = intval(($pivot * $count) / 100); + $num_above = $count - $num_below; + + for ($i = $num_above; $i > 0; --$i) + { + $color[2] = (($i * 100) + (($num_above - $i) * $pivot)) / $num_above; + $results[] = $this->allocate($color, $mode); + } + + ++$num_below; + + for ($i = $num_below - 1; $i > 0; --$i) + { + $color[2] = ($i * $pivot) / $num_below;; + $results[] = $this->allocate($color, $mode); + } + + return $results; + + break; + + case 'both': + + // This is a hard problem. I chicken out and do an even triangle + // the problem is that it disregards the original saturation and value, + // and as such a generated result might come arbitrarily close to our original value. + $length = ceil(sqrt($count * 2)); + for ($i = $length; $i > 0; --$i) + { + for ($j = $i; $j > 0; --$j) + { + $color[1] = ($i * 100) / $length; + $color[2] = ($j * 100) / $i; + $results[] = $this->allocate($color, $mode); + --$count; + if (!$count) + { + return $results; + } + } + } + + return $results; + + break; + } + + return false; + } + + function is_dark($resource) + { + $color = (($pre = $this->r($resource)) !== false) ? $this->colors[$pre] : $this->colors[$resource]; + switch($this->mode) + { + case 'ahsv': + case 'hsv': + + return ($color[2] <= 50); + + break; + + case 'rgb': + + return (max($color[0], $color[1], $color[2]) <= 128); + + break; + } + return false; + } + + /** + * Convert from one color model to another + * + * note: properly following coding standards here yields unweildly amounts of whitespace, rendering this less than easily readable + * + */ + function model_convert($color, $from_model, $to_model) + { + if ($from_model == $to_model) + { + return $color; + } + switch ($to_model) + { + case 'hsv': + switch($from_model) + { + case 'ahsv': + return color_manager::ah2h($color); + break; + + case 'rgb': + return color_manager::rgb2hsv($color); + break; + } + break; + + case 'ahsv': + switch($from_model) + { + case 'hsv': + return color_manager::h2ah($color); + break; + + case 'rgb': + return color_manager::h2ah(color_manager::rgb2hsv($color)); + break; + } + break; + + case 'rgb': + switch($from_model) + { + case 'hsv': + return color_manager::hsv2rgb($color); + break; + + case 'ahsv': + return color_manager::hsv2rgb(color_manager::ah2h($color)); + break; + } + break; + } + return false; + } + + /** + * Slightly altered from wikipedia's algorithm + */ + function hsv2rgb($hsv) + { + color_manager::normalize_hue($hsv[0]); + $h = $hsv[0]; + $s = min(1, max(0, $hsv[1] / 100)); + $v = min(1, max(0, $hsv[2] / 100)); + + $hi = floor($hsv[0] / 60); // calculate hue sector + + $p = $v * (1 - $s); // calculate opposite color + $f = ($h / 60) - $hi; // calculate distance between hex vertices + if (!($hi & 1)) // coming in or going out? + { + $f = 1 - $f; + } + $q = $v * (1 - ($f * $s)); // calculate adjacent color + + 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); + $h = $max - $min; // if max - min is 0, we want hue to be 0 anyway. + 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; + } + } + color_manager::normalize_hue($h); + return array($h, $s * 100, $v * 100); + } + + /** + * Bleh + */ + function normalize_hue(&$hue) + { + $hue %= 360; + if ($hue < 0) + { + $hue += 360; + } + } + + /** + * Alternate hue to hue + */ + function ah2h($ahue) + { + if (is_array($ahue)) + { + $ahue[0] = color_manager::ah2h($ahue[0]); + return $ahue; + } + color_manager::normalize_hue($ahue); + if ($ahue >= 240) // blue through red is already ok + { + return $ahue; + } + if ($ahue >= 180) // ahue green is at 180 + { + // return (240 - (2 * (240 - $ahue))); + return (2 * $ahue) - 240; // equivalent + } + if ($ahue >= 120) // ahue yellow is at 120 (RYB rather than RGB) + { + return $ahue - 60; + } + return $ahue / 2; + } + + /** + * hue to Alternate hue + */ + function h2ah($hue) + { + if (is_array($hue)) + { + $hue[0] = color_manager::h2ah($hue[0]); + return $hue; + } + color_manager::normalize_hue($hue); + if ($hue >= 240) // blue through red is already ok + { + return $hue; + } + else if ($hue <= 60) + { + return $hue * 2; + } + else if ($hue <= 120) + { + return $hue + 60; + } + else + { + return ($hue + 240) / 2; + } + } +} + +function vector_distance(&$char, $x, $y, $range = 0.1) +{ + $distance = $range + 1; + foreach ($char AS $vector) + { + $d = $range + 1; + switch ($vector[0]) + { + case 'arc': + + $dx = $x - $vector[1]; + $dy = -($y - $vector[2]); //because our arcs are upside-down.... + if (abs($dx) > abs($dy)) + { + $phi = rad2deg(atan(($dy * $vector[3])/($dx * $vector[4]))); + $phi += ($dx < 0) ? 180 : 360; + $phi %= 360; + } + else + { + $phi = 90 - rad2deg(atan(($dx * $vector[4])/($dy * $vector[3]))); + $phi += ($dy < 0) ? 180 : 360; + $phi %= 360; + } + + $internal = $vector[6] > $vector[5]; //external wraps over the 360 point + $low = $phi >= $vector[5]; //phi is above our low range + $high = $phi <= $vector[6]; //phi is below our high range. + if ($internal ? ($low && $high) : ($low || $high)) //if it wraps, it can only be one or the other + { + $radphi = deg2rad($phi); // i'm awesome. or not. + $px = cos($radphi) * 0.5 * $vector[3]; + $py = sin($radphi) * 0.5 * $vector[4]; + $d = sqrt(pow($px - $dx, 2) + pow($py - $dy, 2)); + } + + break; + + case 'line': + + $bx = $x - $vector[1]; + $by = $y - $vector[2]; + $dx = cos($vector[5]); + $dy = sin($vector[5]); + $r = ($by * $dx) - ($bx * $dy); + if ($r < $range && $r > -$range) + { + if (abs($dx) > abs($dy)) + { + $s = (($bx + ($dy * $r)) / $dx); + } + else + { + $s = (($by + ($dx * $r)) / $dy); + } + if ($s > -$range) + { + if ($s < 0) + { + $d = sqrt(pow($s, 2) + pow($r, 2)); + } + elseif ($s < $vector[6]) + { + $d = $r; + } + elseif ($s < $vector[6] + $range) + { + $d = sqrt(pow($s - $vector[6], 2) + pow($r, 2)); + } + } + } + + break; + } + $distance = min($distance, abs($d)); + } + return $distance; +} ?>
\ No newline at end of file diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index 5bf505243b..61016b5b31 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -31,14 +31,15 @@ define('USER_FOUNDER', 3); //define('USER_GUEST', 4); // ACL -define('ACL_NO', 0); +define('ACL_NEVER', 0); define('ACL_YES', 1); -define('ACL_UNSET', -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); @@ -135,8 +136,8 @@ define('FIELD_DATE', 6); // Table names define('ACL_GROUPS_TABLE', $table_prefix . 'acl_groups'); define('ACL_OPTIONS_TABLE', $table_prefix . 'acl_options'); -define('ACL_ROLES_TABLE', $table_prefix . 'acl_roles'); 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'); @@ -145,10 +146,6 @@ 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('PROFILE_FIELDS_TABLE', $table_prefix . 'profile_fields'); -define('PROFILE_LANG_TABLE', $table_prefix . 'profile_lang'); -define('PROFILE_FIELDS_DATA_TABLE', $table_prefix . 'profile_fields_data'); -define('PROFILE_FIELDS_LANG_TABLE', $table_prefix . 'profile_fields_lang'); define('DISALLOW_TABLE', $table_prefix . 'disallow'); define('DRAFTS_TABLE', $table_prefix . 'drafts'); define('EXTENSIONS_TABLE', $table_prefix . 'extensions'); @@ -163,11 +160,17 @@ 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_TO_TABLE', $table_prefix . 'privmsgs_to'); 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('RATINGS_TABLE', $table_prefix . 'ratings'); define('REPORTS_TABLE', $table_prefix . 'reports'); @@ -186,15 +189,13 @@ define('STYLES_THEME_TABLE', $table_prefix . 'styles_theme'); define('STYLES_IMAGESET_TABLE', $table_prefix . 'styles_imageset'); define('TOPICS_TABLE', $table_prefix . 'topics'); define('TOPICS_POSTED_TABLE', $table_prefix . 'topics_posted'); -define('TOPICS_WATCH_TABLE', $table_prefix . 'topics_watch'); 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('USERS_NOTES_TABLE', $table_prefix . 'users_notes'); define('WARNINGS_TABLE', $table_prefix . 'warnings'); define('WORDS_TABLE', $table_prefix . 'words'); -define('POLL_OPTIONS_TABLE', $table_prefix . 'poll_options'); -define('POLL_VOTES_TABLE', $table_prefix . 'poll_votes'); define('ZEBRA_TABLE', $table_prefix . 'zebra'); // Additional tables diff --git a/phpBB/includes/db/dbal.php b/phpBB/includes/db/dbal.php index ecfe71f1ef..f774b5dcc3 100644 --- a/phpBB/includes/db/dbal.php +++ b/phpBB/includes/db/dbal.php @@ -177,8 +177,6 @@ class dbal * Idea for this from Ikonboard * Possible query values: INSERT, INSERT_SELECT, MULTI_INSERT, UPDATE, SELECT * - * If a key is 'module_name' and firebird used it gets adjusted to '"module_name"' - * on INSERT, INSERT_SELECT, UPDATE and SELECT */ function sql_build_array($query, $assoc_ary = false) { @@ -193,24 +191,16 @@ class dbal { foreach ($assoc_ary as $key => $var) { - $fields[] = ($key == 'module_name' && SQL_LAYER == 'firebird') ? '"' . $key . '"' : $key; + $fields[] = $key; - if (is_null($var)) - { - $values[] = 'NULL'; - } - else if (is_string($var)) - { - $values[] = "'" . $this->sql_escape($var) . "'"; - } - else if (is_array($var) && is_string($var[0])) + if (is_array($var) && is_string($var[0])) { // This is used for INSERT_SELECT(s) $values[] = $var[0]; } else { - $values[] = (is_bool($var)) ? intval($var) : $var; + $values[] = $this->_sql_validate_value($var); } } @@ -224,18 +214,7 @@ class dbal $values = array(); foreach ($sql_ary as $key => $var) { - if (is_null($var)) - { - $values[] = 'NULL'; - } - else if (is_string($var)) - { - $values[] = "'" . $this->sql_escape($var) . "'"; - } - else - { - $values[] = (is_bool($var)) ? intval($var) : $var; - } + $values[] = $this->_sql_validate_value($var); } $ary[] = '(' . implode(', ', $values) . ')'; } @@ -247,20 +226,7 @@ class dbal $values = array(); foreach ($assoc_ary as $key => $var) { - $key = ($key == 'module_name' && SQL_LAYER == 'firebird') ? '"' . $key . '"' : $key; - - if (is_null($var)) - { - $values[] = "$key = NULL"; - } - else if (is_string($var)) - { - $values[] = "$key = '" . $this->sql_escape($var) . "'"; - } - else - { - $values[] = (is_bool($var)) ? "$key = " . intval($var) : "$key = $var"; - } + $values[] = "$key = " . $this->_sql_validate_value($var); } $query = implode(($query == 'UPDATE') ? ', ' : ' AND ', $values); } @@ -268,6 +234,49 @@ class dbal return $query; } + function sql_in_set($field, $array, $negate = false) + { + if (!sizeof($array)) + { + trigger_error('No values specified for SQL IN comparison', E_USER_ERROR); + } + + $values = array(); + foreach ($array as $var) + { + $values[] = $this->_sql_validate_value($var); + } + + if (sizeof($values) == 1) + { + return $field . ($negate ? ' <> ' : ' = ') . $values[0]; + } + else + { + return $field . ($negate ? ' NOT IN ' : ' IN ' ) . '(' . implode(', ', $values) . ')'; + } + } + + /** + * 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 * @@ -286,7 +295,17 @@ class dbal $table_array = array(); foreach ($array['FROM'] as $table_name => $alias) { - $table_array[] = $table_name . ' ' . $alias; + if (is_array($alias)) + { + foreach ($alias as $multi_alias) + { + $table_array[] = $table_name . ' ' . $multi_alias; + } + } + else + { + $table_array[] = $table_name . ' ' . $alias; + } } $sql .= $this->_sql_custom_build('FROM', implode(', ', $table_array)); @@ -355,7 +374,7 @@ class dbal // 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 persist.'; + $message .= '<br /><br />An sql error occurred while fetching this page. Please contact an administrator if this problem persists.'; } else { diff --git a/phpBB/includes/db/firebird.php b/phpBB/includes/db/firebird.php index d5a91fe9bb..7ea5dd3612 100644 --- a/phpBB/includes/db/firebird.php +++ b/phpBB/includes/db/firebird.php @@ -22,7 +22,7 @@ if (!defined('SQL_LAYER')) { define('SQL_LAYER', 'firebird'); - include($phpbb_root_path . 'includes/db/dbal.' . $phpEx); + include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); /** * Firebird/Interbase Database Abstraction Layer @@ -32,6 +32,7 @@ if (!defined('SQL_LAYER')) class dbal_firebird extends dbal { var $last_query_text = ''; + var $service_handle = false; /** * Connect to server @@ -45,10 +46,25 @@ class dbal_firebird extends dbal $this->db_connect_id = ($this->persistency) ? @ibase_pconnect($this->server . ':' . $this->dbname, $this->user, $sqlpassword, false, false, 3) : @ibase_connect($this->server . ':' . $this->dbname, $this->user, $sqlpassword, false, false, 3); + $this->service_handle = (function_exists('ibase_service_attach')) ? @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 + */ + function sql_server_info() + { + if ($this->service_handle !== false && function_exists('ibase_server_info')) + { + return @ibase_server_info($this->service_handle, IBASE_SVC_SERVER_VERSION); + } + + return 'Firebird/Interbase'; + } + + /** * SQL Transaction * @access: private */ @@ -74,6 +90,12 @@ class dbal_firebird extends dbal /** * 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) { @@ -94,7 +116,14 @@ class dbal_firebird extends dbal if (!$this->transaction) { - @ibase_commit_ret(); + if (function_exists('ibase_commit_ret')) + { + @ibase_commit_ret(); + } + else + { + @ibase_commit(); + } } if ($cache_ttl && method_exists($cache, 'sql_save')) @@ -141,6 +170,18 @@ class dbal_firebird extends dbal */ function sql_numrows($query_id = false) { + global $cache; + + if (!$query_id) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_numrows($query_id); + } + return false; } @@ -199,6 +240,8 @@ class dbal_firebird extends dbal */ function sql_fetchfield($field, $rownum = false, $query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; @@ -211,6 +254,11 @@ class dbal_firebird extends dbal $this->sql_rowseek($rownum, $query_id); } + if (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; } @@ -224,11 +272,18 @@ class dbal_firebird extends dbal */ function sql_rowseek($rownum, $query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; } + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_rowseek($query_id, $rownum); + } + // 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++) { @@ -274,11 +329,18 @@ class dbal_firebird extends dbal */ function sql_freeresult($query_id = false) { + global $cache; + if (!$query_id) { $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]); @@ -323,6 +385,11 @@ class dbal_firebird extends dbal */ function _sql_close() { + if ($this->service_handle !== false) + { + @ibase_service_detach($this->service_handle); + } + return @ibase_close($this->db_connect_id); } diff --git a/phpBB/includes/db/mssql.php b/phpBB/includes/db/mssql.php index cc4de3695a..fe6cf75b12 100644 --- a/phpBB/includes/db/mssql.php +++ b/phpBB/includes/db/mssql.php @@ -22,7 +22,7 @@ if (!defined('SQL_LAYER')) { define('SQL_LAYER', 'mssql'); - include($phpbb_root_path . 'includes/db/dbal.' . $phpEx); + include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); /** * MSSQL Database Abstraction Layer @@ -56,6 +56,28 @@ class dbal_mssql extends dbal } /** + * Version information about used database + */ + function sql_server_info() + { + $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); + } + + if ($row) + { + return 'MSSQL<br />' . implode(' ', $row); + } + + return 'MSSQL'; + } + + /** * SQL Transaction * @access: private */ @@ -81,6 +103,12 @@ class dbal_mssql extends dbal /** * 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) { @@ -181,11 +209,18 @@ class dbal_mssql extends dbal */ function sql_numrows($query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; } + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_numrows($query_id); + } + return ($query_id) ? @mssql_num_rows($query_id) : false; } @@ -234,6 +269,8 @@ class dbal_mssql extends dbal */ function sql_fetchfield($field, $rownum = false, $query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; @@ -246,6 +283,11 @@ class dbal_mssql extends dbal $this->sql_rowseek($rownum, $query_id); } + if (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; } @@ -259,11 +301,18 @@ class dbal_mssql extends dbal */ function sql_rowseek($rownum, $query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; } + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_rowseek($query_id, $rownum); + } + return ($query_id) ? @mssql_data_seek($query_id, $rownum) : false; } @@ -291,11 +340,18 @@ class dbal_mssql extends dbal */ function sql_freeresult($query_id = false) { + global $cache; + if (!$query_id) { $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]); diff --git a/phpBB/includes/db/mssql_odbc.php b/phpBB/includes/db/mssql_odbc.php index 658251ea2a..e1b2675a23 100644 --- a/phpBB/includes/db/mssql_odbc.php +++ b/phpBB/includes/db/mssql_odbc.php @@ -22,7 +22,7 @@ if (!defined('SQL_LAYER')) { define('SQL_LAYER', 'mssql_odbc'); - include($phpbb_root_path . 'includes/db/dbal.' . $phpEx); + include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); /** * Unified ODBC functions @@ -50,6 +50,28 @@ class dbal_mssql_odbc extends dbal } /** + * Version information about used database + */ + function sql_server_info() + { + $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); + } + + if ($row) + { + return 'MSSQL (ODBC)<br />' . implode(' ', $row); + } + + return 'MSSQL (ODBC)'; + } + + /** * SQL Transaction * @access: private */ @@ -79,6 +101,12 @@ class dbal_mssql_odbc extends dbal /** * 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) { @@ -183,11 +211,18 @@ class dbal_mssql_odbc extends dbal */ function sql_numrows($query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; } + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_numrows($query_id); + } + return ($query_id) ? @odbc_num_rows($query_id) : false; } @@ -225,6 +260,8 @@ class dbal_mssql_odbc extends dbal */ function sql_fetchfield($field, $rownum = false, $query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; @@ -237,6 +274,11 @@ class dbal_mssql_odbc extends dbal $this->sql_rowseek($rownum, $query_id); } + if (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; } @@ -250,11 +292,18 @@ class dbal_mssql_odbc extends dbal */ function sql_rowseek($rownum, $query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; } + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_rowseek($query_id, $rownum); + } + $this->sql_freeresult($query_id); $query_id = $this->sql_query($this->last_query_text); @@ -301,11 +350,18 @@ class dbal_mssql_odbc extends dbal */ function sql_freeresult($query_id = false) { + global $cache; + if (!$query_id) { $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]); diff --git a/phpBB/includes/db/mysql.php b/phpBB/includes/db/mysql.php index fd7e10a822..7e363721a9 100644 --- a/phpBB/includes/db/mysql.php +++ b/phpBB/includes/db/mysql.php @@ -22,7 +22,7 @@ if (!defined('SQL_LAYER')) { define('SQL_LAYER', 'mysql'); - include($phpbb_root_path . 'includes/db/dbal.' . $phpEx); + include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); /** * MySQL Database Abstraction Layer @@ -56,6 +56,14 @@ class dbal_mysql extends dbal } /** + * Version information about used database + */ + function sql_server_info() + { + return 'MySQL ' . @mysql_get_server_info($this->db_connect_id); + } + + /** * SQL Transaction * @access: private */ @@ -81,6 +89,12 @@ class dbal_mysql extends dbal /** * 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) { @@ -163,11 +177,18 @@ class dbal_mysql extends dbal */ function sql_numrows($query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; } + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_numrows($query_id); + } + return ($query_id) ? @mysql_num_rows($query_id) : false; } @@ -205,6 +226,8 @@ class dbal_mysql extends dbal */ function sql_fetchfield($field, $rownum = false, $query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; @@ -214,11 +237,22 @@ class dbal_mysql extends dbal { if ($rownum === false) { + if (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; } else { + if (isset($cache->sql_rowset[$query_id])) + { + $cache->sql_rowseek($query_id, $rownum); + return $cache->sql_fetchfield($query_id, $field); + } + return @mysql_result($query_id, $rownum, $field); } } @@ -232,11 +266,18 @@ class dbal_mysql extends dbal */ function sql_rowseek($rownum, $query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; } + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_rowseek($query_id, $rownum); + } + return ($query_id) ? @mysql_data_seek($query_id, $rownum) : false; } @@ -253,11 +294,18 @@ class dbal_mysql extends dbal */ function sql_freeresult($query_id = false) { + global $cache; + if (!$query_id) { $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]); diff --git a/phpBB/includes/db/mysql4.php b/phpBB/includes/db/mysql4.php index 13271d9346..071f4c4b55 100644 --- a/phpBB/includes/db/mysql4.php +++ b/phpBB/includes/db/mysql4.php @@ -22,7 +22,7 @@ if (!defined('SQL_LAYER')) { define('SQL_LAYER', 'mysql4'); - include($phpbb_root_path . 'includes/db/dbal.' . $phpEx); + include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); /** * MySQL4 Database Abstraction Layer @@ -58,6 +58,14 @@ class dbal_mysql4 extends dbal } /** + * Version information about used database + */ + function sql_server_info() + { + return 'MySQL ' . @mysql_get_server_info($this->db_connect_id); + } + + /** * SQL Transaction * @access: private */ @@ -83,6 +91,12 @@ class dbal_mysql4 extends dbal /** * 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) { @@ -166,11 +180,18 @@ class dbal_mysql4 extends dbal */ function sql_numrows($query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; } + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_numrows($query_id); + } + return ($query_id) ? @mysql_num_rows($query_id) : false; } @@ -208,6 +229,8 @@ class dbal_mysql4 extends dbal */ function sql_fetchfield($field, $rownum = false, $query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; @@ -217,11 +240,22 @@ class dbal_mysql4 extends dbal { if ($rownum === false) { + if (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; } else { + if (isset($cache->sql_rowset[$query_id])) + { + $cache->sql_rowseek($query_id, $rownum); + return $cache->sql_fetchfield($query_id, $field); + } + return @mysql_result($query_id, $rownum, $field); } } @@ -235,11 +269,18 @@ class dbal_mysql4 extends dbal */ function sql_rowseek($rownum, $query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; } + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_rowseek($query_id, $rownum); + } + return ($query_id) ? @mysql_data_seek($query_id, $rownum) : false; } @@ -256,11 +297,18 @@ class dbal_mysql4 extends dbal */ function sql_freeresult($query_id = false) { + global $cache; + if (!$query_id) { $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]); diff --git a/phpBB/includes/db/mysqli.php b/phpBB/includes/db/mysqli.php index b93bf98c1a..fa4d3ffdc7 100644 --- a/phpBB/includes/db/mysqli.php +++ b/phpBB/includes/db/mysqli.php @@ -22,7 +22,7 @@ if (!defined('SQL_LAYER')) { define('SQL_LAYER', 'mysqli'); - include($phpbb_root_path . 'includes/db/dbal.' . $phpEx); + include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); /** * MySQLi Database Abstraction Layer @@ -58,6 +58,14 @@ class dbal_mysqli extends dbal } /** + * Version information about used database + */ + function sql_server_info() + { + return 'MySQL(i) ' . @mysqli_get_server_info($this->db_connect_id); + } + + /** * SQL Transaction * @access: private */ @@ -87,6 +95,12 @@ class dbal_mysqli extends dbal /** * 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) { @@ -165,11 +179,18 @@ class dbal_mysqli extends dbal */ function sql_numrows($query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; } + if (!is_object($query_id) && isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_numrows($query_id); + } + return ($query_id) ? @mysqli_num_rows($query_id) : false; } @@ -207,6 +228,8 @@ class dbal_mysqli extends dbal */ function sql_fetchfield($field, $rownum = false, $query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; @@ -219,6 +242,11 @@ class dbal_mysqli extends dbal $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; } @@ -232,11 +260,18 @@ class dbal_mysqli extends dbal */ function sql_rowseek($rownum, $query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; } + if (!is_object($query_id) && isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_rowseek($query_id, $rownum); + } + return ($query_id) ? @mysqli_data_seek($query_id, $rownum) : false; } @@ -253,18 +288,19 @@ class dbal_mysqli extends dbal */ function sql_freeresult($query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; } - // Make sure it is not a cached query - if (is_object($this->query_result)) + if (!is_object($query_id) && isset($cache->sql_rowset[$query_id])) { - return @mysqli_free_result($query_id); + return $cache->sql_freeresult($query_id); } - return false; + return @mysqli_free_result($query_id); } /** diff --git a/phpBB/includes/db/oracle.php b/phpBB/includes/db/oracle.php index 464e6ad9de..fc5bf6f78e 100644 --- a/phpBB/includes/db/oracle.php +++ b/phpBB/includes/db/oracle.php @@ -22,7 +22,7 @@ if(!defined('SQL_LAYER')) { define('SQL_LAYER', 'oracle'); - include($phpbb_root_path . 'includes/db/dbal.' . $phpEx); + include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); /** * Oracle Database Abstraction Layer @@ -48,6 +48,14 @@ class dbal_oracle extends dbal } /** + * Version information about used database + */ + function sql_server_info() + { + return 'Oracle ' . @ociserverversion($this->db_connect_id); + } + + /** * SQL Transaction * @access: private */ @@ -73,6 +81,12 @@ class dbal_oracle extends dbal /** * 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) { @@ -155,6 +169,52 @@ class dbal_oracle extends dbal { $this->query_result = false; + // Any implicit columns exist? + if (strpos($query, '.*') !== false) + { + // This sucker does a few things for us. It grabs all the explicitly named columns and what tables are being used + preg_match('/SELECT (?:DISTINCT )?(.*?)FROM(.*?)(?:WHERE|(ORDER|GROUP) BY|$)/s', $query, $tables); + + // The prefixes of the explicit columns don't matter, they simply get in the way + preg_match_all('/\.(\w+)/', trim($tables[1]), $columns); + + // Flip lets us do an easy isset() call + $columns = array_flip($columns[1]); + + $table_data = trim($tables[2]); + + // Grab the implicitly named columns, they need expanding... + preg_match_all('/(\w)\.\*/', $query, $info); + + $cols = array(); + + foreach ($info[1] as $table_alias) + { + // We need to get the name of the aliased table + preg_match('/(\w+) ' . $table_alias . '/', $table_data, $table_name); + $table_name = $table_name[1]; + + $sql = "SELECT column_name + FROM all_tab_cols + WHERE table_name = '" . strtoupper($table_name) . "'"; + + $result = $this->sql_query($sql); + while ($row = $this->sql_fetchrow($result)) + { + if (!isset($columns[strtolower($row['column_name'])])) + { + $cols[] = $table_alias . '.' . strtolower($row['column_name']); + } + } + $this->sql_freeresult($result); + + // Remove the implicity .* with it's full expansion + $query = str_replace($table_alias . '.*', implode(', ', $cols), $query); + + unset($cols); + } + } + $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); @@ -171,11 +231,18 @@ class dbal_oracle extends dbal */ function sql_numrows($query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; } + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_numrows($query_id); + } + $result = @ocifetchstatement($query_id, $this->rowset); // OCIFetchStatment kills our query result so we have to execute the statment again @@ -224,7 +291,7 @@ class dbal_oracle extends dbal // OCI->CLOB? if (is_object($value)) { - $value = ($value->size()) ? $value->read($value->size()) : ''; + $value = $value->load(); } $result_row[strtolower($key)] = $value; @@ -239,6 +306,8 @@ class dbal_oracle extends dbal */ function sql_fetchfield($field, $rownum = false, $query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; @@ -251,6 +320,11 @@ class dbal_oracle extends dbal $this->sql_rowseek($rownum, $query_id); } + if (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; } @@ -264,11 +338,18 @@ class dbal_oracle extends dbal */ function sql_rowseek($rownum, $query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; } + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_rowseek($query_id, $rownum); + } + if (!$query_id) { return false; @@ -326,11 +407,18 @@ class dbal_oracle extends dbal */ function sql_freeresult($query_id = false) { + global $cache; + if (!$query_id) { $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]); diff --git a/phpBB/includes/db/postgres.php b/phpBB/includes/db/postgres.php index ad8e0a01da..1836952346 100644 --- a/phpBB/includes/db/postgres.php +++ b/phpBB/includes/db/postgres.php @@ -22,7 +22,7 @@ if (!defined('SQL_LAYER')) { define('SQL_LAYER', 'postgres'); - include($phpbb_root_path . 'includes/db/dbal.' . $phpEx); + include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); /** * PostgreSQL Database Abstraction Layer @@ -85,6 +85,25 @@ class dbal_postgres extends dbal } /** + * Version information about used database + */ + function sql_server_info() + { + if (version_compare(phpversion(), '5.0.0', '>=')) + { + $version = @pg_version($this->db_connect_id); + return 'PostgreSQL' . ((!empty($version)) ? ' ' . $version['client'] : ''); + } + else + { + $query_id = @pg_query($this->db_connect_id, 'select version()'); + $row = @pg_fetch_assoc($query_id, null); + $version = $row['version']; + return ((!empty($version)) ? ' ' . $version : ''); + } + } + + /** * SQL Transaction * @access: private */ @@ -110,6 +129,12 @@ class dbal_postgres extends dbal /** * 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) { @@ -202,11 +227,18 @@ class dbal_postgres extends dbal */ function sql_numrows($query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; } + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_numrows($query_id); + } + return ($query_id) ? @pg_num_rows($query_id) : false; } @@ -235,7 +267,16 @@ class dbal_postgres extends dbal return $cache->sql_fetchrow($query_id); } - return ($query_id) ? @pg_fetch_assoc($query_id, NULL) : false; + $row = @pg_fetch_assoc($query_id, null); + if ($row) + { + foreach ($row as $key => $value) + { + $row[$key] = (strpos($key, 'bitfield') === false) ? $value : pg_unescape_bytea($value); + } + } + + return ($query_id) ? $row : false; } /** @@ -244,6 +285,8 @@ class dbal_postgres extends dbal */ function sql_fetchfield($field, $rownum = false, $query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; @@ -256,6 +299,11 @@ class dbal_postgres extends dbal $this->sql_rowseek($rownum, $query_id); } + if (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; } @@ -269,11 +317,18 @@ class dbal_postgres extends dbal */ function sql_rowseek($rownum, $query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; } + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_rowseek($query_id, $rownum); + } + return ($query_id) ? @pg_result_seek($query_id, $rownum) : false; } @@ -311,11 +366,18 @@ class dbal_postgres extends dbal */ function sql_freeresult($query_id = false) { + global $cache; + if (!$query_id) { $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]); diff --git a/phpBB/includes/db/sqlite.php b/phpBB/includes/db/sqlite.php index 87d9af8c7f..cd6d40e3c7 100644 --- a/phpBB/includes/db/sqlite.php +++ b/phpBB/includes/db/sqlite.php @@ -22,10 +22,11 @@ if (!defined('SQL_LAYER')) { define('SQL_LAYER', 'sqlite'); - include($phpbb_root_path . 'includes/db/dbal.' . $phpEx); + 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 @@ -47,11 +48,20 @@ class dbal_sqlite extends dbal { @sqlite_query('PRAGMA short_column_names = 1', $this->db_connect_id); } + return ($this->db_connect_id) ? true : array('message' => $error); } /** + * Version information about used database + */ + function sql_server_info() + { + return 'SQLite ' . @sqlite_libversion(); + } + + /** * SQL Transaction * @access: private */ @@ -77,6 +87,12 @@ class dbal_sqlite extends dbal /** * 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) { @@ -159,11 +175,18 @@ class dbal_sqlite extends dbal */ function sql_numrows($query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; } + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_numrows($query_id); + } + return ($query_id) ? @sqlite_num_rows($query_id) : false; } @@ -192,7 +215,9 @@ class dbal_sqlite extends dbal return $cache->sql_fetchrow($query_id); } - return ($query_id) ? @sqlite_fetch_array($query_id, SQLITE_ASSOC) : false; + $row = @sqlite_fetch_array($query_id, SQLITE_ASSOC); + + return $row; } /** @@ -201,6 +226,8 @@ class dbal_sqlite extends dbal */ function sql_fetchfield($field, $rownum = false, $query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; @@ -208,15 +235,17 @@ class dbal_sqlite extends dbal if ($query_id) { - if ($rownum === false) + if ($rownum !== false) { - return @sqlite_column($query_id, $field); + $this->sql_rowseek($rownum, $query_id); } - else + + if (isset($cache->sql_rowset[$query_id])) { - $this->sql_rowseek($rownum, $query_id); - return @sqlite_column($query_id, $field); + return $cache->sql_fetchfield($query_id, $field); } + + return @sqlite_column($query_id, $field); } return false; @@ -228,11 +257,18 @@ class dbal_sqlite extends dbal */ function sql_rowseek($rownum, $query_id = false) { + global $cache; + if (!$query_id) { $query_id = $this->query_result; } + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_rowseek($query_id, $rownum); + } + return ($query_id) ? @sqlite_seek($query_id, $rownum) : false; } @@ -249,6 +285,18 @@ class dbal_sqlite extends dbal */ function sql_freeresult($query_id = false) { + global $cache; + + if (!$query_id) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_freeresult($query_id); + } + return true; } diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 7b36c36548..48fec2d795 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -145,7 +145,7 @@ function unique_id($extra = 'c') if ($dss_seeded !== true) { - set_config('rand_seed', $config['rand_seed']); + set_config('rand_seed', $config['rand_seed'], true); $dss_seeded = true; } @@ -376,6 +376,71 @@ if (!function_exists('stripos')) } } +if (!function_exists('realpath')) +{ + /** + * Replacement for realpath if it is disabled + * This function is from the php manual by nospam at savvior dot com + */ + function phpbb_realpath($path) + { + $translated_path = getenv('PATH_TRANSLATED'); + + $translated_path = str_replace('\\', '/', $translated_path); + $translated_path = str_replace(basename(getenv('PATH_INFO')), '', $translated_path); + + $translated_path .= '/'; + + if ($path == '.' || $path == './') + { + return $translated_path; + } + + // now check for back directory + $translated_path .= $path; + + $dirs = explode('/', $translated_path); + + foreach ($dirs as $key => $value) + { + if ($value == '..') + { + $dirs[$key] = ''; + $dirs[$key - 2] = ''; + } + } + + $translated_path = ''; + + foreach ($dirs as $key => $value) + { + if (strlen($value) > 0) + { + $translated_path .= $value . '/'; + } + } + + $translated_path = substr($translated_path, 0, strlen($translated_path) - 1); + + if (is_dir($translated_path) || is_file($translated_path)) + { + return $translated_path; + } + + return false; + } +} +else +{ + /** + * A wrapper for realpath + */ + function phpbb_realpath($path) + { + return realpath($path); + } +} + // functions used for building option fields /** @@ -429,13 +494,18 @@ function style_select($default = '', $all = false) /** * Pick a timezone */ -function tz_select($default = '') +function tz_select($default = '', $truncate = false) { global $sys_timezone, $user; $tz_select = ''; foreach ($user->lang['tz_zones'] as $offset => $zone) { + if ($truncate) + { + $zone = (strlen($zone) > 70) ? substr($zone, 0, 70) . '...' : $zone; + } + if (is_numeric($offset)) { $selected = ($offset == $default) ? ' selected="selected"' : ''; @@ -469,7 +539,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ $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 + 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) ? unserialize($tracking_topics) : array(); @@ -506,13 +576,13 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ { $sql = 'DELETE FROM ' . TOPICS_TRACK_TABLE . " WHERE user_id = {$user->data['user_id']} - AND forum_id IN (" . implode(', ', $forum_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 forum_id IN (" . implode(', ', $forum_id) . ')'; + AND " . $db->sql_in_set('forum_id', $forum_id); $result = $db->sql_query($sql); $sql_update = array(); @@ -527,7 +597,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ $sql = 'UPDATE ' . FORUMS_TRACK_TABLE . ' SET mark_time = ' . time() . " WHERE user_id = {$user->data['user_id']} - AND forum_id IN (" . implode(', ', $sql_update) . ')'; + AND " . $db->sql_in_set('forum_id', $sql_update); $db->sql_query($sql); } @@ -563,7 +633,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ } } } - else + 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) ? unserialize($tracking) : array(); @@ -628,7 +698,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ $db->sql_return_on_error(false); } } - else + 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) ? unserialize($tracking) : array(); @@ -675,7 +745,8 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ if ($user->data['is_registered']) { - $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_lastmark = ' . intval(base_convert(max($time_keys) + $config['board_startdate'], 36, 10)) . " WHERE user_id = {$user->data['user_id']}"); + $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 { @@ -817,7 +888,7 @@ function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_lis $sql = 'SELECT topic_id, mark_time FROM ' . TOPICS_TRACK_TABLE . " WHERE user_id = {$user->data['user_id']} - AND topic_id IN (" . implode(', ', $topic_ids) . ")"; + AND " . $db->sql_in_set('topic_id', $topic_ids); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -859,7 +930,7 @@ function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_lis } } } - else + else if ($config['load_anon_lastread'] || $user->data['is_registered']) { global $tracking_topics; @@ -925,6 +996,111 @@ function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_lis return $last_read; } +/** +* Check for read forums and update topic tracking info accordingly +* +* @param int $forum_id the forum id to check +* @param int $forum_last_post_time the forums last post time +* @param int $f_mark_time the forums last mark time if user is registered and load_db_lastread enabled +* @param int $mark_time_forum false if the mark time needs to be obtained, else the last users forum mark time +* +*/ +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']) + { + 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) ? 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 + 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 (!in_array(base_convert($row['topic_id'], 10, 36), array_keys($check_forum))) + { + $unread = true; + break; + } + } + $db->sql_freeresult($result); + + $row = $unread; + } + } + else + { + $row = true; + } + + if (!$row) + { + markread('topics', $forum_id); + } +} + // Pagination functions /** @@ -1095,8 +1271,6 @@ function generate_board_url($without_script_path = false) $server_name = (!empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : getenv('SERVER_NAME'); $server_port = (!empty($_SERVER['SERVER_PORT'])) ? (int) $_SERVER['SERVER_PORT'] : (int) getenv('SERVER_PORT'); - $url = (($config['cookie_secure']) ? 'https://' : 'http://') . $server_name; - // Forcing server vars is the only way to specify/override the protocol if ($config['force_server_vars'] || !$server_name) { @@ -1106,6 +1280,12 @@ function generate_board_url($without_script_path = false) $url = $server_protocol . $server_name; } + 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; + } if ($server_port && (($config['cookie_secure'] && $server_port <> 443) || (!$config['cookie_secure'] && $server_port <> 80))) { @@ -1128,15 +1308,12 @@ function redirect($url) { global $db, $cache, $config, $user; - if (isset($db)) + if (empty($user->lang)) { - $db->sql_close(); + $user->add_lang('common'); } - if (isset($cache)) - { - $cache->unload(); - } + garbage_collection(); // Make sure no &'s are in, this will break the redirect $url = str_replace('&', '&', $url); @@ -1184,8 +1361,8 @@ function redirect($url) else { // Get the realpath of dirname - $root_dirs = explode('/', str_replace('\\', '/', realpath('./'))); - $page_dirs = explode('/', str_replace('\\', '/', realpath($pathinfo['dirname']))); + $root_dirs = explode('/', str_replace('\\', '/', phpbb_realpath('./'))); + $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); @@ -1445,13 +1622,17 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa if ($admin && !$auth->acl_get('a_')) { // Not authd - add_log('admin', 'LOG_ADMIN_AUTH_FAIL'); + // 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'])) { - $username = request_var('username', '', true); + $username = request_var('username', ''); $password = request_var('password', ''); $autologin = (!empty($_POST['autologin'])) ? true : false; $viewonline = (!empty($_POST['viewonline'])) ? 0 : 1; @@ -1478,7 +1659,12 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa } else { - add_log('admin', 'LOG_ADMIN_AUTH_FAIL'); + // 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'); + } } } @@ -1496,12 +1682,6 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa trigger_error($message . '<br /><br />' . sprintf($l_redirect, '<a href="' . $redirect . '">', '</a>')); } - // The user wanted to re-authenticate, but something failed - log this - if ($admin) - { - add_log('admin', 'LOG_ADMIN_AUTH_FAIL'); - } - // Something failed, determine what... if ($result['status'] == LOGIN_BREAK) { @@ -1625,13 +1805,13 @@ function login_forum_box($forum_data) $sql_in = array(); do { - $sql_in[] = "'" . $db->sql_escape($row['session_id']) . "'"; + $sql_in[] = (string) $row['session_id']; } while ($row = $db->sql_fetchrow($result)); // Remove expired sessions $sql = 'DELETE FROM ' . FORUMS_ACCESS_TABLE . ' - WHERE session_id NOT IN (' . implode(', ', $sql_in) . ')'; + WHERE ' . $db->sql_in_set('session_id', $sql_in, true); $db->sql_query($sql); } $db->sql_freeresult($result); @@ -1737,7 +1917,7 @@ function decode_message(&$message, $bbcode_uid = '') * 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) +function generate_text_for_display($text, $uid, $bitfield, $flags) { global $__bbcode; @@ -1746,13 +1926,6 @@ function generate_text_for_display($text, $uid, $bitfield) return ''; } - // Get flags... they are always allow_bbcode, allow_smilies and allow_urls - $flags = $bitfield; - if ($flags >> 3) - { - $flags = bindec(substr(decbin($flags), strlen(decbin($flags >> 3)))); - } - // Parse bbcode if bbcode uid stored and bbcode enabled if ($uid && ($flags & 1)) { @@ -1764,11 +1937,11 @@ function generate_text_for_display($text, $uid, $bitfield) if (empty($__bbcode)) { - $__bbcode = new bbcode($bitfield >> 3); + $__bbcode = new bbcode($bitfield); } else { - $__bbcode->bbcode($bitfield >> 3); + $__bbcode->bbcode($bitfield); } $__bbcode->bbcode_second_pass($text, $uid); @@ -1785,12 +1958,12 @@ function generate_text_for_display($text, $uid, $bitfield) * 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, $allow_bbcode = false, $allow_urls = false, $allow_smilies = false) +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 = 0; + $bitfield = ''; if (!$text) { @@ -1815,7 +1988,7 @@ function generate_text_for_storage(&$text, &$uid, &$bitfield, $allow_bbcode = fa } $flags = (($allow_bbcode) ? 1 : 0) + (($allow_smilies) ? 2 : 0) + (($allow_urls) ? 4 : 0); - $bitfield = $flags + ($message_parser->bbcode_bitfield << 3); + $bitfield = $message_parser->bbcode_bitfield; return; } @@ -1824,17 +1997,10 @@ function generate_text_for_storage(&$text, &$uid, &$bitfield, $allow_bbcode = fa * 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, $bitfield) +function generate_text_for_edit($text, $uid, $flags) { global $phpbb_root_path, $phpEx; - // Get forum flags... - $flags = $bitfield; - if ($flags >> 3) - { - $flags = bindec(substr(decbin($flags), strlen(decbin($flags >> 3)))); - } - decode_message($text, $uid); return array( @@ -1880,7 +2046,7 @@ function make_clickable($text, $server_url = false) $magic_url_replace[] = "'\$1<!-- w --><a href=\"http://\$2\" target=\"_blank\">' . ((strlen('\$2') > 55) ? substr(str_replace('&', '&', '\$2'), 0, 39) . ' ... ' . substr(str_replace('&', '&', '\$2'), -10) : '\$2') . '</a><!-- w -->'"; // 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 ]|\()([a-z0-9&\-_.]+?@[\w\-]+\.(?:[\w\-\.]+\.)?[\w]+)#ie'; + $magic_url_match[] = '/(^|[\n ]|\()(' . get_preg_expression('email') . ')/ie'; $magic_url_replace[] = "'\$1<!-- e --><a href=\"mailto:\$2\">' . ((strlen('\$2') > 55) ? substr('\$2', 0, 39) . ' ... ' . substr('\$2', -10) : '\$2') . '</a><!-- e -->'"; } @@ -2000,25 +2166,40 @@ function extension_allowed($forum_id, $extension, &$extensions) // Little helpers /** +* Little helper for the build_hidden_fields function +*/ +function _build_hidden_fields($key, $value, $specialchar) +{ + $hidden_fields = ''; + + if (!is_array($value)) + { + $key = ($specialchar) ? htmlspecialchars($key) : $key; + $value = ($specialchar) ? htmlspecialchars($value) : $value; + + $hidden_fields .= '<input type="hidden" name="' . $key . '" value="' . $value . '" />' . "\n"; + } + else + { + foreach ($value as $_key => $_value) + { + $hidden_fields .= _build_hidden_fields($key . '[' . $_key . ']', $_value, $specialchar); + } + } + + return $hidden_fields; +} + +/** * Build simple hidden fields from array */ -function build_hidden_fields($field_ary) +function build_hidden_fields($field_ary, $specialchar = false) { $s_hidden_fields = ''; foreach ($field_ary as $name => $vars) { - if (is_array($vars)) - { - foreach ($vars as $key => $value) - { - $s_hidden_fields .= '<input type="hidden" name="' . $name . '[' . $key . ']" value="' . $value . '" />'; - } - } - else - { - $s_hidden_fields .= '<input type="hidden" name="' . $name . '" value="' . $vars . '" />'; - } + $s_hidden_fields .= _build_hidden_fields($name, $vars, $specialchar); } return $s_hidden_fields; @@ -2139,7 +2320,7 @@ function get_backtrace() $output = '<div style="font-family: monospace;">'; $backtrace = debug_backtrace(); - $path = realpath($phpbb_root_path); + $path = phpbb_realpath($phpbb_root_path); foreach ($backtrace as $number => $trace) { @@ -2184,6 +2365,58 @@ function get_backtrace() return $output; } +/** +* This function returns a regular expression pattern for commonly used expressions +* Use with / as delimiter +* mode can be: email| +*/ +function get_preg_expression($mode) +{ + switch ($mode) + { + case 'email': + return '[a-z0-9&\'\.\-_\+]+@[a-z0-9\-]+\.([a-z0-9\-]+\.)*?[a-z]+'; + break; + } + + return ''; +} + +/** +* Truncates string while retaining special characters if going over the max length +* The default max length is 60 at the moment +*/ +function truncate_string($string, $max_length = 60) +{ + $chars = array(); + + // split the multibyte characters first + $string_ary = preg_split('#(&\#[0-9]+;)#', $string, -1, PREG_SPLIT_DELIM_CAPTURE); + + // Now go through the array and split the other characters + foreach ($string_ary as $key => $value) + { + if (strpos($value, '&#') === 0) + { + $chars[] = $value; + continue; + } + + // decode html entities and put them back later + $_chars = str_split(html_entity_decode($value)); + $chars = array_merge($chars, array_map('htmlspecialchars', $_chars)); + } + + // Now check the length ;) + if (sizeof($chars) <= $max_length) + { + return $string; + } + + // Cut off the last elements from the array + return implode('', array_slice($chars, 0, $max_length)); +} + // Handler, header and footer /** @@ -2221,8 +2454,8 @@ function msg_handler($errno, $msg_text, $errfile, $errline) if (strpos($errfile, 'cache') === false && strpos($errfile, 'template.') === false) { // remove complete path to installation, with the risk of changing backslashes meant to be there - $errfile = str_replace(array(realpath($phpbb_root_path), '\\'), array('', '/'), $errfile); - $msg_text = str_replace(array(realpath($phpbb_root_path), '\\'), array('', '/'), $msg_text); + $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"; } @@ -2232,16 +2465,8 @@ function msg_handler($errno, $msg_text, $errfile, $errline) case E_USER_ERROR: - if (isset($db)) - { - $db->sql_close(); - } + garbage_collection(); - if (isset($cache)) - { - $cache->unload(); - } - 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>'; @@ -2390,7 +2615,15 @@ function page_header($page_title = '', $display_online_list = true) if (!empty($_REQUEST['f'])) { $f = request_var('f', 0); - $reading_sql = " AND s.session_page LIKE '%f=$f%'"; + + // Do not change this (it is defined as _f_={forum_id}x within session.php) + $reading_sql = " AND s.session_page LIKE '%\_f\_={$f}x%'"; + + // Specify escape character for MSSQL + if (SQL_LAYER == 'mssql' || SQL_LAYER == 'mssql_odbc') + { + $reading_sql .= " ESCAPE '\\'"; + } } // Get number of online guests @@ -2463,7 +2696,7 @@ function page_header($page_title = '', $display_online_list = true) if (!$online_userlist) { - $online_userlist = $user->lang['NONE']; + $online_userlist = $user->lang['NO_ONLINE_USERS']; } if (empty($_REQUEST['f'])) @@ -2616,7 +2849,9 @@ function page_header($page_title = '', $display_online_list = true) 'U_RESTORE_PERMISSIONS' => ($user->data['user_perm_from'] && $auth->acl_get('a_switchperm')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=restore_perm') : '', 'S_USER_LOGGED_IN' => ($user->data['user_id'] != ANONYMOUS) ? true : false, + 'S_BOARD_DISABLED' => ($config['board_disable'] && !defined('IN_LOGIN') && $auth->acl_gets('a_', 'm_')) ? true : false, 'S_REGISTERED_USER' => $user->data['is_registered'], + 'S_IS_BOT' => $user->data['is_bot'], 'S_USER_PM_POPUP' => $user->optionget('popuppm'), 'S_USER_LANG' => $user->data['user_lang'], 'S_USER_BROWSER' => (isset($user->data['session_browser'])) ? $user->data['session_browser'] : $user->lang['UNKNOWN_BROWSER'], @@ -2653,7 +2888,7 @@ function page_header($page_title = '', $display_online_list = true) { header('Content-type: text/html; charset=' . $user->lang['ENCODING']); } - header('Cache-Control: private, no-cache="set-cookie", pre-check=0, post-check=0'); + header('Cache-Control: private, no-cache="set-cookie"'); header('Expires: 0'); header('Pragma: no-cache'); @@ -2726,7 +2961,6 @@ function page_footer() else if (time() - $config['database_gc'] > $config['database_last_gc']) { // Tidy the database - // This includes recalculation binary trees, ... $cron_type = 'tidy_database'; } else if (time() - $config['search_gc'] > $config['search_last_gc']) @@ -2770,4 +3004,101 @@ function garbage_collection() $db->sql_close(); } +/** +*/ +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 (!isset($this->data[$byte])) + { + // Of course, if it doesn't exist then the result if FALSE + return false; + } + + $c = $this->data[$byte]; + + // Lookup the ($n % 8)th bit of the byte + $bit = 7 - ($n & 7); + return (bool) (ord($c) & (1 << $bit)); + } + + function set($n) + { + $byte = $n >> 3; + $bit = 7 - ($n & 7); + + if (isset($this->data[$byte])) + { + $this->data[$byte] = $this->data[$byte] | chr(1 << $bit); + } + else + { + if ($byte - strlen($this->data) > 0) + { + $this->data .= str_repeat("\0", $byte - strlen($this->data)); + } + $this->data .= chr(1 << $bit); + } + } + + function clear($n) + { + $byte = $n >> 3; + + if (!isset($this->data[$byte])) + { + return; + } + + $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_admin.php b/phpBB/includes/functions_admin.php index a83e34e09a..307044b9a0 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -10,16 +10,10 @@ /** * Recalculate Binary Tree -*/ function recalc_btree($sql_id, $sql_table, $module_class = '') { global $db; - /* Init table, id's, etc... - $sql_id = 'module_id'; // 'forum_id' - $sql_table = MODULES_TABLE; // FORUMS_TABLE - */ - if (!$sql_id || !$sql_table) { return; @@ -103,15 +97,16 @@ function recalc_btree($sql_id, $sql_table, $module_class = '') } $db->sql_freeresult($f_result); } +*/ /** * Simple version of jumpbox, just lists authed forums */ -function make_forum_select($select_id = false, $ignore_id = false, $ignore_acl = false, $ignore_nonpost = false, $ignore_emptycat = true, $return_array = false) +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) ? '' : array('f_list', 'a_forum', 'a_forumadd', 'a_forumdel'); + $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, parent_id, forum_name, forum_type, forum_status, left_id, right_id @@ -211,8 +206,8 @@ function group_select_options($group_id, $exclude_ids = false) { global $db, $user, $config; - $exclude_sql = ($exclude_ids !== false && sizeof($exclude_ids)) ? 'WHERE group_id NOT IN (' . implode(', ', array_map('intval', $exclude_ids)) . ')' : ''; - $sql_and = ($config['coppa_hide_groups']) ? (($exclude_sql) ? ' AND ' : ' WHERE ') . "group_name NOT IN ('INACTIVE_COPPA', 'REGISTERED_COPPA')" : ''; + $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 NOT IN ('INACTIVE_COPPA', 'REGISTERED_COPPA')" : ''; $sql = 'SELECT group_id, group_name, group_type FROM ' . GROUPS_TABLE . " @@ -245,7 +240,7 @@ function get_forum_list($acl_list = 'f_list', $id_only = true, $postable_only = // This query is identical to the jumpbox one $expire_time = ($no_cache) ? 0 : 120; - $sql = 'SELECT forum_id, parent_id, forum_name, forum_type, left_id, right_id + $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); @@ -361,7 +356,7 @@ function filelist($rootdir, $dir = '', $type = 'gif|jpg|jpeg|png') return $matches; } -/* +/** * Move topic(s) */ function move_topics($topic_ids, $forum_id, $auto_sync = true) @@ -381,7 +376,7 @@ function move_topics($topic_ids, $forum_id, $auto_sync = true) } $sql = 'DELETE FROM ' . TOPICS_TABLE . ' - WHERE topic_moved_id IN (' . implode(', ', $topic_ids) . ') + WHERE ' . $db->sql_in_set('topic_moved_id', $topic_ids) . ' AND forum_id = ' . $forum_id; $db->sql_query($sql); @@ -389,7 +384,7 @@ function move_topics($topic_ids, $forum_id, $auto_sync = true) { $sql = 'SELECT DISTINCT forum_id FROM ' . TOPICS_TABLE . ' - WHERE topic_id ' . $sql_where; + WHERE ' . $db->sql_in_set('topic_id', $topic_ids); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -404,7 +399,7 @@ function move_topics($topic_ids, $forum_id, $auto_sync = true) { $sql = "UPDATE $table SET forum_id = $forum_id - WHERE topic_id IN (" . implode(', ', $topic_ids) . ')'; + WHERE " . $db->sql_in_set('topic_id', $topic_ids); $db->sql_query($sql); } unset($table_ary); @@ -433,7 +428,7 @@ function move_posts($post_ids, $topic_id, $auto_sync = true) $sql = 'SELECT DISTINCT topic_id, forum_id FROM ' . POSTS_TABLE . ' - WHERE post_id IN (' . implode(', ', $post_ids) . ')'; + WHERE ' . $db->sql_in_set('post_id', $post_ids); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -457,12 +452,12 @@ function move_posts($post_ids, $topic_id, $auto_sync = true) $sql = 'UPDATE ' . POSTS_TABLE . ' SET forum_id = ' . $forum_row['forum_id'] . ", topic_id = $topic_id - WHERE post_id IN (" . implode(', ', $post_ids) . ')'; + 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 post_msg_id IN (" . implode(', ', $post_ids) . ')'; + WHERE " . $db->sql_in_set('post_msg_id', $post_ids); $db->sql_query($sql); if ($auto_sync) @@ -470,6 +465,7 @@ function move_posts($post_ids, $topic_id, $auto_sync = true) $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); } @@ -483,7 +479,7 @@ function move_posts($post_ids, $topic_id, $auto_sync = true) */ function delete_topics($where_type, $where_ids, $auto_sync = true) { - global $db; + global $db, $config; $forum_ids = $topic_ids = array(); @@ -491,6 +487,10 @@ function delete_topics($where_type, $where_ids, $auto_sync = true) { $where_ids = array_unique($where_ids); } + else + { + $where_ids = array($where_ids); + } if (!sizeof($where_ids)) { @@ -498,12 +498,12 @@ function delete_topics($where_type, $where_ids, $auto_sync = true) } $return = array( - 'posts' => delete_posts($where_type, $where_ids, false, false) + 'posts' => delete_posts($where_type, $where_ids, false, true) ); $sql = 'SELECT topic_id, forum_id - FROM ' . TOPICS_TABLE . " - WHERE $where_type " . ((!is_array($where_ids)) ? "= $where_ids" : 'IN (' . implode(', ', $where_ids) . ')'); + FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set($where_type, $where_ids); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -520,8 +520,6 @@ function delete_topics($where_type, $where_ids, $auto_sync = true) return $return; } - $sql_where = ' IN (' . implode(', ', $topic_ids) . ')'; - $db->sql_transaction('begin'); $table_ary = array(TOPICS_TRACK_TABLE, TOPICS_POSTED_TABLE, POLL_VOTES_TABLE, POLL_OPTIONS_TABLE, TOPICS_WATCH_TABLE, TOPICS_TABLE); @@ -529,13 +527,13 @@ function delete_topics($where_type, $where_ids, $auto_sync = true) foreach ($table_ary as $table) { $sql = "DELETE FROM $table - WHERE topic_id $sql_where"; + WHERE " . $db->sql_in_set('topic_id', $topic_ids); $db->sql_query($sql); } unset($table_ary); $sql = 'DELETE FROM ' . TOPICS_TABLE . ' - WHERE topic_moved_id' . $sql_where; + WHERE ' . $db->sql_in_set('topic_moved_id', $topic_ids); $db->sql_query($sql); $db->sql_transaction('commit'); @@ -546,6 +544,8 @@ function delete_topics($where_type, $where_ids, $auto_sync = true) sync('topic_reported', $where_type, $where_ids); } + set_config('num_topics', $config['num_topics'] - sizeof($return['topics']), true); + return $return; } @@ -560,17 +560,21 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = { $where_ids = array_unique($where_ids); } + else + { + $where_ids = array($where_ids); + } - if (empty($where_ids)) + if (!sizeof($where_ids)) { return false; } - $post_ids = $topic_ids = $forum_ids = array(); + $post_ids = $topic_ids = $forum_ids = $post_counts = array(); - $sql = 'SELECT post_id, poster_id, topic_id, forum_id - FROM ' . POSTS_TABLE . " - WHERE $where_type " . ((!is_array($where_ids)) ? '= ' . (int) $where_ids : 'IN (' . implode(', ', array_map('intval', $where_ids)) . ')'); + $sql = 'SELECT post_id, poster_id, post_postcount, topic_id, forum_id + FROM ' . POSTS_TABLE . ' + WHERE ' . $db->sql_in_set($where_type, array_map('intval', $where_ids)); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -579,6 +583,11 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = $poster_ids[] = $row['poster_id']; $topic_ids[] = $row['topic_id']; $forum_ids[] = $row['forum_id']; + + if ($row['post_postcount']) + { + $post_counts[$row['poster_id']] = (!empty($post_counts[$row['poster_id']])) ? $post_counts[$row['poster_id']] + 1 : 1; + } } $db->sql_freeresult($result); @@ -587,8 +596,6 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = return false; } - $sql_where = implode(', ', $post_ids); - $db->sql_transaction('begin'); $table_ary = array(POSTS_TABLE, REPORTS_TABLE); @@ -596,11 +603,23 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = foreach ($table_ary as $table) { $sql = "DELETE FROM $table - WHERE post_id IN ($sql_where)"; + WHERE " . $db->sql_in_set('post_id', $post_ids); $db->sql_query($sql); } unset($table_ary); + // Adjust users post counts + if (sizeof($post_counts)) + { + foreach ($post_counts as $poster_id => $substract) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_posts = user_posts - ' . $substract . ' + WHERE user_id = ' . $poster_id; + $db->sql_query($sql); + } + } + // Remove the message from the search index $search_type = basename($config['search_type']); @@ -619,7 +638,7 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = trigger_error($error); } - $search->index_remove($post_ids, $poster_ids); + $search->index_remove($post_ids, $poster_ids, $forum_ids); delete_attachments('post', $post_ids, false); @@ -638,6 +657,8 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = sync('forum', 'forum_id', $forum_ids, true); } + set_config('num_posts', $config['num_posts'] - sizeof($post_ids), true); + return sizeof($post_ids); } @@ -676,7 +697,7 @@ function delete_attachments($mode, $ids, $resync = true) { $sql = 'SELECT post_msg_id as post_id, topic_id, physical_filename, thumbnail, filesize FROM ' . ATTACHMENTS_TABLE . ' - WHERE ' . $sql_id . ' IN (' . implode(', ', $ids) . ')'; + WHERE ' . $db->sql_in_set($sql_id, $ids); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -692,7 +713,7 @@ function delete_attachments($mode, $ids, $resync = true) { $sql = 'SELECT topic_id, physical_filename, thumbnail, filesize FROM ' . ATTACHMENTS_TABLE . ' - WHERE post_msg_id IN (' . implode(', ', $ids) . ') + WHERE ' . $db->sql_in_set('post_msg_id', $ids) . ' AND in_message = 0'; $result = $db->sql_query($sql); @@ -706,7 +727,7 @@ function delete_attachments($mode, $ids, $resync = true) // Delete attachments $sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . ' - WHERE ' . $sql_id . ' IN (' . implode(', ', $ids) . ')'; + WHERE ' . $db->sql_in_set($sql_id, $ids); $db->sql_query($sql); $num_deleted = $db->sql_affectedrows(); @@ -754,7 +775,7 @@ function delete_attachments($mode, $ids, $resync = true) { $sql = 'UPDATE ' . POSTS_TABLE . ' SET post_attachment = 0 - WHERE post_id IN (' . implode(', ', $post_ids) . ')'; + WHERE ' . $db->sql_in_set('post_id', $post_ids); $db->sql_query($sql); } @@ -764,7 +785,7 @@ function delete_attachments($mode, $ids, $resync = true) $sql = 'SELECT post_msg_id FROM ' . ATTACHMENTS_TABLE . ' - WHERE post_msg_id IN (' . implode(', ', $post_ids) . ') + WHERE ' . $db->sql_in_set('post_msg_id', $post_ids) . ' AND in_message = 0'; $result = $db->sql_query($sql); @@ -780,7 +801,7 @@ function delete_attachments($mode, $ids, $resync = true) { $sql = 'UPDATE ' . POSTS_TABLE . ' SET post_attachment = 0 - WHERE post_id IN (' . implode(', ', $unset_ids) . ')'; + WHERE ' . $db->sql_in_set('post_id', $unset_ids); $db->sql_query($sql); } @@ -788,7 +809,7 @@ function delete_attachments($mode, $ids, $resync = true) $sql = 'SELECT post_msg_id FROM ' . ATTACHMENTS_TABLE . ' - WHERE post_msg_id IN (' . implode(', ', $post_ids) . ') + WHERE ' . $db->sql_in_set('post_msg_id', $post_ids) . ' AND in_message = 1'; $result = $db->sql_query($sql); @@ -804,7 +825,7 @@ function delete_attachments($mode, $ids, $resync = true) { $sql = 'UPDATE ' . PRIVMSGS_TABLE . ' SET message_attachment = 0 - WHERE msg_id IN (' . implode(', ', $unset_ids) . ')'; + WHERE ' . $db->sql_in_set('msg_id', $unset_ids); $db->sql_query($sql); } } @@ -817,7 +838,7 @@ function delete_attachments($mode, $ids, $resync = true) { $sql = 'UPDATE ' . TOPICS_TABLE . ' SET topic_attachment = 0 - WHERE topic_id IN (' . implode(', ', $topic_ids) . ')'; + WHERE ' . $db->sql_in_set('topic_id', $topic_ids); $db->sql_query($sql); } @@ -827,7 +848,7 @@ function delete_attachments($mode, $ids, $resync = true) $sql = 'SELECT topic_id FROM ' . ATTACHMENTS_TABLE . ' - WHERE topic_id IN (' . implode(', ', $topic_ids) . ')'; + WHERE ' . $db->sql_in_set('topic_id', $topic_ids); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -842,7 +863,7 @@ function delete_attachments($mode, $ids, $resync = true) { $sql = 'UPDATE ' . TOPICS_TABLE . ' SET topic_attachment = 0 - WHERE topic_id IN (' . implode(', ', $unset_ids) . ')'; + WHERE ' . $db->sql_in_set('topic_id', $unset_ids); $db->sql_query($sql); } } @@ -856,7 +877,7 @@ function delete_attachments($mode, $ids, $resync = true) */ function delete_topic_shadows($max_age, $forum_id = '', $auto_sync = true) { - $where = (is_array($forum_id)) ? 'AND t.forum_id IN (' . implode(', ', array_map('intval', $forum_id)) . ')' : (($forum_id) ? 'AND t.forum_id = ' . (int) $forum_id : ''); + $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 (SQL_LAYER) { @@ -888,7 +909,7 @@ function delete_topic_shadows($max_age, $forum_id = '', $auto_sync = true) if (sizeof($topic_ids)) { $sql = 'DELETE FROM ' . TOPICS_TABLE . ' - WHERE topic_id IN (' . implode(',', $topic_ids) . ')'; + WHERE ' . $db->sql_in_set('topic_id', $topic_ids); $db->sql_query($sql); } break; @@ -915,13 +936,13 @@ function update_posted_info(&$topic_ids) // First of all, let us remove any posted information for these topics $sql = 'DELETE FROM ' . TOPICS_POSTED_TABLE . ' - WHERE topic_id IN (' . implode(', ', $topic_ids) . ')'; + 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 topic_id IN (' . implode(', ', $topic_ids) . ') + WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . ' AND poster_id <> ' . ANONYMOUS . ' GROUP BY poster_id, topic_id'; $result = $db->sql_query($sql); @@ -1041,7 +1062,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, // 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 ' . $mode{0} . ".$where_type IN (" . implode(', ', $where_ids) . ')'; + $where_sql = 'WHERE ' . $db->sql_in_set($mode{0} . '.' . $where_type, $where_ids); $where_sql_and = $where_sql . "\n\tAND"; } } @@ -1053,7 +1074,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, } // $where_type contains the field for the where clause (forum_id, topic_id) - $where_sql = 'WHERE ' . $mode{0} . ".$where_type IN (" . implode(', ', $where_ids) . ')'; + $where_sql = 'WHERE ' . $db->sql_in_set($mode{0} . '.' . $where_type, $where_ids); $where_sql_and = $where_sql . "\n\tAND"; } @@ -1091,7 +1112,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, } $sql = 'DELETE FROM ' . TOPICS_TABLE . ' - WHERE topic_id IN (' . implode(', ', $topic_id_ary) . ')'; + WHERE ' . $db->sql_in_set('topic_id', $topic_id_ary); $db->sql_query($sql); break; @@ -1130,7 +1151,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, $sql = 'UPDATE ' . TOPICS_TABLE . ' SET topic_approved = 1 - topic_approved - WHERE topic_id IN (' . implode(', ', $topic_ids) . ')'; + WHERE ' . $db->sql_in_set('topic_id', $topic_ids); $db->sql_query($sql); break; } @@ -1157,7 +1178,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, $sql = 'SELECT DISTINCT(post_id) FROM ' . REPORTS_TABLE . ' - WHERE post_id IN (' . implode(', ', $post_ids) . ') + WHERE ' . $db->sql_in_set('post_id', $post_ids) . ' AND report_closed = 0'; $result = $db->sql_query($sql); @@ -1186,7 +1207,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, { $sql = 'UPDATE ' . POSTS_TABLE . ' SET post_reported = 1 - post_reported - WHERE post_id IN (' . implode(', ', $post_ids) . ')'; + WHERE ' . $db->sql_in_set('post_id', $post_ids); $db->sql_query($sql); } break; @@ -1228,7 +1249,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, { $sql = 'UPDATE ' . TOPICS_TABLE . ' SET topic_reported = 1 - topic_reported - WHERE topic_id IN (' . implode(', ', $topic_ids) . ')'; + WHERE ' . $db->sql_in_set('topic_id', $topic_ids); $db->sql_query($sql); } break; @@ -1254,7 +1275,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, $sql = 'SELECT DISTINCT(post_msg_id) FROM ' . ATTACHMENTS_TABLE . ' - WHERE post_msg_id IN (' . implode(', ', $post_ids) . ') + WHERE ' . $db->sql_in_set('post_msg_id', $post_ids) . ' AND in_message = 0'; $result = $db->sql_query($sql); @@ -1283,7 +1304,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, { $sql = 'UPDATE ' . POSTS_TABLE . ' SET post_attachment = 1 - post_attachment - WHERE post_id IN (' . implode(', ', $post_ids) . ')'; + WHERE ' . $db->sql_in_set('post_id', $post_ids); $db->sql_query($sql); } break; @@ -1325,7 +1346,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, { $sql = 'UPDATE ' . TOPICS_TABLE . ' SET topic_attachment = 1 - topic_attachment - WHERE topic_id IN (' . implode(', ', $topic_ids) . ')'; + WHERE ' . $db->sql_in_set('topic_id', $topic_ids); $db->sql_query($sql); } break; @@ -1360,10 +1381,15 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, } $db->sql_freeresult($result); + if (!sizeof($forum_ids)) + { + break; + } + // 2: Get topic counts for each forum $sql = 'SELECT forum_id, topic_approved, COUNT(topic_id) AS forum_topics FROM ' . TOPICS_TABLE . ' - WHERE forum_id IN (' . implode(', ', $forum_ids) . ') + WHERE ' . $db->sql_in_set('forum_id', $forum_ids) . ' GROUP BY forum_id, topic_approved'; $result = $db->sql_query($sql); @@ -1382,7 +1408,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, // 3: Get post count and last_post_id for each forum $sql = 'SELECT forum_id, COUNT(post_id) AS forum_posts, MAX(post_id) AS last_post_id FROM ' . POSTS_TABLE . ' - WHERE forum_id IN (' . implode(', ', $forum_ids) . ') + WHERE ' . $db->sql_in_set('forum_id', $forum_ids) . ' AND post_approved = 1 GROUP BY forum_id'; $result = $db->sql_query($sql); @@ -1403,7 +1429,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, { $sql = 'SELECT p.post_id, p.poster_id, p.post_time, p.post_username, u.username FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u - WHERE p.post_id IN (' . implode(', ', $post_ids) . ') + WHERE ' . $db->sql_in_set('p.post_id', $post_ids) . ' AND p.poster_id = u.user_id'; $result = $db->sql_query($sql); @@ -1469,15 +1495,21 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, break; case 'topic': - $topic_data = $post_ids = $approved_unapproved_ids = $resync_forums = $delete_topics = $delete_posts = array(); + $topic_data = $post_ids = $approved_unapproved_ids = $resync_forums = $delete_topics = $delete_posts = $moved_topics = array(); - $sql = 'SELECT t.topic_id, t.forum_id, t.topic_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_last_post_id, t.topic_last_poster_id, t.topic_last_poster_name, t.topic_last_post_time + $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_last_post_id, t.topic_last_poster_id, t.topic_last_poster_name, 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; @@ -1581,9 +1613,34 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, unset($delete_topics, $delete_topic_ids); } + // 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); + } + $sql = 'SELECT p.post_id, p.topic_id, p.post_approved, p.poster_id, p.post_username, p.post_time, u.username FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u - WHERE p.post_id IN (' . implode(',', $post_ids) . ') + WHERE ' . $db->sql_in_set('p.post_id', $post_ids) . ' AND u.user_id = p.poster_id'; $result = $db->sql_query($sql); @@ -1617,7 +1674,7 @@ function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, { $sql = 'UPDATE ' . TOPICS_TABLE . ' SET topic_approved = 1 - topic_approved - WHERE topic_id IN (' . implode(', ', $approved_unapproved_ids) . ')'; + WHERE ' . $db->sql_in_set('topic_id', $approved_unapproved_ids); $db->sql_query($sql); } unset($approved_unapproved_ids); @@ -1704,9 +1761,18 @@ function prune($forum_id, $prune_mode, $prune_date, $prune_flags = 0, $auto_sync { global $db; - $sql_forum = (is_array($forum_id)) ? ' IN (' . implode(', ', array_map('intval', $forum_id)) . ')' : ' = ' . (int) $forum_id; + if (!is_array($forum_id)) + { + $forum_id = array($forum_id); + } + + if (!sizeof($forum_id)) + { + return; + } $sql_and = ''; + if (!($prune_flags & 4)) { $sql_and .= ' AND topic_type <> ' . POST_ANNOUNCE; @@ -1728,8 +1794,8 @@ function prune($forum_id, $prune_mode, $prune_date, $prune_flags = 0, $auto_sync } $sql = 'SELECT topic_id - FROM ' . TOPICS_TABLE . " - WHERE forum_id $sql_forum + FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_id) . " AND poll_start = 0 $sql_and"; $result = $db->sql_query($sql); @@ -1744,8 +1810,8 @@ function prune($forum_id, $prune_mode, $prune_date, $prune_flags = 0, $auto_sync if ($prune_flags & 2) { $sql = 'SELECT topic_id - FROM ' . TOPICS_TABLE . " - WHERE forum_id $sql_forum + FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_id) . " AND poll_start > 0 AND poll_last_vote < $prune_date $sql_and"; @@ -1879,7 +1945,7 @@ function cache_moderators() // Clear table $db->sql_query(((SQL_LAYER != 'sqlite') ? 'TRUNCATE TABLE ' : 'DELETE FROM ') . MODERATOR_CACHE_TABLE); - // We add moderators who have forum moderator permissions without an explicit ACL_NO setting + // 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... @@ -1909,12 +1975,13 @@ function cache_moderators() ), 'WHERE' => '(o.auth_option_id = a.auth_option_id OR o.auth_option_id = r.auth_option_id) - AND ((a.auth_setting = ' . ACL_NO . ' AND r.auth_setting IS NULL) - OR r.auth_setting = ' . ACL_NO . ') + 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 ug.user_id IN (' . implode(', ', $ug_id_ary) . ") + AND ' . $db->sql_in_set('ug.user_id', $ug_id_ary) . " AND ug.user_pending = 0 - AND o.auth_option LIKE 'm\_%'", + AND o.auth_option LIKE 'm\_%'" . + ((SQL_LAYER == 'mssql' || SQL_LAYER == 'mssql_odbc') ? " ESCAPE '\\'" : ''), )); $result = $db->sql_query($sql); @@ -1932,7 +1999,7 @@ function cache_moderators() // Get usernames... $sql = 'SELECT user_id, username FROM ' . USERS_TABLE . ' - WHERE user_id IN (' . implode(', ', array_keys($hold_ary)) . ')'; + WHERE ' . $db->sql_in_set('user_id', array_keys($hold_ary)); $result = $db->sql_query($sql); $usernames_ary = array(); @@ -1967,7 +2034,7 @@ function cache_moderators() // Make sure not hidden or special groups are involved... $sql = 'SELECT group_name, group_id, group_type FROM ' . GROUPS_TABLE . ' - WHERE group_id IN (' . implode(', ', $ug_id_ary) . ')'; + WHERE ' . $db->sql_in_set('group_id', $ug_id_ary); $result = $db->sql_query($sql); $groupnames_ary = array(); @@ -2060,7 +2127,7 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id } else if (is_array($forum_id)) { - $sql_forum = 'AND l.forum_id IN (' . implode(', ', array_map('intval', $forum_id)) . ')'; + $sql_forum = 'AND ' . $db->sql_in_set('l.forum_id', array_map('intval', $forum_id)); } else { @@ -2131,12 +2198,8 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id if (isset($user->lang[$row['log_operation']])) { - foreach ($log_data_ary as $log_data) - { - $log_data = str_replace("\n", '<br />', censor_text($log_data)); - - $log[$i]['action'] = preg_replace('#%s#', $log_data, $log[$i]['action'], 1); - } + $log[$i]['action'] = vsprintf($log[$i]['action'], $log_data_ary); + $log[$i]['action'] = str_replace("\n", '<br />', censor_text($log[$i]['action'])); } else { @@ -2156,7 +2219,7 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id // 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 topic_id IN (' . implode(', ', array_map('intval', $topic_id_list)) . ')'; + WHERE ' . $db->sql_in_set('topic_id', array_map('intval', $topic_id_list)); $result = $db->sql_query($sql); $default_forum_id = 0; @@ -2454,9 +2517,8 @@ function tidy_warnings() { $db->sql_transaction('begin'); - $sql_where = ' IN (' . implode(', ', $warning_list) . ')'; - $sql = 'DELETE FROM ' . WARNINGS_TABLE . " - WHERE warning_id $sql_where"; + $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) @@ -2479,20 +2541,7 @@ function tidy_database() { global $db; - // Recalculate binary tree for forums - recalc_btree('forum_id', FORUMS_TABLE); - - // Recalculate binary tree for modules - $sql = 'SELECT module_class - FROM ' . MODULES_TABLE . ' - GROUP BY module_class'; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - recalc_btree('module_id', MODULES_TABLE, $row['module_class']); - } - $db->sql_freeresult($result); set_config('database_last_gc', time(), true); } diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php index b095b3e286..f6b73afa0e 100644 --- a/phpBB/includes/functions_display.php +++ b/phpBB/includes/functions_display.php @@ -46,16 +46,16 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod // Display list of active topics for this category? $show_active = (isset($root_data['forum_flags']) && $root_data['forum_flags'] & 16) ? true : false; + $sql_from = FORUMS_TABLE . ' f '; + $lastread_select = $sql_lastread = ''; + if ($config['load_db_lastread'] && $user->data['is_registered']) { $sql_from = FORUMS_TABLE . ' f LEFT JOIN ' . FORUMS_TRACK_TABLE . ' ft ON (ft.user_id = ' . $user->data['user_id'] . ' AND ft.forum_id = f.forum_id)'; $lastread_select = ', ft.mark_time '; } - else + else if ($config['load_anon_lastread'] || $user->data['is_registered']) { - $sql_from = FORUMS_TABLE . ' f '; - $lastread_select = $sql_lastread = ''; - $tracking_topics = (isset($_COOKIE[$config['cookie_name'] . '_track'])) ? ((STRIP) ? stripslashes($_COOKIE[$config['cookie_name'] . '_track']) : $_COOKIE[$config['cookie_name'] . '_track']) : ''; $tracking_topics = ($tracking_topics) ? unserialize($tracking_topics) : array(); @@ -116,7 +116,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod { $forum_tracking_info[$forum_id] = (!empty($row['mark_time'])) ? $row['mark_time'] : $user->data['user_lastmark']; } - else + else if ($config['load_anon_lastread'] || $user->data['is_registered']) { if (!$user->data['is_registered']) { @@ -156,7 +156,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod $parent_id = $forum_id; $forum_rows[$forum_id] = $row; - if (!$row['parent_id'] && $row['forum_type'] == FORUM_CAT && $row['parent_id'] == $root_data['forum_id']) + if ($row['forum_type'] == FORUM_CAT && $row['parent_id'] == $root_data['forum_id']) { $branch_root_id = $forum_id; } @@ -228,13 +228,13 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod foreach ($forum_rows as $row) { // Empty category - if (!$row['parent_id'] && $row['forum_type'] == FORUM_CAT) + 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']), + 'FORUM_DESC' => generate_text_for_display($row['forum_desc'], $row['forum_desc_uid'], $row['forum_desc_bitfield'], $row['forum_desc_options']), 'FORUM_FOLDER_IMG' => ($row['forum_image']) ? '<img src="' . $phpbb_root_path . $row['forum_image'] . '" alt="' . $user->lang['FORUM_CAT'] . '" />' : '', 'FORUM_FOLDER_IMG_SRC' => ($row['forum_image']) ? $phpbb_root_path . $row['forum_image'] : '', 'U_VIEWFORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id'])) @@ -273,14 +273,14 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod } $l_subforums = (sizeof($subforums[$forum_id]) == 1) ? $user->lang['SUBFORUM'] . ': ' : $user->lang['SUBFORUMS'] . ': '; - $folder_image = ($forum_unread) ? 'sub_forum_new' : 'sub_forum'; + $folder_image = ($forum_unread) ? 'forum_unread_subforum' : 'forum_read_subforum'; } else { switch ($row['forum_type']) { case FORUM_POST: - $folder_image = ($forum_unread) ? 'forum_new' : 'forum'; + $folder_image = ($forum_unread) ? 'forum_unread' : 'forum_read'; break; case FORUM_LINK: @@ -292,7 +292,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod // Which folder should we display? if ($row['forum_status'] == ITEM_LOCKED) { - $folder_image = 'forum_locked'; + $folder_image = ($forum_unread) ? 'forum_unread_locked' : 'forum_read_locked'; $folder_alt = 'FORUM_LOCKED'; } else @@ -334,7 +334,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod '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']), + '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' => ($row['forum_image']) ? '<img src="' . $phpbb_root_path . $row['forum_image'] . '" alt="' . $user->lang[$folder_alt] . '" />' : $user->img($folder_image, $folder_alt), @@ -358,7 +358,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod 'U_MARK_FORUMS' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $root_data['forum_id'] . '&mark=forums'), 'S_HAS_SUBFORUM' => ($visible_forums) ? true : false, 'L_SUBFORUM' => ($visible_forums == 1) ? $user->lang['SUBFORUM'] : $user->lang['SUBFORUMS'], - 'LAST_POST_IMG' => $user->img('icon_post_latest', 'VIEW_LATEST_POST')) + 'LAST_POST_IMG' => $user->img('icon_topic_latest', 'VIEW_LATEST_POST')) ); if ($return_moderators) @@ -383,7 +383,7 @@ function generate_forum_rules(&$forum_data) 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'] = 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( @@ -443,7 +443,7 @@ function generate_forum_nav(&$forum_data) $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_DESC' => generate_text_for_display($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options'])) ); return; @@ -556,18 +556,22 @@ function get_moderators(&$forum_moderators, $forum_id = false) return; } - if ($forum_id !== false && is_array($forum_id)) + $forum_sql = ''; + + if ($forum_id !== false) { + if (!is_array($forum_id)) + { + $forum_id = array($forum_id); + } + // If we don't have a forum then we can't have a moderator if (!sizeof($forum_id)) { return; } - $forum_sql = 'AND forum_id IN (' . implode(', ', $forum_id) . ')'; - } - else - { - $forum_sql = ($forum_id !== false) ? 'AND forum_id = ' . $forum_id : ''; + + $forum_sql = 'AND ' . $db->sql_in_set('forum_id', $forum_id); } $sql = 'SELECT * @@ -626,7 +630,7 @@ function topic_status(&$topic_row, $replies, $unread_topic, &$folder_img, &$fold if ($topic_row['topic_status'] == ITEM_MOVED) { $topic_type = $user->lang['VIEW_TOPIC_MOVED']; - $folder_img = 'folder_moved'; + $folder_img = 'topic_moved'; $folder_alt = 'VIEW_TOPIC_MOVED'; } else @@ -634,28 +638,32 @@ function topic_status(&$topic_row, $replies, $unread_topic, &$folder_img, &$fold 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 = 'folder_announce'; - $folder_new = 'folder_announce_new'; + $folder = 'announce_read'; + $folder_new = 'announce_unread'; break; case POST_STICKY: $topic_type = $user->lang['VIEW_TOPIC_STICKY']; - $folder = 'folder_sticky'; - $folder_new = 'folder_sticky_new'; + $folder = 'sticky_read'; + $folder_new = 'sticky_unread'; break; default: - if ($replies >= $config['hot_threshold']) - { - $folder = 'folder_hot'; - $folder_new = 'folder_hot_new'; - } - else + $topic_type = ''; + $folder = 'topic_read'; + $folder_new = 'topic_unread'; + + if ($config['hot_threshold'] && $replies >= $config['hot_threshold']) { - $folder = 'folder'; - $folder_new = 'folder_new'; + $folder .= '_hot'; + $folder_new .= '_hot'; } break; } @@ -663,17 +671,18 @@ function topic_status(&$topic_row, $replies, $unread_topic, &$folder_img, &$fold if ($topic_row['topic_status'] == ITEM_LOCKED) { $topic_type = $user->lang['VIEW_TOPIC_LOCKED']; - $folder = 'folder_locked'; - $folder_new = 'folder_locked_new'; + $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 .= '_posted'; + $folder_img .= '_mine'; } } @@ -719,9 +728,9 @@ function display_attachments($forum_id, $blockname, &$attachment_data, &$update_ if (isset($extensions[$attachment['extension']])) { - if ($user->img('icon_attach', '') && !$extensions[$attachment['extension']]['upload_icon']) + if ($user->img('icon_topic_attach', '') && !$extensions[$attachment['extension']]['upload_icon']) { - $upload_icon = $user->img('icon_attach', ''); + $upload_icon = $user->img('icon_topic_attach', ''); } else if ($extensions[$attachment['extension']]['upload_icon']) { @@ -733,7 +742,7 @@ function display_attachments($forum_id, $blockname, &$attachment_data, &$update_ $size_lang = ($filesize >= 1048576) ? $user->lang['MB'] : ( ($filesize >= 1024) ? $user->lang['KB'] : $user->lang['BYTES'] ); $filesize = ($filesize >= 1048576) ? round((round($filesize / 1048576 * 100) / 100), 2) : (($filesize >= 1024) ? round((round($filesize / 1024 * 100) / 100), 2) : $filesize); - $comment = str_replace("\n", '<br />', censor_text($attachment['comment'])); + $comment = str_replace("\n", '<br />', censor_text($attachment['attach_comment'])); $block_array += array( 'UPLOAD_ICON' => $upload_icon, @@ -784,12 +793,13 @@ function display_attachments($forum_id, $blockname, &$attachment_data, &$update_ } } + $download_link = (!$force_physical && $attachment['attach_id']) ? append_sid("{$phpbb_root_path}download.$phpEx", 'id=' . $attachment['attach_id'] . '&f=' . $forum_id) : $filename; + switch ($display_cat) { // Images case ATTACHMENT_CATEGORY_IMAGE: $l_downloaded_viewed = $user->lang['VIEWED']; - $download_link = $filename; $block_array += array( 'S_IMAGE' => true, @@ -801,17 +811,24 @@ function display_attachments($forum_id, $blockname, &$attachment_data, &$update_ // Images, but display Thumbnail case ATTACHMENT_CATEGORY_THUMB: $l_downloaded_viewed = $user->lang['VIEWED']; - $download_link = (!$force_physical && $attachment['attach_id']) ? append_sid("{$phpbb_root_path}download.$phpEx", 'id=' . $attachment['attach_id']) : $filename; + $thumbnail_link = (!$force_physical && $attachment['attach_id']) ? append_sid("{$phpbb_root_path}download.$phpEx", 'id=' . $attachment['attach_id'] . '&t=1&f=' . $forum_id) : $thumbnail_filename; $block_array += array( 'S_THUMBNAIL' => true, - 'THUMB_IMAGE' => $thumbnail_filename, + 'THUMB_IMAGE' => $thumbnail_link, ); break; // Windows Media Streams case ATTACHMENT_CATEGORY_WM: $l_downloaded_viewed = $user->lang['VIEWED']; + + // The download link is slightly different, because somehow phpBB is not able to get the correct results if called + // within the wmp object (cookies are not present). + // $download_link = (!$force_physical && $attachment['attach_id']) ? generate_board_url() . append_sid("/download.$phpEx", 'id=' . $attachment['attach_id'] . '&f=' . $forum_id, false, $user->session_id) : $filename; + + // 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( @@ -825,7 +842,6 @@ function display_attachments($forum_id, $blockname, &$attachment_data, &$update_ // Real Media Streams case ATTACHMENT_CATEGORY_RM: $l_downloaded_viewed = $user->lang['VIEWED']; - $download_link = $filename; $block_array += array( 'S_RM_FILE' => true, @@ -856,7 +872,6 @@ function display_attachments($forum_id, $blockname, &$attachment_data, &$update_ */ default: $l_downloaded_viewed = $user->lang['DOWNLOADED']; - $download_link = (!$force_physical && $attachment['attach_id']) ? append_sid("{$phpbb_root_path}download.$phpEx", 'id=' . $attachment['attach_id']) : $filename; $block_array += array( 'S_FILE' => true, @@ -893,6 +908,40 @@ function display_attachments($forum_id, $blockname, &$attachment_data, &$update_ } /** +* 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; + + // Start counting from 22 for the bbcode ids (every bbcode takes two ids - opening/closing) + $num_predefined_bbcodes = 22; + + /* + * @todo while adjusting custom bbcodes, think about caching this query as well as correct ordering + */ + $sql = 'SELECT bbcode_id, bbcode_tag, bbcode_helpline + FROM ' . BBCODES_TABLE . ' + WHERE display_on_posting = 1'; + $result = $db->sql_query($sql); + + $i = 0; + while ($row = $db->sql_fetchrow($result)) + { + $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']) + ); + + $i++; + } + $db->sql_freeresult($result); +} + +/** * Display reasons */ function display_reasons($reason_id = 0) @@ -967,7 +1016,7 @@ function display_user_activity(&$userdata) } $forum_ary = array_unique($forum_ary); - $post_count_sql = (sizeof($forum_ary)) ? 'AND f.forum_id NOT IN (' . implode(', ', $forum_ary) . ')' : ''; + $post_count_sql = (sizeof($forum_ary)) ? 'AND ' . $db->sql_in_set('f.forum_id', $forum_ary, true) : ''; // Firebird does not support ORDER BY on aliased columns // MySQL does not support ORDER BY on functions @@ -1073,10 +1122,10 @@ function display_user_activity(&$userdata) $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($user->lang['POST_PCT'], $active_f_pct), + 'ACTIVE_FORUM_PCT' => sprintf($user->lang['POST_PCT_ACTIVE'], $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($user->lang['POST_PCT'], $active_t_pct), + 'ACTIVE_TOPIC_PCT' => sprintf($user->lang['POST_PCT_ACTIVE'], $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)) ); diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index 5bd9b0ab41..052f372443 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -352,8 +352,8 @@ class messenger $headers .= "Content-transfer-encoding: 8bit\n"; $headers .= "X-Priority: {$this->mail_priority}\n"; $headers .= 'X-MSMail-Priority: ' . (($this->mail_priority == MAIL_LOW_PRIORITY) ? 'Low' : (($this->mail_priority == MAIL_NORMAL_PRIORITY) ? 'Normal' : 'High')) . "\n"; - $headers .= "X-Mailer: PhpBB\n"; - $headers .= "X-MimeOLE: phpBB\n"; + $headers .= "X-Mailer: PhpBB3\n"; + $headers .= "X-MimeOLE: phpBB3\n"; $headers .= "X-phpBB-Origin: phpbb://" . str_replace(array('http://', 'https://'), array('', ''), generate_board_url()) . "\n"; $headers .= ($this->extra_headers != '') ? $this->extra_headers : ''; @@ -363,7 +363,14 @@ class messenger $mail_to = ($to == '') ? 'Undisclosed-Recipient:;' : $to; $err_msg = ''; - $result = ($config['smtp_delivery']) ? smtpmail($this->addresses, $this->subject, wordwrap($this->msg), $err_msg, $this->encoding, $headers) : @$config['email_function_name']($mail_to, $this->subject, implode("\n", preg_split("/\r?\n/", wordwrap($this->msg))), $headers); + if ($config['smtp_delivery']) + { + $result = smtpmail($this->addresses, $this->subject, wordwrap($this->msg), $err_msg, $this->encoding, $headers); + } + else + { + $result = @$config['email_function_name']($mail_to, $this->subject, implode("\n", preg_split("/\r?\n/", wordwrap($this->msg))), $headers); + } if (!$result) { @@ -808,8 +815,11 @@ function smtpmail($addresses, $subject, $message, &$err_msg, $encoding, $headers $smtp = new smtp_class; + $errno = 0; + $errstr = ''; + // Ok we have error checked as much as we can to this point let's get on it already. - if (!$smtp->socket = fsockopen($config['smtp_host'], $config['smtp_port'], $errno, $errstr, 20)) + if (!$smtp->socket = @fsockopen($config['smtp_host'], $config['smtp_port'], $errno, $errstr, 20)) { $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 false; diff --git a/phpBB/includes/functions_module.php b/phpBB/includes/functions_module.php index 0452be7067..9541c9f4cf 100644 --- a/phpBB/includes/functions_module.php +++ b/phpBB/includes/functions_module.php @@ -20,8 +20,8 @@ class p_master var $p_mode; var $p_parent; + var $active_module = false; var $acl_forum_id = false; - var $module_ary = array(); /** @@ -86,7 +86,7 @@ class p_master } // Category with no members, ignore - if (!$row['module_name'] && ($row['left_id'] + 1 == $row['right_id'])) + if (!$row['module_basename'] && ($row['left_id'] + 1 == $row['right_id'])) { unset($this->module_cache['modules'][$key]); continue; @@ -135,7 +135,7 @@ class p_master } // Category with no members on their way down (we have to check every level) - if (!$row['module_name']) + if (!$row['module_basename']) { $empty_category = true; @@ -145,7 +145,7 @@ class p_master if ($temp_row['left_id'] > $row['left_id'] && $temp_row['left_id'] < $row['right_id']) { // Module there - if ($temp_row['module_name'] && $temp_row['module_enabled']) + if ($temp_row['module_basename'] && $temp_row['module_enabled']) { $empty_category = false; break; @@ -168,15 +168,15 @@ class p_master // We need to prefix the functions to not create a naming conflict // Function for building 'url_extra' - $url_func = '_module_' . $row['module_name'] . '_url'; + $url_func = '_module_' . $row['module_basename'] . '_url'; // Function for building the language name - $lang_func = '_module_' . $row['module_name'] . '_lang'; + $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_name']; + $custom_func = '_module_' . $row['module_basename']; - $names[$row['module_name'] . '_' . $row['module_mode']][] = true; + $names[$row['module_basename'] . '_' . $row['module_mode']][] = true; $module_row = array( 'depth' => $depth, @@ -185,15 +185,15 @@ class p_master 'parent' => (int) $row['parent_id'], 'cat' => ($row['right_id'] > $row['left_id'] + 1) ? true : false, - 'is_duplicate' => ($row['module_name'] && sizeof($names[$row['module_name'] . '_' . $row['module_mode']]) > 1) ? true : false, + 'is_duplicate' => ($row['module_basename'] && sizeof($names[$row['module_basename'] . '_' . $row['module_mode']]) > 1) ? true : false, - 'name' => (string) $row['module_name'], + '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']) : '', - 'lang' => ($row['module_name'] && 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']), + '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'], @@ -239,6 +239,7 @@ class p_master function set_active($id = false, $mode = false) { $icat = false; + $this->active_module = false; if (request_var('icat', '')) { @@ -247,20 +248,20 @@ class p_master } $category = false; - foreach ($this->module_ary as $row_id => $itep_ary) + 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 ( - (($itep_ary['name'] === $id || $itep_ary['id'] === (int) $id) && (($itep_ary['mode'] == $mode && !$itep_ary['cat']) || ($icat && $itep_ary['cat']))) || - ($itep_ary['parent'] === $category && !$itep_ary['cat'] && !$icat) || - (($itep_ary['name'] === $id || $itep_ary['id'] === (int) $id) && !$mode && !$itep_ary['cat']) || - (!$id && !$mode && !$itep_ary['cat']) + (($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['name'] === $id || $item_ary['id'] === (int) $id) && !$mode && !$item_ary['cat']) || + (!$id && !$mode && !$item_ary['cat']) ) { - if ($itep_ary['cat']) + if ($item_ary['cat']) { $id = $icat; $icat = false; @@ -268,20 +269,21 @@ class p_master continue; } - $this->p_id = $itep_ary['id']; - $this->p_parent = $itep_ary['parent']; - $this->p_name = $itep_ary['name']; - $this->p_mode = $itep_ary['mode']; - $this->p_left = $itep_ary['left']; - $this->p_right = $itep_ary['right']; + $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']; break; } - else if (($itep_ary['cat'] && $itep_ary['id'] === (int) $id) || ($itep_ary['parent'] === $category && $itep_ary['cat'])) + else if (($item_ary['cat'] && $item_ary['id'] === (int) $id) || ($item_ary['parent'] === $category && $item_ary['cat'])) { - $category = $itep_ary['id']; + $category = $item_ary['id']; } } } @@ -298,6 +300,11 @@ class p_master $module_path = $phpbb_root_path . 'includes/' . $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")) @@ -464,10 +471,10 @@ class p_master // 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 => $itep_ary) + foreach ($this->module_ary as $row_id => $item_ary) { // Skip hidden modules - if (!$itep_ary['display']) + if (!$item_ary['display']) { continue; } @@ -475,7 +482,7 @@ class p_master // Skip branch if ($right_id !== false) { - if ($itep_ary['left'] < $right_id) + if ($item_ary['left'] < $right_id) { continue; } @@ -484,14 +491,14 @@ class p_master } // Category with no members on their way down (we have to check every level) - if (!$itep_ary['name']) + 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'] > $itep_ary['left'] && $temp_row['left'] < $itep_ary['right']) + if ($temp_row['left'] > $item_ary['left'] && $temp_row['left'] < $item_ary['right']) { // Module there and displayed? if ($temp_row['name'] && $temp_row['display']) @@ -507,18 +514,18 @@ class p_master // Skip the branch if ($empty_category) { - $right_id = $itep_ary['right']; + $right_id = $item_ary['right']; continue; } } // Select first id we can get - if (!$current_id && (in_array($itep_ary['id'], array_keys($this->module_cache['parents'])) || $itep_ary['id'] == $this->p_id)) + if (!$current_id && (in_array($item_ary['id'], array_keys($this->module_cache['parents'])) || $item_ary['id'] == $this->p_id)) { - $current_id = $itep_ary['id']; + $current_id = $item_ary['id']; } - $depth = $itep_ary['depth']; + $depth = $item_ary['depth']; if ($depth > $current_depth) { @@ -534,30 +541,30 @@ class p_master } } - $u_title = $module_url . $delim . 'i=' . (($itep_ary['cat']) ? $itep_ary['id'] : $itep_ary['name'] . (($itep_ary['is_duplicate']) ? '&icat=' . $current_id : '') . '&mode=' . $itep_ary['mode']); - $u_title .= (!$itep_ary['cat'] && isset($itep_ary['url_extra'])) ? $itep_ary['url_extra'] : ''; + $u_title = $module_url . $delim . 'i=' . (($item_ary['cat']) ? $item_ary['id'] : $item_ary['name'] . (($item_ary['is_duplicate']) ? '&icat=' . $current_id : '') . '&mode=' . $item_ary['mode']); + $u_title .= (!$item_ary['cat'] && isset($item_ary['url_extra'])) ? $item_ary['url_extra'] : ''; // Only output a categories items if it's currently selected - if (!$depth || ($depth && (in_array($itep_ary['parent'], array_values($this->module_cache['parents'])) || $itep_ary['parent'] == $this->p_parent))) + 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' => $itep_ary['lang'], - 'S_SELECTED' => (in_array($itep_ary['id'], array_keys($this->module_cache['parents'])) || $itep_ary['id'] == $this->p_id) ? true : false, + 'L_TITLE' => $item_ary['lang'], + 'S_SELECTED' => (in_array($item_ary['id'], array_keys($this->module_cache['parents'])) || $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($itep_ary, CASE_UPPER))); + $template->assign_block_vars($use_tabular_offset, array_merge($tpl_ary, array_change_key_case($item_ary, CASE_UPPER))); } $tpl_ary = array( - 'L_TITLE' => $itep_ary['lang'], - 'S_SELECTED' => (in_array($itep_ary['id'], array_keys($this->module_cache['parents'])) || $itep_ary['id'] == $this->p_id) ? true : false, + 'L_TITLE' => $item_ary['lang'], + 'S_SELECTED' => (in_array($item_ary['id'], array_keys($this->module_cache['parents'])) || $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($itep_ary, CASE_UPPER))); + $template->assign_block_vars($linear_offset, array_merge($tpl_ary, array_change_key_case($item_ary, CASE_UPPER))); $current_depth = $depth; } @@ -593,7 +600,10 @@ class p_master { $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); } @@ -633,9 +643,9 @@ class p_master */ function set_display($id, $mode = false, $display = true) { - foreach ($this->module_ary as $row_id => $itep_ary) + foreach ($this->module_ary as $row_id => $item_ary) { - if (($itep_ary['name'] === $id || $itep_ary['id'] === (int) $id) && (!$mode || $itep_ary['mode'] === $mode)) + if (($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && (!$mode || $item_ary['mode'] === $mode)) { $this->module_ary[$row_id]['display'] = (int) $display; } diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 127d7b2af4..b40fdb369c 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -114,9 +114,9 @@ function update_post_information($type, $ids, $return_update_sql = false) $update_sql = $empty_forums = array(); $sql = 'SELECT ' . $type . '_id, MAX(post_id) as last_post_id - FROM ' . POSTS_TABLE . " + FROM ' . POSTS_TABLE . ' WHERE post_approved = 1 - AND {$type}_id IN (" . implode(', ', $ids) . ") + AND ' . $db->sql_in_set($type . '_id', $ids) . " GROUP BY {$type}_id"; $result = $db->sql_query($sql); @@ -150,7 +150,7 @@ function update_post_information($type, $ids, $return_update_sql = false) $sql = 'SELECT p.' . $type . '_id, p.post_id, p.post_time, p.poster_id, p.post_username, u.user_id, u.username FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u WHERE p.poster_id = u.user_id - AND p.post_id IN (' . implode(', ', $last_post_ids) . ')'; + AND ' . $db->sql_in_set('p.post_id', $last_post_ids); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -339,9 +339,18 @@ function upload_attachment($form_name, $forum_id, $local = false, $local_storage $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)) { - $allowed_filesize = ($extensions[$file->get('extension')]['max_filesize'] != 0) ? $extensions[$file->get('extension')]['max_filesize'] : (($is_message) ? $config['max_filesize_pm'] : $config['max_filesize']); + 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); } @@ -521,9 +530,10 @@ function create_thumbnail($source, $destination, $mimetype) $used_imagick = false; - if ($config['img_imagick']) + // Only use imagemagick if defined and the passthru function not disabled + if ($config['img_imagick'] && function_exists('passthru')) { - passthru($config['img_imagick'] . 'convert' . ((defined('PHP_OS') && preg_match('#win#i', PHP_OS)) ? '.exe' : '') . ' -quality 85 -antialias -sample ' . $new_width . 'x' . $new_height . ' "' . str_replace('\\', '/', $source) . '" +profile "*" "' . str_replace('\\', '/', $destination) . '"'); + passthru(escapeshellcmd($config['img_imagick']) . 'convert' . ((defined('PHP_OS') && preg_match('#^win#i', PHP_OS)) ? '.exe' : '') . ' -quality 85 -antialias -sample ' . $new_width . 'x' . $new_height . ' "' . str_replace('\\', '/', $source) . '" +profile "*" "' . str_replace('\\', '/', $destination) . '"'); if (file_exists($destination)) { $used_imagick = true; @@ -572,6 +582,12 @@ function create_thumbnail($source, $destination, $mimetype) 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: @@ -666,7 +682,7 @@ function posting_gen_attachment_entry(&$attachment_data, &$filename_data) $template->assign_block_vars('attach_row', array( 'FILENAME' => basename($attach_row['real_filename']), 'ATTACH_FILENAME' => basename($attach_row['physical_filename']), - 'FILE_COMMENT' => $attach_row['comment'], + 'FILE_COMMENT' => $attach_row['attach_comment'], 'ATTACH_ID' => $attach_row['attach_id'], 'ASSOC_INDEX' => $count, @@ -741,7 +757,7 @@ function load_drafts($topic_id = 0, $forum_id = 0, $id = 0) { $sql = 'SELECT topic_id, forum_id, topic_title FROM ' . TOPICS_TABLE . ' - WHERE topic_id IN (' . implode(',', array_unique($topic_ids)) . ')'; + WHERE ' . $db->sql_in_set('topic_id', array_unique($topic_ids)); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -822,11 +838,11 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id return false; } - $bbcode_bitfield = 0; + $bbcode_bitfield = ''; do { $rowset[] = $row; - $bbcode_bitfield |= $row['bbcode_bitfield']; + $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']); } while ($row = $db->sql_fetchrow($result)); $db->sql_freeresult($result); @@ -876,7 +892,7 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id $template->assign_block_vars($mode . '_row', array( 'POSTER_NAME' => $poster, 'POST_SUBJECT' => $post_subject, - 'MINI_POST_IMG' => $user->img('icon_post', $user->lang['POST']), + 'MINI_POST_IMG' => $user->img('icon_post_target', $user->lang['POST']), 'POST_DATE' => $user->format_date($row['post_time']), 'MESSAGE' => str_replace("\n", '<br />', $message), 'DECODED_MESSAGE' => $decoded_message, @@ -891,7 +907,7 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id if ($mode == 'topic_review') { - $template->assign_var('QUOTE_IMG', $user->img('btn_quote', $user->lang['REPLY_WITH_QUOTE'])); + $template->assign_var('QUOTE_IMG', $user->img('icon_post_quote', $user->lang['REPLY_WITH_QUOTE'])); } return true; @@ -1093,7 +1109,7 @@ function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id $sql = 'UPDATE ' . TOPICS_WATCH_TABLE . " SET notify_status = 1 WHERE topic_id = $topic_id - AND user_id IN (" . implode(', ', $update_notification['topic']) . ")"; + AND " . $db->sql_in_set('user_id', $update_notification['topic']); $db->sql_query($sql); } @@ -1102,7 +1118,7 @@ function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id $sql = 'UPDATE ' . FORUMS_WATCH_TABLE . " SET notify_status = 1 WHERE forum_id = $forum_id - AND user_id IN (" . implode(', ', $update_notification['forum']) . ")"; + AND " . $db->sql_in_set('user_id', $update_notification['forum']); $db->sql_query($sql); } @@ -1111,7 +1127,7 @@ function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id { $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . " WHERE topic_id = $topic_id - AND user_id IN (" . implode(', ', $delete_ids['topic']) . ")"; + AND " . $db->sql_in_set('user_id', $delete_ids['topic']); $db->sql_query($sql); } @@ -1119,7 +1135,7 @@ function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id { $sql = 'DELETE FROM ' . FORUMS_WATCH_TABLE . " WHERE forum_id = $forum_id - AND user_id IN (" . implode(', ', $delete_ids['forum']) . ")"; + AND " . $db->sql_in_set('user_id', $delete_ids['forum']); $db->sql_query($sql); } @@ -1165,7 +1181,6 @@ function delete_post($forum_id, $topic_id, $post_id, &$data) { case 'delete_topic': delete_topics('topic_id', array($topic_id), false); - set_config('num_topics', $config['num_topics'] - 1, true); if ($data['topic_type'] != POST_GLOBAL) { @@ -1258,8 +1273,7 @@ function delete_post($forum_id, $topic_id, $post_id, &$data) break; } - $sql_data[USERS_TABLE] = ($auth->acl_get('f_postcount', $forum_id)) ? 'user_posts = user_posts - 1' : ''; - set_config('num_posts', $config['num_posts'] - 1, true); +// $sql_data[USERS_TABLE] = ($data['post_postcount']) ? 'user_posts = user_posts - 1' : ''; $db->sql_transaction('begin'); @@ -1338,6 +1352,11 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u $post_mode = ($data['topic_first_post_id'] == $data['topic_last_post_id']) ? '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 achive 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 informations about which tables and which rows to update/insert $sql_data = array(); $poster_id = ($mode == 'edit') ? $data['poster_id'] : (int) $user->data['user_id']; @@ -1366,6 +1385,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u 'post_attachment' => (isset($data['filename_data']['physical_filename']) && sizeof($data['filename_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; @@ -1529,8 +1549,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u ); } - $sql = 'INSERT INTO ' . POSTS_TABLE . ' ' . - $db->sql_build_array('INSERT', $sql_data[POSTS_TABLE]['sql']); + $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(); @@ -1695,7 +1714,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u { // update entry in db if attachment already stored in db and filespace $sql = 'UPDATE ' . ATTACHMENTS_TABLE . " - SET comment = '" . $db->sql_escape($attach_row['comment']) . "' + SET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "' WHERE attach_id = " . (int) $attach_row['attach_id']; $db->sql_query($sql); } @@ -1714,7 +1733,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u 'poster_id' => $poster_id, 'physical_filename' => basename($attach_row['physical_filename']), 'real_filename' => basename($attach_row['real_filename']), - 'comment' => $attach_row['comment'], + 'attach_comment' => $attach_row['attach_comment'], 'extension' => $attach_row['extension'], 'mimetype' => $attach_row['mimetype'], 'filesize' => $attach_row['filesize'], @@ -1843,7 +1862,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u trigger_error($error); } - $search->index($mode, $data['post_id'], $data['message'], $subject, $poster_id); + $search->index($mode, $data['post_id'], $data['message'], $subject, $user->lang['ENCODING'], $poster_id, ($topic_type == POST_GLOBAL) ? 0 : $data['forum_id']); } $db->sql_transaction('commit'); @@ -1886,6 +1905,35 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u // We do not use post_time here, this is intended (post_time can have a date in the past if editing a message) markread('topic', $data['forum_id'], $data['topic_id'], time()); + // + if ($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 = ' . $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'] || $config['load_anon_lastread'] || $user->data['is_registered']) + { + // Update forum info + $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($data['forum_id'], $forum_last_post_time, $f_mark_time, false); + } + // Send Notifications if ($mode != 'edit' && $mode != 'delete' && ($auth->acl_get('f_noapprove', $data['forum_id']) || $auth->acl_get('m_approve', $data['forum_id']))) { diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index 7a9cdfb322..fe38b6276b 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -86,8 +86,8 @@ $global_privmsgs_rules = array( ), CHECK_STATUS => array( - RULE_ANSWERED => array('check0' => 'replied', 'function' => '{CHECK0} == 1'), - RULE_FORWARDED => array('check0' => 'forwarded', 'function' => '{CHECK0} == 1'), + RULE_ANSWERED => array('check0' => 'pm_replied', 'function' => '{CHECK0} == 1'), + RULE_FORWARDED => array('check0' => 'pm_forwarded', 'function' => '{CHECK0} == 1'), ), CHECK_TO => array( @@ -121,7 +121,7 @@ function get_folder($user_id, $folder_id = false) $folder = array(); // Get folder informations - $sql = 'SELECT folder_id, COUNT(msg_id) as num_messages, SUM(unread) as num_unread + $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 . ' @@ -262,7 +262,7 @@ function check_rule(&$rules, &$rule_row, &$message_row, $user_id) // Replace Rule Literals $evaluate = preg_replace('/{(STRING|USER_ID|GROUP_ID)}/', '$rule_row["rule_" . strtolower("\1")]', $evaluate); - // Eval Statement + // Evil Statement $result = false; eval('$result = (' . $evaluate . ') ? true : false;'); @@ -280,7 +280,7 @@ function check_rule(&$rules, &$rule_row, &$message_row, $user_id) case ACTION_MARK_AS_READ: case ACTION_MARK_AS_IMPORTANT: case ACTION_DELETE_MESSAGE: - return array('action' => $rule_row['rule_action'], 'unread' => $message_row['unread'], 'marked' => $message_row['marked']); + return array('action' => $rule_row['rule_action'], 'pm_unread' => $message_row['pm_unread'], 'pm_marked' => $message_row['pm_marked']); break; default: @@ -387,7 +387,7 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false) { $sql = 'SELECT * FROM ' . USER_GROUP_TABLE . ' - WHERE user_id IN (' . implode(', ', $user_ids) . ') + WHERE ' . $db->sql_in_set('user_id', $user_ids) . ' AND user_pending = 0'; $result = $db->sql_query($sql); @@ -447,18 +447,24 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false) switch ($rule_ary['action']) { case ACTION_PLACE_INTO_FOLDER: + // Folder actions have precedence, so we will remove any other ones $folder_action = true; $_folder_id = (int) $rule_ary['folder_id']; + $move_into_folder = array(); $move_into_folder[$_folder_id][] = $msg_id; $num_new++; break; case ACTION_MARK_AS_READ: - if ($rule_ary['unread']) + if ($rule_ary['pm_unread']) { $unread_ids[] = $msg_id; } - $move_into_folder[PRIVMSGS_INBOX][] = $msg_id; + + if (!$folder_action) + { + $move_into_folder[PRIVMSGS_INBOX][] = $msg_id; + } break; case ACTION_DELETE_MESSAGE: @@ -466,11 +472,15 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false) break; case ACTION_MARK_AS_IMPORTANT: - if (!$rule_ary['marked']) + if (!$rule_ary['pm_marked']) { $important_ids[] = $msg_id; } - $move_into_folder[PRIVMSGS_INBOX][] = $msg_id; + + if (!$folder_action) + { + $move_into_folder[PRIVMSGS_INBOX][] = $msg_id; + } break; } } @@ -495,8 +505,8 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false) if (sizeof($unread_ids)) { $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' - SET unread = 0 - WHERE msg_id IN (' . implode(', ', $unread_ids) . ") + 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); @@ -506,10 +516,10 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false) if (sizeof($important_ids)) { $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' - SET marked = !marked + SET pm_marked = !pm_marked WHERE folder_id = ' . PRIVMSGS_NO_BOX . " AND user_id = $user_id - AND msg_id IN (" . implode(', ', $important_ids) . ')'; + AND " . $db->sql_in_set('msg_id', $important_ids); $db->sql_query($sql); } @@ -520,10 +530,16 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false) { // 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 folder_id IN (' . implode(', ', array_keys($move_into_folder)) . (($full_folder_action >= 0) ? ', ' . $full_folder_action : '') . ") + WHERE ' . $db->sql_in_set('folder_id', $sql_folder) . " AND user_id = $user_id"; $result = $db->sql_query($sql); @@ -533,6 +549,8 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false) } $db->sql_freeresult($result); + unset($sql_folder); + if (in_array(PRIVMSGS_INBOX, array_keys($move_into_folder))) { $sql = 'SELECT folder_id, COUNT(msg_id) as num_messages @@ -586,6 +604,7 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false) $delete_ids[] = $row['msg_id']; } $db->sql_freeresult($result); + delete_pm($user_id, $delete_ids, $dest_folder); } } @@ -594,21 +613,22 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false) if ($full_folder_action == FULL_FOLDER_HOLD) { $num_not_moved += sizeof($msg_ary); + $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' SET folder_id = ' . PRIVMSGS_HOLD_BOX . ' WHERE folder_id = ' . PRIVMSGS_NO_BOX . " AND user_id = $user_id - AND msg_id IN (" . implode(', ', $msg_ary) . ')'; + AND " . $db->sql_in_set('msg_id', $msg_ary); $db->sql_query($sql); } else { $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . " - SET folder_id = $dest_folder, new = 0 + SET folder_id = $dest_folder, pm_new = 0 WHERE folder_id = " . PRIVMSGS_NO_BOX . " AND user_id = $user_id - AND new = 1 - AND msg_id IN (" . implode(', ', $msg_ary) . ')'; + AND pm_new = 1 + AND " . $db->sql_in_set('msg_id', $msg_ary); $db->sql_query($sql); if ($dest_folder != PRIVMSGS_INBOX) @@ -633,7 +653,7 @@ function place_pm_into_folder(&$global_privmsgs_rules, $release = false) $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' SET folder_id = ' . PRIVMSGS_SENTBOX . ' WHERE folder_id = ' . PRIVMSGS_OUTBOX . ' - AND msg_id IN (' . implode(', ', array_keys($action_ary)) . ')'; + AND ' . $db->sql_in_set('msg_id', array_keys($action_ary)); $db->sql_query($sql); } @@ -718,7 +738,7 @@ function move_pm($user_id, $message_limit, $move_msg_ids, $dest_folder, $cur_fol SET folder_id = $dest_folder WHERE folder_id = $cur_folder_id AND user_id = $user_id - AND msg_id IN (" . implode(', ', $move_msg_ids) . ')'; + AND " . $db->sql_in_set('msg_id', $move_msg_ids); $db->sql_query($sql); $num_moved = $db->sql_affectedrows(); @@ -761,7 +781,7 @@ function update_unread_status($unread, $msg_id, $user_id, $folder_id) global $db; $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . " - SET unread = 0 + SET pm_unread = 0 WHERE msg_id = $msg_id AND user_id = $user_id AND folder_id = $folder_id"; @@ -794,10 +814,10 @@ function handle_mark_actions($user_id, $mark_action) case 'mark_important': $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . " - SET marked = !marked + SET pm_marked = !pm_marked WHERE folder_id = $cur_folder_id AND user_id = $user_id - AND msg_id IN (" . implode(', ', $msg_ids) . ')'; + AND " . $db->sql_in_set('msg_id', $msg_ids); $db->sql_query($sql); break; @@ -865,9 +885,9 @@ function delete_pm($user_id, $msg_ids, $folder_id) } // Get PM Informations for later deleting - $sql = 'SELECT msg_id, unread, new + $sql = 'SELECT msg_id, pm_unread, pm_new FROM ' . PRIVMSGS_TO_TABLE . ' - WHERE msg_id IN (' . implode(', ', array_map('intval', $msg_ids)) . ") + 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); @@ -876,8 +896,8 @@ function delete_pm($user_id, $msg_ids, $folder_id) $num_unread = $num_new = $num_deleted = 0; while ($row = $db->sql_fetchrow($result)) { - $num_unread += (int) $row['unread']; - $num_new += (int) $row['new']; + $num_unread += (int) $row['pm_unread']; + $num_new += (int) $row['pm_new']; $delete_rows[$row['msg_id']] = 1; } @@ -896,19 +916,19 @@ function delete_pm($user_id, $msg_ids, $folder_id) // Remove PM from Outbox $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . " WHERE user_id = $user_id AND folder_id = " . PRIVMSGS_OUTBOX . ' - AND msg_id IN (' . implode(', ', array_keys($delete_rows)) . ')'; + 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 msg_id IN (" . implode(', ', array_keys($delete_rows)) . ')'; + 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 informations (sent time for example) $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' - SET deleted = 1 - WHERE msg_id IN (' . implode(', ', array_keys($delete_rows)) . ')'; + SET pm_deleted = 1 + WHERE ' . $db->sql_in_set('msg_id', array_keys($delete_rows)); $db->sql_query($sql); $num_deleted = $db->sql_affectedrows(); @@ -919,7 +939,7 @@ function delete_pm($user_id, $msg_ids, $folder_id) $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . " WHERE user_id = $user_id AND folder_id = $folder_id - AND msg_id IN (" . implode(', ', array_keys($delete_rows)) . ')'; + AND " . $db->sql_in_set('msg_id', array_keys($delete_rows)); $db->sql_query($sql); $num_deleted = $db->sql_affectedrows(); } @@ -949,7 +969,7 @@ function delete_pm($user_id, $msg_ids, $folder_id) // Now we have to check which messages we can delete completely $sql = 'SELECT msg_id FROM ' . PRIVMSGS_TO_TABLE . ' - WHERE msg_id IN (' . implode(', ', array_keys($delete_rows)) . ')'; + WHERE ' . $db->sql_in_set('msg_id', array_keys($delete_rows)); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -958,12 +978,12 @@ function delete_pm($user_id, $msg_ids, $folder_id) } $db->sql_freeresult($result); - $delete_ids = implode(', ', array_keys($delete_rows)); + $delete_ids = array_keys($delete_rows); - if ($delete_ids) + if (sizeof($delete_ids)) { $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . ' - WHERE msg_id IN (' . $delete_ids . ')'; + WHERE ' . $db->sql_in_set('msg_id', $delete_ids); $db->sql_query($sql); } @@ -1039,7 +1059,7 @@ function write_pm_addresses($check_ary, $author_id, $plaintext = false) { $sql = 'SELECT user_id, username, user_colour FROM ' . USERS_TABLE . ' - WHERE user_id IN (' . implode(', ', $u) . ') + WHERE ' . $db->sql_in_set('user_id', $u) . ' AND user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')'; $result = $db->sql_query($sql); @@ -1066,7 +1086,7 @@ function write_pm_addresses($check_ary, $author_id, $plaintext = false) { $sql = 'SELECT group_name, group_type FROM ' . GROUPS_TABLE . ' - WHERE group_id IN (' . implode(', ', $g) . ')'; + WHERE ' . $db->sql_in_set('group_id', $g); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -1082,7 +1102,7 @@ function write_pm_addresses($check_ary, $author_id, $plaintext = false) { $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 g.group_id IN (' . implode(', ', $g) . ') + 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); @@ -1222,7 +1242,7 @@ function submit_pm($mode, $subject, &$data, $update_message, $put_in_outbox = tr { $sql = 'SELECT group_id, user_id FROM ' . USER_GROUP_TABLE . ' - WHERE group_id IN (' . implode(', ', array_keys($data['address_list']['g'])) . ') + WHERE ' . $db->sql_in_set('group_id', array_keys($data['address_list']['g'])) . ' AND user_pending = 0'; $result = $db->sql_query($sql); @@ -1250,7 +1270,7 @@ function submit_pm($mode, $subject, &$data, $update_message, $put_in_outbox = tr // Set message_replied switch for this user $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' - SET replied = 1 + SET pm_replied = 1 WHERE user_id = ' . $data['from_user_id'] . ' AND msg_id = ' . $data['reply_from_msg_id']; @@ -1300,6 +1320,8 @@ function submit_pm($mode, $subject, &$data, $update_message, $put_in_outbox = tr 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)); @@ -1328,13 +1350,13 @@ function submit_pm($mode, $subject, &$data, $update_message, $put_in_outbox = tr 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, - 'new' => 1, - 'unread' => 1, - 'forwarded' => ($mode == 'forward') ? 1 : 0 + '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 ); } @@ -1359,20 +1381,20 @@ function submit_pm($mode, $subject, &$data, $update_message, $put_in_outbox = tr $sql = 'UPDATE ' . USERS_TABLE . ' SET user_new_privmsg = user_new_privmsg + 1, user_unread_privmsg = user_unread_privmsg + 1, user_last_privmsg = ' . time() . ' - WHERE user_id IN (' . implode(', ', array_keys($recipients)) . ')'; + 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, - 'new' => 0, - 'unread' => 0, - 'forwarded' => ($mode == 'forward') ? 1 : 0)) + '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)) ); } @@ -1401,7 +1423,7 @@ function submit_pm($mode, $subject, &$data, $update_message, $put_in_outbox = tr { // update entry in db if attachment already stored in db and filespace $sql = 'UPDATE ' . ATTACHMENTS_TABLE . " - SET comment = '" . $db->sql_escape($attach_row['comment']) . "' + SET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "' WHERE attach_id = " . (int) $attach_row['attach_id']; $db->sql_query($sql); } @@ -1415,7 +1437,7 @@ function submit_pm($mode, $subject, &$data, $update_message, $put_in_outbox = tr 'poster_id' => $data['from_user_id'], 'physical_filename' => basename($attach_row['physical_filename']), 'real_filename' => basename($attach_row['real_filename']), - 'comment' => $attach_row['comment'], + 'attach_comment' => $attach_row['attach_comment'], 'extension' => $attach_row['extension'], 'mimetype' => $attach_row['mimetype'], 'filesize' => $attach_row['filesize'], @@ -1477,19 +1499,23 @@ function pm_notification($mode, $author, $recipients, $subject, $message) $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; + 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); - unset($recipients[ANONYMOUS], $recipients[$user->data['user_id']]); - while ($row = $db->sql_fetchrow($result)) { - if (isset($row['ban_userid'])) - { - unset($recipients[$row['ban_userid']]); - } + unset($recipients[$row['ban_userid']]); } $db->sql_freeresult($result); @@ -1498,11 +1524,9 @@ function pm_notification($mode, $author, $recipients, $subject, $message) return; } - $recipient_list = implode(', ', array_keys($recipients)); - $sql = 'SELECT user_id, username, user_email, user_lang, user_notify_pm, user_notify_type, user_jabber - FROM ' . USERS_TABLE . " - WHERE user_id IN ($recipient_list)"; + 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(); diff --git a/phpBB/includes/functions_profile_fields.php b/phpBB/includes/functions_profile_fields.php index 9910d58e5b..6f71724754 100644 --- a/phpBB/includes/functions_profile_fields.php +++ b/phpBB/includes/functions_profile_fields.php @@ -230,7 +230,7 @@ class custom_profile } else { - $sql = 'SELECT option_id, value + $sql = 'SELECT option_id, lang_value FROM ' . PROFILE_FIELDS_LANG_TABLE . " WHERE field_id = $field_id AND lang_id = $lang_id @@ -240,7 +240,7 @@ class custom_profile while ($row = $db->sql_fetchrow($result)) { - $this->options_lang[$field_id][$lang_id][($row['option_id'] + 1)] = $row['value']; + $this->options_lang[$field_id][$lang_id][($row['option_id'] + 1)] = $row['lang_value']; } $db->sql_freeresult($result); } @@ -286,8 +286,8 @@ class custom_profile while ($row = $db->sql_fetchrow($result)) { - $cp_data[$row['field_ident']] = $this->get_profile_field($row); - $check_value = $cp_data[$row['field_ident']]; + $cp_data['_' . $row['field_ident']] = $this->get_profile_field($row); + $check_value = $cp_data['_' . $row['field_ident']]; if (($cp_result = $this->validate_profile_field($row['field_type'], $check_value, $row)) !== false) { @@ -358,14 +358,14 @@ class custom_profile $this->build_cache(); } - if (!implode(', ', $user_id)) + if (!sizeof($user_id)) { return array(); } $sql = 'SELECT * FROM ' . PROFILE_FIELDS_DATA_TABLE . ' - WHERE user_id IN (' . implode(', ', array_map('intval', $user_id)) . ')'; + WHERE ' . $db->sql_in_set('user_id', array_map('intval', $user_id)); $result = $db->sql_query($sql); $field_data = array(); @@ -382,7 +382,7 @@ class custom_profile { foreach ($field_data as $user_id => $row) { - $user_fields[$user_id][$used_ident]['value'] = $row[$used_ident]; + $user_fields[$user_id][$used_ident]['value'] = $row['_' . $used_ident]; $user_fields[$user_id][$used_ident]['data'] = $this->profile_cache[$used_ident]; } } @@ -494,7 +494,15 @@ class custom_profile return NULL; } - return $this->options_lang[$field_id][$lang_id][(int) $value]; + $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': @@ -534,7 +542,7 @@ class custom_profile global $user; $profile_row['field_ident'] = (isset($profile_row['var_name'])) ? $profile_row['var_name'] : 'pf_' . $profile_row['field_ident']; - $user_ident = str_replace('pf_', '', $profile_row['field_ident']); + $user_ident = '_' . str_replace('pf_', '', $profile_row['field_ident']); // checkbox - only testing for isset if ($profile_row['field_type'] == FIELD_BOOL && $profile_row['field_length'] == 2) @@ -601,7 +609,7 @@ class custom_profile global $user, $template; $profile_row['field_ident'] = (isset($profile_row['var_name'])) ? $profile_row['var_name'] : 'pf_' . $profile_row['field_ident']; - $user_ident = str_replace('pf_', '', $profile_row['field_ident']); + $user_ident = '_' . str_replace('pf_', '', $profile_row['field_ident']); $now = getdate(); @@ -779,13 +787,13 @@ class custom_profile $sql_not_in = array(); foreach ($cp_data as $key => $null) { - $sql_not_in[] = "'" . $db->sql_escape($key) . "'"; + $sql_not_in[] = (strncmp($key, '_', 1) === 0) ? substr($key, 1) : $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 f.field_ident NOT IN (' . implode(', ', $sql_not_in) . ')' : '') . ' + ' . ((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); @@ -796,7 +804,8 @@ class custom_profile $now = getdate(); $row['field_default_value'] = sprintf('%2d-%2d-%4d', $now['mday'], $now['mon'], $now['year']); } - $cp_data[$row['field_ident']] = (in_array($row['field_type'], array(FIELD_TEXT, FIELD_STRING))) ? $row['lang_default_value'] : $row['field_default_value']; + + $cp_data['_' . $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); diff --git a/phpBB/includes/functions_template.php b/phpBB/includes/functions_template.php index 9b201871b1..7f29c2a040 100644 --- a/phpBB/includes/functions_template.php +++ b/phpBB/includes/functions_template.php @@ -69,6 +69,89 @@ class template_compile } /** + * Straight-forward strategy: use PHP's tokenizer to escape everything that + * looks like a PHP tag. + * + * We open/close PHP tags at the beginning of the template to clearly indicate + * that we are in HTML mode. If we find a PHP tag, we escape it then we reiterate + * over the whole file. That can become quite slow if the file is stuffed with + * <?php tags, but there's only so much we can do. + * + * Known issue: templates need to be rechecked everytime the value of the php.ini + * settings asp_tags or short_tags are changed + */ + function remove_php_tags(&$code) + { + if (!function_exists('token_get_all')) + { + /** + * If the tokenizer extension is not available, try to load it and if + * it's still not available we fall back to some pattern replacement. + * + * Note that the pattern replacement may affect the well-formedness + * of the HTML if a PHP tag is found because even if we escape PHP + * opening tags we do NOT escape PHP closing tags and cannot do so + * reliably without the use of a full-blown tokenizer. + * + * The bottom line is, a template should NEVER contain PHP because it + * would comprise the security of the installation, that's why we + * prevent it from being executed. Our job is to secure the installation, + * not fix unsecure templates. if a template contains some PHP then it + * should not be used at all. + */ + @dl('tokenizer'); + + if (!function_exists('token_get_all')) + { + $match = array( + '\\?php[\n\r\s\t]+', + '[\\?%]=', + '[\\?%][^\w]', + 'script[\n\r\s\t]+language[\n\r\s\t]*=[\n\r\s\t]*[\'"]php[\'"]' + ); + + $code = preg_replace('#<(' . implode('|', $match) . ')#is', '<$1', $code); + return; + } + } + + do + { + $tokens = token_get_all('<?php ?>' . $code); + $code = ''; + $php_found = false; + + foreach ($tokens as $i => $token) + { + if (!is_array($token)) + { + $code .= $token; + } + else if ($token[0] == T_OPEN_TAG || $token[0] == T_OPEN_TAG_WITH_ECHO || $token[0] == T_CLOSE_TAG) + { + if ($i > 1) + { + $code .= htmlspecialchars($token[1]); + $php_found = true; + } + } + else + { + $code .= $token[1]; + } + } + unset($tokens); + + // Fix for a tokenizer oddity + if (!strncmp($code, '<?php ?>', 11)) + { + $code = substr($code, 11); + } + } + while ($php_found); + } + + /** * The all seeing all doing compile method. Parts are inspired by or directly from Smarty * @access: private */ @@ -86,8 +169,13 @@ class template_compile // 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 > - $match_php_tags = array('#\<\?php .*?\?\>#is', '#\<\script language="php"\>.*?\<\/script\>#is', '#\<\?.*?\?\>#s', '#\<%.*?%\>#s'); +/* + $match_php_tags = array('#\<\?php.*?\?\>#is', '#<[^\w<]*(script)(((?:"[^"]*"|\'[^\']*\'|[^<>\'"])+)?(language[^<>\'"]+("[^"]*php[^"]*"|\'[^\']*php[^\']*\'))((?:"[^"]*"|\'[^\']*\'|[^<>\'"])+)?)?>.*?</script>#is', '#\<\?.*?\?\>#s', '#\<%.*?%\>#s'); $code = preg_replace($match_php_tags, '', $code); +*/ + + // An alternative to the above would be calling this function which would be the ultimate solution but also has its drawbacks. + $this->remove_php_tags($code); // Pull out all block/statement level elements and seperate plain text preg_match_all('#<!-- PHP -->(.*?)<!-- ENDPHP -->#s', $code, $matches); @@ -464,7 +552,7 @@ class template_compile { preg_match('#^((?:[a-z0-9\-_]+\.)+)?\$(?=[A-Z])([A-Z0-9_\-]*)(?: = (\'?)([^\']*)(\'?))?$#', $tag_args, $match); - if (empty($match[2]) || (empty($match[4]) && $op)) + if (empty($match[2]) || (!isset($match[4]) && $op)) { return; } diff --git a/phpBB/includes/functions_transfer.php b/phpBB/includes/functions_transfer.php index 190447829f..d2cc95f728 100644 --- a/phpBB/includes/functions_transfer.php +++ b/phpBB/includes/functions_transfer.php @@ -245,7 +245,7 @@ class ftp extends transfer // 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); - $this->root_path = (($root_path{0} != '/' ) ? '/' : '') . ((substr($root_path, -1, 1) == '/') ? '' : '/') . $root_path; + $this->root_path = (($root_path{0} != '/' ) ? '/' : '') . $root_path . ((substr($root_path, -1, 1) == '/') ? '' : '/'); // Init some needed values transfer::transfer(); @@ -321,7 +321,7 @@ class ftp extends transfer } /** - * Remove directory (RMDIR) + * Rename file * @access: private */ function _rename($old_handle, $new_handle) @@ -460,7 +460,7 @@ class ftp_fsock extends transfer // Make sure $this->root_path is layed out the same way as the $user->page['root_script_path'] value (prefixed with / and no / at the end) $this->root_path = str_replace('\\', '/', $this->root_path); - $this->root_path = (($root_path{0} != '/' ) ? '/' : '') . ((substr($root_path, -1, 1) == '/') ? '' : '/') . $root_path; + $this->root_path = (($root_path{0} != '/' ) ? '/' : '') . $root_path . ((substr($root_path, -1, 1) == '/') ? '' : '/'); // Init some needed values transfer::transfer(); @@ -543,6 +543,16 @@ class ftp_fsock extends transfer } /** + * 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 */ @@ -562,7 +572,7 @@ class ftp_fsock extends transfer */ function _chmod($file, $perms) { - return $this->_send_command('SITE CHMOD', $perms . ' ' . $file);; + return $this->_send_command('SITE CHMOD', $perms . ' ' . $file); } /** @@ -579,19 +589,19 @@ class ftp_fsock extends transfer return false; } - $this->_putcmd('STOR', $to_file, 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)); + @fwrite($this->data_connection, @fread($fp, 4096)); } @fclose($fp); @@ -710,7 +720,7 @@ class ftp_fsock extends transfer { return false; } - @stream_set_timeout($$this->data_connection, $this->timeout); + @stream_set_timeout($this->data_connection, $this->timeout); return true; } @@ -721,7 +731,7 @@ class ftp_fsock extends transfer */ function _close_data_connection() { - return @fclose($this->data_connecton); + return @fclose($this->data_connection); } /** diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index c246e98396..c03e92d0b0 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -34,14 +34,16 @@ function user_get_id_name(&$user_id_ary, &$username_ary) $$which_ary = array($$which_ary); } - $sql_in = ($which_ary == 'user_id_ary') ? array_map('intval', $$which_ary) : preg_replace('#^\s*(.*)\s*$#e', "\"'\" . \$db->sql_escape('\\1') . \"'\"", $$which_ary); + $sql_in = ($which_ary == 'user_id_ary') ? array_map('intval', $$which_ary) : $$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'; $sql = 'SELECT user_id, username - FROM ' . USERS_TABLE . " - WHERE $sql_where IN (" . implode(', ', $sql_in) . ')'; + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set($sql_where, $sql_in); $result = $db->sql_query($sql); if (!($row = $db->sql_fetchrow($result))) @@ -50,7 +52,6 @@ function user_get_id_name(&$user_id_ary, &$username_ary) return 'NO_USERS'; } - $user_id_ary = $username_ary = array(); do { $username_ary[$row['user_id']] = $row['username']; @@ -115,7 +116,7 @@ function user_update_name($old_name, $new_name) if ($config['newest_username'] == $old_name) { - set_config('newest_username', $new_name); + set_config('newest_username', $new_name, true); } } @@ -140,10 +141,14 @@ function user_add($user_row, $cp_data = false) 'user_type' => $user_row['user_type'], ); + /** + * @todo user_allow_email is not used anywhere. Think about removing it. + */ + // These are the additional vars able to be specified $additional_vars = array( 'user_permissions' => '', - 'user_timezone' => 0, + 'user_timezone' => $config['board_timezone'], 'user_dateformat' => $config['default_dateformat'], 'user_lang' => $config['default_lang'], 'user_style' => $config['default_style'], @@ -181,7 +186,7 @@ function user_add($user_row, $cp_data = false) 'user_sig' => '', 'user_sig_bbcode_uid' => '', - 'user_sig_bbcode_bitfield' => 0, + 'user_sig_bbcode_bitfield' => '', ); // Now fill the sql array with not required variables @@ -202,8 +207,6 @@ function user_add($user_row, $cp_data = false) } } - $db->sql_transaction('begin'); - $sql = 'INSERT INTO ' . USERS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); $db->sql_query($sql); @@ -232,7 +235,16 @@ function user_add($user_row, $cp_data = false) ); $db->sql_query($sql); - $db->sql_transaction('commit'); + // Now make it the users default group... + group_set_user_default($user_row['group_id'], array($user_id)); + + // 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) + { + set_config('newest_user_id', $user_id, true); + set_config('newest_username', $user_row['username'], true); + set_config('num_users', $config['num_users'] + 1, true); + } return $user_id; } @@ -295,7 +307,7 @@ function user_delete($mode, $user_id, $post_username = false) { $sql = 'SELECT topic_id, topic_replies, topic_replies_real FROM ' . TOPICS_TABLE . ' - WHERE topic_id IN (' . implode(', ', array_keys($topic_id_ary)) . ')'; + WHERE ' . $db->sql_in_set('topic_id', array_keys($topic_id_ary)); $result = $db->sql_query($sql); $del_topic_ary = array(); @@ -311,7 +323,7 @@ function user_delete($mode, $user_id, $post_username = false) if (sizeof($del_topic_ary)) { $sql = 'DELETE FROM ' . TOPICS_TABLE . ' - WHERE topic_id IN (' . implode(', ', $del_topic_ary) . ')'; + WHERE ' . $db->sql_in_set('topic_id', $del_topic_ary); $db->sql_query($sql); } } @@ -322,7 +334,7 @@ function user_delete($mode, $user_id, $post_username = false) break; } - $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); + $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); foreach ($table_ary as $table) { @@ -339,6 +351,9 @@ function user_delete($mode, $user_id, $post_username = false) set_config('num_users', $config['num_users'] - 1, true); + // Adjust last post info... + + $db->sql_transaction('commit'); return false; @@ -369,10 +384,12 @@ function user_active_flip($user_id, $user_type, $user_actkey = false, $username WHERE user_id = $user_id"; $result = $db->sql_query($sql); + $group_name = ($user_type == USER_NORMAL) ? 'REGISTERED' : 'INACTIVE'; while ($row = $db->sql_fetchrow($result)) { - if ($group_name = array_search($row['group_id'], $group_id_ary)) + if ($name = array_search($row['group_id'], $group_id_ary)) { + $group_name = $name; break; } } @@ -472,6 +489,23 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas $ban_end = 0; } + $founder = array(); + + if (!$ban_exclude) + { + // Create a list of founder... + $sql = 'SELECT user_id, user_email + 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']; + } + $db->sql_freeresult($result); + } + $banlist_ary = array(); switch ($mode) @@ -494,14 +528,25 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas $username = trim($username); if ($username != '') { - $sql_usernames[] = "'" . $db->sql_escape($username) . "'"; + $sql_usernames[] = strtolower($username); } } - $sql_usernames = implode(', ', $sql_usernames); + + // Make sure we have been given someone to ban + if (!sizeof($sql_usernames)) + { + trigger_error($user->lang['NO_USER_SPECIFIED']); + } $sql = 'SELECT user_id FROM ' . USERS_TABLE . ' - WHERE username IN (' . $sql_usernames . ')'; + WHERE ' . $db->sql_in_set('LOWER(username)', $sql_usernames); + + if (sizeof($founder)) + { + $sql .= ' AND ' . $db->sql_in_set('user_id', array_keys($founder), true); + } + $result = $db->sql_query($sql); if ($row = $db->sql_fetchrow($result)) @@ -618,9 +663,14 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas foreach ($ban_list as $ban_item) { - if (preg_match('#^.*?@*|(([a-z0-9\-]+\.)+([a-z]{2,3}))$#i', trim($ban_item))) + $ban_item = trim($ban_item); + + if (preg_match('#^.*?@*|(([a-z0-9\-]+\.)+([a-z]{2,3}))$#i', $ban_item)) { - $banlist_ary[] = trim($ban_item); + if (!sizeof($founder) || !in_array($ban_item, $founder)) + { + $banlist_ary[] = $ban_item; + } } } @@ -711,17 +761,11 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas switch ($mode) { case 'user': - $sql_where = (in_array('*', $banlist_ary)) ? '' : 'WHERE session_user_id IN (' . implode(', ', $banlist_ary) . ')'; + $sql_where = (in_array('*', $banlist_ary)) ? '' : 'WHERE ' . $db->sql_in_set('session_user_id', $banlist_ary); break; case 'ip': - $banlist_ary_sql = array(); - - foreach ($banlist_ary as $ban_entry) - { - $banlist_ary_sql[] = "'" . $db->sql_escape($ban_entry) . "'"; - } - $sql_where = 'WHERE session_ip IN (' . implode(', ', $banlist_ary_sql) . ')'; + $sql_where = 'WHERE ' . $db->sql_in_set('session_ip', $banlist_ary); break; case 'email': @@ -729,12 +773,12 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas foreach ($banlist_ary as $ban_entry) { - $banlist_ary_sql[] = "'" . $db->sql_escape(str_replace('*', '%', $ban_entry)) . "'"; + $banlist_ary_sql[] = (string) str_replace('*', '%', $ban_entry); } $sql = 'SELECT user_id FROM ' . USERS_TABLE . ' - WHERE user_email IN (' . implode(', ', $banlist_ary_sql) . ')'; + WHERE ' . $db->sql_in_set('user_email', $banlist_ary_sql); $result = $db->sql_query($sql); $sql_in = array(); @@ -747,7 +791,7 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas } while ($row = $db->sql_fetchrow($result)); - $sql_where = 'WHERE session_user_id IN (' . implode(', ', $sql_in) . ")"; + $sql_where = 'WHERE ' . $db->sql_in_set('session_user_id', $sql_in); } $db->sql_freeresult($result); break; @@ -758,12 +802,19 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas $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_log('admin', $log_entry . strtoupper($mode), $ban_reason, $ban_list_log); + return true; } @@ -789,30 +840,30 @@ function user_unban($mode, $ban) $ban = array($ban); } - $unban_sql = implode(', ', array_map('intval', $ban)); + $unban_sql = array_map('intval', $ban); - if ($unban_sql) + if (sizeof($unban_sql)) { // Grab details of bans for logging information later switch ($mode) { case 'user': $sql = 'SELECT u.username AS unban_info - FROM ' . USERS_TABLE . ' u, ' . BANLIST_TABLE . " b - WHERE b.ban_id IN ($unban_sql) - AND u.user_id = b.ban_userid"; + 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 ban_id IN ($unban_sql)"; + 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 ban_id IN ($unban_sql)"; + FROM ' . BANLIST_TABLE . ' + WHERE ' . $db->sql_in_set('ban_id', $unban_sql); break; } $result = $db->sql_query($sql); @@ -824,8 +875,8 @@ function user_unban($mode, $ban) } $db->sql_freeresult($result); - $sql = 'DELETE FROM ' . BANLIST_TABLE . " - WHERE ban_id IN ($unban_sql)"; + $sql = 'DELETE FROM ' . BANLIST_TABLE . ' + WHERE ' . $db->sql_in_set('ban_id', $unban_sql); $db->sql_query($sql); add_log('admin', 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list); @@ -912,6 +963,8 @@ function validate_data($data, $val_ary) /** * 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) { @@ -934,6 +987,8 @@ function validate_string($string, $optional = false, $min = 0, $max = 0) /** * 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) { @@ -956,6 +1011,8 @@ function validate_num($num, $optional = false, $min = 0, $max = 1E99) /** * 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) { @@ -976,6 +1033,8 @@ function validate_match($string, $optional = false, $match) * 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 +* +* @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_username($username) { @@ -1048,6 +1107,8 @@ function validate_username($username) /** * Check to see if email address is banned or already present in the DB +* +* @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_email($email) { @@ -1058,12 +1119,12 @@ function validate_email($email) return false; } - if (!preg_match('#^[a-z0-9\.\-_\+]+?@(.*?\.)*?[a-z0-9\-_]+?\.[a-z]{2,4}$#i', $email)) + if (!preg_match('/^' . get_preg_expression('email') . '$/i', $email)) { return 'EMAIL_INVALID'; } - if ($user->check_ban('', '', $email, true) == true) + if ($user->check_ban(false, false, $email, true) == true) { return 'EMAIL_BANNED'; } @@ -1122,7 +1183,7 @@ function avatar_remote($data, &$error) // Make sure getimagesize works... if (($image_data = @getimagesize($data['remotelink'])) === false) { - $error[] = $user->lang['AVATAR_URL_INVALID']; + $error[] = $user->lang['UNABLE_GET_IMAGE_SIZE']; return false; } @@ -1202,7 +1263,7 @@ function avatar_gallery($category, $avatar_select, $items_per_column, $block_var if (!file_exists($path) || !is_dir($path)) { - $avatar_list = array($user->lang['NONE'] => array()); + $avatar_list = array($user->lang['NO_AVATAR_CATEGORY'] => array()); } else { @@ -1242,7 +1303,7 @@ function avatar_gallery($category, $avatar_select, $items_per_column, $block_var if (!sizeof($avatar_list)) { - $avatar_list = array($user->lang['NONE'] => array()); + $avatar_list = array($user->lang['NO_AVATAR_CATEGORY'] => array()); } @ksort($avatar_list); @@ -1336,14 +1397,14 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow 'group_name' => (string) $name, 'group_desc' => (string) $desc, 'group_desc_uid' => '', - 'group_desc_bitfield' => 0, + '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'], $allow_desc_bbcode, $allow_desc_urls, $allow_desc_smilies); + 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)) @@ -1361,6 +1422,8 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow // 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 = 'UPDATE ' . GROUPS_TABLE . ' @@ -1484,6 +1547,9 @@ function group_delete($group_id, $group_name = false) WHERE group_id = $group_id"; $db->sql_query($sql); + // Re-cache moderators + cache_moderators(); + add_log('admin', 'LOG_GROUP_DELETE', $group_name); return 'GROUP_DELETED'; @@ -1497,9 +1563,9 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false, global $db, $auth; // We need both username and user_id info - user_get_id_name($user_id_ary, $username_ary); + $result = user_get_id_name($user_id_ary, $username_ary); - if (!sizeof($user_id_ary)) + if (!sizeof($user_id_ary) || $result !== false) { return 'NO_USER'; } @@ -1507,7 +1573,7 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false, // Remove users who are already members of this group $sql = 'SELECT user_id, group_leader FROM ' . USER_GROUP_TABLE . ' - WHERE user_id IN (' . implode(', ', $user_id_ary) . ") + WHERE ' . $db->sql_in_set('user_id', $user_id_ary) . " AND group_id = $group_id"; $result = $db->sql_query($sql); @@ -1563,7 +1629,7 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false, { $sql = 'UPDATE ' . USER_GROUP_TABLE . ' SET group_leader = 1 - WHERE user_id IN (' . implode(', ', $update_id_ary) . ") + WHERE ' . $db->sql_in_set('user_id', $update_id_ary) . " AND group_id = $group_id"; $db->sql_query($sql); } @@ -1600,16 +1666,16 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false, $group_order = array('ADMINISTRATORS', 'GLOBAL_MODERATORS', 'REGISTERED_COPPA', 'REGISTERED', 'BOTS', 'GUESTS'); // We need both username and user_id info - user_get_id_name($user_id_ary, $username_ary); + $result = user_get_id_name($user_id_ary, $username_ary); - if (!sizeof($user_id_ary)) + if (!sizeof($user_id_ary) || $result !== false) { return 'NO_USER'; } $sql = 'SELECT * FROM ' . GROUPS_TABLE . ' - WHERE group_name IN (' . implode(', ', preg_replace('#^(.*)$#', "'\\1'", $group_order)) . ')'; + WHERE ' . $db->sql_in_set('group_name', $group_order); $result = $db->sql_query($sql); $group_order_id = $special_group_data = array(); @@ -1638,7 +1704,7 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false, // 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 user_id IN (' . implode(', ', $user_id_ary) . ")"; + WHERE ' . $db->sql_in_set('user_id', $user_id_ary); $result = $db->sql_query($sql); $default_groups = array(); @@ -1651,7 +1717,7 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false, // 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 ug.user_id IN (' . implode(', ', $user_id_ary) . ") + 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 . ' @@ -1687,7 +1753,7 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false, // Ok, get the original avatar data from users having an uploaded one (we need to remove these from the filesystem) $sql = 'SELECT user_id, user_avatar FROM ' . USERS_TABLE . ' - WHERE user_id IN (' . implode(', ', $sql_where_ary[$gid]) . ') + WHERE ' . $db->sql_in_set('user_id', $sql_where_ary[$gid]) . ' AND user_avatar_type = ' . AVATAR_UPLOAD; $result = $db->sql_query($sql); @@ -1699,7 +1765,7 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false, } $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $special_group_data[$gid]) . ' - WHERE user_id IN (' . implode(', ', $sql_where_ary[$gid]) . ')'; + WHERE ' . $db->sql_in_set('user_id', $sql_where_ary[$gid]); $db->sql_query($sql); } } @@ -1707,7 +1773,7 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false, $sql = 'DELETE FROM ' . USER_GROUP_TABLE . " WHERE group_id = $group_id - AND user_id IN (" . implode(', ', $user_id_ary) . ')'; + AND " . $db->sql_in_set('user_id', $user_id_ary); $db->sql_query($sql); // Clear permissions cache of relevant users @@ -1733,9 +1799,9 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna global $db, $auth, $phpbb_root_path, $phpEx, $config; // We need both username and user_id info - user_get_id_name($user_id_ary, $username_ary); + $result = user_get_id_name($user_id_ary, $username_ary); - if (!sizeof($user_id_ary)) + if (!sizeof($user_id_ary) || $result !== false) { return false; } @@ -1752,7 +1818,7 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna $sql = 'UPDATE ' . USER_GROUP_TABLE . ' SET group_leader = ' . (($action == 'promote') ? 1 : 0) . " WHERE group_id = $group_id - AND user_id IN (" . implode(', ', $user_id_ary) . ')'; + AND " . $db->sql_in_set('user_id', $user_id_ary); $db->sql_query($sql); $log = ($action == 'promote') ? 'LOG_GROUP_PROMOTED' : 'LOG_GROUP_DEMOTED'; @@ -1765,7 +1831,7 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna WHERE ug.group_id = ' . $group_id . ' AND ug.user_pending = 1 AND ug.user_id = u.user_id - AND ug.user_id IN (' . implode(', ', $user_id_ary) . ')'; + AND ' . $db->sql_in_set('ug.user_id', $user_id_ary); $result = $db->sql_query($sql); $user_id_ary = $email_users = array(); @@ -1784,7 +1850,7 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna $sql = 'UPDATE ' . USER_GROUP_TABLE . " SET user_pending = 0 WHERE group_id = $group_id - AND user_id IN (" . implode(', ', $user_id_ary) . ')'; + AND " . $db->sql_in_set('user_id', $user_id_ary); $db->sql_query($sql); // Send approved email to users... @@ -1840,7 +1906,7 @@ function group_set_user_default($group_id, $user_id_ary, $group_attributes = fal { global $db; - if (!$user_id_ary) + if (empty($user_id_ary)) { return; } @@ -1890,7 +1956,7 @@ function group_set_user_default($group_id, $user_id_ary, $group_attributes = fal // Ok, get the original avatar data from users having an uploaded one (we need to remove these from the filesystem) $sql = 'SELECT user_id, user_avatar FROM ' . USERS_TABLE . ' - WHERE user_id IN (' . implode(', ', $user_id_ary) . ') + WHERE ' . $db->sql_in_set('user_id', $user_id_ary) . ' AND user_avatar_type = ' . AVATAR_UPLOAD; $result = $db->sql_query($sql); @@ -1902,7 +1968,7 @@ function group_set_user_default($group_id, $user_id_ary, $group_attributes = fal } $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' - WHERE user_id IN (' . implode(', ', $user_id_ary) . ')'; + WHERE ' . $db->sql_in_set('user_id', $user_id_ary); $db->sql_query($sql); } @@ -1943,22 +2009,29 @@ function group_memberships($group_id_ary = false, $user_id_ary = false, $return_ 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.user_email FROM ' . USER_GROUP_TABLE . ' ug, ' . USERS_TABLE . ' u WHERE ug.user_id = u.user_id AND '; - if ($group_id_ary && $user_id_ary) + if ($group_id_ary) { - $sql .= " ug.group_id " . ((is_array($group_id_ary)) ? ' IN (' . implode(', ', $group_id_ary) . ')' : " = $group_id_ary") . " - AND ug.user_id " . ((is_array($user_id_ary)) ? ' IN (' . implode(', ', $user_id_ary) . ')' : " = $user_id_ary"); + $sql .= ' ' . $db->sql_in_set('ug.group_id', $group_id_ary); } - else if ($group_id_ary) - { - $sql .= " ug.group_id " . ((is_array($group_id_ary)) ? ' IN (' . implode(', ', $group_id_ary) . ')' : " = $group_id_ary"); - } - else if ($user_id_ary) + + if ($user_id_ary) { - $sql .= " ug.user_id " . ((is_array($user_id_ary)) ? ' IN (' . implode(', ', $user_id_ary) . ')' : " = $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); diff --git a/phpBB/includes/mcp/mcp_forum.php b/phpBB/includes/mcp/mcp_forum.php index ceb2dcbff7..09470b8269 100644 --- a/phpBB/includes/mcp/mcp_forum.php +++ b/phpBB/includes/mcp/mcp_forum.php @@ -16,6 +16,8 @@ function mcp_forum_view($id, $mode, $action, $forum_info) global $template, $db, $user, $auth, $cache; global $phpEx, $phpbb_root_path, $config; + include_once($phpbb_root_path . 'includes/functions_display.' . $phpEx); + $url = append_sid("{$phpbb_root_path}mcp.$phpEx?" . extra_url()); if ($action == 'merge_select') @@ -61,10 +63,10 @@ function mcp_forum_view($id, $mode, $action, $forum_info) $template->assign_vars(array( '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_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_reported', 'TOPIC_REPORTED'), - 'UNAPPROVED_IMG' => $user->img('icon_unapproved', 'TOPIC_UNAPPROVED'), + 'REPORTED_IMG' => $user->img('icon_topic_reported', 'TOPIC_REPORTED'), + 'UNAPPROVED_IMG' => $user->img('icon_topic_unapproved', 'TOPIC_UNAPPROVED'), 'S_CAN_DELETE' => $auth->acl_get('m_delete', $forum_id), 'S_CAN_MOVE' => $auth->acl_get('m_move', $forum_id), @@ -107,56 +109,11 @@ function mcp_forum_view($id, $mode, $action, $forum_info) { $topic_title = ''; - if ($row['topic_status'] == ITEM_LOCKED) - { - $folder_img = 'folder_locked'; - $folder_alt = 'VIEW_TOPIC_LOCKED'; - } - else - { - if ($row['topic_type'] == POST_ANNOUNCE || $row['topic_type'] == POST_GLOBAL) - { - $folder_img = 'folder_announce'; - $folder_alt = 'VIEW_TOPIC_ANNOUNCEMENT'; - } - else if ($row['topic_type'] == POST_STICKY) - { - $folder_img = 'folder_sticky'; - $folder_alt = 'VIEW_TOPIC_STICKY'; - } - else if ($row['topic_status'] == ITEM_MOVED) - { - $folder_img = 'folder_moved'; - $folder_alt = 'VIEW_TOPIC_MOVED'; - } - else - { - $folder_img = 'folder'; - $folder_alt = 'NO_NEW_POSTS'; - } - } - - if ($row['topic_type'] == POST_ANNOUNCE || $row['topic_type'] == POST_GLOBAL) - { - $topic_type = $user->lang['VIEW_TOPIC_ANNOUNCEMENT'] . ' '; - } - else if ($row['topic_type'] == POST_STICKY) - { - $topic_type = $user->lang['VIEW_TOPIC_STICKY'] . ' '; - } - else if ($row['topic_status'] == ITEM_MOVED) - { - $topic_type = $user->lang['VIEW_TOPIC_MOVED'] . ' '; - } - else - { - $topic_type = ''; - } + $replies = ($auth->acl_get('m_approve', $forum_id)) ? $row['topic_replies_real'] : $row['topic_replies']; - if (intval($row['poll_start'])) - { - $topic_type .= $user->lang['VIEW_TOPIC_POLL'] . ' '; - } + // Get folder img, topic status/type related informations + $folder_img = $folder_alt = $topic_type = ''; + topic_status($row, $replies, false, $folder_img, $folder_alt, $topic_type); $topic_title = censor_text($row['topic_title']); @@ -172,13 +129,13 @@ function mcp_forum_view($id, $mode, $action, $forum_info) 'U_MCP_QUEUE' => $u_mcp_queue, 'U_MCP_REPORT' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&mode=topic_view&t=' . $row['topic_id'] . '&action=reports'), - 'ATTACH_ICON_IMG' => ($auth->acl_gets('f_download', 'u_download', $row['forum_id']) && $row['topic_attachment']) ? $user->img('icon_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', + 'ATTACH_ICON_IMG' => ($auth->acl_gets('f_download', 'u_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_unapproved', ($topic_unapproved) ? 'TOPIC_UNAPPROVED' : 'POSTS_UNAPPROVED') : '', + 'UNAPPROVED_IMG' => ($topic_unapproved || $posts_unapproved) ? $user->img('icon_topic_unapproved', ($topic_unapproved) ? 'TOPIC_UNAPPROVED' : 'POSTS_UNAPPROVED') : '', 'TOPIC_TYPE' => $topic_type, 'TOPIC_TITLE' => $topic_title, @@ -220,7 +177,7 @@ function mcp_resync_topics($topic_ids) $sql = 'SELECT topic_id, forum_id, topic_title FROM ' . TOPICS_TABLE . ' - WHERE topic_id IN (' . implode(', ', $topic_ids) . ')'; + WHERE ' . $db->sql_in_set('topic_id', $topic_ids); $result = $db->sql_query($sql); // Log this action diff --git a/phpBB/includes/mcp/mcp_front.php b/phpBB/includes/mcp/mcp_front.php index 3fe9b60018..745b2c0d61 100644 --- a/phpBB/includes/mcp/mcp_front.php +++ b/phpBB/includes/mcp/mcp_front.php @@ -41,7 +41,7 @@ function mcp_front_view($id, $mode, $action) $sql = 'SELECT forum_id, forum_name FROM ' . FORUMS_TABLE . ' - WHERE forum_id IN (' . implode(', ', $forum_list) . ')'; + WHERE ' . $db->sql_in_set('forum_id', $forum_list); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -54,7 +54,7 @@ function mcp_front_view($id, $mode, $action) FROM ' . POSTS_TABLE . ' WHERE forum_id IN (0, ' . implode(', ', $forum_list) . ') AND post_approved = 0 - ORDER BY post_id DESC'; + ORDER BY post_time DESC'; $result = $db->sql_query_limit($sql, 5); while ($row = $db->sql_fetchrow($result)) @@ -65,10 +65,10 @@ function mcp_front_view($id, $mode, $action) $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.username, 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 p.post_id IN (' . implode(', ', $post_list) . ') + 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_id DESC'; + ORDER BY p.post_time DESC'; $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -158,7 +158,7 @@ function mcp_front_view($id, $mode, $action) AND r.user_id = u.user_id AND p.forum_id IN (0, ' . implode(', ', $forum_list) . ')', - 'ORDER_BY' => 'p.post_id DESC' + 'ORDER_BY' => 'p.post_time DESC' )); $result = $db->sql_query_limit($sql, 5); diff --git a/phpBB/includes/mcp/mcp_logs.php b/phpBB/includes/mcp/mcp_logs.php index 2850505e66..f9cf7d27df 100755 --- a/phpBB/includes/mcp/mcp_logs.php +++ b/phpBB/includes/mcp/mcp_logs.php @@ -43,8 +43,8 @@ class mcp_logs // Set up general vars $start = request_var('start', 0); - $deletemark = (isset($_POST['del_marked'])) ? true : false; - $deleteall = (isset($_POST['del_all'])) ? true : false; + $deletemark = ($action == 'del_marked') ? true : false; + $deleteall = ($action == 'del_all') ? true : false; $marked = request_var('mark', array(0)); // Sort keys @@ -84,14 +84,14 @@ class mcp_logs $sql_in[] = $mark; } - $where_sql = ' AND log_id IN (' . implode(', ', $sql_in) . ')'; + $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 = ' . LOD_MOD . " + WHERE log_type = ' . LOG_MOD . " $where_sql"; $db->sql_query($sql); @@ -102,7 +102,7 @@ class mcp_logs // 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' => 'l.user_id', 't' => 'l.log_time', 'i' => 'l.log_ip', 'o' => 'l.log_operation'); + $sort_by_sql = array('u' => 'u.username', '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); @@ -121,6 +121,8 @@ class mcp_logs 'TOTAL' => ($log_count == 1) ? $user->lang['TOTAL_LOG'] : sprintf($user->lang['TOTAL_LOGS'], $log_count), 'PAGINATION' => generate_pagination($this->u_action . "&$u_sort_param", $log_count, $config['topics_per_page'], $start), + '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, diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index abae0d55d4..b77c3e4451 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -224,8 +224,8 @@ function lock_unlock($action, $ids) if (confirm_box(true)) { $sql = "UPDATE $table - SET $set_id = " . (($action == 'lock' || $action == 'lock_post') ? ITEM_LOCKED : ITEM_UNLOCKED) . " - WHERE $sql_id IN (" . implode(', ', $ids) . ")"; + 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); @@ -311,7 +311,7 @@ function change_topic_type($action, $topic_ids) { $sql = 'UPDATE ' . TOPICS_TABLE . " SET topic_type = $new_topic_type - WHERE topic_id IN (" . implode(', ', $topic_ids) . ') + WHERE " . $db->sql_in_set('topic_id', $topic_ids) . ' AND forum_id <> 0'; $db->sql_query($sql); @@ -320,26 +320,68 @@ function change_topic_type($action, $topic_ids) { $sql = 'UPDATE ' . TOPICS_TABLE . " SET topic_type = $new_topic_type, forum_id = $forum_id - WHERE topic_id IN (" . implode(', ', $topic_ids) . ') + 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 = $forum_id + WHERE " . $db->sql_in_set('topic_id', $topic_ids) . ' + AND forum_id = 0'; + $db->sql_query($sql); + + sync('forum', 'forum_id', $forum_id); } } else { - $sql = 'UPDATE ' . TOPICS_TABLE . " - SET topic_type = $new_topic_type, forum_id = 0 - WHERE topic_id IN (" . implode(', ', $topic_ids) . ")"; - $db->sql_query($sql); + // 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); + + sync('forum', 'forum_id', $forum_id); + } } $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_TYPE_CHANGED' : 'TOPICS_TYPE_CHANGED'; - $data = get_topic_data($topic_ids); - - foreach ($data as $topic_id => $row) + if (sizeof($topic_ids)) { - add_log('mod', $forum_id, $topic_id, 'LOG_TOPIC_TYPE_CHANGED', $row['topic_title']); + $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 @@ -480,7 +522,7 @@ function mcp_move_topic($topic_ids) else { $template->assign_vars(array( - 'S_FORUM_SELECT' => make_forum_select($to_forum_id, $forum_id, false, true, true), + 'S_FORUM_SELECT' => make_forum_select($to_forum_id, $forum_id, false, true, true, true), 'S_CAN_LEAVE_SHADOW' => true, 'ADDITIONAL_MSG' => $additional_msg) ); @@ -541,11 +583,7 @@ function mcp_delete_topic($topic_ids) add_log('mod', $forum_id, 0, 'LOG_TOPIC_DELETED', $row['topic_title']); } - $return = delete_topics('topic_id', $topic_ids, true); - - /** - * @todo Adjust total post count (mcp_delete_topic) - */ + $return = delete_topics('topic_id', $topic_ids); } else { @@ -602,7 +640,7 @@ function mcp_delete_post($post_ids) $sql = 'SELECT DISTINCT topic_id FROM ' . POSTS_TABLE . ' - WHERE post_id IN (' . implode(', ', $post_ids) . ')'; + WHERE ' . $db->sql_in_set('post_id', $post_ids); $result = $db->sql_query($sql); $topic_id_list = array(); @@ -625,7 +663,7 @@ function mcp_delete_post($post_ids) $sql = 'SELECT COUNT(topic_id) AS topics_left FROM ' . TOPICS_TABLE . ' - WHERE topic_id IN (' . implode(', ', $topic_id_list) . ')'; + 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; @@ -809,7 +847,7 @@ function mcp_fork_topic($topic_ids) $sql = 'SELECT * FROM ' . POSTS_TABLE . " WHERE topic_id = $topic_id - ORDER BY post_id ASC"; + ORDER BY post_time ASC"; $result = $db->sql_query($sql); $post_rows = array(); @@ -848,7 +886,7 @@ function mcp_fork_topic($topic_ids) 'post_checksum' => (string) $row['post_checksum'], 'post_encoding' => (string) $row['post_encoding'], 'post_attachment' => (int) $row['post_attachment'], - 'bbcode_bitfield' => (int) $row['bbcode_bitfield'], + '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'], @@ -880,7 +918,7 @@ function mcp_fork_topic($topic_ids) 'physical_filename' => (string) basename($attach_row['physical_filename']), 'real_filename' => (string) basename($attach_row['real_filename']), 'download_count' => (int) $attach_row['download_count'], - 'comment' => (string) $attach_row['comment'], + 'attach_comment' => (string) $attach_row['attach_comment'], 'extension' => (string) $attach_row['extension'], 'mimetype' => (string) $attach_row['mimetype'], 'filesize' => (int) $attach_row['filesize'], @@ -898,8 +936,8 @@ function mcp_fork_topic($topic_ids) // Sync new topics, parent forums and board stats sync('topic', 'topic_id', $new_topic_id_list, true); sync('forum', 'forum_id', $to_forum_id, true); - set_config('num_topics', $config['num_topics'] + sizeof($new_topic_id_list)); - set_config('num_posts', $config['num_posts'] + $total_posts); + set_config('num_topics', $config['num_topics'] + sizeof($new_topic_id_list), true); + set_config('num_posts', $config['num_posts'] + $total_posts, true); foreach ($new_topic_id_list as $topic_id => $new_topic_id) { diff --git a/phpBB/includes/mcp/mcp_notes.php b/phpBB/includes/mcp/mcp_notes.php index 1f8e8f63a0..cc4ed0e72b 100755 --- a/phpBB/includes/mcp/mcp_notes.php +++ b/phpBB/includes/mcp/mcp_notes.php @@ -68,7 +68,7 @@ class mcp_notes global $template, $db, $user, $auth; $user_id = request_var('u', 0); - $username = request_var('username', '', true); + $username = request_var('username', ''); $start = request_var('start', 0); $st = request_var('st', 0); $sk = request_var('sk', 'b'); @@ -106,7 +106,7 @@ class mcp_notes { $sql_in[] = $mark; } - $where_sql = ' AND log_id IN (' . implode(', ', $sql_in) . ')'; + $where_sql = ' AND ' . $db->sql_in_set('log_id', $sql_in); unset($sql_in); } @@ -161,7 +161,7 @@ class mcp_notes $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' => 'l.user_id', 'b' => 'l.log_time', 'c' => 'l.log_ip', 'd' => 'l.log_operation'); + $sort_by_sql = array('a' => 'l.username', '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); @@ -184,6 +184,7 @@ class mcp_notes 'REPORT_BY' => $row['username'], 'REPORT_AT' => $user->format_date($row['time']), 'ACTION' => $row['action'], + 'IP' => $row['ip'], 'ID' => $row['id']) ); } diff --git a/phpBB/includes/mcp/mcp_post.php b/phpBB/includes/mcp/mcp_post.php index f9e0494fc8..08bcc713f8 100644 --- a/phpBB/includes/mcp/mcp_post.php +++ b/phpBB/includes/mcp/mcp_post.php @@ -59,7 +59,7 @@ function mcp_post_details($id, $mode, $action) if ($action == 'chgposter') { - $username = request_var('username', '', true); + $username = request_var('username', ''); $sql_where = "username = '" . $db->sql_escape($username) . "'"; } else @@ -125,13 +125,15 @@ function mcp_post_details($id, $mode, $action) 'U_MCP_REPORT' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&mode=report_details&f=' . $post_info['forum_id'] . '&p=' . $post_id), 'U_MCP_USER_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&mode=user_notes&u=' . $post_info['user_id']), 'U_MCP_WARN_USER' => ($auth->acl_getf_global('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&mode=warn_user&u=' . $post_info['user_id']) : '', + 'U_VIEW_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&p=' . $post_info['post_id'] . '#p' . $post_info['post_id']), 'U_VIEW_PROFILE' => ($post_info['user_id'] != ANONYMOUS) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $post_info['user_id']) : '', + 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&t=' . $post_info['topic_id']), 'RETURN_TOPIC' => sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f={$post_info['forum_id']}&p=$post_id") . "#p$post_id\">", '</a>'), 'RETURN_FORUM' => sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.$phpEx", "f={$post_info['forum_id']}&start={$start}") . '">', '</a>'), - 'REPORTED_IMG' => $user->img('icon_reported', $user->lang['POST_REPORTED']), - 'UNAPPROVED_IMG' => $user->img('icon_unapproved', $user->lang['POST_UNAPPROVED']), - 'EDIT_IMG' => $user->img('btn_edit', $user->lang['EDIT_POST']), + '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']), 'POSTER_NAME' => $poster, 'POST_PREVIEW' => $message, @@ -334,31 +336,20 @@ function change_poster(&$post_info, $userdata) $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) + 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 - $auth_user_from = new auth(); - $auth_user_from->acl($post_info); - - $auth_user_to = new auth(); - $auth_user_to->acl($userdata); - - // Decrease post count by one for the old user - if ($auth_user_from->acl_get('f_postcount', $post_info['forum_id'])) + if ($post_info['post_postcount']) { $sql = 'UPDATE ' . USERS_TABLE . ' SET user_posts = user_posts - 1 WHERE user_id = ' . $post_info['user_id']; $db->sql_query($sql); - } - // Increase post count by one for the new user - if ($auth_user_to->acl_get('f_postcount', $post_info['forum_id'])) - { $sql = 'UPDATE ' . USERS_TABLE . ' SET user_posts = user_posts + 1 WHERE user_id = ' . $userdata['user_id']; diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php index 560431ce87..95e89fa9dc 100644 --- a/phpBB/includes/mcp/mcp_queue.php +++ b/phpBB/includes/mcp/mcp_queue.php @@ -131,12 +131,14 @@ class mcp_queue 'U_MCP_REPORT' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports&mode=report_details&f=' . $post_info['forum_id'] . '&p=' . $post_id), 'U_MCP_USER_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&mode=user_notes&u=' . $post_info['user_id']), 'U_MCP_WARN_USER' => ($auth->acl_getf_global('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&mode=warn_user&u=' . $post_info['user_id']) : '', + 'U_VIEW_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&p=' . $post_info['post_id'] . '#p' . $post_info['post_id']), 'U_VIEW_PROFILE' => ($post_info['user_id'] != ANONYMOUS) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $post_info['user_id']) : '', + 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&t=' . $post_info['topic_id']), 'RETURN_QUEUE' => sprintf($user->lang['RETURN_QUEUE'], '<a href="' . append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue' . (($topic_id) ? '&mode=unapproved_topics' : '&mode=unapproved_posts')) . "&start=$start\">", '</a>'), - 'REPORTED_IMG' => $user->img('icon_reported', $user->lang['POST_REPORTED']), - 'UNAPPROVED_IMG' => $user->img('icon_unapproved', $user->lang['POST_UNAPPROVED']), - 'EDIT_IMG' => $user->img('btn_edit', $user->lang['EDIT_POST']), + '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']), 'POSTER_NAME' => $poster, 'POST_PREVIEW' => $message, @@ -179,6 +181,8 @@ class mcp_queue $forum_list[] = $row['forum_id']; } + $global_id = $forum_list[0]; + if (!($forum_list = implode(', ', $forum_list))) { trigger_error('NOT_MODERATOR'); @@ -190,8 +194,6 @@ class mcp_queue $result = $db->sql_query($sql); $forum_info['forum_topics'] = (int) $db->sql_fetchfield('sum_forum_topics'); $db->sql_freeresult($result); - - $global_id = $forum_list[0]; } else { @@ -248,11 +250,11 @@ class mcp_queue if (sizeof($post_ids)) { - $sql = 'SELECT t.topic_id, t.topic_title, t.forum_id, p.post_id, p.post_username, p.poster_id, p.post_time, u.username - FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t, ' . USERS_TABLE . " u - WHERE p.post_id IN (" . implode(', ', $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 + 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"; + AND u.user_id = p.poster_id'; $result = $db->sql_query($sql); $post_data = $rowset = array(); @@ -279,7 +281,7 @@ class mcp_queue } else { - $sql = 'SELECT t.forum_id, t.topic_id, t.topic_title, 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 + $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 FROM ' . TOPICS_TABLE . " t WHERE topic_approved = 0 AND forum_id IN (0, $forum_list) @@ -304,7 +306,7 @@ class mcp_queue // Select the names for the forum_ids $sql = 'SELECT forum_id, forum_name FROM ' . FORUMS_TABLE . ' - WHERE forum_id IN (' . implode(',', $forum_names) . ')'; + WHERE ' . $db->sql_in_set('forum_id', $forum_names); $result = $db->sql_query($sql, 3600); $forum_names = array(); @@ -334,15 +336,13 @@ class mcp_queue $template->assign_block_vars('postrow', array( 'U_VIEWFORUM' => (!$global_topic) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id']) : '', - // Q: Why accessing the topic by a post_id instead of its topic_id? - // A: To prevent the post from being hidden because of wrong encoding or different charset - 'U_VIEWTOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $row['forum_id'] . '&p=' . $row['post_id']) . (($mode == 'unapproved_posts') ? '#p' . $row['post_id'] : ''), + 'U_VIEWPOST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $row['forum_id'] . '&p=' . $row['post_id']) . (($mode == 'unapproved_posts') ? '#p' . $row['post_id'] : ''), 'U_VIEW_DETAILS' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=queue&start=$start&mode=approve_details&f={$row['forum_id']}&p={$row['post_id']}" . (($mode == 'unapproved_topics') ? "&t={$row['topic_id']}" : '')), 'U_VIEWPROFILE' => ($row['poster_id'] != ANONYMOUS) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $row['poster_id']) : '', 'POST_ID' => $row['post_id'], 'FORUM_NAME' => (!$global_topic) ? $forum_names[$row['forum_id']] : $user->lang['GLOBAL_ANNOUNCEMENT'], - 'TOPIC_TITLE' => $row['topic_title'], + 'POST_SUBJECT' => $row['post_subject'], 'POSTER' => $poster, 'POST_TIME' => $user->format_date($row['post_time'])) ); @@ -358,6 +358,7 @@ class mcp_queue 'S_FORUM_OPTIONS' => $forum_options, 'S_MCP_ACTION' => build_url(array('t', 'f', 'sd', 'st', 'sk')), + 'S_TOPICS' => ($mode == 'unapproved_posts') ? false : true, 'PAGINATION' => generate_pagination($this->u_action . "&f=$forum_id", $total, $config['topics_per_page'], $start), 'PAGE_NUMBER' => on_page($total, $config['topics_per_page'], $start), @@ -448,7 +449,7 @@ function approve_post($post_id_list, $mode) { $sql = 'UPDATE ' . TOPICS_TABLE . ' SET topic_approved = 1 - WHERE topic_id IN (' . implode(', ', $topic_approve_sql) . ')'; + WHERE ' . $db->sql_in_set('topic_id', $topic_approve_sql); $db->sql_query($sql); } @@ -456,7 +457,7 @@ function approve_post($post_id_list, $mode) { $sql = 'UPDATE ' . POSTS_TABLE . ' SET post_approved = 1 - WHERE post_id IN (' . implode(', ', $post_approve_sql) . ')'; + WHERE ' . $db->sql_in_set('post_id', $post_approve_sql); $db->sql_query($sql); } diff --git a/phpBB/includes/mcp/mcp_reports.php b/phpBB/includes/mcp/mcp_reports.php index 004c774957..a52bc02359 100755 --- a/phpBB/includes/mcp/mcp_reports.php +++ b/phpBB/includes/mcp/mcp_reports.php @@ -61,20 +61,14 @@ class mcp_reports $post_id = request_var('p', 0); - $post_info = get_post_data(array($post_id), 'm_approve'); + // closed reports are accessed by report id + $report_id = request_var('r', 0); - if (!sizeof($post_info)) - { - trigger_error('NO_POST_SELECTED'); - } - - $post_info = $post_info[$post_id]; - - $sql = 'SELECT r.user_id, r.report_closed, report_time, r.report_text, rr.reason_title, rr.reason_description, u.username - FROM ' . REPORTS_TABLE . ' r, ' . REPORTS_REASONS_TABLE . ' rr, ' . USERS_TABLE . " u - WHERE r.post_id = $post_id + $sql = 'SELECT r.post_id, r.user_id, r.report_closed, report_time, r.report_text, rr.reason_title, rr.reason_description, u.username + 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 r.report_closed = 0") . ' AND rr.reason_id = r.reason_id - AND r.user_id = u.user_id"; + AND r.user_id = u.user_id'; $result = $db->sql_query($sql); $report = $db->sql_fetchrow($result); $db->sql_freeresult($result); @@ -84,6 +78,20 @@ class mcp_reports trigger_error('NO_POST_REPORT'); } + if ($report_id) + { + $post_id = $report['post_id']; + } + + $post_info = get_post_data(array($post_id), 'm_report'); + + if (!sizeof($post_info)) + { + trigger_error('NO_POST_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'])])) { @@ -134,14 +142,16 @@ class mcp_reports 'U_MCP_USER_NOTES' => append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=notes&mode=user_notes&u=' . $post_info['user_id']), 'U_MCP_WARN_REPORTER' => ($auth->acl_getf_global('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&mode=warn_user&u=' . $report['user_id']) : '', 'U_MCP_WARN_USER' => ($auth->acl_getf_global('m_warn')) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&mode=warn_user&u=' . $post_info['user_id']) : '', + 'U_VIEW_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&p=' . $post_info['post_id'] . '#p' . $post_info['post_id']), 'U_VIEW_PROFILE' => ($post_info['user_id'] != ANONYMOUS) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $post_info['user_id']) : '', 'U_VIEW_REPORTER_PROFILE' => ($report['user_id'] != ANONYMOUS) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $report['user_id']) : '', + 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $post_info['forum_id'] . '&t=' . $post_info['topic_id']), - 'EDIT_IMG' => $user->img('btn_edit', $user->lang['EDIT_POST']), - 'UNAPPROVED_IMG' => $user->img('icon_unapproved', $user->lang['POST_UNAPPROVED']), + 'EDIT_IMG' => $user->img('icon_post_edit', $user->lang['EDIT_POST']), + 'UNAPPROVED_IMG' => $user->img('icon_topic_unapproved', $user->lang['POST_UNAPPROVED']), 'RETURN_REPORTS' => sprintf($user->lang['RETURN_REPORTS'], '<a href="' . append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=reports' . (($post_info['post_reported']) ? '&mode=reports' : '&mode=reports_closed') . '&start=' . $start) . '">', '</a>'), - 'REPORTED_IMG' => $user->img('icon_reported', $user->lang['POST_REPORTED']), + 'REPORTED_IMG' => $user->img('icon_topic_reported', $user->lang['POST_REPORTED']), 'REPORT_REASON_TITLE' => $reason['title'], 'REPORT_REASON_DESCRIPTION' => $reason['description'], 'REPORTER_NAME' => ($report['user_id'] == ANONYMOUS) ? $user->lang['GUEST'] : $report['username'], @@ -181,22 +191,25 @@ class mcp_reports $forum_id = $topic_info['forum_id']; } + $forum_list = array(); + if (!$forum_id) { - $forum_list = array(); foreach ($forum_list_reports as $row) { $forum_list[] = $row['forum_id']; } - if (!($forum_list = implode(', ', $forum_list))) + $global_id = $forum_list[0]; + + if (!sizeof($forum_list)) { trigger_error('NOT_MODERATOR'); } $sql = 'SELECT SUM(forum_topics) as sum_forum_topics - FROM ' . FORUMS_TABLE . " - WHERE forum_id IN ($forum_list)"; + 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); @@ -211,10 +224,11 @@ class mcp_reports } $forum_info = $forum_info[$forum_id]; - $forum_list = $forum_id; + $forum_list = array($forum_id); + $global_id = $forum_id; } - $forum_list .= ', 0'; + $forum_list[] = 0; $forum_data = array(); $forum_options = '<option value="0"' . (($forum_id == 0) ? ' selected="selected"' : '') . '>' . $user->lang['ALL_FORUMS'] . '</option>'; @@ -242,9 +256,9 @@ class mcp_reports $report_state = 'AND r.report_closed = 1'; } - $sql = 'SELECT p.post_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 p.forum_id IN ($forum_list) + $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' : '') . ' @@ -256,36 +270,28 @@ class mcp_reports $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); $i = 0; - $post_ids = array(); + $report_ids = array(); while ($row = $db->sql_fetchrow($result)) { - $post_ids[] = $row['post_id']; - $row_num[$row['post_id']] = $i++; + $report_ids[] = $row['report_id']; + $row_num[$row['report_id']] = $i++; } $db->sql_freeresult($result); - if (sizeof($post_ids)) + 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, r.user_id as reporter_id, ru.username as reporter_name, r.report_time - FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t, ' . REPORTS_TABLE . ' r, ' . USERS_TABLE . ' u, ' . USERS_TABLE . " ru - WHERE p.post_id IN (" . implode(', ', $post_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, r.user_id as reporter_id, ru.username as reporter_name, 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 ru.user_id = r.user_id'; $result = $db->sql_query($sql); - $post_data = $rowset = array(); + $report_data = $rowset = array(); while ($row = $db->sql_fetchrow($result)) { - $post_data[$row['post_id']] = $row; - } - $db->sql_freeresult($result); - - foreach ($post_ids as $post_id) - { - $row = $post_data[$post_id]; - if ($row['poster_id'] == ANONYMOUS) { $poster = (!empty($row['post_username'])) ? $row['post_username'] : $user->lang['GUEST']; @@ -295,16 +301,20 @@ class mcp_reports $poster = $row['username']; } + $global_topic = ($row['forum_id']) ? false : true; + if ($global_topic) + { + $row['forum_id'] = $global_id; + } + $template->assign_block_vars('postrow', array( - 'U_VIEWFORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id']), - // Q: Why accessing the topic by a post_id instead of its topic_id? - // A: To prevent the post from being hidden because of wrong encoding or different charset - 'U_VIEWTOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $row['forum_id'] . '&p=' . $row['post_id']) . '#p' . $row['post_id'], - 'U_VIEW_DETAILS' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=reports&start=$start&mode=report_details&f={$forum_id}&p={$row['post_id']}"), + 'U_VIEWFORUM' => (!$global_topic) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id']) : '', + 'U_VIEWPOST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $row['forum_id'] . '&p=' . $row['post_id']) . '#p' . $row['post_id'], + 'U_VIEW_DETAILS' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=reports&start=$start&mode=report_details&f={$row['forum_id']}&r={$row['report_id']}"), 'U_VIEW_POSTER_PROFILE' => ($row['poster_id'] != ANONYMOUS) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $row['poster_id']) : '', 'U_VIEW_REPORTER_PROFILE' => ($row['reporter_id'] != ANONYMOUS) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $row['reporter_id']) : '', - 'FORUM_NAME' => ($row['forum_id']) ? $forum_data[$row['forum_id']]['forum_name'] : $user->lang['ALL_FORUMS'], + 'FORUM_NAME' => (!$global_topic) ? $forum_data[$row['forum_id']]['forum_name'] : $user->lang['GLOBAL_ANNOUNCEMENT'], 'POSTER' => $poster, 'POST_ID' => $row['post_id'], 'POST_SUBJECT' => $row['post_subject'], @@ -314,7 +324,8 @@ class mcp_reports 'TOPIC_TITLE' => $row['topic_title']) ); } - unset($post_data, $post_ids, $row); + $db->sql_freeresult($result); + unset($report_ids, $row); } // Now display the page @@ -377,7 +388,7 @@ function close_report($post_id_list, $mode, $action) $sql = 'SELECT r.post_id, r.report_closed, r.user_id, r.user_notify, u.username, u.user_email, u.user_jabber, u.user_lang, u.user_notify_type FROM ' . REPORTS_TABLE . ' r, ' . USERS_TABLE . ' u - WHERE r.post_id IN (' . implode(',', array_keys($post_info)) . ') + WHERE ' . $db->sql_in_set('r.post_id', array_keys($post_info)) . ' ' . (($action == 'close') ? 'AND r.report_closed = 0' : '') . ' AND r.user_id = u.user_id'; $result = $db->sql_query($sql); @@ -411,9 +422,9 @@ function close_report($post_id_list, $mode, $action) // Get a list of topics that still contain reported posts $sql = 'SELECT DISTINCT topic_id FROM ' . POSTS_TABLE . ' - WHERE topic_id IN (' . implode(', ', $close_report_topics) . ') + WHERE ' . $db->sql_in_set('topic_id', $close_report_topics) . ' AND post_reported = 1 - AND post_id NOT IN (' . implode(', ', $close_report_posts) . ')'; + AND ' . $db->sql_in_set('post_id', $close_report_posts, true); $result = $db->sql_query($sql); $keep_report_topics = array(); @@ -432,24 +443,27 @@ function close_report($post_id_list, $mode, $action) { $sql = 'UPDATE ' . REPORTS_TABLE . ' SET report_closed = 1 - WHERE post_id IN (' . implode(', ', $close_report_posts) . ')'; + WHERE ' . $db->sql_in_set('post_id', $close_report_posts); } else { $sql = 'DELETE FROM ' . REPORTS_TABLE . ' - WHERE post_id IN (' . implode(', ', $close_report_posts) . ')'; + WHERE ' . $db->sql_in_set('post_id', $close_report_posts); } $db->sql_query($sql); $sql = 'UPDATE ' . POSTS_TABLE . ' SET post_reported = 0 - WHERE post_id IN (' . implode(', ', $close_report_posts) . ')'; + WHERE ' . $db->sql_in_set('post_id', $close_report_posts); $db->sql_query($sql); - $sql = 'UPDATE ' . TOPICS_TABLE . ' - SET topic_reported = 0 - WHERE topic_id IN (' . implode(', ', $close_report_topics) . ')'; - $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); + $db->sql_query($sql); + } $db->sql_transaction('commit'); } diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php index 92125cd14d..691b92bd36 100644 --- a/phpBB/includes/mcp/mcp_topic.php +++ b/phpBB/includes/mcp/mcp_topic.php @@ -88,11 +88,11 @@ function mcp_topic_view($id, $mode, $action) $result = $db->sql_query_limit($sql, $posts_per_page, $start); $rowset = array(); - $bbcode_bitfield = 0; + $bbcode_bitfield = ''; while ($row = $db->sql_fetchrow($result)) { $rowset[] = $row; - $bbcode_bitfield |= $row['bbcode_bitfield']; + $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']); } $db->sql_freeresult($result); @@ -132,7 +132,7 @@ function mcp_topic_view($id, $mode, $action) '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' => ($row['post_time'] > $user->data['user_lastvisit'] && $user->data['is_registered']) ? $user->img('icon_post_new', $user->lang['NEW_POST']) : $user->img('icon_post', $user->lang['POST']), + 'MINI_POST_IMG' => ($row['post_time'] > $user->data['user_lastvisit'] && $user->data['is_registered']) ? $user->img('icon_post_target_unread', $user->lang['NEW_POST']) : $user->img('icon_post_target', $user->lang['POST']), 'S_POST_REPORTED' => ($row['post_reported']) ? true : false, 'S_POST_UNAPPROVED' => ($row['post_approved']) ? false : true, @@ -186,11 +186,11 @@ function mcp_topic_view($id, $mode, $action) 'POSTS_PER_PAGE' => $posts_per_page, 'ACTION' => $action, - 'REPORTED_IMG' => $user->img('icon_reported', 'POST_REPORTED', false, true), - 'UNAPPROVED_IMG' => $user->img('icon_unapproved', 'POST_UNAPPROVED', false, true), + 'REPORTED_IMG' => $user->img('icon_topic_reported', 'POST_REPORTED', false, true), + 'UNAPPROVED_IMG' => $user->img('icon_topic_unapproved', 'POST_UNAPPROVED', false, true), 'S_MCP_ACTION' => "$url&i=$id&mode=$mode&action=$action&start=$start", - 'S_FORUM_SELECT' => '<select name="to_forum_id">' . (($to_forum_id) ? make_forum_select($to_forum_id) : make_forum_select($topic_info['forum_id'])) . '</select>', + '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, diff --git a/phpBB/includes/mcp/mcp_warn.php b/phpBB/includes/mcp/mcp_warn.php index a8ee952c93..bc428570ab 100755 --- a/phpBB/includes/mcp/mcp_warn.php +++ b/phpBB/includes/mcp/mcp_warn.php @@ -188,6 +188,7 @@ function mcp_warn_post_view($id, $mode, $action) 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 = request_var('warning', '', true); @@ -210,6 +211,12 @@ function mcp_warn_post_view($id, $mode, $action) trigger_error($user->lang['CANNOT_WARN_ANONYMOUS']); } + // Prevent someone from warning themselves + if ($userrow['user_id'] == $user->data['user_id']) + { + trigger_error($user->lang['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 @@ -290,6 +297,8 @@ function mcp_warn_post_view($id, $mode, $action) 'AVATAR_IMG' => $avatar_img, 'RANK_IMG' => $rank_img, + + 'L_WARNING_POST_DEFAULT' => sprintf($user->lang['WARNING_POST_DEFAULT'], generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&p=$post_id"), ) ); } @@ -303,7 +312,7 @@ function mcp_warn_user_view($id, $mode, $action) global $template, $db, $user, $auth; $user_id = request_var('u', 0); - $username = request_var('username', '', true); + $username = request_var('username', ''); $notify = (isset($_REQUEST['notify_user'])) ? true : false; $warning = request_var('warning', '', true); @@ -321,6 +330,12 @@ function mcp_warn_user_view($id, $mode, $action) trigger_error('NO_USER'); } + // Prevent someone from warning themselves + if ($userrow['user_id'] == $user->data['user_id']) + { + trigger_error($user->lang['CANNOT_WARN_SELF']); + } + $user_id = $userrow['user_id']; if ($warning && $action == 'add_warning') @@ -401,7 +416,7 @@ function add_warning($userrow, $warning, $send_pm = true, $post_id = 0) 'enable_smilies' => true, 'enable_urls' => false, 'icon_id' => 0, - 'bbcode_bitfield' => (int) $message_parser->bbcode_bitfield, + 'bbcode_bitfield' => $message_parser->bbcode_bitfield, 'bbcode_uid' => $message_parser->bbcode_uid, 'message' => $message_parser->message, 'address_list' => array('u' => array($userrow['user_id'] => 'to')), diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index a0dcd821fd..6aa78d091f 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -43,7 +43,9 @@ class bbcode_firstpass extends bbcode } global $user; - $this->bbcode_bitfield = 0; + + $this->bbcode_bitfield = ''; + $bitfield = new bitfield(); $size = strlen($this->message); foreach ($this->bbcodes as $bbcode_name => $bbcode_data) @@ -72,10 +74,29 @@ class bbcode_firstpass extends bbcode $new_size = strlen($this->message); if ($size != $new_size) { - $this->bbcode_bitfield |= (1 << $bbcode_data['bbcode_id']); + $bitfield->set($bbcode_data['bbcode_id']); $size = $new_size; } } + + $this->bbcode_bitfield = $bitfield->get_base64(); + } + + /** + * Prepare some bbcodes for better parsing + */ + function prepare_bbcodes() + { + // 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) + { + $in = str_replace("\r\n", "\n", $this->message); + + $this->message = preg_replace(array('#\[quote(=".*?")?\]([^\n])#is', '#([^\n])\[\/quote\]#is'), array("[quote\\1]\n\\2", "\\1\n[/quote]"), $this->message); + $this->message = preg_replace(array('#\[quote(=".*?")?\]([^\n])#is', '#([^\n])\[\/quote\]#is'), array("[quote\\1]\n\\2", "\\1\n[/quote]"), $this->message); + } + + // Add other checks which needs to be placed before actually parsing anything (be it bbcodes, smilies, urls...) } /** @@ -97,7 +118,7 @@ class bbcode_firstpass extends bbcode 'url' => array('bbcode_id' => 3, 'regexp' => array('#\[url(=(.*))?\](.*)\[/url\]#iUe' => "\$this->validate_url('\$2', '\$3')")), 'img' => array('bbcode_id' => 4, 'regexp' => array('#\[img\](https?://)([a-z0-9\-\.,\?!%\*_:;~\\&$@/=\+]+)\[/img\]#ie' => "\$this->bbcode_img('\$1\$2')")), 'size' => array('bbcode_id' => 5, 'regexp' => array('#\[size=([\-\+]?[1-2]?[0-9])\](.*?)\[/size\]#ise' => "\$this->bbcode_size('\$1', '\$2')")), - 'color' => array('bbcode_id' => 6, 'regexp' => array('!\[color=(#[0-9A-F]{6}|[a-z\-]+)\](.*?)\[/color\]!ise' => "\$this->bbcode_color('\$1', '\$2')")), + 'color' => array('bbcode_id' => 6, 'regexp' => array('!\[color=(#[0-9A-Fa-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-z|0-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')")), @@ -147,7 +168,7 @@ class bbcode_firstpass extends bbcode $in = str_replace("\r\n", "\n", str_replace('\"', '"', $in)); // Trimming here to make sure no empty bbcodes are parsed accidently - if (!trim($in)) + if (trim($in) == '') { return false; } @@ -389,12 +410,11 @@ class bbcode_firstpass extends bbcode switch (strtolower($stx)) { case 'php': - $code = trim($code); $remove_tags = false; $code = str_replace(array('<', '>'), array('<', '>'), $code); - if (!preg_match('/^\<\?.*?\?\>/is', $code)) + if (!preg_match('/\<\?.*?\?\>/is', $code)) { $remove_tags = true; $code = "<?php $code ?>"; @@ -417,7 +437,7 @@ class bbcode_firstpass extends bbcode { $str_from[] = '<span class="syntaxdefault"><?php </span>'; $str_to[] = ''; - $str_from[] = '<span class="syntaxdefault"><?php '; + $str_from[] = '<span class="syntaxdefault"><?php '; $str_to[] = '<span class="syntaxdefault">'; } @@ -432,6 +452,12 @@ class bbcode_firstpass extends bbcode $code = preg_replace('#^<span class="[a-z]+"><span class="([a-z]+)">(.*)</span></span>#s', '<span class="$1">$2</span>', $code); $code = preg_replace('#(?:[\n\r\s\t]| )*</span>$#', '</span>', $code); + // remove newline at the end + if (!empty($code) && $code{strlen($code)-1} == "\n") + { + $code = substr($code, 0, -1); + } + $out .= "[code=$stx:" . $this->bbcode_uid . ']' . $code . '[/code:' . $this->bbcode_uid . ']'; break; @@ -565,12 +591,6 @@ class bbcode_firstpass extends bbcode $tok = ']'; $out = '['; - // Add newline at the end and in front of each quote block to prevent parsing errors (urls, smilies, etc.) - $in = preg_replace(array('#\[quote(=".*?")?\]([^\n])#is', '#([^\n])\[\/quote\]#is'), array("[quote\\1]\n\\2", "\\1\n[/quote]"), $in); - $in = preg_replace(array('#\[quote(=".*?")?\]([^\n])#is', '#([^\n])\[\/quote\]#is'), array("[quote\\1]\n\\2", "\\1\n[/quote]"), $in); - - $in = str_replace("\r\n", "\n", str_replace('\"', '"', trim($in))); - $in = substr($in, 1); $close_tags = $error_ary = array(); $buffer = ''; @@ -677,7 +697,8 @@ class bbcode_firstpass extends bbcode else { $out .= $buffer . $tok; - $tok = ($tok == '[') ? ']' : '[]'; + // $tok = ($tok == '[') ? ']' : '[]'; + $tok = '[]'; $buffer = ''; } } @@ -709,7 +730,7 @@ class bbcode_firstpass extends bbcode $validated = true; - if (!preg_match('!([a-z0-9]+[a-z0-9\-\._]*@(?:(?:[0-9]{1,3}\.){3,5}[0-9]{1,3}|[a-z0-9]+[a-z0-9\-\._]*\.[a-z]+))!i', $email)) + if (!preg_match('/^' . get_preg_expression('email') . '$/i', $email)) { $validated = false; } @@ -792,8 +813,10 @@ class bbcode_firstpass extends bbcode { global $config, $phpEx, $user; + $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, substr($user->page['root_script_path'], 0, -1)) !== false) + if (strpos($url, ".{$phpEx}") !== false && strpos($url, $check_path) !== false) { $server_name = (!empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : getenv('SERVER_NAME'); @@ -805,7 +828,7 @@ class bbcode_firstpass extends bbcode // Check again in correct order... $pos_ext = strpos($url, ".{$phpEx}"); - $pos_path = strpos($url, substr($user->page['root_script_path'], 0, -1)); + $pos_path = strpos($url, $check_path); $pos_domain = strpos($url, $server_name); if ($pos_domain !== false && $pos_path >= $pos_domain && $pos_ext >= $pos_path) @@ -897,15 +920,7 @@ class parse_message extends bbcode_firstpass } } - // Parse smilies - if ($allow_smilies) - { - $this->smilies($config['max_' . $mode . '_smilies']); - } - - $num_urls = 0; - - // Parse BBCode + // Prepare BBcode (just prepares some tags for better parsing) if ($allow_bbcode && strpos($this->message, '[') !== false) { $this->bbcode_init(); @@ -917,8 +932,22 @@ class parse_message extends bbcode_firstpass $this->bbcodes[$bool]['disabled'] = true; } } - $this->parse_bbcode(); + $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']; } @@ -1129,7 +1158,7 @@ class parse_message extends bbcode_firstpass { $new_entry = array( 'physical_filename' => $filedata['physical_filename'], - 'comment' => $this->filename_data['filecomment'], + 'attach_comment' => $this->filename_data['filecomment'], 'real_filename' => $filedata['real_filename'], 'extension' => $filedata['extension'], 'mimetype' => $filedata['mimetype'], @@ -1199,7 +1228,7 @@ class parse_message extends bbcode_firstpass $edit_comment = request_var('edit_comment', array(0 => '')); $edit_comment = key($edit_comment); - $this->attachment_data[$edit_comment]['comment'] = $actual_comment_list[$edit_comment]; + $this->attachment_data[$edit_comment]['attach_comment'] = $actual_comment_list[$edit_comment]; } if (($add_file || $preview) && $upload_file) @@ -1213,7 +1242,7 @@ class parse_message extends bbcode_firstpass { $new_entry = array( 'physical_filename' => $filedata['physical_filename'], - 'comment' => $this->filename_data['filecomment'], + 'attach_comment' => $this->filename_data['filecomment'], 'real_filename' => $filedata['real_filename'], 'extension' => $filedata['extension'], 'mimetype' => $filedata['mimetype'], @@ -1279,7 +1308,7 @@ class parse_message extends bbcode_firstpass // Get the data from the attachments $sql = 'SELECT attach_id, physical_filename, real_filename, extension, mimetype, filesize, filetime, thumbnail FROM ' . ATTACHMENTS_TABLE . ' - WHERE attach_id IN (' . implode(', ', array_keys($attach_ids)) . ') + WHERE ' . $db->sql_in_set('attach_id', array_keys($attach_ids)) . ' AND poster_id = ' . $check_user_id; $result = $db->sql_query($sql); @@ -1289,7 +1318,7 @@ class parse_message extends bbcode_firstpass { $pos = $attach_ids[$row['attach_id']]; $this->attachment_data[$pos] = $row; - set_var($this->attachment_data[$pos]['comment'], $_POST['attachment_data'][$pos]['comment'], 'string', true); + set_var($this->attachment_data[$pos]['attach_comment'], $_POST['attachment_data'][$pos]['attach_comment'], 'string', true); unset($attach_ids[$row['attach_id']]); } @@ -1308,8 +1337,8 @@ class parse_message extends bbcode_firstpass include_once($phpbb_root_path . 'includes/functions_upload.' . $phpEx); $sql = 'SELECT attach_id - FROM ' . ATTACHMENTS_TABLE . " - WHERE LOWER(physical_filename) IN ('" . implode("', '", array_map('strtolower', $filenames)) . "')"; + FROM ' . ATTACHMENTS_TABLE . ' + WHERE ' . $db->sql_in_set('LOWER(physical_filename)', array_map('strtolower', $filenames)); $result = $db->sql_query_limit($sql, 1); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); @@ -1329,7 +1358,7 @@ class parse_message extends bbcode_firstpass 'thumbnail' => (file_exists($phpbb_root_path . $config['upload_path'] . '/thumb_' . $physical_filename)) ? 1 : 0, ); - set_var($this->attachment_data[$pos]['comment'], $_POST['attachment_data'][$pos]['comment'], 'string', true); + set_var($this->attachment_data[$pos]['attach_comment'], $_POST['attachment_data'][$pos]['attach_comment'], 'string', true); set_var($this->attachment_data[$pos]['real_filename'], $_POST['attachment_data'][$pos]['real_filename'], 'string', true); set_var($this->attachment_data[$pos]['filetime'], $_POST['attachment_data'][$pos]['filetime'], 'int'); @@ -1357,21 +1386,21 @@ class parse_message extends bbcode_firstpass // 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'], $poll['enable_urls'], $poll['enable_smilies'], $poll['img_status'], false, false, false); - $this->bbcode_bitfield |= $bbcode_bitfield; + $this->message = $tmp_message; // Parse Poll Title $tmp_message = $this->message; $this->message = $poll['poll_title']; - $bbcode_bitfield = $this->bbcode_bitfield; + $poll['poll_title'] = $this->parse($poll['enable_bbcode'], $poll['enable_urls'], $poll['enable_smilies'], $poll['img_status'], false, false, false); - $this->bbcode_bitfield |= $bbcode_bitfield; + $this->message = $tmp_message; unset($tmp_message); diff --git a/phpBB/includes/search/fulltext_mysql.php b/phpBB/includes/search/fulltext_mysql.php index b65818dad7..4a9a57df34 100644 --- a/phpBB/includes/search/fulltext_mysql.php +++ b/phpBB/includes/search/fulltext_mysql.php @@ -27,8 +27,11 @@ include_once($phpbb_root_path . 'includes/search/search.' . $phpEx); */ class fulltext_mysql extends search_backend { - var $stats; - var $word_length; + var $stats = array(); + var $word_length = array(); + var $split_words = array(); + var $search_query; + var $common_words = array(); function fulltext_mysql(&$error) { @@ -98,6 +101,7 @@ class fulltext_mysql extends search_backend /** * 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' @@ -157,6 +161,8 @@ class fulltext_mysql extends search_backend } } + $this->search_query = implode(' ', $this->split_words); + if (sizeof($this->split_words)) { $this->split_words = array_values($this->split_words); @@ -306,19 +312,19 @@ class fulltext_mysql extends search_backend } else { - $m_approve_fid_sql = ' AND (p.post_approved = 1 OR p.forum_id NOT IN (' . implode(', ', $m_approve_fid_ary) . '))'; + $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'; - $sql_author = (sizeof($author_ary) == 1) ? ' = ' . $author_ary[0] : 'IN (' . implode(',', $author_ary) . ')'; + $sql_author = (sizeof($author_ary) == 1) ? ' = ' . $author_ary[0] : 'IN (' . implode(', ', $author_ary) . ')'; $sql_where_options = $sql_sort_join; $sql_where_options .= ($topic_id) ? ' AND p.topic_id = ' . $topic_id : ''; $sql_where_options .= ($join_topic) ? ' AND t.topic_id = p.topic_id' : ''; - $sql_where_options .= (sizeof($ex_fid_ary)) ? ' AND p.forum_id NOT IN (' . implode(',', $ex_fid_ary) . ')' : ''; + $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 .= (sizeof($author_ary)) ? ' AND p.poster_id ' . $sql_author : ''; $sql_where_options .= ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : ''; @@ -445,8 +451,8 @@ class fulltext_mysql extends search_backend $id_ary = array(); // Create some display specific sql strings - $sql_author = 'p.poster_id ' . ((sizeof($author_ary) > 1) ? 'IN (' . implode(',', $author_ary) . ')' : '= ' . $author_ary[0]); - $sql_fora = (sizeof($ex_fid_ary)) ? ' AND p.forum_id NOT IN (' . implode(',', $ex_fid_ary) . ')' : ''; + $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)) : ''; @@ -481,7 +487,7 @@ class fulltext_mysql extends search_backend } else { - $m_approve_fid_sql = ' AND (p.post_approved = 1 OR p.forum_id IN (' . implode($m_approve_fid_ary) . '))'; + $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 @@ -555,7 +561,7 @@ class fulltext_mysql extends search_backend * * @param string $mode contains the post mode: edit, post, reply, quote ... */ - function index($mode, $post_id, &$message, &$subject, $poster_id) + function index($mode, $post_id, &$message, &$subject, $encoding, $poster_id, $forum_id) { global $db; @@ -606,7 +612,7 @@ class fulltext_mysql extends search_backend /** * Destroy cached results, that might be outdated after deleting a post */ - function index_remove($post_ids, $author_ids) + function index_remove($post_ids, $author_ids, $forum_ids) { $this->destroy_cache(array(), $author_ids); } @@ -637,7 +643,7 @@ class fulltext_mysql extends search_backend return $error; } - if (!is_array($this->stats)) + if (empty($this->stats)) { $this->get_stats(); } @@ -670,7 +676,7 @@ class fulltext_mysql extends search_backend return $error; } - if (!is_array($this->stats)) + if (empty($this->stats)) { $this->get_stats(); } @@ -695,7 +701,7 @@ class fulltext_mysql extends search_backend */ function index_created() { - if (!is_array($this->stats)) + if (empty($this->stats)) { $this->get_stats(); } @@ -710,7 +716,7 @@ class fulltext_mysql extends search_backend { global $user; - if (!is_array($this->stats)) + if (empty($this->stats)) { $this->get_stats(); } diff --git a/phpBB/includes/search/fulltext_native.php b/phpBB/includes/search/fulltext_native.php index eec7415dd8..bc11d2ed20 100755 --- a/phpBB/includes/search/fulltext_native.php +++ b/phpBB/includes/search/fulltext_native.php @@ -22,246 +22,305 @@ include_once($phpbb_root_path . 'includes/search/search.' . $phpEx); /** * fulltext_native -* phpBB's own db driven fulltext search +* phpBB's own db driven fulltext search, version 2 * @package search */ class fulltext_native extends search_backend { - var $stats; - var $word_length; + 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 $config; + 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); + } + if (!function_exists('utf8_strlen')) + { + include($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx); + } + + $error = false; } /** - * Splits keywords entered by a user into an array of words stored in $this->split_words + * 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. * - * @param string $keywords Contains the keyword as entered by the user - * @param string $terms is either 'all' or 'any' - * @return false if no valid keywords were found and otherwise true + * 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) + function split_keywords($keywords, $terms) { - global $db, $config; + global $db, $config, $user; - $drop_char_match = array('^', '$', '(', ')', '<', '>', '`', '\'', '"', ',', '@', '_', '?', '%', '~', '.', '[', ']', '{', '}', ':', '\\', '/', '=', '!', "\n", "\r"); - $drop_char_replace = array(' ', ' ', ' ', ' ', ' ', '', '', ' ', ' ', ' ', '', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '' , ' ', ' ', ' ', ' ', ' ', ' '); + // Clean up the query search + $match = array( + // Replace multiple spaces with a single space + '# +#', - $this->get_ignore_words(); - $this->get_synonyms(); + // Strip spaces after: +-|( + '#([+\\-|(]) #', - if ($terms == 'all') - { - $match = array('#\sand\s#i', '#\sor\s#i', '#\snot\s#i', '#\+#', '#-#', '#\|#'); - $replace = array(' + ', ' | ', ' - ', ' + ', ' - ', ' | '); - - $keywords = preg_replace($match, $replace, $keywords); - } + // Strip spaces before: |*) + '# ([|*)])#', - $match = array(); - // NCRs like etc. - $match[] = '#(&|&)[a-z0-9]+?;#i'; + // Make word|word|word work without brackets + '#^[^()]*\\|[^()]*$#', - // Filter out as above - $keywords = preg_replace($match, ' ', strtolower(trim($keywords))); + // Remove nested brackets + '#(\\([^()]*)(?=\\()#', + '#\\)([^()]*)(?=\\))#', + ); - // Filter out non alphabetical characters - $keywords = str_replace($drop_char_match, $drop_char_replace, $keywords); + $replace = array( + ' ', + '$1', + '$1', + '($0)', + '$1)', + '$1', + ); - // Filter out ; and # but not &#[0-9]+; - $keywords = preg_replace('#&\#([0-9]+);#', '<$1>', $keywords); - $keywords = str_replace(array(';', '&', '#'), ' ', $keywords); - $keywords = str_replace(array('<', '>'), array('&#', ';'), $keywords); + $keywords = trim(preg_replace($match, $replace, $this->cleanup($keywords, '+-|()*', $user->lang['ENCODING']))); - // Split words - $this->split_words = explode(' ', preg_replace('#\s+#', ' ', $keywords)); + // remove some useless bracket combinations which might be created by the previous regexps + $keywords = str_replace(array('()', ')|('), array('', '|'), $keywords); - if (sizeof($this->ignore_words)) - { - $this->common_words = array_intersect($this->split_words, $this->ignore_words); - $this->split_words = array_diff($this->split_words, $this->ignore_words); - } + // $keywords input format: each word seperated by a space, words in a bracket are not seperated - if (sizeof($this->match_synonym)) + // the user wants to search for any word, convert the search query + if ($terms == 'any') { - $this->split_words = str_replace($this->match_synonym, $this->replace_synonym, $this->split_words); - } + $words = array(); - $prefixes = array('+', '-', '|'); - $prefixed = false; - $in_words = ''; - - $lengths = $this->get_word_lengths($this->split_words); - - foreach ($this->split_words as $i => $word) - { - if (in_array($word, $prefixes)) + preg_match_all('#([^\\s+\\-|()]+)(?:$|[\\s+\\-|()])#', $keywords, $words); + if (sizeof($words[1])) { - $prefixed = true; - continue; + $keywords = '(' . implode('|', $words[1]) . ')'; } - - // check word length - if (($lengths[$i] < $config['fulltext_native_min_chars']) || ($lengths[$i] > $config['fulltext_native_max_chars'])) - { - if ($prefixed) - { - $this->common_words[] = $this->split_words[$i - 1]; - unset($this->split_words[$i - 1]); - } - $this->common_words[] = $this->split_words[$i]; - unset($this->split_words[$i]); - } - else if (strpos($word, '*') === false) - { - $in_words .= (($in_words) ? ', ' : '') . '\'' . $db->sql_escape($word) . '\''; - } - - $prefixed = false; } - unset($lengths); + // set the search_query which is shown to the user + $this->search_query = utf8_encode_ncr($keywords, ENT_QUOTES); + + $exact_words = array(); + preg_match_all('#([^\\s+\\-|*()]+)(?:$|[\\s+\\-|()])#', $keywords, $exact_words); + $exact_words = $exact_words[1]; - if ($in_words) + if (sizeof($exact_words)) { - // identify common words and ignore them - $sql = 'SELECT word_text - FROM ' . SEARCH_WORDLIST_TABLE . " - WHERE word_text IN ($in_words) - AND word_common = 1"; + $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)) { - $key = array_search($row['word_text'], $this->split_words); - - if (isset($this->split_words[$key - 1]) && (in_array($this->split_words[$key - 1], $prefixes))) + if ($row['word_common']) { - $this->common_words[] = $this->split_words[$key - 1]; - unset($this->split_words[$key - 1]); + $this->common_words[] = $row['wort_text']; + continue; } - $this->common_words[] = $row['word_text']; - unset($this->split_words[$key]); + + $words[$row['word_text']] = (int) $row['word_id']; } $db->sql_freeresult($result); } + unset($exact_words); - if (sizeof($this->split_words)) - { - $this->split_words = array_values($this->split_words); - sort($this->split_words); - return true; - } - return false; - } + // now analyse the search query, first split it using the spaces + $query = explode(' ', $keywords); - /** - * Returns any array of string lengths for the given array of strings - * It counts multibyte entities as single characters and ignores "*" - * - * @param array $words an array of strings - * - * @return Array of string lengths - */ - function get_word_lengths($words) - { - return array_map('strlen', str_replace('*', '', preg_replace('#&\#[0-9]+;#', 'x', $words))); - } - - /** - * Turns text into an array of words that can be stored in the word list table - */ - function split_message($text) - { - global $config; + $this->must_contain_ids = array(); + $this->must_not_contain_ids = array(); + $this->must_exclude_one_ids = array(); - static $drop_char_match, $drop_char_replace; + $mode = ''; + $ignore_no_id = true; - $this->get_ignore_words(); - $this->get_synonyms(); - - if (!is_array($drop_char_match)) + foreach ($query as $word) { - $drop_char_match = array('-', '^', '$', '(', ')', '<', '>', '`', '\'', '"', '|', ',', '@', '_', '?', '%', '~', '.', '[', ']', '{', '}', ':', '\\', '/', '=', '\'', '!', '*', '+', "\n", "\r"); - $drop_char_replace = array(' ', ' ', ' ', ' ', ' ', ' ', ' ', '', '', ' ', ' ', ' ', ' ', '', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '' , ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '); - } - - $match = array(); - // Comments for hardcoded bbcode elements (urls, smilies, html) - $match[] = '#<!\-\- .* \-\->(.*?)<!\-\- .* \-\->#is'; - // NCRs like etc. - $match[] = '#(&|&)[a-z0-9]+;#i'; - // Do not index code - $match[] = '#\[code(?:=.*?)?(\:?[0-9a-z]{5,})\].*?\[\/code(\:?[0-9a-z]{5,})\]#is'; - // BBcode - $match[] = '#\[\/?[a-z\*\+\-]+(?:=.*?)?(\:?[0-9a-z]{5,})\]#'; - - $text = preg_replace($match, ' ', ' ' . strtolower(trim($text)) . ' '); + if (empty($word)) + { + continue; + } - // Filter out non-alphabetical chars - $text = str_replace($drop_char_match, $drop_char_replace, $text); + // words which should not be included + if ($word[0] == '-') + { + $word = substr($word, 1); - // Filter out ; and # but not &#[0-9]+; - $text = preg_replace('#&\#([0-9]+);#', '<$1>', $text); - $text = str_replace(array(';', '&', '#'), ' ', $text); - $text = str_replace(array('<', '>'), array('&#', ';'), $text); + // a group of which at least one may not be in the resulting posts + if ($word[0] == '(') + { + $word = 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); + } - // Split words - $text = explode(' ', preg_replace('#\s+#', ' ', trim($text))); + // a group of words of which at least one word should be in every resulting post + if ($word[0] == '(') + { + $word = explode('|', substr($word, 1, -1)); + } + $ignore_no_id = false; + $mode = 'must_contain'; + } - if (sizeof($this->ignore_words)) - { - $text = array_diff($text, $this->ignore_words); + // if this is an array of words then retrieve an id for each + if (is_array($word)) + { + $id_words = array(); + foreach ($word as $i => $word_part) + { + if (strpos($word_part, '*') !== false) + { + $id_words[] = '\'' . $db->sql_escape(str_replace('*', '%', $word_part)) . '\''; + } + if (isset($words[$word_part])) + { + $id_words[] = $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) + { + trigger_error(sprintf($user->lang['WORDS_IN_NO_POST'], utf8_encode_ncr(implode(', ', $word)))); + } + } + // else we only need one id + else if (($wildcard = strpos($word, '*') !== false) || isset($words[$word])) + { + if ($wildcard) + { + $this->{$mode . '_ids'}[] = '\'' . $db->sql_escape(str_replace('*', '%', $word)) . '\''; + } + else + { + $this->{$mode . '_ids'}[] = $words[$word]; + } + } + // throw an error if we shall not ignore unexistant words + else if (!$ignore_no_id) + { + trigger_error(sprintf($user->lang['WORD_IN_NO_POST'], utf8_encode_ncr($word))); + } } - if (sizeof($this->match_synonym)) + // we can't search for negatives only + if (!sizeof($this->must_contain_ids)) { - $text = str_replace($this->match_synonym, $this->replace_synonym, $text); + return false; } - // remove too short or too long words - $text = array_map('trim', array_values($text)); - - $lengths = $this->get_word_lengths($text); + sort($this->must_contain_ids); + sort($this->must_not_contain_ids); + sort($this->must_exclude_one_ids); - for ($i = 0, $n = sizeof($text); $i < $n; $i++) + if (!empty($this->search_query)) { - if ($lengths[$i] < $config['fulltext_native_min_chars'] || $lengths[$i] > $config['fulltext_native_max_chars']) - { - unset($text[$i]); - } + return true; } - - return $text; + return false; } /** - * Performs a search on keywords depending on display specific params. + * Performs a search on keywords depending on display specific params. You have to run split_keywords() first. + * + * @param string $type contains either posts or topics depending on what should be searched for + * @param string $fields contains either titleonly (topic titles should be searched), msgonly (only message bodies should be searched), firstpost (only subject and body of the first post should be searched) or all (all post bodies and subjects should be searched) + * @param string $terms is either 'all' (use query as entered, words without prefix should default to "have to be in field") or 'any' (ignore search query parts and just return all posts that contain any of the specified words) + * @param array $sort_by_sql contains SQL code for the ORDER BY part of a query + * @param string $sort_key is the key of $sort_by_sql for the selected sorting + * @param string $sort_dir is either a or d representing ASC and DESC + * @param string $sort_days specifies the maximum amount of days a post may be old + * @param array $ex_fid_ary specifies an array of forum ids which should not be searched + * @param array $m_approve_fid_ary specifies an array of forum ids in which the searcher is allowed to view unapproved posts + * @param int $topic_id is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched + * @param array $author_ary an array of author ids if the author should be ignored during the search the array is empty + * @param array $id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered + * @param int $start indicates the first index of the page + * @param int $per_page number of ids each page is supposed to contain + * @return boolean|int total number of results * - * @param array $id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered - * @param int $start indicates the first index of the page - * @param int $per_page number of ids each page is supposed to contain - * @return total number of results + * @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, &$id_ary, $start, $per_page) { global $config, $db; // No keywords? No posts. - if (!sizeof($this->split_words)) + if (empty($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), + serialize($this->must_contain_ids), + serialize($this->must_not_contain_ids), + serialize($this->must_exclude_one_ids), $type, $fields, $terms, @@ -274,323 +333,328 @@ class fulltext_native extends search_backend ))); // 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) + $total_results = 0; + if ($this->obtain_ids($search_key, $total_results, $id_ary, $start, $per_page, $sort_dir) == SEARCH_RESULT_IN_CACHE) { - return $result_count; + return $total_results; } - $result_count = 0; $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 = ''; + $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(), + POSTS_TABLE => 'p' + ), + 'LEFT_JOIN' => array() + ); + $sql_where[] = 'm0.post_id = p.post_id'; - switch ($sql_sort[0]) + if ($type == 'topics') { - case 'u': - $sql_sort_table = USERS_TABLE . ' u, '; - $sql_sort_join = ' AND u.user_id = p.poster_id '; - 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; - + $sql_array['FROM'][TOPICS_TABLE] = 't'; + $group_by = true; } + $title_match = ''; + $group_by = true; // Build some display specific sql strings switch ($fields) { case 'titleonly': - $sql_match = ' AND m.title_match = 1 AND p.post_id = t.topic_first_post_id'; - $join_topic = true; + $title_match = 'title_match = 1'; + $group_by = false; + // no break + case 'firstpost': + $sql_array['FROM'][TOPICS_TABLE] = 't'; + $sql_where[] = 'p.post_id = t.topic_first_post_id'; break; case 'msgonly': - $sql_match = ' AND m.title_match = 0'; + $title_match = 'title_match = 0'; + $group_by = false; break; - - case 'firstpost': - $sql_match = ' AND p.post_id = t.topic_first_post_id'; - $join_topic = true; - break; - - default: - $sql_match = ''; } - 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 p.forum_id NOT IN (' . implode(', ', $m_approve_fid_ary) . '))'; - } + /** + * @todo Add a query optimizer (handle stuff like "+(4|3) +4") + */ - $sql_select = ($type == 'posts') ? 'm.post_id' : 'DISTINCT t.topic_id'; - $sql_from = ($join_topic) ? TOPICS_TABLE . ' t, ' : ''; - $field = ($type == 'posts') ? 'm.post_id' : 't.topic_id'; - $sql_author = (sizeof($author_ary) == 1) ? ' = ' . $author_ary[0] : 'IN (' . implode(',', $author_ary) . ')'; - - $sql_where_options = $sql_sort_join; - $sql_where_options .= ($topic_id) ? ' AND p.topic_id = ' . $topic_id : ''; - $sql_where_options .= ($join_topic) ? ' AND t.topic_id = p.topic_id' : ''; - $sql_where_options .= (sizeof($ex_fid_ary)) ? ' AND p.forum_id NOT IN (' . implode(',', $ex_fid_ary) . ')' : ''; - $sql_where_options .= $m_approve_fid_sql; - $sql_where_options .= (sizeof($author_ary)) ? ' AND p.poster_id ' . $sql_author : ''; - $sql_where_options .= ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : ''; - $sql_where_options .= $sql_match; - - // split the words into three arrays (AND, OR, NOT) - $sql_words = array('AND' => array(), 'OR' => array(), 'NOT' => array()); - $bool = ($terms == 'all') ? 'AND' : 'OR'; - - foreach ($this->split_words as $word) + foreach ($this->must_contain_ids as $subquery) { - switch ($word) + if (is_array($subquery)) { - case '-': - $bool = 'NOT'; - continue; - - case '+': - $bool = 'AND'; - continue; - - case '|': - $bool = 'OR'; - continue; + $group_by = true; - default: - $bool = ($terms != 'all') ? 'OR' : $bool; - $sql_words[$bool][] = "'" . $db->sql_escape(preg_replace('#\*+#', '%', trim($word))) . "'"; - $bool = ($terms == 'all') ? 'AND' : 'OR'; - break; - } - } - - // Select all post_ids that contain all AND-words - $result_ary= array('AND' => array(), 'OR' => array(), 'NOT' => array()); - if (sizeof($sql_words['AND'])) - { - $sql_in = ''; - foreach ($sql_words['AND'] as $word) - { - // first select all post ids that match a word containing a wildcard - if (strstr($word, '%')) + $word_id_sql = array(); + $word_ids = array(); + foreach ($subquery as $id) { - $sql = "SELECT $sql_select - FROM $sql_from$sql_sort_table" . POSTS_TABLE . ' p, ' . SEARCH_WORDMATCH_TABLE . ' m, ' . SEARCH_WORDLIST_TABLE . " w - WHERE w.word_text LIKE $word - AND m.word_id = w.word_id - AND w.word_common <> 1 - AND p.post_id = m.post_id - $sql_where_options - GROUP BY $field - ORDER BY $sql_sort"; - $result = $db->sql_query($sql); - - if (!($row = $db->sql_fetchrow($result))) - { - $db->sql_freeresult($result); - $id_ary = array(); - return false; - } - - $ids = array(); - do - { - $ids[] = ($type == 'topics') ? $row['topic_id'] : $row['post_id']; - } - while ($row = $db->sql_fetchrow($result)); - $db->sql_freeresult($result); - - // remove ids that are not present in all AND-word results - if (sizeof($result_ary['AND'])) + if (is_string($id)) { - $result_ary['AND'] = array_intersect($result_ary['AND'], $ids); + $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 { - $result_ary['AND'] = $ids; + $word_ids[] = $id; } - unset($ids); - } - else - { - $sql_in .= (($sql_in) ? ', ' : '') . $word; } + + $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; - if ($sql_in) + $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 = "SELECT $sql_select, COUNT(DISTINCT m.word_id) as matches, " . $sort_by_sql[$sort_key] . " - FROM $sql_from$sql_sort_table" . POSTS_TABLE . ' p, ' . SEARCH_WORDMATCH_TABLE . ' m, ' . SEARCH_WORDLIST_TABLE . " w - WHERE w.word_text IN ($sql_in) - AND m.word_id = w.word_id - AND w.word_common <> 1 - AND p.post_id = m.post_id - $sql_where_options - GROUP BY $field, " . $sort_by_sql[$sort_key] . ' - ORDER BY ' . $sql_sort; - $result = $db->sql_query($sql); + $sql_where[] = "m$m_num.word_id = $subquery"; + } + + $sql_array['FROM'][SEARCH_WORDMATCH_TABLE][] = 'm' . $m_num; - if (!($row = $db->sql_fetchrow($result))) - { - $db->sql_freeresult($result); - $id_ary = array(); - return false; - } + if ($title_match) + { + $sql_where[] = "m$m_num.$title_match"; + } - // A little trick so we only need one query: using DISTINCT makes every word unique so if the - // number of all words for one post_id equals the number of AND-words it has to contain all - // AND-words - $ids = array(); - do - { - if ($row['matches'] == sizeof($sql_words['AND'])) - { - $ids[] = ($type == 'topics') ? $row['topic_id'] : $row['post_id']; - } - } - while ($row = $db->sql_fetchrow($result)); - $db->sql_freeresult($result); + if ($m_num != 0) + { + $sql_where[] = "m$m_num.post_id = m0.post_id"; + } + $m_num++; + } - // remove ids that are not present in all AND-word results - if (sizeof($result_ary['AND'])) - { - $result_ary['AND'] = array_intersect($result_ary['AND'], $ids); - } - else - { - $result_ary['AND'] = $ids; - } - unset($ids); + 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++; } } - // Select all post_ids that contain one of the OR-words - if (sizeof($sql_words['OR'])) + if (sizeof($this->must_not_contain_ids)) { - $sql_where = $sql_in = ''; - foreach ($sql_words['OR'] as $word) + $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 (strstr($word, '%')) + if (is_string($id)) { - $sql_where .= (($sql_where) ? ' OR w.word_text ' : 'w.word_text ') . "LIKE $word"; + $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++; } - else - { - $sql_in .= (($sql_in) ? ', ' : '') . $word; - } - } - $sql_where = ($sql_in) ? $sql_where . (($sql_where) ? ' OR ' : '') . 'w.word_text IN (' . $sql_in . ')' : $sql_where; - - $sql = "SELECT $sql_select - FROM $sql_from$sql_sort_table" . POSTS_TABLE . ' p, ' . SEARCH_WORDMATCH_TABLE . ' m, ' . SEARCH_WORDLIST_TABLE . " w - WHERE ($sql_where) - AND m.word_id = w.word_id - AND w.word_common <> 1 - AND p.post_id = m.post_id - $sql_where_options - ORDER BY $sql_sort"; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - $result_ary['OR'][] = ($type == 'topics') ? $row['topic_id'] : $row['post_id']; + $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++; } - $db->sql_freeresult($result); + $sql_where[] = '(' . implode(' OR ', $is_null_joins) . ')'; } - // remove post_ids that do not contain any OR-word - if (sizeof($result_ary['OR'])) + if (!sizeof($m_approve_fid_ary)) { - $id_ary = (sizeof($result_ary['AND'])) ? array_intersect($result_ary['AND'], $result_ary['OR']) : $result_ary['OR']; + $sql_where[] = 'p.post_approved = 1'; } - else + 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)) { - $id_ary = (sizeof($result_ary['AND'])) ? $result_ary['AND'] : array(); + $sql_where[] = $db->sql_in_set('p.poster_id', $author_ary); } - unset($result_ary['AND']); - unset($result_ary['OR']); + if (sizeof($ex_fid_ary)) + { + $sql_where[] = $db->sql_in_set('p.forum_id', $ex_fid_ary, true); + } - // remove all post_ids that contain a NOT-word - if (sizeof($sql_words['NOT']) && sizeof($id_ary)) + if ($sort_days) { - $sql_where = $sql_in = ''; - foreach ($sql_words['NOT'] as $word) + $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; + + switch (SQL_LAYER) { - if (strstr($word, '%')) - { - $sql_where .= (($sql_where) ? ' OR w.word_text ' : 'w.word_text ') . "LIKE $word"; - } - else + case 'mysql': + case 'mysql4': + case 'mysqli': + $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': + if (!isset($sql_array['FROM'][TOPICS_TABLE])) { - $sql_in .= (($sql_in) ? ', ' : '') . $word; + $sql_array['FROM'][TOPICS_TABLE] = 't'; + $sql_where[] = 'p.topic_id = t.topic_id'; } - } - $sql_where = ($sql_in) ? $sql_where . (($sql_where) ? ' OR ' : '') . 'w.word_text IN (' . $sql_in . ')' : $sql_where; - - $sql = "SELECT $sql_select - FROM $sql_from" . POSTS_TABLE . ' p, ' . SEARCH_WORDMATCH_TABLE . ' m, ' . SEARCH_WORDLIST_TABLE . " w - WHERE ($sql_where) - AND m.word_id = w.word_id - AND w.word_common <> 1 - AND p.post_id = m.post_id - $sql_where_options"; - $result = $db->sql_query($sql); + break; - while ($row = $db->sql_fetchrow($result)) - { - $result_ary['NOT'][] = ($type == 'topics') ? $row['topic_id'] : $row['post_id']; - } - $db->sql_freeresult($result); + case 'f': + $sql_array['FROM'][FORUMS_TABLE] = 'f'; + $sql_where[] = 'f.forum_id = p.forum_id'; + break; } - if (sizeof($result_ary['NOT'])) + $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 = (sizeof($id_ary)) ? array_diff($id_ary, $result_ary['NOT']) : array(); + $id_ary[] = $row[(($type == 'posts') ? 'post_id' : 'topic_id')]; } - unset($result_ary); + $db->sql_freeresult($result); if (!sizeof($id_ary)) { return false; } - $result_count = sizeof($id_ary); + // if we use mysql and the total result count is not cached yet, retrieve it from the db + if (!$total_results && $is_mysql) + { + $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 - $id_ary = array_slice($id_ary, $start); - $this->save_ids($search_key, implode(' ', $this->split_words), $author_ary, $result_count, $id_ary, $start, $sort_dir); + $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 $result_count; + return $total_results; } /** * Performs a search on an author's posts without caring about message contents. Depends on display specific params * - * @param array $id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered - * @param int $start indicates the first index of the page - * @param int $per_page number of ids each page is supposed to contain - * @return total number of results + * @param string $type contains either posts or topics depending on what should be searched for + * @param array $sort_by_sql contains SQL code for the ORDER BY part of a query + * @param string $sort_key is the key of $sort_by_sql for the selected sorting + * @param string $sort_dir is either a or d representing ASC and DESC + * @param string $sort_days specifies the maximum amount of days a post may be old + * @param array $ex_fid_ary specifies an array of forum ids which should not be searched + * @param array $m_approve_fid_ary specifies an array of forum ids in which the searcher is allowed to view unapproved posts + * @param int $topic_id is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched + * @param array $author_ary an array of author ids + * @param array $id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered + * @param int $start indicates the first index of the page + * @param int $per_page number of ids each page is supposed to contain + * @return boolean|int total number of results + * + * @access public */ function author_search($type, &$sort_by_sql, &$sort_key, &$sort_dir, &$sort_days, &$ex_fid_ary, &$m_approve_fid_ary, &$topic_id, &$author_ary, &$id_ary, $start, $per_page) { @@ -617,17 +681,17 @@ class fulltext_native extends search_backend ))); // 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) + $total_results = 0; + if ($this->obtain_ids($search_key, $total_results, $id_ary, $start, $per_page, $sort_dir) == SEARCH_RESULT_IN_CACHE) { - return $result_count; + return $total_results; } $id_ary = array(); // Create some display specific sql strings - $sql_author = 'p.poster_id ' . ((sizeof($author_ary) > 1) ? 'IN (' . implode(',', $author_ary) . ')' : '= ' . $author_ary[0]); - $sql_fora = (sizeof($ex_fid_ary)) ? ' AND p.forum_id NOT IN (' . implode(',', $ex_fid_ary) . ')' : ''; + $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 : ''; @@ -662,47 +726,73 @@ class fulltext_native extends search_backend } else { - $m_approve_fid_sql = ' AND (p.post_approved = 1 OR p.forum_id IN (' . implode($m_approve_fid_ary) . '))'; + $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 (!$result_count) + if (!$total_results) { - if ($type == 'posts') - { - $sql = 'SELECT COUNT(p.post_id) as result_count - FROM ' . POSTS_TABLE . " p - WHERE $sql_author - $sql_topic_id - $m_approve_fid_sql - $sql_fora - $sql_time"; - } - else + switch (SQL_LAYER) { - $sql = 'SELECT COUNT(DISTINCT t.topic_id) as result_count - FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p - WHERE $sql_author - $sql_topic_id - $m_approve_fid_sql - $sql_fora - AND t.topic_id = p.topic_id - $sql_time"; - } - $result = $db->sql_query($sql); + case 'mysql': + case 'mysql4': + case 'mysqli': + $select = 'SQL_CALC_FOUND_ROWS ' . $select; + $is_mysql = true; + break; - if ($row = $db->sql_fetchrow()) - { - $result_count = $row['result_count']; + default: + if ($type == 'posts') + { + $sql = 'SELECT COUNT(p.post_id) as total_results + FROM ' . POSTS_TABLE . " p + WHERE $sql_author + $sql_topic_id + $m_approve_fid_sql + $sql_fora + $sql_time"; + } + else + { + if (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 + $m_approve_fid_sql + $sql_fora + AND t.topic_id = p.topic_id + $sql_time" . ((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; } - $db->sql_freeresult($result); } // Build the query for really selecting the post_ids if ($type == 'posts') { - $sql = 'SELECT p.post_id - FROM ' . $sql_sort_table . POSTS_TABLE . ' p' . (($topic_id) ? ', ' . TOPICS_TABLE . ' t' : '') . " + $sql = "SELECT $select + FROM " . $sql_sort_table . POSTS_TABLE . ' p' . (($topic_id) ? ', ' . TOPICS_TABLE . ' t' : '') . " WHERE $sql_author $sql_topic_id $m_approve_fid_sql @@ -714,8 +804,8 @@ class fulltext_native extends search_backend } else { - $sql = 'SELECT t.topic_id - FROM ' . $sql_sort_table . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p + $sql = "SELECT $select + FROM " . $sql_sort_table . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p WHERE $sql_author $sql_topic_id $m_approve_fid_sql @@ -737,35 +827,140 @@ class fulltext_native extends search_backend } $db->sql_freeresult($result); + if (!$total_results && $is_mysql) + { + $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, $result_count, $id_ary, $start, $sort_dir); + $this->save_ids($search_key, '', $author_ary, $total_results, $id_ary, $start, $sort_dir); $id_ary = array_slice($id_ary, 0, $per_page); - return $result_count; + 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 user's encoding + * @return array Array of UTF-8 words + * + * @access private + */ + function split_message($text) + { + global $phpbb_root_path, $phpEx; + global $config, $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-z\*\+\-]+(?:=.*?)?(\:?[0-9a-z]{5,})\]#'; + + $min = $config['fulltext_native_min_chars']; + $max = $config['fulltext_native_max_chars']; + + $isset_min = $min - 1; + + /** + * Clean up the string, remove HTML tags, remove BBCodes + */ + $word = strtok($this->cleanup(preg_replace($match, ' ', strip_tags($text)), '', $user->lang['ENCODING']), ' '); + + while (isset($word[0])) + { + if (isset($word[252]) + || !isset($word[$isset_min])) + { + /** + * Words longer than 252 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 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 string $encoding The post content's encoding + * @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) + function index($mode, $post_id, &$message, &$subject, $encoding, $poster_id, $forum_id) { - global $config, $db; + global $config, $db, $user; - // 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']) { + /** + * 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 = ($subject) ? $this->split_message($subject) : array(); + $split_title = $this->split_message($subject); + $cur_words = array('post' => array(), 'title' => array()); $words = array(); @@ -815,7 +1010,7 @@ class fulltext_native extends search_backend { $sql = 'SELECT word_id, word_text FROM ' . SEARCH_WORDLIST_TABLE . ' - WHERE word_text IN (' . implode(', ', preg_replace('#^(.*)$#', '\'$1\'', $unique_add_words)) . ')'; + WHERE ' . $db->sql_in_set('word_text', $unique_add_words); $result = $db->sql_query($sql); $word_ids = array(); @@ -825,27 +1020,17 @@ class fulltext_native extends search_backend } $db->sql_freeresult($result); - $new_words = array_map(array(&$db, 'sql_escape'), array_diff($unique_add_words, array_keys($word_ids))); + $new_words = array_diff($unique_add_words, array_keys($word_ids)); if (sizeof($new_words)) { switch (SQL_LAYER) { case 'mysql': - $sql = 'INSERT INTO ' . SEARCH_WORDLIST_TABLE . ' (word_text) - VALUES ' . implode(', ', preg_replace('#^(.*)$#', '(\'$1\')', $new_words)); - $db->sql_query($sql); - break; - case 'mysql4': case 'mysqli': - case 'mssql': - case 'mssql_odbc': - case 'sqlite': - // make sure the longest word comes first, so nothing will be truncated - usort($new_words, array(&$this, 'strlencmp')); - - $sql = 'INSERT INTO ' . SEARCH_WORDLIST_TABLE . ' (word_text) ' . implode(' UNION ALL ', preg_replace('#^(.*)$#', "SELECT '\$1'", $new_words)); + $sql = 'INSERT INTO ' . SEARCH_WORDLIST_TABLE . " (word_text) + VALUES ('" . implode("'),('", array_map(array(&$db, 'sql_escape'), $new_words)) . "')"; $db->sql_query($sql); break; @@ -853,7 +1038,7 @@ class fulltext_native extends search_backend foreach ($new_words as $word) { $sql = 'INSERT INTO ' . SEARCH_WORDLIST_TABLE . " (word_text) - VALUES ('$word')"; + VALUES ('" . $db->sql_escape($word) . "')"; $db->sql_query($sql); } } @@ -875,7 +1060,7 @@ class fulltext_native extends search_backend } $sql = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE . ' - WHERE word_id IN (' . implode(', ', $sql_in) . ') + WHERE ' . $db->sql_in_set('word_id', $sql_in) . ' AND post_id = ' . intval($post_id) . " AND title_match = $title_match"; $db->sql_query($sql); @@ -892,7 +1077,7 @@ class fulltext_native extends search_backend $sql = 'INSERT INTO ' . SEARCH_WORDMATCH_TABLE . " (post_id, word_id, title_match) SELECT $post_id, word_id, $title_match FROM " . SEARCH_WORDLIST_TABLE . ' - WHERE word_text IN (' . implode(', ', preg_replace('#^(.*)$#', '\'$1\'', $word_ary)) . ')'; + WHERE ' . $db->sql_in_set('word_text', $word_ary); $db->sql_query($sql); } } @@ -924,16 +1109,18 @@ class fulltext_native extends search_backend /** * Removes entries from the wordmatch table for the specified post_ids */ - function index_remove($post_ids, $author_ids) + function index_remove($post_ids, $author_ids, $forum_ids) { global $db; - $sql = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE . ' - WHERE post_id IN (' . implode(', ', $post_ids) . ')'; - $db->sql_query($sql); + if (sizeof($post_ids)) + { + $sql = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE . ' + WHERE ' . $db->sql_in_set('post_id', $post_ids); + $db->sql_query($sql); + } // SEARCH_WORDLIST_TABLE will be updated by tidy() - $this->destroy_cache(array(), $author_ids); } @@ -958,63 +1145,47 @@ class fulltext_native extends search_backend // Remove common (> 60% of posts ) words if ($config['num_posts'] >= 100) { + // First, get the IDs of common words $sql = 'SELECT word_id FROM ' . SEARCH_WORDMATCH_TABLE . ' GROUP BY word_id HAVING COUNT(word_id) > ' . floor($config['num_posts'] * 0.6); $result = $db->sql_query($sql); - if ($row = $db->sql_fetchrow($result)) + $sql_in = array(); + while ($row = $db->sql_fetchrow($result)) { - $sql_in = array(); - do - { - $sql_in[] = $row['word_id']; - } - while ($row = $db->sql_fetchrow($result)); + $sql_in[] = $row['word_id']; + } + $db->sql_freeresult($result); - $destroy_cache_words = $sql_in; + if (sizeof($sql_in)) + { + // Get the text of those new common words + $sql = 'SELECT word_text + FROM ' . SEARCH_WORDLIST_TABLE . ' + WHERE ' . $db->sql_in_set('word_id', $sql_in); + $result = $db->sql_query($sql); - $sql_in = implode(', ', $sql_in); + while ($row = $db->sql_fetchrow($result)) + { + $destroy_cache_words[] = $row['word_text']; + } + $db->sql_freeresult($result); - $sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . " + // Flag the words + $sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . ' SET word_common = 1 - WHERE word_id IN ($sql_in)"; + WHERE ' . $db->sql_in_set('word_id', $sql_in); $db->sql_query($sql); - $sql = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE . " - WHERE word_id IN ($sql_in)"; + // 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); } - $db->sql_freeresult($result); - } - - // Remove words with no matches ... this is a potentially nasty query - $sql = 'SELECT w.word_id - FROM ' . SEARCH_WORDLIST_TABLE . ' w - LEFT JOIN ' . SEARCH_WORDMATCH_TABLE . ' m ON (w.word_id = m.word_id) - WHERE w.word_common = 0 AND m.word_id IS NULL - GROUP BY w.word_id'; - $result = $db->sql_query($sql); - - if ($row = $db->sql_fetchrow($result)) - { - $sql_in = array(); - do - { - $sql_in[] = $row['word_id']; - } - while ($row = $db->sql_fetchrow($result)); - - $destroy_cache_words = array_merge($destroy_cache_words, $sql_in); - - $sql = 'DELETE FROM ' . SEARCH_WORDLIST_TABLE . ' - WHERE word_id IN (' . implode(', ', $sql_in) . ')'; - $db->sql_query($sql); unset($sql_in); } - $db->sql_freeresult($result); // destroy cached search results containing any of the words that are now common or were removed $this->destroy_cache(array_unique($destroy_cache_words)); @@ -1039,7 +1210,7 @@ class fulltext_native extends search_backend */ function index_created() { - if (!is_array($this->stats)) + if (!sizeof($this->stats)) { $this->get_stats(); } @@ -1054,7 +1225,7 @@ class fulltext_native extends search_backend { global $user; - if (!is_array($this->stats)) + if (!sizeof($this->stats)) { $this->get_stats(); } @@ -1082,12 +1253,259 @@ class fulltext_native extends search_backend } /** + * 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 + */ + function cleanup($text, $allowed_chars = null, $encoding = 'iso-8859-1') + { + 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 = html_entity_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 + */ + $text = 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> diff --git a/phpBB/includes/search/search.php b/phpBB/includes/search/search.php index 6fcacac483..fa91b9eef5 100755 --- a/phpBB/includes/search/search.php +++ b/phpBB/includes/search/search.php @@ -33,8 +33,6 @@ class search_backend var $ignore_words = array(); var $match_synonym = array(); var $replace_synonym = array(); - var $split_words = array(); - var $common_words = array(); function search_backend(&$error) { @@ -196,7 +194,7 @@ class search_backend } $db->sql_freeresult($result); } - //set_config('last_search_time', time()); + $sql = 'UPDATE ' . USERS_TABLE . ' SET user_last_search = ' . time() . ' WHERE user_id = ' . $user->data['user_id']; diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php index 09ae84a210..64a203e0bf 100644 --- a/phpBB/includes/session.php +++ b/phpBB/includes/session.php @@ -51,7 +51,7 @@ class session // Now, remove the sid and let us get a clean query string... foreach ($args as $key => $argument) { - if (strpos($argument, 'sid=') === 0) + if (strpos($argument, 'sid=') === 0 || strpos($argument, '_f_=') === 0) { unset($args[$key]); break; @@ -67,8 +67,8 @@ class session $page_name = htmlspecialchars(basename($script_name)); // current directory within the phpBB root (for example: adm) - $root_dirs = explode('/', str_replace('\\', '/', realpath($root_path))); - $page_dirs = explode('/', str_replace('\\', '/', realpath('./'))); + $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); @@ -106,8 +106,8 @@ class session 'page_dir' => $page_dir, 'query_string' => $query_string, - 'script_path' => htmlspecialchars($script_path), - 'root_script_path' => htmlspecialchars($root_script_path), + 'script_path' => str_replace(' ', '%20', htmlspecialchars($script_path)), + 'root_script_path' => str_replace(' ', '%20', htmlspecialchars($root_script_path)), 'page' => $page ); @@ -143,7 +143,8 @@ class session $this->host = (!empty($_SERVER['HTTP_HOST'])) ? (string) $_SERVER['HTTP_HOST'] : 'localhost'; $this->page = $this->extract_current_page($phpbb_root_path); - $this->page['page'] .= (isset($_POST['f'])) ? ((strpos($this->page['page'], '?') !== false) ? '&' : '?') . 'f=' . intval($_POST['f']) : ''; + // Add forum to the page for tracking online users - also adding a "x" to the end to properly identify the number + $this->page['page'] .= (isset($_REQUEST['f'])) ? ((strpos($this->page['page'], '?') !== false) ? '&' : '?') . '_f_=' . (int) $_REQUEST['f'] . 'x' : ''; if (isset($_COOKIE[$config['cookie_name'] . '_sid']) || isset($_COOKIE[$config['cookie_name'] . '_u'])) { @@ -156,6 +157,13 @@ class session $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 { @@ -171,17 +179,10 @@ class session // Load limit check (if applicable) if ($config['limit_load']) { - if (@file_exists('/proc/loadavg') && @is_readable('/proc/loadavg')) + if ($load = @file_get_contents('/proc/loadavg')) { - if ($load = @file_get_contents('/proc/loadavg')) - { - $this->load = array_slice(explode(' ', $load), 0, 1); - $this->load = floatval($this->load[0]); - } - else - { - set_config('limit_load', '0'); - } + $this->load = array_slice(explode(' ', $load), 0, 1); + $this->load = floatval($this->load[0]); } else { @@ -206,7 +207,7 @@ class session // 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']; - + $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'])); @@ -219,18 +220,14 @@ class session // 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); - if (file_exists($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx)) + $method = 'validate_session_' . $method; + if (function_exists($method)) { - include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx); - - $method = 'validate_session_' . $method; - if (function_exists($method)) + if (!$method($this->data)) { - if (!$method($this->data)) - { - $session_expired = true; - } + $session_expired = true; } } @@ -356,21 +353,17 @@ class session } $method = basename(trim($config['auth_method'])); + include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx); - if (file_exists($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx)) + $method = 'autologin_' . $method; + if (function_exists($method)) { - include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx); + $this->data = $method(); - $method = 'autologin_' . $method; - if (function_exists($method)) + if (sizeof($this->data)) { - $this->data = $method(); - - if (sizeof($this->data)) - { - $this->cookie_data['k'] = ''; - $this->cookie_data['u'] = $this->data['user_id']; - } + $this->cookie_data['k'] = ''; + $this->cookie_data['u'] = $this->data['user_id']; } } @@ -420,7 +413,7 @@ class session $db->sql_freeresult($result); } - if ($this->data['user_id'] != ANONYMOUS) + 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()); } @@ -437,7 +430,7 @@ class session // @todo Change to !$this->data['user_type'] & USER_FOUNDER && !$this->data['user_type'] & USER_BOT in time if ($this->data['user_type'] != USER_FOUNDER) { - $this->check_ban(); + $this->check_ban($this->data['user_id'], $this->ip); } // @@ -470,8 +463,10 @@ class session $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) . "'"; + $sql = 'DELETE + FROM ' . SESSIONS_TABLE . ' + WHERE session_id = \'' . $db->sql_escape($this->session_id) . '\' + AND session_user_id = ' . ANONYMOUS; if (!$this->session_id || !$db->sql_query($sql) || !$db->sql_affectedrows()) { @@ -490,15 +485,16 @@ class session trigger_error('BOARD_UNAVAILABLE'); } } + } - $this->session_id = $this->data['session_id'] = md5(unique_id()); + $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_id'] = (string) $this->session_id; + $sql_ary['session_page'] = (string) substr($this->page['page'], 0, 199); + + $sql = 'INSERT INTO ' . SESSIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); + $db->sql_query($sql); - $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 @@ -507,8 +503,8 @@ class session $this->set_login_key(); } - $SID = '?sid='; - $_SID = ''; + $SID = '?sid=' . $this->session_id; + $_SID = $this->session_id; if (!$bot) { @@ -518,9 +514,6 @@ class session $this->set_cookie('k', $this->cookie_data['k'], $cookie_expire); $this->set_cookie('sid', $this->session_id, $cookie_expire); - $SID = '?sid=' . $this->session_id; - $_SID = $this->session_id; - unset($cookie_expire); } @@ -546,16 +539,12 @@ class session // Allow connecting logout with external auth method logout $method = basename(trim($config['auth_method'])); + include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx); - if (file_exists($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx)) + $method = 'logout_' . $method; + if (function_exists($method)) { - include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx); - - $method = 'logout_' . $method; - if (function_exists($method)) - { - $method($this->data); - } + $method($this->data); } if ($this->data['user_id'] != ANONYMOUS) @@ -657,7 +646,7 @@ class session WHERE session_time < ' . (int) ($this->time_now - $config['session_length']); $db->sql_query($sql); - set_config('session_last_gc', $this->time_now); + set_config('session_last_gc', $this->time_now, true); break; default: @@ -669,33 +658,30 @@ class session GROUP BY session_user_id, session_page'; $result = $db->sql_query_limit($sql, 5); - $del_user_id = ''; + $del_user_id = array(); $del_sessions = 0; - if ($row = $db->sql_fetchrow($result)) + + while ($row = $db->sql_fetchrow($result)); { - do + if ($row['session_user_id'] != ANONYMOUS) { - if ($row['session_user_id'] != ANONYMOUS) - { - $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_lastvisit = ' . $row['recent_time'] . ", user_lastpage = '" . $db->sql_escape($row['session_page']) . "' - WHERE user_id = " . $row['session_user_id']; - $db->sql_query($sql); - } - - $del_user_id .= (($del_user_id != '') ? ', ' : '') . (int) $row['session_user_id']; - $del_sessions++; + $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); } - while ($row = $db->sql_fetchrow($result)); + + $del_user_id[] = (int) $row['session_user_id']; + $del_sessions++; } $db->sql_freeresult($result); - if ($del_user_id) + if (sizeof($del_user_id)) { // Delete expired sessions - $sql = 'DELETE FROM ' . SESSIONS_TABLE . " - WHERE session_user_id IN ($del_user_id) - AND session_time < " . ($this->time_now - $config['session_length']); + $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); } @@ -755,16 +741,44 @@ class session { global $config, $db; - $user_id = ($user_id === false) ? $this->data['user_id'] : $user_id; - $user_ip = ($user_ip === false) ? $this->ip : $user_ip; - $user_email = ($user_email === false) ? $this->data['user_email'] : $user_email; - $banned = false; $sql = 'SELECT ban_ip, ban_userid, ban_email, ban_exclude, ban_give_reason, ban_end FROM ' . BANLIST_TABLE . ' - WHERE ban_end >= ' . time() . ' - OR ban_end = 0'; + WHERE (ban_end >= ' . time() . ' OR ban_end = 0)'; + + // Determine which entries to check, only return those + if ($user_email === false) + { + $sql .= " AND ban_email = ''"; + } + + if ($user_ip === false) + { + $sql .= " AND (ban_ip = '' OR (ban_ip <> '' AND ban_exclude = 1))"; + } + + if ($user_id === false) + { + $sql .= ' AND (ban_userid = 0 OR (ban_userid <> 0 AND ban_exclude = 1))'; + } + else + { + $sql .= ' AND (ban_userid = ' . $user_id; + + if ($user_email !== false) + { + $sql .= " OR ban_email <> ''"; + } + + if ($user_ip !== false) + { + $sql .= " OR ban_ip <> ''"; + } + + $sql .= ')'; + } + $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -1066,8 +1080,33 @@ class user extends session { $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' => implode('', file("{$phpbb_root_path}styles/" . $this->theme['theme_path'] . '/theme/stylesheet.css')), + 'theme_data' => $stylesheet, 'theme_mtime' => time(), 'theme_storedb' => 1 ); @@ -1102,9 +1141,9 @@ class user extends session // 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') && $config['chg_passforce'] && $this->data['user_passchg'] < time() - ($config['chg_passforce'] * 86400)) + if (!defined('IN_ADMIN') && $config['chg_passforce'] && $this->data['is_registered'] && $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") + if (strpos($this->page['query_string'], 'mode=reg_details') === false && $this->page['page_name'] != "ucp.$phpEx") { redirect(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=profile&mode=reg_details')); } @@ -1205,17 +1244,18 @@ class user extends session */ function format_date($gmepoch, $format = false, $forcedate = false) { - static $lang_dates, $midnight; + static $midnight; - if (empty($lang_dates)) + $lang_dates = $this->lang['datetime']; + $format = (!$format) ? $this->date_format : $format; + + // Short representation of month in format + if ((strpos($format, '\M') === false && strpos($format, 'M') !== false) || (strpos($format, '\r') === false && strpos($format, 'r') !== false)) { - foreach ($this->lang['datetime'] as $match => $replace) - { - $lang_dates[$match] = $replace; - } + $lang_dates['May'] = $lang_dates['May_short']; } - $format = (!$format) ? $this->date_format : $format; + unset($lang_dates['May_short']); if (!$midnight) { diff --git a/phpBB/includes/template.php b/phpBB/includes/template.php index 1e1ad31193..5281860ac5 100644 --- a/phpBB/includes/template.php +++ b/phpBB/includes/template.php @@ -50,6 +50,10 @@ class template $this->root = $phpbb_root_path . 'styles/' . $user->theme['template_path'] . '/template'; $this->cachepath = $phpbb_root_path . 'cache/tpl_' . $user->theme['template_path'] . '_'; } + else + { + trigger_error('Template path could not be found: styles/' . $user->theme['template_path'] . '/template', E_USER_ERROR); + } return true; } @@ -183,7 +187,7 @@ class template $filename = $this->cachepath . str_replace('/', '.', $this->filename[$handle]) . '.' . $phpEx; - $recompile = (($config['load_tplcompile'] && @filemtime($filename) < filemtime($this->files[$handle])) || !file_exists($filename)) ? true : false; + $recompile = (($config['load_tplcompile'] && @filemtime($filename) < filemtime($this->files[$handle])) || !file_exists($filename) || @filesize($filename) === 0) ? true : false; // Recompile page if the original template is newer, otherwise load the compiled version if (!$recompile) diff --git a/phpBB/includes/ucp/ucp_attachments.php b/phpBB/includes/ucp/ucp_attachments.php index 08a2549646..549e3a11b2 100644 --- a/phpBB/includes/ucp/ucp_attachments.php +++ b/phpBB/includes/ucp/ucp_attachments.php @@ -60,7 +60,7 @@ class ucp_attachments // 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.comment', 'c' => 'a.extension', 'd' => 'a.filesize', 'e' => 'a.download_count', 'f' => 'a.filetime', 'g' => 't.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']); @@ -93,7 +93,7 @@ class ucp_attachments 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'] . " ORDER BY $order_by"; - $result = $db->sql_query_limit($sql, $config['posts_per_page'], $start); + $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); $row_count = 0; if ($row = $db->sql_fetchrow($result)) @@ -114,7 +114,7 @@ class ucp_attachments $template->assign_block_vars('attachrow', array( 'ROW_NUMBER' => $row_count + ($start + 1), 'FILENAME' => $row['real_filename'], - 'COMMENT' => str_replace("\n", '<br />', $row['comment']), + 'COMMENT' => str_replace("\n", '<br />', $row['attach_comment']), 'EXTENSION' => $row['extension'], 'SIZE' => ($row['filesize'] >= 1048576) ? ($row['filesize'] >> 20) . ' ' . $user->lang['MB'] : (($row['filesize'] >= 1024) ? ($row['filesize'] >> 10) . ' ' . $user->lang['KB'] : $row['filesize'] . ' ' . $user->lang['BYTES']), 'DOWNLOAD_COUNT' => $row['download_count'], @@ -138,8 +138,8 @@ class ucp_attachments $db->sql_freeresult($result); $template->assign_vars(array( - 'PAGE_NUMBER' => on_page($num_attachments, $config['posts_per_page'], $start), - 'PAGINATION' => generate_pagination($this->u_action . "&sk=$sort_key&sd=$sort_dir", $num_attachments, $config['posts_per_page'], $start), + 'PAGE_NUMBER' => on_page($num_attachments, $config['topics_per_page'], $start), + 'PAGINATION' => generate_pagination($this->u_action . "&sk=$sort_key&sd=$sort_dir", $num_attachments, $config['topics_per_page'], $start), 'TOTAL_ATTACHMENTS' => $num_attachments, 'L_TITLE' => $user->lang['UCP_ATTACHMENTS'], diff --git a/phpBB/includes/ucp/ucp_confirm.php b/phpBB/includes/ucp/ucp_confirm.php index 37f9d485f9..2c83306e5e 100644 --- a/phpBB/includes/ucp/ucp_confirm.php +++ b/phpBB/includes/ucp/ucp_confirm.php @@ -59,7 +59,7 @@ class ucp_confirm if (function_exists('imagettfbbox') && function_exists('imagettftext')) { - $policy_modules += array('policy_overlap', 'policy_shape', 'policy_cells', 'policy_stencil', 'policy_composite'); + $policy_modules = array_merge($policy_modules, array('policy_overlap', 'policy_shape', 'policy_cells', 'policy_stencil', 'policy_composite')); } foreach ($policy_modules as $key => $name) @@ -73,6 +73,16 @@ class ucp_confirm $policy = ''; if (@extension_loaded('gd') && sizeof($policy_modules)) { + $change_lang = request_var('change_lang', ''); + + if ($change_lang) + { + $lang = $change_lang; + $user->lang_name = $lang = $change_lang; + $user->lang_path = $phpbb_root_path . 'language/' . $lang . '/'; + $user->lang = array(); + $user->add_lang(array('common', 'ucp')); + } include($phpbb_root_path . 'includes/captcha/captcha_gd.' . $phpEx); $policy = $policy_modules[array_rand($policy_modules)]; } diff --git a/phpBB/includes/ucp/ucp_groups.php b/phpBB/includes/ucp/ucp_groups.php index 23dda1438f..47403c83da 100644 --- a/phpBB/includes/ucp/ucp_groups.php +++ b/phpBB/includes/ucp/ucp_groups.php @@ -33,6 +33,8 @@ class ucp_groups switch ($mode) { case 'membership': + + $this->page_title = 'UCP_USERGROUPS_MEMBER'; if ($submit || isset($_POST['change_default'])) { @@ -298,7 +300,7 @@ class ucp_groups $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']) : $user->lang['GROUP_IS_SPECIAL'], + '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], @@ -314,9 +316,9 @@ class ucp_groups // 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_desc, group_desc_uid, group_desc_bitfield, group_type + $sql = 'SELECT group_id, group_name, group_desc, group_desc_uid, group_desc_bitfield, group_desc_options, group_type FROM ' . GROUPS_TABLE . ' - WHERE group_id NOT IN (' . implode(', ', $group_id_ary) . ") + WHERE ' . $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); @@ -350,7 +352,7 @@ class ucp_groups $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']) : $user->lang['GROUP_IS_SPECIAL'], + '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], @@ -377,6 +379,7 @@ class ucp_groups case 'manage': + $this->page_title = 'UCP_USERGROUPS_MANAGE'; $action = (isset($_POST['addusers'])) ? 'addusers' : request_var('action', ''); $group_id = request_var('g', 0); @@ -549,7 +552,7 @@ class ucp_groups 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_bitfield']); + $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']; } @@ -720,7 +723,7 @@ class ucp_groups 'PAGINATION' => generate_pagination($this->u_action . "&action=$action&g=$group_id", $total_members, $config['topics_per_page'], $start, true), 'U_ACTION' => $this->u_action . "&g=$group_id", - 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=list&field=usernames')) + 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=ucp&field=usernames')) ); break; @@ -893,7 +896,7 @@ class ucp_groups default: $user->add_lang('acp/common'); - $sql = 'SELECT g.group_id, g.group_name, g.group_desc, g.group_desc_uid, g.group_desc_bitfield, g.group_type, ug.group_leader + $sql = 'SELECT g.group_id, g.group_name, 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 @@ -905,7 +908,7 @@ class ucp_groups { $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']), + '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'], @@ -922,7 +925,6 @@ class ucp_groups } $this->tpl_name = 'ucp_groups_' . $mode; - $this->page_title = 'UCP_GROUPS_' . strtoupper($mode); } } diff --git a/phpBB/includes/ucp/ucp_main.php b/phpBB/includes/ucp/ucp_main.php index 6e00a1ed7b..8936a7728b 100644 --- a/phpBB/includes/ucp/ucp_main.php +++ b/phpBB/includes/ucp/ucp_main.php @@ -50,9 +50,9 @@ class ucp_main $sql_select .= ', tt.mark_time'; } - $topic_type = $user->lang['VIEW_TOPIC_ANNOUNCEMENT']; - $folder = 'folder_announce'; - $folder_new = $folder . '_new'; + $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); @@ -65,7 +65,7 @@ class ucp_main if (sizeof($forum_ary)) { - $sql .= ' AND forum_id NOT IN ( ' . implode(', ', $forum_ary) . ')'; + $sql .= ' AND ' . $db->sql_in_set('forum_id', $forum_ary); } $result = $db->sql_query_limit($sql, 1); $g_forum_id = (int) $db->sql_fetchfield('forum_id'); @@ -105,20 +105,18 @@ class ucp_main $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) { - $topic_type = $user->lang['VIEW_TOPIC_LOCKED']; - $folder = 'folder_locked'; - $folder_new = 'folder_locked_new'; + $folder_img .= '_locked'; } - $folder_img = ($unread_topic) ? $folder_new : $folder; - $folder_alt = ($unread_topic) ? 'NEW_POSTS' : (($row['topic_status'] == ITEM_LOCKED) ? 'TOPIC_LOCKED' : 'NO_NEW_POSTS'); - // Posted image? if (!empty($row['topic_posted']) && $row['topic_posted']) { - $folder_img .= '_posted'; + $folder_img .= '_mine'; } $template->assign_block_vars('topicrow', array( @@ -129,11 +127,11 @@ class ucp_main 'TOPIC_TITLE' => censor_text($row['topic_title']), 'TOPIC_TYPE' => $topic_type, - 'LAST_POST_IMG' => $user->img('icon_post_latest', 'VIEW_LATEST_POST'), - 'NEWEST_POST_IMG' => $user->img('icon_post_newest', 'VIEW_NEWEST_POST'), + 'LAST_POST_IMG' => $user->img('icon_topic_latest', 'VIEW_LATEST_POST'), + 'NEWEST_POST_IMG' => $user->img('icon_topic_newest', 'VIEW_NEWEST_POST'), '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_gets('f_download', 'u_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_attach', '') : '', + 'ATTACH_ICON_IMG' => ($auth->acl_gets('f_download', 'u_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, @@ -188,27 +186,27 @@ class ucp_main if ($unwatch) { - $forums = (isset($_POST['f'])) ? implode(', ', array_map('intval', array_keys($_POST['f']))) : false; - $topics = (isset($_POST['t'])) ? implode(', ', array_map('intval', array_keys($_POST['t']))) : false; + $forums = (isset($_POST['f'])) ? array_map('intval', array_keys($_POST['f'])) : array(); + $topics = (isset($_POST['t'])) ? array_map('intval', array_keys($_POST['t'])) : array(); - if ($forums || $topics) + if (sizeof($forums) || sizeof($topics)) { $l_unwatch = ''; - if ($forums) + if (sizeof($forums)) { - $sql = 'DELETE FROM ' . FORUMS_WATCH_TABLE . " - WHERE forum_id IN ($forums) - AND user_id = " . $user->data['user_id']; + $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 ($topics) + if (sizeof($topics)) { - $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . " - WHERE topic_id IN ($topics) - AND user_id = " . $user->data['user_id']; + $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'; @@ -273,12 +271,12 @@ class ucp_main // Which folder should we display? if ($row['forum_status'] == ITEM_LOCKED) { - $folder_image = ($unread_forum) ? 'folder_locked_new' : 'folder_locked'; + $folder_image = ($unread_forum) ? 'forum_unread_locked' : 'forum_read_locked'; $folder_alt = 'FORUM_LOCKED'; } else { - $folder_image = ($unread_forum) ? 'folder_new' : 'folder'; + $folder_image = ($unread_forum) ? 'forum_unread' : 'forum_read'; $folder_alt = ($unread_forum) ? 'NEW_POSTS' : 'NO_NEW_POSTS'; } @@ -302,7 +300,7 @@ class ucp_main 'FORUM_FOLDER_IMG' => $user->img($folder_image, $folder_alt), 'FORUM_FOLDER_IMG_SRC' => $user->img($folder_image, $folder_alt, false, '', 'src'), 'FORUM_NAME' => $row['forum_name'], - 'LAST_POST_IMG' => $user->img('icon_post_latest', 'VIEW_LATEST_POST'), + 'LAST_POST_IMG' => $user->img('icon_topic_latest', 'VIEW_LATEST_POST'), 'LAST_POST_TIME' => $last_post_time, 'LAST_POST_AUTHOR' => $last_poster, @@ -432,14 +430,14 @@ class ucp_main 'TOPIC_TITLE' => censor_text($row['topic_title']), 'TOPIC_TYPE' => $topic_type, - 'LAST_POST_IMG' => $user->img('icon_post_latest', 'VIEW_LATEST_POST'), - 'NEWEST_POST_IMG' => $user->img('icon_post_newest', 'VIEW_NEWEST_POST'), + 'LAST_POST_IMG' => $user->img('icon_topic_latest', 'VIEW_LATEST_POST'), + 'NEWEST_POST_IMG' => $user->img('icon_topic_newest', 'VIEW_NEWEST_POST'), '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'] : '', - 'ATTACH_ICON_IMG' => ($auth->acl_gets('f_download', 'u_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', + 'ATTACH_ICON_IMG' => ($auth->acl_gets('f_download', 'u_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, @@ -513,7 +511,7 @@ class ucp_main { $sql = 'DELETE FROM ' . BOOKMARKS_TABLE . ' WHERE user_id = ' . $user->data['user_id'] . ' - AND topic_id IN (' . implode(', ', $topics) . ')'; + AND ' . $db->sql_in_set('topic_id', $topics); $db->sql_query($sql); // Re-Order bookmarks (possible with one query? This query massaker is not really acceptable...) @@ -591,8 +589,8 @@ class ucp_main '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_gets('f_download', 'u_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_attach', '') : '', - 'LAST_POST_IMG' => $user->img('icon_post_latest', 'VIEW_LATEST_POST'), + 'ATTACH_ICON_IMG' => ($auth->acl_gets('f_download', 'u_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_topic_attach', '') : '', + 'LAST_POST_IMG' => $user->img('icon_topic_latest', 'VIEW_LATEST_POST'), 'U_LAST_POST' => $view_topic_url . '&p=' . $row['topic_last_post_id'] . '#p' . $row['topic_last_post_id'], 'U_LAST_POST_AUTHOR' => ($row['topic_last_poster_id'] != ANONYMOUS && $row['topic_last_poster_id']) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $row['topic_last_poster_id']) : '', @@ -622,13 +620,13 @@ class ucp_main if ($delete) { - $drafts = (isset($_POST['d'])) ? implode(', ', array_map('intval', array_keys($_POST['d']))) : ''; + $drafts = (!empty($_POST['d'])) ? array_map('intval', array_keys($_POST['d'])) : array(); - if ($drafts) + if (sizeof($drafts)) { - $sql = 'DELETE FROM ' . DRAFTS_TABLE . " - WHERE draft_id IN ($drafts) - AND user_id = " .$user->data['user_id']; + $sql = 'DELETE FROM ' . DRAFTS_TABLE . ' + WHERE ' . $db->sql_in_set('draft_id', $drafts) . ' + AND user_id = ' . $user->data['user_id']; $db->sql_query($sql); $message = $user->lang['DRAFTS_DELETED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); @@ -636,6 +634,8 @@ class ucp_main meta_refresh(3, $this->u_action); trigger_error($message); } + + unset($drafts); } if ($submit && $edit) @@ -703,7 +703,7 @@ class ucp_main { $sql = 'SELECT topic_id, forum_id, topic_title FROM ' . TOPICS_TABLE . ' - WHERE topic_id IN (' . implode(',', array_unique($topic_ids)) . ')'; + WHERE ' . $db->sql_in_set('topic_id', array_unique($topic_ids)); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) diff --git a/phpBB/includes/ucp/ucp_pm.php b/phpBB/includes/ucp/ucp_pm.php index c23456715f..5d1a4297ee 100644 --- a/phpBB/includes/ucp/ucp_pm.php +++ b/phpBB/includes/ucp/ucp_pm.php @@ -148,8 +148,11 @@ class ucp_pm 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; @@ -315,7 +318,7 @@ class ucp_pm } // Update unread status - update_unread_status($message_row['unread'], $message_row['msg_id'], $user->data['user_id'], $folder_id); + 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); diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php index bc7f22427b..ff95bfc307 100644 --- a/phpBB/includes/ucp/ucp_pm_compose.php +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -18,6 +18,7 @@ function compose_pm($id, $mode, $action) global $phpbb_root_path, $phpEx, $config; 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) @@ -137,7 +138,7 @@ function compose_pm($id, $mode, $action) trigger_error('NO_MESSAGE'); } - $sql = 'SELECT msg_id, unread, new, author_id, folder_id + $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"; @@ -236,14 +237,14 @@ function compose_pm($id, $mode, $action) $check_value = 0; } - if (($to_group_id || isset($address_list['g'])) && !$config['allow_mass_pm']) + if (($to_group_id || isset($address_list['g'])) && (!$config['allow_mass_pm'] || !$auth->acl_get('u_masspm'))) { trigger_error('NO_AUTH_GROUP_MESSAGE'); } if ($action == 'edit' && !$refresh && !$preview && !$submit) { - if (!($message_time > time() - $config['pm_edit_time'] || !$config['pm_edit_time'])) + if (!($message_time > time() - ($config['pm_edit_time'] * 60) || !$config['pm_edit_time'])) { trigger_error('CANNOT_EDIT_MESSAGE_TIME'); } @@ -300,7 +301,7 @@ function compose_pm($id, $mode, $action) handle_message_list_actions($address_list, $remove_u, $remove_g, $add_to, $add_bcc); // Check for too many recipients - if (!$config['allow_mass_pm'] && num_recipients($address_list) > 1) + if ((!$config['allow_mass_pm'] || !$auth->acl_get('u_masspm')) && num_recipients($address_list) > 1) { $address_list = get_recipient_pos($address_list, 1); $error[] = $user->lang['TOO_MANY_RECIPIENTS']; @@ -310,7 +311,7 @@ function compose_pm($id, $mode, $action) if ($message_attachment && !$submit && !$refresh && !$preview && $action == 'edit') { - $sql = 'SELECT attach_id, physical_filename, comment, real_filename, extension, mimetype, filesize, filetime, thumbnail + $sql = 'SELECT attach_id, physical_filename, attach_comment, real_filename, extension, mimetype, filesize, filetime, thumbnail FROM ' . ATTACHMENTS_TABLE . " WHERE post_msg_id = $msg_id AND in_message = 1 @@ -519,7 +520,7 @@ function compose_pm($id, $mode, $action) 'enable_bbcode' => (bool) $enable_bbcode, 'enable_smilies' => (bool) $enable_smilies, 'enable_urls' => (bool) $enable_urls, - 'bbcode_bitfield' => (int) $message_parser->bbcode_bitfield, + 'bbcode_bitfield' => $message_parser->bbcode_bitfield, 'bbcode_uid' => $message_parser->bbcode_uid, 'message' => $message_parser->message, 'attachment_data' => $message_parser->attachment_data, @@ -572,7 +573,6 @@ function compose_pm($id, $mode, $action) // Attachment Preview if (sizeof($message_parser->attachment_data)) { - include($phpbb_root_path . 'includes/functions_display.' . $phpEx); $extensions = $update_count = array(); $template->assign_var('S_HAS_ATTACHMENTS', true); @@ -663,7 +663,7 @@ function compose_pm($id, $mode, $action) { $sql = 'SELECT user_id as id, username as name, user_colour as colour FROM ' . USERS_TABLE . ' - WHERE user_id IN (' . implode(', ', array_map('intval', array_keys($address_list['u']))) . ')'; + WHERE ' . $db->sql_in_set('user_id', array_map('intval', array_keys($address_list['u']))); $result['u'] = $db->sql_query($sql); } @@ -672,7 +672,7 @@ function compose_pm($id, $mode, $action) $sql = 'SELECT group_id as id, group_name as name, group_colour as colour, group_type FROM ' . GROUPS_TABLE . ' WHERE group_receive_pm = 1 - AND group_id IN (' . implode(', ', array_map('intval', array_keys($address_list['g']))) . ')'; + AND ' . $db->sql_in_set('group_id', array_map('intval', array_keys($address_list['g']))); $result['g'] = $db->sql_query($sql); } @@ -787,7 +787,7 @@ function compose_pm($id, $mode, $action) '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'], - 'MINI_POST_IMG' => $user->img('icon_post', $user->lang['PM']), + 'MINI_POST_IMG' => $user->img('icon_post_target', $user->lang['PM']), 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', 'S_EDIT_POST' => ($action == 'edit'), @@ -818,23 +818,7 @@ function compose_pm($id, $mode, $action) ); // Build custom bbcodes array - $sql = 'SELECT bbcode_id, bbcode_tag - FROM ' . BBCODES_TABLE . ' - WHERE display_on_posting = 1'; - $result = $db->sql_query($sql); - - $i = 0; - while ($row = $db->sql_fetchrow($result)) - { - $template->assign_block_vars('custom_tags', array( - 'BBCODE_NAME' => "'[{$row['bbcode_tag']}]', '[/" . str_replace('=', '', $row['bbcode_tag']) . "]'", - 'BBCODE_ID' => 22 + ($i * 2), - 'BBCODE_TAG' => $row['bbcode_tag']) - ); - - $i++; - } - $db->sql_freeresult($result); + display_custom_bbcodes(); // Attachment entry if ($auth->acl_get('u_pm_attach') && $config['allow_pm_attach'] && $form_enctype) @@ -884,8 +868,8 @@ function handle_message_list_actions(&$address_list, $remove_u, $remove_g, $add_ $user_id_ary = array(); // Build usernames to add - $usernames = (isset($_REQUEST['username'])) ? array(request_var('username', '', true)) : array(); - $username_list = request_var('username_list', '', true); + $usernames = (isset($_REQUEST['username'])) ? array(request_var('username', '')) : array(); + $username_list = request_var('username_list', ''); if ($username_list) { $usernames = array_merge($usernames, explode("\n", $username_list)); @@ -910,7 +894,7 @@ function handle_message_list_actions(&$address_list, $remove_u, $remove_g, $add_ { $sql = 'SELECT user_id FROM ' . USERS_TABLE . ' - WHERE user_id IN (' . implode(', ', $user_id_ary) . ') + WHERE ' . $db->sql_in_set('user_id', $user_id_ary) . ' AND user_allow_pm = 1'; $result = $db->sql_query($sql); diff --git a/phpBB/includes/ucp/ucp_pm_viewfolder.php b/phpBB/includes/ucp/ucp_pm_viewfolder.php index 30dc8a8b09..91a44c31c1 100644 --- a/phpBB/includes/ucp/ucp_pm_viewfolder.php +++ b/phpBB/includes/ucp/ucp_pm_viewfolder.php @@ -29,7 +29,23 @@ function view_folder($id, $mode, $folder_id, $folder) $icons = array(); $cache->obtain_icons($icons); - $color_rows = array('marked', 'replied', 'friend', 'foe'); + $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) { @@ -117,15 +133,15 @@ function view_folder($id, $mode, $folder_id, $folder) { $sql = 'SELECT user_id as id, username as name, user_colour as colour FROM ' . USERS_TABLE . ' - WHERE user_id'; + WHERE '; } else { $sql = 'SELECT group_id as id, group_name as name, group_colour as colour, group_type FROM ' . GROUPS_TABLE . ' - WHERE group_id'; + WHERE '; } - $sql .= ' IN (' . implode(', ', array_map('intval', array_keys($recipient_list[$ug_type]))) . ')'; + $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); @@ -161,8 +177,8 @@ function view_folder($id, $mode, $folder_id, $folder) { $row = &$folder_info['rowset'][$message_id]; - $folder_img = ($row['unread']) ? 'folder_new' : 'folder'; - $folder_alt = ($row['unread']) ? 'NEW_MESSAGES' : 'NO_NEW_MESSAGES'; + $folder_img = ($row['pm_unread']) ? 'pm_unread' : 'pm_read'; + $folder_alt = ($row['pm_unread']) ? 'NEW_MESSAGES' : 'NO_NEW_MESSAGES'; // Generate all URIs ... $message_author = '<a href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $row['author_id']) . '">' . $row['username'] . '</a>'; @@ -172,7 +188,7 @@ function view_folder($id, $mode, $folder_id, $folder) $row_indicator = ''; foreach ($color_rows as $var) { - if (($var != 'friend' && $var != 'foe' && $row[$var]) + if (($var != 'friend' && $var != 'foe' && $row['pm_' . $var]) || (($var == 'friend' || $var == 'foe') && isset(${$var}[$row['author_id']]) && ${$var}[$row['author_id']])) { @@ -194,13 +210,14 @@ function view_folder($id, $mode, $folder_id, $folder) '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="" />' : '', '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_download') && $row['message_attachment'] && $config['allow_pm_attach'] && $config['auth_download_pm']) ? $user->img('icon_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', + '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['deleted']) ? true : false, + 'S_PM_DELETED' => ($row['pm_deleted']) ? true : false, - 'U_VIEW_PM' => ($row['deleted']) ? '' : $view_message_url, - 'U_REMOVE_PM' => ($row['deleted']) ? $remove_message_url : '', + '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]) : '') ); } @@ -260,15 +277,15 @@ function view_folder($id, $mode, $folder_id, $folder) { $sql = 'SELECT user_id as id, username as name FROM ' . USERS_TABLE . ' - WHERE user_id'; + WHERE '; } else { $sql = 'SELECT group_id as id, group_name as name FROM ' . GROUPS_TABLE . ' - WHERE group_id'; + WHERE '; } - $sql .= ' IN (' . implode(', ', array_map('intval', array_keys($address[$message_id][$ug_type]))) . ')'; + $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); @@ -451,7 +468,7 @@ function get_pm_from($folder_id, $folder, $user_id) '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('btn_locked', 'PM_LOCKED') : $user->img('btn_post_pm', 'POST_PM'), + 'POST_IMG' => (!$auth->acl_get('u_sendpm')) ? $user->img('button_topic_locked', 'PM_LOCKED') : $user->img('button_pm_new', 'POST_PM'), 'L_NO_MESSAGES' => (!$auth->acl_get('u_sendpm')) ? $user->lang['POST_PM_LOCKED'] : $user->lang['NO_MESSAGES'], diff --git a/phpBB/includes/ucp/ucp_pm_viewmessage.php b/phpBB/includes/ucp/ucp_pm_viewmessage.php index e66b519327..4a399d847d 100644 --- a/phpBB/includes/ucp/ucp_pm_viewmessage.php +++ b/phpBB/includes/ucp/ucp_pm_viewmessage.php @@ -23,7 +23,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) $author_id = (int) $message_row['author_id']; // Not able to view message, it was deleted by the sender - if ($message_row['deleted']) + if ($message_row['pm_deleted']) { trigger_error('NO_AUTH_READ_REMOVED_MESSAGE'); } @@ -85,7 +85,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) if ($message_row['message_attachment'] && $config['allow_pm_attach']) { - if ($config['auth_download_pm'] && $auth->acl_get('u_pm_download')) + if ($auth->acl_get('u_pm_download')) { include($phpbb_root_path . 'includes/functions_display.' . $phpEx); @@ -134,7 +134,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) { $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET download_count = download_count + 1 - WHERE attach_id IN (' . implode(', ', array_unique($update_count)) . ')'; + WHERE ' . $db->sql_in_set('attach_id', array_unique($update_count)); $db->sql_query($sql); } } @@ -172,16 +172,16 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) 'AUTHOR_POSTS' => (!empty($user_info['user_posts'])) ? $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('btn_online', $user->lang['ONLINE']) : $user->img('btn_offline', $user->lang['OFFLINE'])), + '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('btn_delete', $user->lang['DELETE_MESSAGE']), - 'INFO_IMG' => $user->img('btn_info', $user->lang['VIEW_PM_INFO']), - 'PROFILE_IMG' => $user->img('btn_profile', $user->lang['READ_PROFILE']), - 'EMAIL_IMG' => $user->img('btn_email', $user->lang['SEND_EMAIL']), - 'QUOTE_IMG' => $user->img('btn_quote', $user->lang['POST_QUOTE_PM']), - 'REPLY_IMG' => $user->img('btn_reply_pm', $user->lang['POST_REPLY_PM']), - 'EDIT_IMG' => $user->img('btn_edit', $user->lang['POST_EDIT_PM']), - 'MINI_POST_IMG' => $user->img('icon_post', $user->lang['PM']), + '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']), + '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' => $user->format_date($message_row['message_time']), 'SUBJECT' => $message_row['message_subject'], @@ -189,12 +189,12 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) 'SIGNATURE' => ($message_row['enable_sig']) ? $signature : '', 'EDITED_MESSAGE' => $l_edited_by, - 'U_INFO' => ($auth->acl_get('m_info') && $message_row['forwarded']) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'mode=pm_details&p=' . $message_row['msg_id'], true, $user->session_id) : '', + 'U_INFO' => ($auth->acl_get('m_info') && $message_row['pm_forwarded']) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'mode=pm_details&p=' . $message_row['msg_id'], true, $user->session_id) : '', 'U_DELETE' => ($auth->acl_get('u_pm_delete')) ? "$url&mode=compose&action=delete&f=$folder_id&p=" . $message_row['msg_id'] : '', 'U_AUTHOR_PROFILE' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $author_id), 'U_EMAIL' => $user_info['email'], 'U_QUOTE' => ($auth->acl_get('u_sendpm')) ? "$url&mode=compose&action=quote&f=$folder_id&p=" . $message_row['msg_id'] : '', - 'U_EDIT' => (($message_row['message_time'] > time() - $config['pm_edit_time'] || !$config['pm_edit_time']) && $folder_id == PRIVMSGS_OUTBOX && $auth->acl_get('u_pm_edit')) ? "$url&mode=compose&action=edit&f=$folder_id&p=" . $message_row['msg_id'] : '', + 'U_EDIT' => (($message_row['message_time'] > time() - ($config['pm_edit_time'] * 60) || !$config['pm_edit_time']) && $folder_id == PRIVMSGS_OUTBOX && $auth->acl_get('u_pm_edit')) ? "$url&mode=compose&action=edit&f=$folder_id&p=" . $message_row['msg_id'] : '', 'U_POST_REPLY_PM' => ($auth->acl_get('u_sendpm')) ? "$url&mode=compose&action=reply&f=$folder_id&p=" . $message_row['msg_id'] : '', 'U_PREVIOUS_PM' => "$url&f=$folder_id&p=" . $message_row['msg_id'] . "&view=previous", 'U_NEXT_PM' => "$url&f=$folder_id&p=" . $message_row['msg_id'] . "&view=next", @@ -264,7 +264,7 @@ function message_history($msg_id, $user_id, $message_row, $folder) } $rowset = array(); - $bbcode_bitfield = 0; + $bbcode_bitfield = ''; $folder_url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm') . '&folder='; $title = ($sort_dir == 'd') ? $row['message_subject'] : ''; @@ -281,7 +281,7 @@ function message_history($msg_id, $user_id, $message_row, $folder) else { $rowset[$row['msg_id']] = $row; - $bbcode_bitfield |= $row['bbcode_bitfield']; + $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']); } } while ($row = $db->sql_fetchrow($result)); @@ -355,7 +355,7 @@ function message_history($msg_id, $user_id, $message_row, $folder) } $template->assign_vars(array( - 'QUOTE_IMG' => $user->img('btn_quote', $user->lang['REPLY_WITH_QUOTE']), + 'QUOTE_IMG' => $user->img('icon_post_quote', $user->lang['REPLY_WITH_QUOTE']), 'TITLE' => $title, 'U_VIEW_NEXT_HISTORY' => "$url&p=" . (($next_history_pm) ? $next_history_pm : $msg_id), diff --git a/phpBB/includes/ucp/ucp_prefs.php b/phpBB/includes/ucp/ucp_prefs.php index 527c48efa7..ff8df44148 100644 --- a/phpBB/includes/ucp/ucp_prefs.php +++ b/phpBB/includes/ucp/ucp_prefs.php @@ -61,7 +61,7 @@ class ucp_prefs $var_ary = array( 'dateformat' => array('string', false, 3, 30), - 'lang' => array('match', false, '#^[a-z_]{2,}$#i'), + 'lang' => array('match', false, '#^[a-z_\-]{2,}$#i'), 'tz' => array('num', false, -14, 14), ); diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index 9326e41427..d757d6e14d 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -49,10 +49,10 @@ class ucp_profile $data[$var] = request_var($var, $default); } + // Do not check cur_password, it is the old one. $var_ary = array( - 'password_confirm' => array('string', true, $config['min_pass_chars'], $config['max_pass_chars']), 'new_password' => array('string', true, $config['min_pass_chars'], $config['max_pass_chars']), - 'cur_password' => array('string', true, $config['min_pass_chars'], $config['max_pass_chars']), + 'password_confirm' => array('string', true, $config['min_pass_chars'], $config['max_pass_chars']), 'email' => array( array('string', false, 6, 60), array('email', $data['email'])), @@ -153,7 +153,7 @@ class ucp_profile $sql = 'SELECT user_id, username, user_email, user_lang, user_jabber, user_notify_type FROM ' . USERS_TABLE . ' - WHERE user_id IN (' . implode(', ', $admin_ary[0]['a_user']) .')'; + WHERE ' . $db->sql_in_set('user_id', $admin_ary[0]['a_user']); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -225,7 +225,7 @@ class ucp_profile 'S_CHANGE_EMAIL' => ($auth->acl_get('u_chgemail')) ? true : false, 'S_CHANGE_PASSWORD' => ($auth->acl_get('u_chgpasswd')) ? true : false) ); - break; + break; case 'profile_info': @@ -399,7 +399,7 @@ class ucp_profile $cp->generate_profile_fields('profile', $user->get_iso_lang_id()); - break; + break; case 'signature': @@ -408,7 +408,8 @@ class ucp_profile trigger_error('NO_AUTH_SIGNATURE'); } - include($phpbb_root_path . 'includes/functions_posting.'.$phpEx); + include($phpbb_root_path . 'includes/functions_posting.' . $phpEx); + include($phpbb_root_path . 'includes/functions_display.' . $phpEx); $enable_bbcode = ($config['allow_sig_bbcode']) ? request_var('enable_bbcode', $user->optionget('bbcode')) : false; $enable_smilies = ($config['allow_sig_smilies']) ? request_var('enable_smilies', $user->optionget('smilies')) : false; @@ -430,13 +431,13 @@ class ucp_profile { $error[] = implode('<br />', $message_parser->warn_msg); } - + if (!sizeof($error) && $submit) { $sql_ary = array( 'user_sig' => (string) $message_parser->message, 'user_sig_bbcode_uid' => (string) $message_parser->bbcode_uid, - 'user_sig_bbcode_bitfield' => (int) $message_parser->bbcode_bitfield + 'user_sig_bbcode_bitfield' => $message_parser->bbcode_bitfield ); $sql = 'UPDATE ' . USERS_TABLE . ' @@ -486,23 +487,7 @@ class ucp_profile ); // Build custom bbcodes array - $sql = 'SELECT bbcode_id, bbcode_tag - FROM ' . BBCODES_TABLE . ' - WHERE display_on_posting = 1'; - $result = $db->sql_query($sql); - - $i = 0; - while ($row = $db->sql_fetchrow($result)) - { - $template->assign_block_vars('custom_tags', array( - 'BBCODE_NAME' => "'[{$row['bbcode_tag']}]', '[/" . str_replace('=', '', $row['bbcode_tag']) . "]'", - 'BBCODE_ID' => 22 + ($i * 2), - 'BBCODE_TAG' => $row['bbcode_tag']) - ); - - $i++; - } - $db->sql_freeresult($result); + display_custom_bbcodes(); break; @@ -600,7 +585,11 @@ class ucp_profile // Delete old avatar if present if ($user->data['user_avatar'] && $filename != $user->data['user_avatar'] && $user->data['user_avatar_type'] != AVATAR_GALLERY) { - avatar_delete($user->data['user_avatar']); + // Check if the users avatar is actually a group avatar + if (strpos($user->data['user_avatar'], 'g' . $user->data['group_id'] . '_') !== 0 && strpos($user->data['user_avatar'], $user->data['user_id'] . '_') === 0) + { + avatar_delete($user->data['user_avatar']); + } } } @@ -665,7 +654,7 @@ class ucp_profile ); } - break; + break; } $template->assign_vars(array( diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php index 44c15bfb0e..01b92125ac 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -117,15 +117,15 @@ class ucp_register 'username' => array( array('string', false, $config['min_name_chars'], $config['max_name_chars']), array('username')), - 'password_confirm' => array('string', false, $config['min_pass_chars'], $config['max_pass_chars']), 'new_password' => array('string', false, $config['min_pass_chars'], $config['max_pass_chars']), + '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), 'confirm_code' => array('string', !$config['enable_confirm'], 5, 8), 'tz' => array('num', false, -14, 14), - 'lang' => array('match', false, '#^[a-z_]{2,}$#i'), + 'lang' => array('match', false, '#^[a-z_\-]{2,}$#i'), ); $error = validate_data($data, $var_ary); @@ -202,7 +202,7 @@ class ucp_register // Which group by default? $group_reg = ($coppa) ? 'REGISTERED_COPPA' : 'REGISTERED'; $group_inactive = ($coppa) ? 'INACTIVE_COPPA' : 'INACTIVE'; - $group_name = ($config['require_activation'] == USER_ACTIVATION_NONE) ? $group_reg : $group_inactive; + $group_name = ($config['require_activation'] == USER_ACTIVATION_NONE || !$config['email_enable']) ? $group_reg : $group_inactive; $sql = 'SELECT group_id FROM ' . GROUPS_TABLE . " @@ -323,7 +323,7 @@ class ucp_register $sql = 'SELECT user_id, username, user_email, user_lang, user_jabber, user_notify_type FROM ' . USERS_TABLE . ' - WHERE user_id IN (' . implode(', ', $admin_ary[0]['a_user']) .')'; + WHERE ' . $db->sql_in_set('user_id', $admin_ary[0]['a_user']); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -345,13 +345,6 @@ class ucp_register $db->sql_freeresult($result); } } - - if ($user_type == USER_NORMAL || !$config['email_enable']) - { - set_config('newest_user_id', $user_id, true); - set_config('newest_username', $username, true); - set_config('num_users', $config['num_users'] + 1, true); - } unset($data); $message = $message . '<br /><br />' . sprintf($user->lang['RETURN_INDEX'], '<a href="' . append_sid("{$phpbb_root_path}index.$phpEx") . '">', '</a>'); @@ -370,6 +363,7 @@ class ucp_register // Visual Confirmation - Show images if ($config['enable_confirm']) { + $str = ''; if (!$change_lang) { $sql = 'SELECT session_id @@ -381,12 +375,12 @@ class ucp_register $sql_in = array(); do { - $sql_in[] = "'" . $db->sql_escape($row['session_id']) . "'"; + $sql_in[] = (string) $row['session_id']; } while ($row = $db->sql_fetchrow($result)); $sql = 'DELETE FROM ' . CONFIRM_TABLE . ' - WHERE session_id NOT IN (' . implode(', ', $sql_in) . ') + WHERE ' . $db->sql_in_set('session_id', $sql_in, true) . ' AND confirm_type = ' . CONFIRM_REG; $db->sql_query($sql); } @@ -416,8 +410,12 @@ class ucp_register ); $db->sql_query($sql); } + else + { + $str .= '&change_lang=' . $change_lang; + } - $confirm_image = '<img src="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=confirm&id=' . $confirm_id . '&type=' . CONFIRM_REG) . '" alt="" title="" />'; + $confirm_image = '<img src="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=confirm&id=' . $confirm_id . '&type=' . CONFIRM_REG . $str) . '" alt="" title="" />'; $s_hidden_fields .= '<input type="hidden" name="confirm_id" value="' . $confirm_id . '" />'; } @@ -450,7 +448,7 @@ class ucp_register 'CONFIRM_IMG' => $confirm_image, 'L_CONFIRM_EXPLAIN' => sprintf($user->lang['CONFIRM_EXPLAIN'], '<a href="mailto:' . htmlentities($config['board_contact']) . '">', '</a>'), - 'L_ITEMS_REQUIRED' => $l_reg_cond, + 'L_REG_COND' => $l_reg_cond, 'L_USERNAME_EXPLAIN' => sprintf($user->lang[$user_char_ary[str_replace('\\\\', '\\', $config['allow_name_chars'])] . '_EXPLAIN'], $config['min_name_chars'], $config['max_name_chars']), 'L_NEW_PASSWORD_EXPLAIN' => sprintf($user->lang['NEW_PASSWORD_EXPLAIN'], $config['min_pass_chars'], $config['max_pass_chars']), diff --git a/phpBB/includes/ucp/ucp_remind.php b/phpBB/includes/ucp/ucp_remind.php index 9419684725..11edb54b95 100644 --- a/phpBB/includes/ucp/ucp_remind.php +++ b/phpBB/includes/ucp/ucp_remind.php @@ -22,7 +22,7 @@ class ucp_remind global $config, $phpbb_root_path, $phpEx; global $db, $user, $auth, $template; - $username = request_var('username', '', true); + $username = request_var('username', ''); $email = request_var('email', ''); $submit = (isset($_POST['submit'])) ? true : false; @@ -62,7 +62,7 @@ class ucp_remind $messenger = new messenger(false); - $messenger->template('user_activate_passwd', $row['user_lang']); + $messenger->template('user_activate_passwd', $user_row['user_lang']); $messenger->replyto($user->data['user_email']); $messenger->to($user_row['user_email'], $user_row['username']); diff --git a/phpBB/includes/ucp/ucp_resend.php b/phpBB/includes/ucp/ucp_resend.php index 85ec560d14..84ce3fe9b7 100644 --- a/phpBB/includes/ucp/ucp_resend.php +++ b/phpBB/includes/ucp/ucp_resend.php @@ -22,7 +22,7 @@ class ucp_resend global $config, $phpbb_root_path, $phpEx; global $db, $user, $auth, $template; - $username = request_var('username', '', true); + $username = request_var('username', ''); $email = request_var('email', ''); $submit = (isset($_POST['submit'])) ? true : false; @@ -105,7 +105,7 @@ class ucp_resend $sql = 'SELECT user_id, username, user_email, user_lang, user_jabber, user_notify_type FROM ' . USERS_TABLE . ' - WHERE user_id IN (' . implode(', ', $admin_ary[0]['a_user']) .')'; + WHERE ' . $db->sql_in_set('user_id', $admin_ary[0]['a_user']); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) diff --git a/phpBB/includes/ucp/ucp_zebra.php b/phpBB/includes/ucp/ucp_zebra.php index b5cad8b38b..2cf6edcac4 100644 --- a/phpBB/includes/ucp/ucp_zebra.php +++ b/phpBB/includes/ucp/ucp_zebra.php @@ -23,9 +23,12 @@ class ucp_zebra $submit = (isset($_POST['submit']) || isset($_GET['add'])) ? true : false; $s_hidden_fields = ''; + $l_mode = strtoupper($mode); + if ($submit) { - $data = array(); + $data = $error = array(); + $updated = false; $var_ary = array( 'usernames' => array(0), @@ -37,15 +40,9 @@ class ucp_zebra $data[$var] = request_var($var, $default); } - $var_ary = array( - 'add' => array('string', false) - ); - - $error = validate_data($data, $var_ary); - - if ($data['add'] && !sizeof($error)) + if ($data['add']) { - $data['add'] = array_map('strtolower', explode("\n", $data['add'])); + $data['add'] = array_map('trim', array_map('strtolower', 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 @@ -71,26 +68,54 @@ class ucp_zebra } $db->sql_freeresult($result); - $data['add'] = array_diff($data['add'], $friends, $foes, array(strtolower($user->data['username']))); - unset($friends, $foes); + // 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); - $data['add'] = implode(', ', preg_replace('#^[\s]*?(.*?)[\s]*?$#e', "\"'\" . \$db->sql_escape('\\1') . \"'\"", $data['add'])); + if (sizeof($data['add']) < $n && $mode == 'friends') + { + $error[] = $user->lang['NOT_ADDED_FRIENDS_FOES']; + } - if ($data['add']) + // remove the user himself from the username array + $n = sizeof($data['add']); + $data['add'] = array_diff($data['add'], array(strtolower($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 LOWER(username) IN (' . $data['add'] . ') - AND user_type NOT IN (' . USER_IGNORE . ', ' . USER_INACTIVE . ')'; + WHERE ' . $db->sql_in_set('LOWER(username)', $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) + if ($row['user_id'] != ANONYMOUS && $row['user_type'] != USER_IGNORE) { $user_id_ary[] = $row['user_id']; } + else + { + $error[] = $user->lang['NOT_ADDED_' . $l_mode . '_ANONYMOUS']; + } } $db->sql_freeresult($result); @@ -110,6 +135,11 @@ class ucp_zebra $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); @@ -147,39 +177,37 @@ class ucp_zebra break; } } - } - else - { - $error[] = 'NOT_ADDED_' . strtoupper($mode); + + $updated = true; } unset($user_id_ary); } - else + else if (!sizeof($error)) { - $error[] = 'USER_NOT_FOUND_OR_INACTIVE'; + $error[] = $user->lang['USER_NOT_FOUND_OR_INACTIVE']; } } } - else if (sizeof($data['usernames']) && !sizeof($error)) + else if (sizeof($data['usernames'])) { // Force integer values $data['usernames'] = array_map('intval', $data['usernames']); $sql = 'DELETE FROM ' . ZEBRA_TABLE . ' WHERE user_id = ' . $user->data['user_id'] . ' - AND zebra_id IN (' . implode(', ', $data['usernames']) . ')'; + AND ' . $db->sql_in_set('zebra_id', $data['usernames']); $db->sql_query($sql); } - if (!sizeof($error)) + if ($updated) { meta_refresh(3, $this->u_action); - $message = $user->lang[strtoupper($mode) . '_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + $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 />', preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error))); + $template->assign_var('ERROR', implode('<br />', $error)); } } @@ -200,7 +228,7 @@ class ucp_zebra $db->sql_freeresult($result); $template->assign_vars(array( - 'L_TITLE' => $user->lang['UCP_ZEBRA_' . strtoupper($mode)], + 'L_TITLE' => $user->lang['UCP_ZEBRA_' . $l_mode], 'U_SEARCH_USER' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=ucp&field=add'), @@ -210,7 +238,7 @@ class ucp_zebra ); $this->tpl_name = 'ucp_zebra_' . $mode; - $this->page_title = 'UCP_ZEBRA_' . strtoupper($mode); + $this->page_title = 'UCP_ZEBRA_' . $l_mode; } } 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..3bf2f68838 --- /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','Ç'=>'ç','È'=>'è','É'=>'é','Ê'=>'ê','Ë'=>'ë','Ì'=>'ì','Í'=>'í','Î'=>'î','Ï'=>'ï','Ð'=>'ð','Ñ'=>'ñ','Ò'=>'ò','Ó'=>'ó','Ô'=>'ô','Õ'=>'õ','Ö'=>'oe','Ø'=>'ø','Ù'=>'ù','Ú'=>'ú','Û'=>'û','Ü'=>'ü','Ý'=>'ý','Þ'=>'þ','ß'=>'ss','à'=>'à','á'=>'á','â'=>'â','ã'=>'ã','ä'=>'ä','å'=>'å','æ'=>'ae','ç'=>'ç','è'=>'è','é'=>'é','ê'=>'ê','ë'=>'ë','ì'=>'ì','í'=>'í','î'=>'î','ï'=>'ï','ð'=>'ð','ñ'=>'ñ','ò'=>'ò','ó'=>'ó','ô'=>'ô','õ'=>'õ','ö'=>'oe','ø'=>'ø','ù'=>'ù','ú'=>'ú','û'=>'û','ü'=>'ü','ý'=>'ý','þ'=>'þ','ÿ'=>'ÿ','Ā'=>'ā','ā'=>'ā','Ă'=>'ă','ă'=>'ă','Ą'=>'ą','ą'=>'ą','Ć'=>'ć','ć'=>'ć','Ĉ'=>'ĉ','ĉ'=>'ĉ','Ċ'=>'ċ','ċ'=>'ċ','Č'=>'č','č'=>'č','Ď'=>'ď','ď'=>'ď','Đ'=>'đ','đ'=>'đ','Ē'=>'ē','ē'=>'ē','Ĕ'=>'ĕ','ĕ'=>'ĕ','Ė'=>'ė','ė'=>'ė','Ę'=>'ę','ę'=>'ę','Ě'=>'ě','ě'=>'ě','Ĝ'=>'ĝ','ĝ'=>'ĝ','Ğ'=>'ğ','ğ'=>'ğ','Ġ'=>'ġ','ġ'=>'ġ','Ģ'=>'ģ','ģ'=>'ģ','Ĥ'=>'ĥ','ĥ'=>'ĥ','Ħ'=>'ħ','ħ'=>'ħ','Ĩ'=>'ĩ','ĩ'=>'ĩ','Ī'=>'ī','ī'=>'ī','Ĭ'=>'ĭ','ĭ'=>'ĭ','Į'=>'į','į'=>'į','İ'=>'i','ı'=>'ı','IJ'=>'ij','ij'=>'ij','Ĵ'=>'ĵ','ĵ'=>'ĵ','Ķ'=>'ķ','ķ'=>'ķ','ĸ'=>'ĸ','Ĺ'=>'ĺ','ĺ'=>'ĺ','Ļ'=>'ļ','ļ'=>'ļ','Ľ'=>'ľ','ľ'=>'ľ','Ŀ'=>'ŀ','ŀ'=>'ŀ','Ł'=>'ł','ł'=>'ł','Ń'=>'ń','ń'=>'ń','Ņ'=>'ņ','ņ'=>'ņ','Ň'=>'ň','ň'=>'ň','ʼn'=>'ʼn','Ŋ'=>'ŋ','ŋ'=>'ŋ','Ō'=>'ō','ō'=>'ō','Ŏ'=>'ŏ','ŏ'=>'ŏ','Ő'=>'ő','ő'=>'ő','Œ'=>'oe','œ'=>'oe','Ŕ'=>'ŕ','ŕ'=>'ŕ','Ŗ'=>'ŗ','ŗ'=>'ŗ','Ř'=>'ř','ř'=>'ř','Ś'=>'ś','ś'=>'ś','Ŝ'=>'ŝ','ŝ'=>'ŝ','Ş'=>'ş','ş'=>'ş','Š'=>'š','š'=>'š','Ţ'=>'ţ','ţ'=>'ţ','Ť'=>'ť','ť'=>'ť','Ŧ'=>'ŧ','ŧ'=>'ŧ','Ũ'=>'ũ','ũ'=>'ũ','Ū'=>'ū','ū'=>'ū','Ŭ'=>'ŭ','ŭ'=>'ŭ','Ů'=>'ů','ů'=>'ů','Ű'=>'ű','ű'=>'ű','Ų'=>'ų','ų'=>'ų','Ŵ'=>'ŵ','ŵ'=>'ŵ','Ŷ'=>'ŷ','ŷ'=>'ŷ','Ÿ'=>'ÿ','Ź'=>'ź','ź'=>'ź','Ż'=>'ż','ż'=>'ż','Ž'=>'ž','ž'=>'ž','ſ'=>'ſ','ƀ'=>'ƀ','Ɓ'=>'ɓ','Ƃ'=>'ƃ','ƃ'=>'ƃ','Ƅ'=>'ƅ','ƅ'=>'ƅ','Ɔ'=>'ɔ','Ƈ'=>'ƈ','ƈ'=>'ƈ','Ɖ'=>'ɖ','Ɗ'=>'ɗ','Ƌ'=>'ƌ','ƌ'=>'ƌ','ƍ'=>'ƍ','Ǝ'=>'ǝ','Ə'=>'ə','Ɛ'=>'ɛ','Ƒ'=>'ƒ','ƒ'=>'ƒ','Ɠ'=>'ɠ','Ɣ'=>'ɣ','ƕ'=>'hv','Ɩ'=>'ɩ','Ɨ'=>'ɨ','Ƙ'=>'ƙ','ƙ'=>'ƙ','ƚ'=>'ƚ','ƛ'=>'ƛ','Ɯ'=>'ɯ','Ɲ'=>'ɲ','ƞ'=>'ƞ','Ɵ'=>'ɵ','Ơ'=>'ơ','ơ'=>'ơ','Ƣ'=>'oi','ƣ'=>'oi','Ƥ'=>'ƥ','ƥ'=>'ƥ','Ʀ'=>'yr','Ƨ'=>'ƨ','ƨ'=>'ƨ','Ʃ'=>'ʃ','ƪ'=>'ƪ','ƫ'=>'ƫ','Ƭ'=>'ƭ','ƭ'=>'ƭ','Ʈ'=>'ʈ','Ư'=>'ư','ư'=>'ư','Ʊ'=>'ʊ','Ʋ'=>'ʋ','Ƴ'=>'ƴ','ƴ'=>'ƴ','Ƶ'=>'ƶ','ƶ'=>'ƶ','Ʒ'=>'ʒ','Ƹ'=>'ƹ','ƹ'=>'ƹ','ƺ'=>'ƺ','ƻ'=>'ƻ','Ƽ'=>'ƽ','ƽ'=>'ƽ','ƾ'=>'ƾ','ƿ'=>'ƿ','ǀ'=>'ǀ','ǁ'=>'ǁ','ǂ'=>'ǂ','ǃ'=>'ǃ','DŽ'=>'dž','Dž'=>'dž','dž'=>'dž','LJ'=>'lj','Lj'=>'lj','lj'=>'lj','NJ'=>'nj','Nj'=>'nj','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'=>'fi','fl'=>'fl','ffi'=>'ffi','ffl'=>'ffl','ſt'=>'ſt','st'=>'st','ﬓ'=>'ﬓ','ﬔ'=>'ﬔ','ﬕ'=>'ﬕ','ﬖ'=>'ﬖ','ﬗ'=>'ﬗ','יִ'=>'יִ','ﬞ'=>'ﬞ','ײַ'=>'ײַ','ﬠ'=>'ﬠ','ﬡ'=>'ﬡ','ﬢ'=>'ﬢ','ﬣ'=>'ﬣ','ﬤ'=>'ﬤ','ﬥ'=>'ﬥ','ﬦ'=>'ﬦ','ﬧ'=>'ﬧ','ﬨ'=>'ﬨ','שׁ'=>'שׁ','שׂ'=>'שׂ','שּׁ'=>'שּׁ','שּׂ'=>'שּׂ','אַ'=>'אַ','אָ'=>'אָ','אּ'=>'אּ','בּ'=>'בּ','גּ'=>'גּ','דּ'=>'דּ','הּ'=>'הּ','וּ'=>'וּ','זּ'=>'זּ','טּ'=>'טּ','יּ'=>'יּ','ךּ'=>'ךּ','כּ'=>'כּ','לּ'=>'לּ','מּ'=>'מּ','נּ'=>'נּ','סּ'=>'סּ','ףּ'=>'ףּ','פּ'=>'פּ','צּ'=>'צּ','קּ'=>'קּ','רּ'=>'רּ','שּ'=>'שּ','תּ'=>'תּ','וֹ'=>'וֹ','בֿ'=>'בֿ','כֿ'=>'כֿ','פֿ'=>'פֿ','ﭏ'=>'ﭏ','ﭐ'=>'ﭐ','ﭑ'=>'ﭑ','ﭒ'=>'ﭒ','ﭓ'=>'ﭓ','ﭔ'=>'ﭔ','ﭕ'=>'ﭕ','ﭖ'=>'ﭖ','ﭗ'=>'ﭗ','ﭘ'=>'ﭘ','ﭙ'=>'ﭙ','ﭚ'=>'ﭚ','ﭛ'=>'ﭛ','ﭜ'=>'ﭜ','ﭝ'=>'ﭝ','ﭞ'=>'ﭞ','ﭟ'=>'ﭟ','ﭠ'=>'ﭠ','ﭡ'=>'ﭡ','ﭢ'=>'ﭢ','ﭣ'=>'ﭣ','ﭤ'=>'ﭤ','ﭥ'=>'ﭥ','ﭦ'=>'ﭦ','ﭧ'=>'ﭧ','ﭨ'=>'ﭨ','ﭩ'=>'ﭩ','ﭪ'=>'ﭪ','ﭫ'=>'ﭫ','ﭬ'=>'ﭬ','ﭭ'=>'ﭭ','ﭮ'=>'ﭮ','ﭯ'=>'ﭯ','ﭰ'=>'ﭰ','ﭱ'=>'ﭱ','ﭲ'=>'ﭲ','ﭳ'=>'ﭳ','ﭴ'=>'ﭴ','ﭵ'=>'ﭵ','ﭶ'=>'ﭶ','ﭷ'=>'ﭷ','ﭸ'=>'ﭸ','ﭹ'=>'ﭹ','ﭺ'=>'ﭺ','ﭻ'=>'ﭻ','ﭼ'=>'ﭼ','ﭽ'=>'ﭽ','ﭾ'=>'ﭾ','ﭿ'=>'ﭿ','ﮀ'=>'ﮀ','ﮁ'=>'ﮁ','ﮂ'=>'ﮂ','ﮃ'=>'ﮃ','ﮄ'=>'ﮄ','ﮅ'=>'ﮅ','ﮆ'=>'ﮆ','ﮇ'=>'ﮇ','ﮈ'=>'ﮈ','ﮉ'=>'ﮉ','ﮊ'=>'ﮊ','ﮋ'=>'ﮋ','ﮌ'=>'ﮌ','ﮍ'=>'ﮍ','ﮎ'=>'ﮎ','ﮏ'=>'ﮏ','ﮐ'=>'ﮐ','ﮑ'=>'ﮑ','ﮒ'=>'ﮒ','ﮓ'=>'ﮓ','ﮔ'=>'ﮔ','ﮕ'=>'ﮕ','ﮖ'=>'ﮖ','ﮗ'=>'ﮗ','ﮘ'=>'ﮘ','ﮙ'=>'ﮙ','ﮚ'=>'ﮚ','ﮛ'=>'ﮛ','ﮜ'=>'ﮜ','ﮝ'=>'ﮝ','ﮞ'=>'ﮞ','ﮟ'=>'ﮟ','ﮠ'=>'ﮠ','ﮡ'=>'ﮡ','ﮢ'=>'ﮢ','ﮣ'=>'ﮣ','ﮤ'=>'ﮤ','ﮥ'=>'ﮥ','ﮦ'=>'ﮦ','ﮧ'=>'ﮧ','ﮨ'=>'ﮨ','ﮩ'=>'ﮩ','ﮪ'=>'ﮪ','ﮫ'=>'ﮫ','ﮬ'=>'ﮬ','ﮭ'=>'ﮭ','ﮮ'=>'ﮮ','ﮯ'=>'ﮯ','ﮰ'=>'ﮰ','ﮱ'=>'ﮱ','ﯓ'=>'ﯓ','ﯔ'=>'ﯔ','ﯕ'=>'ﯕ','ﯖ'=>'ﯖ','ﯗ'=>'ﯗ','ﯘ'=>'ﯘ','ﯙ'=>'ﯙ','ﯚ'=>'ﯚ','ﯛ'=>'ﯛ','ﯜ'=>'ﯜ','ﯝ'=>'ﯝ','ﯞ'=>'ﯞ','ﯟ'=>'ﯟ','ﯠ'=>'ﯠ','ﯡ'=>'ﯡ','ﯢ'=>'ﯢ','ﯣ'=>'ﯣ','ﯤ'=>'ﯤ','ﯥ'=>'ﯥ','ﯦ'=>'ﯦ','ﯧ'=>'ﯧ','ﯨ'=>'ﯨ','ﯩ'=>'ﯩ','ﯪ'=>'ﯪ','ﯫ'=>'ﯫ','ﯬ'=>'ﯬ','ﯭ'=>'ﯭ','ﯮ'=>'ﯮ','ﯯ'=>'ﯯ','ﯰ'=>'ﯰ','ﯱ'=>'ﯱ','ﯲ'=>'ﯲ','ﯳ'=>'ﯳ','ﯴ'=>'ﯴ','ﯵ'=>'ﯵ','ﯶ'=>'ﯶ','ﯷ'=>'ﯷ','ﯸ'=>'ﯸ','ﯹ'=>'ﯹ','ﯺ'=>'ﯺ','ﯻ'=>'ﯻ','ﯼ'=>'ﯼ','ﯽ'=>'ﯽ','ﯾ'=>'ﯾ','ﯿ'=>'ﯿ','ﰀ'=>'ﰀ','ﰁ'=>'ﰁ','ﰂ'=>'ﰂ','ﰃ'=>'ﰃ','ﰄ'=>'ﰄ','ﰅ'=>'ﰅ','ﰆ'=>'ﰆ','ﰇ'=>'ﰇ','ﰈ'=>'ﰈ','ﰉ'=>'ﰉ','ﰊ'=>'ﰊ','ﰋ'=>'ﰋ','ﰌ'=>'ﰌ','ﰍ'=>'ﰍ','ﰎ'=>'ﰎ','ﰏ'=>'ﰏ','ﰐ'=>'ﰐ','ﰑ'=>'ﰑ','ﰒ'=>'ﰒ','ﰓ'=>'ﰓ','ﰔ'=>'ﰔ','ﰕ'=>'ﰕ','ﰖ'=>'ﰖ','ﰗ'=>'ﰗ','ﰘ'=>'ﰘ','ﰙ'=>'ﰙ','ﰚ'=>'ﰚ','ﰛ'=>'ﰛ','ﰜ'=>'ﰜ','ﰝ'=>'ﰝ','ﰞ'=>'ﰞ','ﰟ'=>'ﰟ','ﰠ'=>'ﰠ','ﰡ'=>'ﰡ','ﰢ'=>'ﰢ','ﰣ'=>'ﰣ','ﰤ'=>'ﰤ','ﰥ'=>'ﰥ','ﰦ'=>'ﰦ','ﰧ'=>'ﰧ','ﰨ'=>'ﰨ','ﰩ'=>'ﰩ','ﰪ'=>'ﰪ','ﰫ'=>'ﰫ','ﰬ'=>'ﰬ','ﰭ'=>'ﰭ','ﰮ'=>'ﰮ','ﰯ'=>'ﰯ','ﰰ'=>'ﰰ','ﰱ'=>'ﰱ','ﰲ'=>'ﰲ','ﰳ'=>'ﰳ','ﰴ'=>'ﰴ','ﰵ'=>'ﰵ','ﰶ'=>'ﰶ','ﰷ'=>'ﰷ','ﰸ'=>'ﰸ','ﰹ'=>'ﰹ','ﰺ'=>'ﰺ','ﰻ'=>'ﰻ','ﰼ'=>'ﰼ','ﰽ'=>'ﰽ','ﰾ'=>'ﰾ','ﰿ'=>'ﰿ','ﱀ'=>'ﱀ','ﱁ'=>'ﱁ','ﱂ'=>'ﱂ','ﱃ'=>'ﱃ','ﱄ'=>'ﱄ','ﱅ'=>'ﱅ','ﱆ'=>'ﱆ','ﱇ'=>'ﱇ','ﱈ'=>'ﱈ','ﱉ'=>'ﱉ','ﱊ'=>'ﱊ','ﱋ'=>'ﱋ','ﱌ'=>'ﱌ','ﱍ'=>'ﱍ','ﱎ'=>'ﱎ','ﱏ'=>'ﱏ','ﱐ'=>'ﱐ','ﱑ'=>'ﱑ','ﱒ'=>'ﱒ','ﱓ'=>'ﱓ','ﱔ'=>'ﱔ','ﱕ'=>'ﱕ','ﱖ'=>'ﱖ','ﱗ'=>'ﱗ','ﱘ'=>'ﱘ','ﱙ'=>'ﱙ','ﱚ'=>'ﱚ','ﱛ'=>'ﱛ','ﱜ'=>'ﱜ','ﱝ'=>'ﱝ','ﱞ'=>'ﱞ','ﱟ'=>'ﱟ','ﱠ'=>'ﱠ','ﱡ'=>'ﱡ','ﱢ'=>'ﱢ','ﱣ'=>'ﱣ','ﱤ'=>'ﱤ','ﱥ'=>'ﱥ','ﱦ'=>'ﱦ','ﱧ'=>'ﱧ','ﱨ'=>'ﱨ','ﱩ'=>'ﱩ','ﱪ'=>'ﱪ','ﱫ'=>'ﱫ','ﱬ'=>'ﱬ','ﱭ'=>'ﱭ','ﱮ'=>'ﱮ','ﱯ'=>'ﱯ','ﱰ'=>'ﱰ','ﱱ'=>'ﱱ','ﱲ'=>'ﱲ','ﱳ'=>'ﱳ','ﱴ'=>'ﱴ','ﱵ'=>'ﱵ','ﱶ'=>'ﱶ','ﱷ'=>'ﱷ','ﱸ'=>'ﱸ','ﱹ'=>'ﱹ','ﱺ'=>'ﱺ','ﱻ'=>'ﱻ','ﱼ'=>'ﱼ','ﱽ'=>'ﱽ','ﱾ'=>'ﱾ','ﱿ'=>'ﱿ','ﲀ'=>'ﲀ','ﲁ'=>'ﲁ','ﲂ'=>'ﲂ','ﲃ'=>'ﲃ','ﲄ'=>'ﲄ','ﲅ'=>'ﲅ','ﲆ'=>'ﲆ','ﲇ'=>'ﲇ','ﲈ'=>'ﲈ','ﲉ'=>'ﲉ','ﲊ'=>'ﲊ','ﲋ'=>'ﲋ','ﲌ'=>'ﲌ','ﲍ'=>'ﲍ','ﲎ'=>'ﲎ','ﲏ'=>'ﲏ','ﲐ'=>'ﲐ','ﲑ'=>'ﲑ','ﲒ'=>'ﲒ','ﲓ'=>'ﲓ','ﲔ'=>'ﲔ','ﲕ'=>'ﲕ','ﲖ'=>'ﲖ','ﲗ'=>'ﲗ','ﲘ'=>'ﲘ','ﲙ'=>'ﲙ','ﲚ'=>'ﲚ','ﲛ'=>'ﲛ','ﲜ'=>'ﲜ','ﲝ'=>'ﲝ','ﲞ'=>'ﲞ','ﲟ'=>'ﲟ','ﲠ'=>'ﲠ','ﲡ'=>'ﲡ','ﲢ'=>'ﲢ','ﲣ'=>'ﲣ','ﲤ'=>'ﲤ','ﲥ'=>'ﲥ','ﲦ'=>'ﲦ','ﲧ'=>'ﲧ','ﲨ'=>'ﲨ','ﲩ'=>'ﲩ','ﲪ'=>'ﲪ','ﲫ'=>'ﲫ','ﲬ'=>'ﲬ','ﲭ'=>'ﲭ','ﲮ'=>'ﲮ','ﲯ'=>'ﲯ','ﲰ'=>'ﲰ','ﲱ'=>'ﲱ','ﲲ'=>'ﲲ','ﲳ'=>'ﲳ','ﲴ'=>'ﲴ','ﲵ'=>'ﲵ','ﲶ'=>'ﲶ','ﲷ'=>'ﲷ','ﲸ'=>'ﲸ','ﲹ'=>'ﲹ','ﲺ'=>'ﲺ','ﲻ'=>'ﲻ','ﲼ'=>'ﲼ','ﲽ'=>'ﲽ','ﲾ'=>'ﲾ','ﲿ'=>'ﲿ','ﳀ'=>'ﳀ','ﳁ'=>'ﳁ','ﳂ'=>'ﳂ','ﳃ'=>'ﳃ','ﳄ'=>'ﳄ','ﳅ'=>'ﳅ','ﳆ'=>'ﳆ','ﳇ'=>'ﳇ','ﳈ'=>'ﳈ','ﳉ'=>'ﳉ','ﳊ'=>'ﳊ','ﳋ'=>'ﳋ','ﳌ'=>'ﳌ','ﳍ'=>'ﳍ','ﳎ'=>'ﳎ','ﳏ'=>'ﳏ','ﳐ'=>'ﳐ','ﳑ'=>'ﳑ','ﳒ'=>'ﳒ','ﳓ'=>'ﳓ','ﳔ'=>'ﳔ','ﳕ'=>'ﳕ','ﳖ'=>'ﳖ','ﳗ'=>'ﳗ','ﳘ'=>'ﳘ','ﳙ'=>'ﳙ','ﳚ'=>'ﳚ','ﳛ'=>'ﳛ','ﳜ'=>'ﳜ','ﳝ'=>'ﳝ','ﳞ'=>'ﳞ','ﳟ'=>'ﳟ','ﳠ'=>'ﳠ','ﳡ'=>'ﳡ','ﳢ'=>'ﳢ','ﳣ'=>'ﳣ','ﳤ'=>'ﳤ','ﳥ'=>'ﳥ','ﳦ'=>'ﳦ','ﳧ'=>'ﳧ','ﳨ'=>'ﳨ','ﳩ'=>'ﳩ','ﳪ'=>'ﳪ','ﳫ'=>'ﳫ','ﳬ'=>'ﳬ','ﳭ'=>'ﳭ','ﳮ'=>'ﳮ','ﳯ'=>'ﳯ','ﳰ'=>'ﳰ','ﳱ'=>'ﳱ','ﳲ'=>'ﳲ','ﳳ'=>'ﳳ','ﳴ'=>'ﳴ','ﳵ'=>'ﳵ','ﳶ'=>'ﳶ','ﳷ'=>'ﳷ','ﳸ'=>'ﳸ','ﳹ'=>'ﳹ','ﳺ'=>'ﳺ','ﳻ'=>'ﳻ','ﳼ'=>'ﳼ','ﳽ'=>'ﳽ','ﳾ'=>'ﳾ','ﳿ'=>'ﳿ','ﴀ'=>'ﴀ','ﴁ'=>'ﴁ','ﴂ'=>'ﴂ','ﴃ'=>'ﴃ','ﴄ'=>'ﴄ','ﴅ'=>'ﴅ','ﴆ'=>'ﴆ','ﴇ'=>'ﴇ','ﴈ'=>'ﴈ','ﴉ'=>'ﴉ','ﴊ'=>'ﴊ','ﴋ'=>'ﴋ','ﴌ'=>'ﴌ','ﴍ'=>'ﴍ','ﴎ'=>'ﴎ','ﴏ'=>'ﴏ','ﴐ'=>'ﴐ','ﴑ'=>'ﴑ','ﴒ'=>'ﴒ','ﴓ'=>'ﴓ','ﴔ'=>'ﴔ','ﴕ'=>'ﴕ','ﴖ'=>'ﴖ','ﴗ'=>'ﴗ','ﴘ'=>'ﴘ','ﴙ'=>'ﴙ','ﴚ'=>'ﴚ','ﴛ'=>'ﴛ','ﴜ'=>'ﴜ','ﴝ'=>'ﴝ','ﴞ'=>'ﴞ','ﴟ'=>'ﴟ','ﴠ'=>'ﴠ','ﴡ'=>'ﴡ','ﴢ'=>'ﴢ','ﴣ'=>'ﴣ','ﴤ'=>'ﴤ','ﴥ'=>'ﴥ','ﴦ'=>'ﴦ','ﴧ'=>'ﴧ','ﴨ'=>'ﴨ','ﴩ'=>'ﴩ','ﴪ'=>'ﴪ','ﴫ'=>'ﴫ','ﴬ'=>'ﴬ','ﴭ'=>'ﴭ','ﴮ'=>'ﴮ','ﴯ'=>'ﴯ','ﴰ'=>'ﴰ','ﴱ'=>'ﴱ','ﴲ'=>'ﴲ','ﴳ'=>'ﴳ','ﴴ'=>'ﴴ','ﴵ'=>'ﴵ','ﴶ'=>'ﴶ','ﴷ'=>'ﴷ','ﴸ'=>'ﴸ','ﴹ'=>'ﴹ','ﴺ'=>'ﴺ','ﴻ'=>'ﴻ','ﴼ'=>'ﴼ','ﴽ'=>'ﴽ','ﵐ'=>'ﵐ','ﵑ'=>'ﵑ','ﵒ'=>'ﵒ','ﵓ'=>'ﵓ','ﵔ'=>'ﵔ','ﵕ'=>'ﵕ','ﵖ'=>'ﵖ','ﵗ'=>'ﵗ','ﵘ'=>'ﵘ','ﵙ'=>'ﵙ','ﵚ'=>'ﵚ','ﵛ'=>'ﵛ','ﵜ'=>'ﵜ','ﵝ'=>'ﵝ','ﵞ'=>'ﵞ','ﵟ'=>'ﵟ','ﵠ'=>'ﵠ','ﵡ'=>'ﵡ','ﵢ'=>'ﵢ','ﵣ'=>'ﵣ','ﵤ'=>'ﵤ','ﵥ'=>'ﵥ','ﵦ'=>'ﵦ','ﵧ'=>'ﵧ','ﵨ'=>'ﵨ','ﵩ'=>'ﵩ','ﵪ'=>'ﵪ','ﵫ'=>'ﵫ','ﵬ'=>'ﵬ','ﵭ'=>'ﵭ','ﵮ'=>'ﵮ','ﵯ'=>'ﵯ','ﵰ'=>'ﵰ','ﵱ'=>'ﵱ','ﵲ'=>'ﵲ','ﵳ'=>'ﵳ','ﵴ'=>'ﵴ','ﵵ'=>'ﵵ','ﵶ'=>'ﵶ','ﵷ'=>'ﵷ','ﵸ'=>'ﵸ','ﵹ'=>'ﵹ','ﵺ'=>'ﵺ','ﵻ'=>'ﵻ','ﵼ'=>'ﵼ','ﵽ'=>'ﵽ','ﵾ'=>'ﵾ','ﵿ'=>'ﵿ','ﶀ'=>'ﶀ','ﶁ'=>'ﶁ','ﶂ'=>'ﶂ','ﶃ'=>'ﶃ','ﶄ'=>'ﶄ','ﶅ'=>'ﶅ','ﶆ'=>'ﶆ','ﶇ'=>'ﶇ','ﶈ'=>'ﶈ','ﶉ'=>'ﶉ','ﶊ'=>'ﶊ','ﶋ'=>'ﶋ','ﶌ'=>'ﶌ','ﶍ'=>'ﶍ','ﶎ'=>'ﶎ','ﶏ'=>'ﶏ','ﶒ'=>'ﶒ','ﶓ'=>'ﶓ','ﶔ'=>'ﶔ','ﶕ'=>'ﶕ','ﶖ'=>'ﶖ','ﶗ'=>'ﶗ','ﶘ'=>'ﶘ','ﶙ'=>'ﶙ','ﶚ'=>'ﶚ','ﶛ'=>'ﶛ','ﶜ'=>'ﶜ','ﶝ'=>'ﶝ','ﶞ'=>'ﶞ','ﶟ'=>'ﶟ','ﶠ'=>'ﶠ','ﶡ'=>'ﶡ','ﶢ'=>'ﶢ','ﶣ'=>'ﶣ','ﶤ'=>'ﶤ','ﶥ'=>'ﶥ','ﶦ'=>'ﶦ','ﶧ'=>'ﶧ','ﶨ'=>'ﶨ','ﶩ'=>'ﶩ','ﶪ'=>'ﶪ','ﶫ'=>'ﶫ','ﶬ'=>'ﶬ','ﶭ'=>'ﶭ','ﶮ'=>'ﶮ','ﶯ'=>'ﶯ','ﶰ'=>'ﶰ','ﶱ'=>'ﶱ','ﶲ'=>'ﶲ','ﶳ'=>'ﶳ','ﶴ'=>'ﶴ','ﶵ'=>'ﶵ','ﶶ'=>'ﶶ','ﶷ'=>'ﶷ','ﶸ'=>'ﶸ','ﶹ'=>'ﶹ','ﶺ'=>'ﶺ','ﶻ'=>'ﶻ','ﶼ'=>'ﶼ','ﶽ'=>'ﶽ','ﶾ'=>'ﶾ','ﶿ'=>'ﶿ','ﷀ'=>'ﷀ','ﷁ'=>'ﷁ','ﷂ'=>'ﷂ','ﷃ'=>'ﷃ','ﷄ'=>'ﷄ','ﷅ'=>'ﷅ','ﷆ'=>'ﷆ','ﷇ'=>'ﷇ','ﷰ'=>'ﷰ','ﷱ'=>'ﷱ','ﷲ'=>'ﷲ','ﷳ'=>'ﷳ','ﷴ'=>'ﷴ','ﷵ'=>'ﷵ','ﷶ'=>'ﷶ','ﷷ'=>'ﷷ','ﷸ'=>'ﷸ','ﷹ'=>'ﷹ','ﷺ'=>'ﷺ','ﷻ'=>'ﷻ','︀'=>'︀','︁'=>'︁','︂'=>'︂','︃'=>'︃','︄'=>'︄','︅'=>'︅','︆'=>'︆','︇'=>'︇','︈'=>'︈','︉'=>'︉','︊'=>'︊','︋'=>'︋','︌'=>'︌','︍'=>'︍','︎'=>'︎','️'=>'️','︠'=>'︠','︡'=>'︡','︢'=>'︢','︣'=>'︣','ﹰ'=>'ﹰ','ﹱ'=>'ﹱ','ﹲ'=>'ﹲ','ﹳ'=>'ﹳ','ﹴ'=>'ﹴ','ﹶ'=>'ﹶ','ﹷ'=>'ﹷ','ﹸ'=>'ﹸ','ﹹ'=>'ﹹ','ﹺ'=>'ﹺ','ﹻ'=>'ﹻ','ﹼ'=>'ﹼ','ﹽ'=>'ﹽ','ﹾ'=>'ﹾ','ﹿ'=>'ﹿ','ﺀ'=>'ﺀ','ﺁ'=>'ﺁ','ﺂ'=>'ﺂ','ﺃ'=>'ﺃ','ﺄ'=>'ﺄ','ﺅ'=>'ﺅ','ﺆ'=>'ﺆ','ﺇ'=>'ﺇ','ﺈ'=>'ﺈ','ﺉ'=>'ﺉ','ﺊ'=>'ﺊ','ﺋ'=>'ﺋ','ﺌ'=>'ﺌ','ﺍ'=>'ﺍ','ﺎ'=>'ﺎ','ﺏ'=>'ﺏ','ﺐ'=>'ﺐ','ﺑ'=>'ﺑ','ﺒ'=>'ﺒ','ﺓ'=>'ﺓ','ﺔ'=>'ﺔ','ﺕ'=>'ﺕ','ﺖ'=>'ﺖ','ﺗ'=>'ﺗ','ﺘ'=>'ﺘ','ﺙ'=>'ﺙ','ﺚ'=>'ﺚ','ﺛ'=>'ﺛ','ﺜ'=>'ﺜ','ﺝ'=>'ﺝ','ﺞ'=>'ﺞ','ﺟ'=>'ﺟ','ﺠ'=>'ﺠ','ﺡ'=>'ﺡ','ﺢ'=>'ﺢ','ﺣ'=>'ﺣ','ﺤ'=>'ﺤ','ﺥ'=>'ﺥ','ﺦ'=>'ﺦ','ﺧ'=>'ﺧ','ﺨ'=>'ﺨ','ﺩ'=>'ﺩ','ﺪ'=>'ﺪ','ﺫ'=>'ﺫ','ﺬ'=>'ﺬ','ﺭ'=>'ﺭ','ﺮ'=>'ﺮ','ﺯ'=>'ﺯ','ﺰ'=>'ﺰ','ﺱ'=>'ﺱ','ﺲ'=>'ﺲ','ﺳ'=>'ﺳ','ﺴ'=>'ﺴ','ﺵ'=>'ﺵ','ﺶ'=>'ﺶ','ﺷ'=>'ﺷ','ﺸ'=>'ﺸ','ﺹ'=>'ﺹ','ﺺ'=>'ﺺ','ﺻ'=>'ﺻ','ﺼ'=>'ﺼ','ﺽ'=>'ﺽ','ﺾ'=>'ﺾ','ﺿ'=>'ﺿ','ﻀ'=>'ﻀ','ﻁ'=>'ﻁ','ﻂ'=>'ﻂ','ﻃ'=>'ﻃ','ﻄ'=>'ﻄ','ﻅ'=>'ﻅ','ﻆ'=>'ﻆ','ﻇ'=>'ﻇ','ﻈ'=>'ﻈ','ﻉ'=>'ﻉ','ﻊ'=>'ﻊ','ﻋ'=>'ﻋ','ﻌ'=>'ﻌ','ﻍ'=>'ﻍ','ﻎ'=>'ﻎ','ﻏ'=>'ﻏ','ﻐ'=>'ﻐ','ﻑ'=>'ﻑ','ﻒ'=>'ﻒ','ﻓ'=>'ﻓ','ﻔ'=>'ﻔ','ﻕ'=>'ﻕ','ﻖ'=>'ﻖ','ﻗ'=>'ﻗ','ﻘ'=>'ﻘ','ﻙ'=>'ﻙ','ﻚ'=>'ﻚ','ﻛ'=>'ﻛ','ﻜ'=>'ﻜ','ﻝ'=>'ﻝ','ﻞ'=>'ﻞ','ﻟ'=>'ﻟ','ﻠ'=>'ﻠ','ﻡ'=>'ﻡ','ﻢ'=>'ﻢ','ﻣ'=>'ﻣ','ﻤ'=>'ﻤ','ﻥ'=>'ﻥ','ﻦ'=>'ﻦ','ﻧ'=>'ﻧ','ﻨ'=>'ﻨ','ﻩ'=>'ﻩ','ﻪ'=>'ﻪ','ﻫ'=>'ﻫ','ﻬ'=>'ﻬ','ﻭ'=>'ﻭ','ﻮ'=>'ﻮ','ﻯ'=>'ﻯ','ﻰ'=>'ﻰ','ﻱ'=>'ﻱ','ﻲ'=>'ﻲ','ﻳ'=>'ﻳ','ﻴ'=>'ﻴ','ﻵ'=>'ﻵ','ﻶ'=>'ﻶ','ﻷ'=>'ﻷ','ﻸ'=>'ﻸ','ﻹ'=>'ﻹ','ﻺ'=>'ﻺ','ﻻ'=>'ﻻ','ﻼ'=>'ﻼ','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','ヲ'=>'ヲ','ァ'=>'ァ','ィ'=>'ィ','ゥ'=>'ゥ','ェ'=>'ェ','ォ'=>'ォ','ャ'=>'ャ','ュ'=>'ュ','ョ'=>'ョ','ッ'=>'ッ','ー'=>'ー','ア'=>'ア','イ'=>'イ','ウ'=>'ウ','エ'=>'エ','オ'=>'オ','カ'=>'カ','キ'=>'キ','ク'=>'ク','ケ'=>'ケ','コ'=>'コ','サ'=>'サ','シ'=>'シ','ス'=>'ス','セ'=>'セ','ソ'=>'ソ','タ'=>'タ','チ'=>'チ','ツ'=>'ツ','テ'=>'テ','ト'=>'ト','ナ'=>'ナ','ニ'=>'ニ','ヌ'=>'ヌ','ネ'=>'ネ','ノ'=>'ノ','ハ'=>'ハ','ヒ'=>'ヒ','フ'=>'フ','ヘ'=>'ヘ','ホ'=>'ホ','マ'=>'マ','ミ'=>'ミ','ム'=>'ム','メ'=>'メ','モ'=>'モ','ヤ'=>'ヤ','ユ'=>'ユ','ヨ'=>'ヨ','ラ'=>'ラ','リ'=>'リ','ル'=>'ル','レ'=>'レ','ロ'=>'ロ','ワ'=>'ワ','ン'=>'ン','゙'=>'゙','゚'=>'゚','ᅠ'=>'ᅠ','ᄀ'=>'ᄀ','ᄁ'=>'ᄁ','ᆪ'=>'ᆪ','ᄂ'=>'ᄂ','ᆬ'=>'ᆬ','ᆭ'=>'ᆭ','ᄃ'=>'ᄃ','ᄄ'=>'ᄄ','ᄅ'=>'ᄅ','ᆰ'=>'ᆰ','ᆱ'=>'ᆱ','ᆲ'=>'ᆲ','ᆳ'=>'ᆳ','ᆴ'=>'ᆴ','ᆵ'=>'ᆵ','ᄚ'=>'ᄚ','ᄆ'=>'ᄆ','ᄇ'=>'ᄇ','ᄈ'=>'ᄈ','ᄡ'=>'ᄡ','ᄉ'=>'ᄉ','ᄊ'=>'ᄊ','ᄋ'=>'ᄋ','ᄌ'=>'ᄌ','ᄍ'=>'ᄍ','ᄎ'=>'ᄎ','ᄏ'=>'ᄏ','ᄐ'=>'ᄐ','ᄑ'=>'ᄑ','ᄒ'=>'ᄒ','ᅡ'=>'ᅡ','ᅢ'=>'ᅢ','ᅣ'=>'ᅣ','ᅤ'=>'ᅤ','ᅥ'=>'ᅥ','ᅦ'=>'ᅦ','ᅧ'=>'ᅧ','ᅨ'=>'ᅨ','ᅩ'=>'ᅩ','ᅪ'=>'ᅪ','ᅫ'=>'ᅫ','ᅬ'=>'ᅬ','ᅭ'=>'ᅭ','ᅮ'=>'ᅮ','ᅯ'=>'ᅯ','ᅰ'=>'ᅰ','ᅱ'=>'ᅱ','ᅲ'=>'ᅲ','ᅳ'=>'ᅳ','ᅴ'=>'ᅴ','ᅵ'=>'ᅵ');
\ 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('À'=>'À','Á'=>'Á','Â'=>'Â','Ã'=>'Ã','Ä'=>'Ä','Å'=>'Å','Ç'=>'Ç','È'=>'È','É'=>'É','Ê'=>'Ê','Ë'=>'Ë','Ì'=>'Ì','Í'=>'Í','Î'=>'Î','Ï'=>'Ï','Ñ'=>'Ñ','Ò'=>'Ò','Ó'=>'Ó','Ô'=>'Ô','Õ'=>'Õ','Ö'=>'Ö','Ù'=>'Ù','Ú'=>'Ú','Û'=>'Û','Ü'=>'Ü','Ý'=>'Ý','à'=>'à','á'=>'á','â'=>'â','ã'=>'ã','ä'=>'ä','å'=>'å','ç'=>'ç','è'=>'è','é'=>'é','ê'=>'ê','ë'=>'ë','ì'=>'ì','í'=>'í','î'=>'î','ï'=>'ï','ñ'=>'ñ','ò'=>'ò','ó'=>'ó','ô'=>'ô','õ'=>'õ','ö'=>'ö','ù'=>'ù','ú'=>'ú','û'=>'û','ü'=>'ü','ý'=>'ý','ÿ'=>'ÿ','Ā'=>'Ā','ā'=>'ā','Ă'=>'Ă','ă'=>'ă','Ą'=>'Ą','ą'=>'ą','Ć'=>'Ć','ć'=>'ć','Ĉ'=>'Ĉ','ĉ'=>'ĉ','Ċ'=>'Ċ','ċ'=>'ċ','Č'=>'Č','č'=>'č','Ď'=>'Ď','ď'=>'ď','Ē'=>'Ē','ē'=>'ē','Ĕ'=>'Ĕ','ĕ'=>'ĕ','Ė'=>'Ė','ė'=>'ė','Ę'=>'Ę','ę'=>'ę','Ě'=>'Ě','ě'=>'ě','Ĝ'=>'Ĝ','ĝ'=>'ĝ','Ğ'=>'Ğ','ğ'=>'ğ','Ġ'=>'Ġ','ġ'=>'ġ','Ģ'=>'Ģ','ģ'=>'ģ','Ĥ'=>'Ĥ','ĥ'=>'ĥ','Ĩ'=>'Ĩ','ĩ'=>'ĩ','Ī'=>'Ī','ī'=>'ī','Ĭ'=>'Ĭ','ĭ'=>'ĭ','Į'=>'Į','į'=>'į','İ'=>'İ','Ĵ'=>'Ĵ','ĵ'=>'ĵ','Ķ'=>'Ķ','ķ'=>'ķ','Ĺ'=>'Ĺ','ĺ'=>'ĺ','Ļ'=>'Ļ','ļ'=>'ļ','Ľ'=>'Ľ','ľ'=>'ľ','Ń'=>'Ń','ń'=>'ń','Ņ'=>'Ņ','ņ'=>'ņ','Ň'=>'Ň','ň'=>'ň','Ō'=>'Ō','ō'=>'ō','Ŏ'=>'Ŏ','ŏ'=>'ŏ','Ő'=>'Ő','ő'=>'ő','Ŕ'=>'Ŕ','ŕ'=>'ŕ','Ŗ'=>'Ŗ','ŗ'=>'ŗ','Ř'=>'Ř','ř'=>'ř','Ś'=>'Ś','ś'=>'ś','Ŝ'=>'Ŝ','ŝ'=>'ŝ','Ş'=>'Ş','ş'=>'ş','Š'=>'Š','š'=>'š','Ţ'=>'Ţ','ţ'=>'ţ','Ť'=>'Ť','ť'=>'ť','Ũ'=>'Ũ','ũ'=>'ũ','Ū'=>'Ū','ū'=>'ū','Ŭ'=>'Ŭ','ŭ'=>'ŭ','Ů'=>'Ů','ů'=>'ů','Ű'=>'Ű','ű'=>'ű','Ų'=>'Ų','ų'=>'ų','Ŵ'=>'Ŵ','ŵ'=>'ŵ','Ŷ'=>'Ŷ','ŷ'=>'ŷ','Ÿ'=>'Ÿ','Ź'=>'Ź','ź'=>'ź','Ż'=>'Ż','ż'=>'ż','Ž'=>'Ž','ž'=>'ž','Ơ'=>'Ơ','ơ'=>'ơ','Ư'=>'Ư','ư'=>'ư','Ǎ'=>'Ǎ','ǎ'=>'ǎ','Ǐ'=>'Ǐ','ǐ'=>'ǐ','Ǒ'=>'Ǒ','ǒ'=>'ǒ','Ǔ'=>'Ǔ','ǔ'=>'ǔ','Ǖ'=>'Ǖ','ǖ'=>'ǖ','Ǘ'=>'Ǘ','ǘ'=>'ǘ','Ǚ'=>'Ǚ','ǚ'=>'ǚ','Ǜ'=>'Ǜ','ǜ'=>'ǜ','Ǟ'=>'Ǟ','ǟ'=>'ǟ','Ǡ'=>'Ǡ','ǡ'=>'ǡ','Ǣ'=>'Ǣ','ǣ'=>'ǣ','Ǧ'=>'Ǧ','ǧ'=>'ǧ','Ǩ'=>'Ǩ','ǩ'=>'ǩ','Ǫ'=>'Ǫ','ǫ'=>'ǫ','Ǭ'=>'Ǭ','ǭ'=>'ǭ','Ǯ'=>'Ǯ','ǯ'=>'ǯ','ǰ'=>'ǰ','Ǵ'=>'Ǵ','ǵ'=>'ǵ','Ǹ'=>'Ǹ','ǹ'=>'ǹ','Ǻ'=>'Ǻ','ǻ'=>'ǻ','Ǽ'=>'Ǽ','ǽ'=>'ǽ','Ǿ'=>'Ǿ','ǿ'=>'ǿ','Ȁ'=>'Ȁ','ȁ'=>'ȁ','Ȃ'=>'Ȃ','ȃ'=>'ȃ','Ȅ'=>'Ȅ','ȅ'=>'ȅ','Ȇ'=>'Ȇ','ȇ'=>'ȇ','Ȉ'=>'Ȉ','ȉ'=>'ȉ','Ȋ'=>'Ȋ','ȋ'=>'ȋ','Ȍ'=>'Ȍ','ȍ'=>'ȍ','Ȏ'=>'Ȏ','ȏ'=>'ȏ','Ȑ'=>'Ȑ','ȑ'=>'ȑ','Ȓ'=>'Ȓ','ȓ'=>'ȓ','Ȕ'=>'Ȕ','ȕ'=>'ȕ','Ȗ'=>'Ȗ','ȗ'=>'ȗ','Ș'=>'Ș','ș'=>'ș','Ț'=>'Ț','ț'=>'ț','Ȟ'=>'Ȟ','ȟ'=>'ȟ','Ȧ'=>'Ȧ','ȧ'=>'ȧ','Ȩ'=>'Ȩ','ȩ'=>'ȩ','Ȫ'=>'Ȫ','ȫ'=>'ȫ','Ȭ'=>'Ȭ','ȭ'=>'ȭ','Ȯ'=>'Ȯ','ȯ'=>'ȯ','Ȱ'=>'Ȱ','ȱ'=>'ȱ','Ȳ'=>'Ȳ','ȳ'=>'ȳ','̈́'=>'̈́','΅'=>'΅','Ά'=>'Ά','Έ'=>'Έ','Ή'=>'Ή','Ί'=>'Ί','Ό'=>'Ό','Ύ'=>'Ύ','Ώ'=>'Ώ','ΐ'=>'ΐ','Ϊ'=>'Ϊ','Ϋ'=>'Ϋ','ά'=>'ά','έ'=>'έ','ή'=>'ή','ί'=>'ί','ΰ'=>'ΰ','ϊ'=>'ϊ','ϋ'=>'ϋ','ό'=>'ό','ύ'=>'ύ','ώ'=>'ώ','ϓ'=>'ϓ','ϔ'=>'ϔ','Ѐ'=>'Ѐ','Ё'=>'Ё','Ѓ'=>'Ѓ','Ї'=>'Ї','Ќ'=>'Ќ','Ѝ'=>'Ѝ','Ў'=>'Ў','Й'=>'Й','й'=>'й','ѐ'=>'ѐ','ё'=>'ё','ѓ'=>'ѓ','ї'=>'ї','ќ'=>'ќ','ѝ'=>'ѝ','ў'=>'ў','Ѷ'=>'Ѷ','ѷ'=>'ѷ','Ӂ'=>'Ӂ','ӂ'=>'ӂ','Ӑ'=>'Ӑ','ӑ'=>'ӑ','Ӓ'=>'Ӓ','ӓ'=>'ӓ','Ӗ'=>'Ӗ','ӗ'=>'ӗ','Ӛ'=>'Ӛ','ӛ'=>'ӛ','Ӝ'=>'Ӝ','ӝ'=>'ӝ','Ӟ'=>'Ӟ','ӟ'=>'ӟ','Ӣ'=>'Ӣ','ӣ'=>'ӣ','Ӥ'=>'Ӥ','ӥ'=>'ӥ','Ӧ'=>'Ӧ','ӧ'=>'ӧ','Ӫ'=>'Ӫ','ӫ'=>'ӫ','Ӭ'=>'Ӭ','ӭ'=>'ӭ','Ӯ'=>'Ӯ','ӯ'=>'ӯ','Ӱ'=>'Ӱ','ӱ'=>'ӱ','Ӳ'=>'Ӳ','ӳ'=>'ӳ','Ӵ'=>'Ӵ','ӵ'=>'ӵ','Ӹ'=>'Ӹ','ӹ'=>'ӹ','آ'=>'آ','أ'=>'أ','ؤ'=>'ؤ','إ'=>'إ','ئ'=>'ئ','ۀ'=>'ۀ','ۂ'=>'ۂ','ۓ'=>'ۓ','ऩ'=>'ऩ','ऱ'=>'ऱ','ऴ'=>'ऴ','ো'=>'ো','ৌ'=>'ৌ','ୈ'=>'ୈ','ୋ'=>'ୋ','ୌ'=>'ୌ','ஔ'=>'ஔ','ொ'=>'ொ','ோ'=>'ோ','ௌ'=>'ௌ','ై'=>'ై','ೀ'=>'ೀ','ೇ'=>'ೇ','ೈ'=>'ೈ','ೊ'=>'ೊ','ೋ'=>'ೋ','ൊ'=>'ൊ','ോ'=>'ോ','ൌ'=>'ൌ','ේ'=>'ේ','ො'=>'ො','ෝ'=>'ෝ','ෞ'=>'ෞ','ཱི'=>'ཱི','ཱུ'=>'ཱུ','ཱྀ'=>'ཱྀ','ဦ'=>'ဦ','ᬆ'=>'ᬆ','ᬈ'=>'ᬈ','ᬊ'=>'ᬊ','ᬌ'=>'ᬌ','ᬎ'=>'ᬎ','ᬒ'=>'ᬒ','ᬻ'=>'ᬻ','ᬽ'=>'ᬽ','ᭀ'=>'ᭀ','ᭁ'=>'ᭁ','ᭃ'=>'ᭃ','Ḁ'=>'Ḁ','ḁ'=>'ḁ','Ḃ'=>'Ḃ','ḃ'=>'ḃ','Ḅ'=>'Ḅ','ḅ'=>'ḅ','Ḇ'=>'Ḇ','ḇ'=>'ḇ','Ḉ'=>'Ḉ','ḉ'=>'ḉ','Ḋ'=>'Ḋ','ḋ'=>'ḋ','Ḍ'=>'Ḍ','ḍ'=>'ḍ','Ḏ'=>'Ḏ','ḏ'=>'ḏ','Ḑ'=>'Ḑ','ḑ'=>'ḑ','Ḓ'=>'Ḓ','ḓ'=>'ḓ','Ḕ'=>'Ḕ','ḕ'=>'ḕ','Ḗ'=>'Ḗ','ḗ'=>'ḗ','Ḙ'=>'Ḙ','ḙ'=>'ḙ','Ḛ'=>'Ḛ','ḛ'=>'ḛ','Ḝ'=>'Ḝ','ḝ'=>'ḝ','Ḟ'=>'Ḟ','ḟ'=>'ḟ','Ḡ'=>'Ḡ','ḡ'=>'ḡ','Ḣ'=>'Ḣ','ḣ'=>'ḣ','Ḥ'=>'Ḥ','ḥ'=>'ḥ','Ḧ'=>'Ḧ','ḧ'=>'ḧ','Ḩ'=>'Ḩ','ḩ'=>'ḩ','Ḫ'=>'Ḫ','ḫ'=>'ḫ','Ḭ'=>'Ḭ','ḭ'=>'ḭ','Ḯ'=>'Ḯ','ḯ'=>'ḯ','Ḱ'=>'Ḱ','ḱ'=>'ḱ','Ḳ'=>'Ḳ','ḳ'=>'ḳ','Ḵ'=>'Ḵ','ḵ'=>'ḵ','Ḷ'=>'Ḷ','ḷ'=>'ḷ','Ḹ'=>'Ḹ','ḹ'=>'ḹ','Ḻ'=>'Ḻ','ḻ'=>'ḻ','Ḽ'=>'Ḽ','ḽ'=>'ḽ','Ḿ'=>'Ḿ','ḿ'=>'ḿ','Ṁ'=>'Ṁ','ṁ'=>'ṁ','Ṃ'=>'Ṃ','ṃ'=>'ṃ','Ṅ'=>'Ṅ','ṅ'=>'ṅ','Ṇ'=>'Ṇ','ṇ'=>'ṇ','Ṉ'=>'Ṉ','ṉ'=>'ṉ','Ṋ'=>'Ṋ','ṋ'=>'ṋ','Ṍ'=>'Ṍ','ṍ'=>'ṍ','Ṏ'=>'Ṏ','ṏ'=>'ṏ','Ṑ'=>'Ṑ','ṑ'=>'ṑ','Ṓ'=>'Ṓ','ṓ'=>'ṓ','Ṕ'=>'Ṕ','ṕ'=>'ṕ','Ṗ'=>'Ṗ','ṗ'=>'ṗ','Ṙ'=>'Ṙ','ṙ'=>'ṙ','Ṛ'=>'Ṛ','ṛ'=>'ṛ','Ṝ'=>'Ṝ','ṝ'=>'ṝ','Ṟ'=>'Ṟ','ṟ'=>'ṟ','Ṡ'=>'Ṡ','ṡ'=>'ṡ','Ṣ'=>'Ṣ','ṣ'=>'ṣ','Ṥ'=>'Ṥ','ṥ'=>'ṥ','Ṧ'=>'Ṧ','ṧ'=>'ṧ','Ṩ'=>'Ṩ','ṩ'=>'ṩ','Ṫ'=>'Ṫ','ṫ'=>'ṫ','Ṭ'=>'Ṭ','ṭ'=>'ṭ','Ṯ'=>'Ṯ','ṯ'=>'ṯ','Ṱ'=>'Ṱ','ṱ'=>'ṱ','Ṳ'=>'Ṳ','ṳ'=>'ṳ','Ṵ'=>'Ṵ','ṵ'=>'ṵ','Ṷ'=>'Ṷ','ṷ'=>'ṷ','Ṹ'=>'Ṹ','ṹ'=>'ṹ','Ṻ'=>'Ṻ','ṻ'=>'ṻ','Ṽ'=>'Ṽ','ṽ'=>'ṽ','Ṿ'=>'Ṿ','ṿ'=>'ṿ','Ẁ'=>'Ẁ','ẁ'=>'ẁ','Ẃ'=>'Ẃ','ẃ'=>'ẃ','Ẅ'=>'Ẅ','ẅ'=>'ẅ','Ẇ'=>'Ẇ','ẇ'=>'ẇ','Ẉ'=>'Ẉ','ẉ'=>'ẉ','Ẋ'=>'Ẋ','ẋ'=>'ẋ','Ẍ'=>'Ẍ','ẍ'=>'ẍ','Ẏ'=>'Ẏ','ẏ'=>'ẏ','Ẑ'=>'Ẑ','ẑ'=>'ẑ','Ẓ'=>'Ẓ','ẓ'=>'ẓ','Ẕ'=>'Ẕ','ẕ'=>'ẕ','ẖ'=>'ẖ','ẗ'=>'ẗ','ẘ'=>'ẘ','ẙ'=>'ẙ','ẛ'=>'ẛ','Ạ'=>'Ạ','ạ'=>'ạ','Ả'=>'Ả','ả'=>'ả','Ấ'=>'Ấ','ấ'=>'ấ','Ầ'=>'Ầ','ầ'=>'ầ','Ẩ'=>'Ẩ','ẩ'=>'ẩ','Ẫ'=>'Ẫ','ẫ'=>'ẫ','Ậ'=>'Ậ','ậ'=>'ậ','Ắ'=>'Ắ','ắ'=>'ắ','Ằ'=>'Ằ','ằ'=>'ằ','Ẳ'=>'Ẳ','ẳ'=>'ẳ','Ẵ'=>'Ẵ','ẵ'=>'ẵ','Ặ'=>'Ặ','ặ'=>'ặ','Ẹ'=>'Ẹ','ẹ'=>'ẹ','Ẻ'=>'Ẻ','ẻ'=>'ẻ','Ẽ'=>'Ẽ','ẽ'=>'ẽ','Ế'=>'Ế','ế'=>'ế','Ề'=>'Ề','ề'=>'ề','Ể'=>'Ể','ể'=>'ể','Ễ'=>'Ễ','ễ'=>'ễ','Ệ'=>'Ệ','ệ'=>'ệ','Ỉ'=>'Ỉ','ỉ'=>'ỉ','Ị'=>'Ị','ị'=>'ị','Ọ'=>'Ọ','ọ'=>'ọ','Ỏ'=>'Ỏ','ỏ'=>'ỏ','Ố'=>'Ố','ố'=>'ố','Ồ'=>'Ồ','ồ'=>'ồ','Ổ'=>'Ổ','ổ'=>'ổ','Ỗ'=>'Ỗ','ỗ'=>'ỗ','Ộ'=>'Ộ','ộ'=>'ộ','Ớ'=>'Ớ','ớ'=>'ớ','Ờ'=>'Ờ','ờ'=>'ờ','Ở'=>'Ở','ở'=>'ở','Ỡ'=>'Ỡ','ỡ'=>'ỡ','Ợ'=>'Ợ','ợ'=>'ợ','Ụ'=>'Ụ','ụ'=>'ụ','Ủ'=>'Ủ','ủ'=>'ủ','Ứ'=>'Ứ','ứ'=>'ứ','Ừ'=>'Ừ','ừ'=>'ừ','Ử'=>'Ử','ử'=>'ử','Ữ'=>'Ữ','ữ'=>'ữ','Ự'=>'Ự','ự'=>'ự','Ỳ'=>'Ỳ','ỳ'=>'ỳ','Ỵ'=>'Ỵ','ỵ'=>'ỵ','Ỷ'=>'Ỷ','ỷ'=>'ỷ','Ỹ'=>'Ỹ','ỹ'=>'ỹ','ἀ'=>'ἀ','ἁ'=>'ἁ','ἂ'=>'ἂ','ἃ'=>'ἃ','ἄ'=>'ἄ','ἅ'=>'ἅ','ἆ'=>'ἆ','ἇ'=>'ἇ','Ἀ'=>'Ἀ','Ἁ'=>'Ἁ','Ἂ'=>'Ἂ','Ἃ'=>'Ἃ','Ἄ'=>'Ἄ','Ἅ'=>'Ἅ','Ἆ'=>'Ἆ','Ἇ'=>'Ἇ','ἐ'=>'ἐ','ἑ'=>'ἑ','ἒ'=>'ἒ','ἓ'=>'ἓ','ἔ'=>'ἔ','ἕ'=>'ἕ','Ἐ'=>'Ἐ','Ἑ'=>'Ἑ','Ἒ'=>'Ἒ','Ἓ'=>'Ἓ','Ἔ'=>'Ἔ','Ἕ'=>'Ἕ','ἠ'=>'ἠ','ἡ'=>'ἡ','ἢ'=>'ἢ','ἣ'=>'ἣ','ἤ'=>'ἤ','ἥ'=>'ἥ','ἦ'=>'ἦ','ἧ'=>'ἧ','Ἠ'=>'Ἠ','Ἡ'=>'Ἡ','Ἢ'=>'Ἢ','Ἣ'=>'Ἣ','Ἤ'=>'Ἤ','Ἥ'=>'Ἥ','Ἦ'=>'Ἦ','Ἧ'=>'Ἧ','ἰ'=>'ἰ','ἱ'=>'ἱ','ἲ'=>'ἲ','ἳ'=>'ἳ','ἴ'=>'ἴ','ἵ'=>'ἵ','ἶ'=>'ἶ','ἷ'=>'ἷ','Ἰ'=>'Ἰ','Ἱ'=>'Ἱ','Ἲ'=>'Ἲ','Ἳ'=>'Ἳ','Ἴ'=>'Ἴ','Ἵ'=>'Ἵ','Ἶ'=>'Ἶ','Ἷ'=>'Ἷ','ὀ'=>'ὀ','ὁ'=>'ὁ','ὂ'=>'ὂ','ὃ'=>'ὃ','ὄ'=>'ὄ','ὅ'=>'ὅ','Ὀ'=>'Ὀ','Ὁ'=>'Ὁ','Ὂ'=>'Ὂ','Ὃ'=>'Ὃ','Ὄ'=>'Ὄ','Ὅ'=>'Ὅ','ὐ'=>'ὐ','ὑ'=>'ὑ','ὒ'=>'ὒ','ὓ'=>'ὓ','ὔ'=>'ὔ','ὕ'=>'ὕ','ὖ'=>'ὖ','ὗ'=>'ὗ','Ὑ'=>'Ὑ','Ὓ'=>'Ὓ','Ὕ'=>'Ὕ','Ὗ'=>'Ὗ','ὠ'=>'ὠ','ὡ'=>'ὡ','ὢ'=>'ὢ','ὣ'=>'ὣ','ὤ'=>'ὤ','ὥ'=>'ὥ','ὦ'=>'ὦ','ὧ'=>'ὧ','Ὠ'=>'Ὠ','Ὡ'=>'Ὡ','Ὢ'=>'Ὢ','Ὣ'=>'Ὣ','Ὤ'=>'Ὤ','Ὥ'=>'Ὥ','Ὦ'=>'Ὦ','Ὧ'=>'Ὧ','ὰ'=>'ὰ','ὲ'=>'ὲ','ὴ'=>'ὴ','ὶ'=>'ὶ','ὸ'=>'ὸ','ὺ'=>'ὺ','ὼ'=>'ὼ','ᾀ'=>'ᾀ','ᾁ'=>'ᾁ','ᾂ'=>'ᾂ','ᾃ'=>'ᾃ','ᾄ'=>'ᾄ','ᾅ'=>'ᾅ','ᾆ'=>'ᾆ','ᾇ'=>'ᾇ','ᾈ'=>'ᾈ','ᾉ'=>'ᾉ','ᾊ'=>'ᾊ','ᾋ'=>'ᾋ','ᾌ'=>'ᾌ','ᾍ'=>'ᾍ','ᾎ'=>'ᾎ','ᾏ'=>'ᾏ','ᾐ'=>'ᾐ','ᾑ'=>'ᾑ','ᾒ'=>'ᾒ','ᾓ'=>'ᾓ','ᾔ'=>'ᾔ','ᾕ'=>'ᾕ','ᾖ'=>'ᾖ','ᾗ'=>'ᾗ','ᾘ'=>'ᾘ','ᾙ'=>'ᾙ','ᾚ'=>'ᾚ','ᾛ'=>'ᾛ','ᾜ'=>'ᾜ','ᾝ'=>'ᾝ','ᾞ'=>'ᾞ','ᾟ'=>'ᾟ','ᾠ'=>'ᾠ','ᾡ'=>'ᾡ','ᾢ'=>'ᾢ','ᾣ'=>'ᾣ','ᾤ'=>'ᾤ','ᾥ'=>'ᾥ','ᾦ'=>'ᾦ','ᾧ'=>'ᾧ','ᾨ'=>'ᾨ','ᾩ'=>'ᾩ','ᾪ'=>'ᾪ','ᾫ'=>'ᾫ','ᾬ'=>'ᾬ','ᾭ'=>'ᾭ','ᾮ'=>'ᾮ','ᾯ'=>'ᾯ','ᾰ'=>'ᾰ','ᾱ'=>'ᾱ','ᾲ'=>'ᾲ','ᾳ'=>'ᾳ','ᾴ'=>'ᾴ','ᾶ'=>'ᾶ','ᾷ'=>'ᾷ','Ᾰ'=>'Ᾰ','Ᾱ'=>'Ᾱ','Ὰ'=>'Ὰ','ᾼ'=>'ᾼ','῁'=>'῁','ῂ'=>'ῂ','ῃ'=>'ῃ','ῄ'=>'ῄ','ῆ'=>'ῆ','ῇ'=>'ῇ','Ὲ'=>'Ὲ','Ὴ'=>'Ὴ','ῌ'=>'ῌ','῍'=>'῍','῎'=>'῎','῏'=>'῏','ῐ'=>'ῐ','ῑ'=>'ῑ','ῒ'=>'ῒ','ῖ'=>'ῖ','ῗ'=>'ῗ','Ῐ'=>'Ῐ','Ῑ'=>'Ῑ','Ὶ'=>'Ὶ','῝'=>'῝','῞'=>'῞','῟'=>'῟','ῠ'=>'ῠ','ῡ'=>'ῡ','ῢ'=>'ῢ','ῤ'=>'ῤ','ῥ'=>'ῥ','ῦ'=>'ῦ','ῧ'=>'ῧ','Ῠ'=>'Ῠ','Ῡ'=>'Ῡ','Ὺ'=>'Ὺ','Ῥ'=>'Ῥ','῭'=>'῭','ῲ'=>'ῲ','ῳ'=>'ῳ','ῴ'=>'ῴ','ῶ'=>'ῶ','ῷ'=>'ῷ','Ὸ'=>'Ὸ','Ὼ'=>'Ὼ','ῼ'=>'ῼ','↚'=>'↚','↛'=>'↛','↮'=>'↮','⇍'=>'⇍','⇎'=>'⇎','⇏'=>'⇏','∄'=>'∄','∉'=>'∉','∌'=>'∌','∤'=>'∤','∦'=>'∦','≁'=>'≁','≄'=>'≄','≇'=>'≇','≉'=>'≉','≠'=>'≠','≢'=>'≢','≭'=>'≭','≮'=>'≮','≯'=>'≯','≰'=>'≰','≱'=>'≱','≴'=>'≴','≵'=>'≵','≸'=>'≸','≹'=>'≹','⊀'=>'⊀','⊁'=>'⊁','⊄'=>'⊄','⊅'=>'⊅','⊈'=>'⊈','⊉'=>'⊉','⊬'=>'⊬','⊭'=>'⊭','⊮'=>'⊮','⊯'=>'⊯','⋠'=>'⋠','⋡'=>'⋡','⋢'=>'⋢','⋣'=>'⋣','⋪'=>'⋪','⋫'=>'⋫','⋬'=>'⋬','⋭'=>'⋭','が'=>'が','ぎ'=>'ぎ','ぐ'=>'ぐ','げ'=>'げ','ご'=>'ご','ざ'=>'ざ','じ'=>'じ','ず'=>'ず','ぜ'=>'ぜ','ぞ'=>'ぞ','だ'=>'だ','ぢ'=>'ぢ','づ'=>'づ','で'=>'で','ど'=>'ど','ば'=>'ば','ぱ'=>'ぱ','び'=>'び','ぴ'=>'ぴ','ぶ'=>'ぶ','ぷ'=>'ぷ','べ'=>'べ','ぺ'=>'ぺ','ぼ'=>'ぼ','ぽ'=>'ぽ','ゔ'=>'ゔ','ゞ'=>'ゞ','ガ'=>'ガ','ギ'=>'ギ','グ'=>'グ','ゲ'=>'ゲ','ゴ'=>'ゴ','ザ'=>'ザ','ジ'=>'ジ','ズ'=>'ズ','ゼ'=>'ゼ','ゾ'=>'ゾ','ダ'=>'ダ','ヂ'=>'ヂ','ヅ'=>'ヅ','デ'=>'デ','ド'=>'ド','バ'=>'バ','パ'=>'パ','ビ'=>'ビ','ピ'=>'ピ','ブ'=>'ブ','プ'=>'プ','ベ'=>'ベ','ペ'=>'ペ','ボ'=>'ボ','ポ'=>'ポ','ヴ'=>'ヴ','ヷ'=>'ヷ','ヸ'=>'ヸ','ヹ'=>'ヹ','ヺ'=>'ヺ','ヾ'=>'ヾ');
\ 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('À'=>'À','Á'=>'Á','Â'=>'Â','Ã'=>'Ã','Ä'=>'Ä','Å'=>'Å','Ç'=>'Ç','È'=>'È','É'=>'É','Ê'=>'Ê','Ë'=>'Ë','Ì'=>'Ì','Í'=>'Í','Î'=>'Î','Ï'=>'Ï','Ñ'=>'Ñ','Ò'=>'Ò','Ó'=>'Ó','Ô'=>'Ô','Õ'=>'Õ','Ö'=>'Ö','Ù'=>'Ù','Ú'=>'Ú','Û'=>'Û','Ü'=>'Ü','Ý'=>'Ý','à'=>'à','á'=>'á','â'=>'â','ã'=>'ã','ä'=>'ä','å'=>'å','ç'=>'ç','è'=>'è','é'=>'é','ê'=>'ê','ë'=>'ë','ì'=>'ì','í'=>'í','î'=>'î','ï'=>'ï','ñ'=>'ñ','ò'=>'ò','ó'=>'ó','ô'=>'ô','õ'=>'õ','ö'=>'ö','ù'=>'ù','ú'=>'ú','û'=>'û','ü'=>'ü','ý'=>'ý','ÿ'=>'ÿ','Ā'=>'Ā','ā'=>'ā','Ă'=>'Ă','ă'=>'ă','Ą'=>'Ą','ą'=>'ą','Ć'=>'Ć','ć'=>'ć','Ĉ'=>'Ĉ','ĉ'=>'ĉ','Ċ'=>'Ċ','ċ'=>'ċ','Č'=>'Č','č'=>'č','Ď'=>'Ď','ď'=>'ď','Ē'=>'Ē','ē'=>'ē','Ĕ'=>'Ĕ','ĕ'=>'ĕ','Ė'=>'Ė','ė'=>'ė','Ę'=>'Ę','ę'=>'ę','Ě'=>'Ě','ě'=>'ě','Ĝ'=>'Ĝ','ĝ'=>'ĝ','Ğ'=>'Ğ','ğ'=>'ğ','Ġ'=>'Ġ','ġ'=>'ġ','Ģ'=>'Ģ','ģ'=>'ģ','Ĥ'=>'Ĥ','ĥ'=>'ĥ','Ĩ'=>'Ĩ','ĩ'=>'ĩ','Ī'=>'Ī','ī'=>'ī','Ĭ'=>'Ĭ','ĭ'=>'ĭ','Į'=>'Į','į'=>'į','İ'=>'İ','Ĵ'=>'Ĵ','ĵ'=>'ĵ','Ķ'=>'Ķ','ķ'=>'ķ','Ĺ'=>'Ĺ','ĺ'=>'ĺ','Ļ'=>'Ļ','ļ'=>'ļ','Ľ'=>'Ľ','ľ'=>'ľ','Ń'=>'Ń','ń'=>'ń','Ņ'=>'Ņ','ņ'=>'ņ','Ň'=>'Ň','ň'=>'ň','Ō'=>'Ō','ō'=>'ō','Ŏ'=>'Ŏ','ŏ'=>'ŏ','Ő'=>'Ő','ő'=>'ő','Ŕ'=>'Ŕ','ŕ'=>'ŕ','Ŗ'=>'Ŗ','ŗ'=>'ŗ','Ř'=>'Ř','ř'=>'ř','Ś'=>'Ś','ś'=>'ś','Ŝ'=>'Ŝ','ŝ'=>'ŝ','Ş'=>'Ş','ş'=>'ş','Š'=>'Š','š'=>'š','Ţ'=>'Ţ','ţ'=>'ţ','Ť'=>'Ť','ť'=>'ť','Ũ'=>'Ũ','ũ'=>'ũ','Ū'=>'Ū','ū'=>'ū','Ŭ'=>'Ŭ','ŭ'=>'ŭ','Ů'=>'Ů','ů'=>'ů','Ű'=>'Ű','ű'=>'ű','Ų'=>'Ų','ų'=>'ų','Ŵ'=>'Ŵ','ŵ'=>'ŵ','Ŷ'=>'Ŷ','ŷ'=>'ŷ','Ÿ'=>'Ÿ','Ź'=>'Ź','ź'=>'ź','Ż'=>'Ż','ż'=>'ż','Ž'=>'Ž','ž'=>'ž','Ơ'=>'Ơ','ơ'=>'ơ','Ư'=>'Ư','ư'=>'ư','Ǎ'=>'Ǎ','ǎ'=>'ǎ','Ǐ'=>'Ǐ','ǐ'=>'ǐ','Ǒ'=>'Ǒ','ǒ'=>'ǒ','Ǔ'=>'Ǔ','ǔ'=>'ǔ','Ǖ'=>'Ǖ','ǖ'=>'ǖ','Ǘ'=>'Ǘ','ǘ'=>'ǘ','Ǚ'=>'Ǚ','ǚ'=>'ǚ','Ǜ'=>'Ǜ','ǜ'=>'ǜ','Ǟ'=>'Ǟ','ǟ'=>'ǟ','Ǡ'=>'Ǡ','ǡ'=>'ǡ','Ǣ'=>'Ǣ','ǣ'=>'ǣ','Ǧ'=>'Ǧ','ǧ'=>'ǧ','Ǩ'=>'Ǩ','ǩ'=>'ǩ','Ǫ'=>'Ǫ','ǫ'=>'ǫ','Ǭ'=>'Ǭ','ǭ'=>'ǭ','Ǯ'=>'Ǯ','ǯ'=>'ǯ','ǰ'=>'ǰ','Ǵ'=>'Ǵ','ǵ'=>'ǵ','Ǹ'=>'Ǹ','ǹ'=>'ǹ','Ǻ'=>'Ǻ','ǻ'=>'ǻ','Ǽ'=>'Ǽ','ǽ'=>'ǽ','Ǿ'=>'Ǿ','ǿ'=>'ǿ','Ȁ'=>'Ȁ','ȁ'=>'ȁ','Ȃ'=>'Ȃ','ȃ'=>'ȃ','Ȅ'=>'Ȅ','ȅ'=>'ȅ','Ȇ'=>'Ȇ','ȇ'=>'ȇ','Ȉ'=>'Ȉ','ȉ'=>'ȉ','Ȋ'=>'Ȋ','ȋ'=>'ȋ','Ȍ'=>'Ȍ','ȍ'=>'ȍ','Ȏ'=>'Ȏ','ȏ'=>'ȏ','Ȑ'=>'Ȑ','ȑ'=>'ȑ','Ȓ'=>'Ȓ','ȓ'=>'ȓ','Ȕ'=>'Ȕ','ȕ'=>'ȕ','Ȗ'=>'Ȗ','ȗ'=>'ȗ','Ș'=>'Ș','ș'=>'ș','Ț'=>'Ț','ț'=>'ț','Ȟ'=>'Ȟ','ȟ'=>'ȟ','Ȧ'=>'Ȧ','ȧ'=>'ȧ','Ȩ'=>'Ȩ','ȩ'=>'ȩ','Ȫ'=>'Ȫ','ȫ'=>'ȫ','Ȭ'=>'Ȭ','ȭ'=>'ȭ','Ȯ'=>'Ȯ','ȯ'=>'ȯ','Ȱ'=>'Ȱ','ȱ'=>'ȱ','Ȳ'=>'Ȳ','ȳ'=>'ȳ','̀'=>'̀','́'=>'́','̓'=>'̓','̈́'=>'̈́','ʹ'=>'ʹ',';'=>';','΅'=>'΅','Ά'=>'Ά','·'=>'·','Έ'=>'Έ','Ή'=>'Ή','Ί'=>'Ί','Ό'=>'Ό','Ύ'=>'Ύ','Ώ'=>'Ώ','ΐ'=>'ΐ','Ϊ'=>'Ϊ','Ϋ'=>'Ϋ','ά'=>'ά','έ'=>'έ','ή'=>'ή','ί'=>'ί','ΰ'=>'ΰ','ϊ'=>'ϊ','ϋ'=>'ϋ','ό'=>'ό','ύ'=>'ύ','ώ'=>'ώ','ϓ'=>'ϓ','ϔ'=>'ϔ','Ѐ'=>'Ѐ','Ё'=>'Ё','Ѓ'=>'Ѓ','Ї'=>'Ї','Ќ'=>'Ќ','Ѝ'=>'Ѝ','Ў'=>'Ў','Й'=>'Й','й'=>'й','ѐ'=>'ѐ','ё'=>'ё','ѓ'=>'ѓ','ї'=>'ї','ќ'=>'ќ','ѝ'=>'ѝ','ў'=>'ў','Ѷ'=>'Ѷ','ѷ'=>'ѷ','Ӂ'=>'Ӂ','ӂ'=>'ӂ','Ӑ'=>'Ӑ','ӑ'=>'ӑ','Ӓ'=>'Ӓ','ӓ'=>'ӓ','Ӗ'=>'Ӗ','ӗ'=>'ӗ','Ӛ'=>'Ӛ','ӛ'=>'ӛ','Ӝ'=>'Ӝ','ӝ'=>'ӝ','Ӟ'=>'Ӟ','ӟ'=>'ӟ','Ӣ'=>'Ӣ','ӣ'=>'ӣ','Ӥ'=>'Ӥ','ӥ'=>'ӥ','Ӧ'=>'Ӧ','ӧ'=>'ӧ','Ӫ'=>'Ӫ','ӫ'=>'ӫ','Ӭ'=>'Ӭ','ӭ'=>'ӭ','Ӯ'=>'Ӯ','ӯ'=>'ӯ','Ӱ'=>'Ӱ','ӱ'=>'ӱ','Ӳ'=>'Ӳ','ӳ'=>'ӳ','Ӵ'=>'Ӵ','ӵ'=>'ӵ','Ӹ'=>'Ӹ','ӹ'=>'ӹ','آ'=>'آ','أ'=>'أ','ؤ'=>'ؤ','إ'=>'إ','ئ'=>'ئ','ۀ'=>'ۀ','ۂ'=>'ۂ','ۓ'=>'ۓ','ऩ'=>'ऩ','ऱ'=>'ऱ','ऴ'=>'ऴ','क़'=>'क़','ख़'=>'ख़','ग़'=>'ग़','ज़'=>'ज़','ड़'=>'ड़','ढ़'=>'ढ़','फ़'=>'फ़','य़'=>'य़','ো'=>'ো','ৌ'=>'ৌ','ড়'=>'ড়','ঢ়'=>'ঢ়','য়'=>'য়','ਲ਼'=>'ਲ਼','ਸ਼'=>'ਸ਼','ਖ਼'=>'ਖ਼','ਗ਼'=>'ਗ਼','ਜ਼'=>'ਜ਼','ਫ਼'=>'ਫ਼','ୈ'=>'ୈ','ୋ'=>'ୋ','ୌ'=>'ୌ','ଡ଼'=>'ଡ଼','ଢ଼'=>'ଢ଼','ஔ'=>'ஔ','ொ'=>'ொ','ோ'=>'ோ','ௌ'=>'ௌ','ై'=>'ై','ೀ'=>'ೀ','ೇ'=>'ೇ','ೈ'=>'ೈ','ೊ'=>'ೊ','ೋ'=>'ೋ','ൊ'=>'ൊ','ോ'=>'ോ','ൌ'=>'ൌ','ේ'=>'ේ','ො'=>'ො','ෝ'=>'ෝ','ෞ'=>'ෞ','གྷ'=>'གྷ','ཌྷ'=>'ཌྷ','དྷ'=>'དྷ','བྷ'=>'བྷ','ཛྷ'=>'ཛྷ','ཀྵ'=>'ཀྵ','ཱི'=>'ཱི','ཱུ'=>'ཱུ','ྲྀ'=>'ྲྀ','ླྀ'=>'ླྀ','ཱྀ'=>'ཱྀ','ྒྷ'=>'ྒྷ','ྜྷ'=>'ྜྷ','ྡྷ'=>'ྡྷ','ྦྷ'=>'ྦྷ','ྫྷ'=>'ྫྷ','ྐྵ'=>'ྐྵ','ဦ'=>'ဦ','ᬆ'=>'ᬆ','ᬈ'=>'ᬈ','ᬊ'=>'ᬊ','ᬌ'=>'ᬌ','ᬎ'=>'ᬎ','ᬒ'=>'ᬒ','ᬻ'=>'ᬻ','ᬽ'=>'ᬽ','ᭀ'=>'ᭀ','ᭁ'=>'ᭁ','ᭃ'=>'ᭃ','Ḁ'=>'Ḁ','ḁ'=>'ḁ','Ḃ'=>'Ḃ','ḃ'=>'ḃ','Ḅ'=>'Ḅ','ḅ'=>'ḅ','Ḇ'=>'Ḇ','ḇ'=>'ḇ','Ḉ'=>'Ḉ','ḉ'=>'ḉ','Ḋ'=>'Ḋ','ḋ'=>'ḋ','Ḍ'=>'Ḍ','ḍ'=>'ḍ','Ḏ'=>'Ḏ','ḏ'=>'ḏ','Ḑ'=>'Ḑ','ḑ'=>'ḑ','Ḓ'=>'Ḓ','ḓ'=>'ḓ','Ḕ'=>'Ḕ','ḕ'=>'ḕ','Ḗ'=>'Ḗ','ḗ'=>'ḗ','Ḙ'=>'Ḙ','ḙ'=>'ḙ','Ḛ'=>'Ḛ','ḛ'=>'ḛ','Ḝ'=>'Ḝ','ḝ'=>'ḝ','Ḟ'=>'Ḟ','ḟ'=>'ḟ','Ḡ'=>'Ḡ','ḡ'=>'ḡ','Ḣ'=>'Ḣ','ḣ'=>'ḣ','Ḥ'=>'Ḥ','ḥ'=>'ḥ','Ḧ'=>'Ḧ','ḧ'=>'ḧ','Ḩ'=>'Ḩ','ḩ'=>'ḩ','Ḫ'=>'Ḫ','ḫ'=>'ḫ','Ḭ'=>'Ḭ','ḭ'=>'ḭ','Ḯ'=>'Ḯ','ḯ'=>'ḯ','Ḱ'=>'Ḱ','ḱ'=>'ḱ','Ḳ'=>'Ḳ','ḳ'=>'ḳ','Ḵ'=>'Ḵ','ḵ'=>'ḵ','Ḷ'=>'Ḷ','ḷ'=>'ḷ','Ḹ'=>'Ḹ','ḹ'=>'ḹ','Ḻ'=>'Ḻ','ḻ'=>'ḻ','Ḽ'=>'Ḽ','ḽ'=>'ḽ','Ḿ'=>'Ḿ','ḿ'=>'ḿ','Ṁ'=>'Ṁ','ṁ'=>'ṁ','Ṃ'=>'Ṃ','ṃ'=>'ṃ','Ṅ'=>'Ṅ','ṅ'=>'ṅ','Ṇ'=>'Ṇ','ṇ'=>'ṇ','Ṉ'=>'Ṉ','ṉ'=>'ṉ','Ṋ'=>'Ṋ','ṋ'=>'ṋ','Ṍ'=>'Ṍ','ṍ'=>'ṍ','Ṏ'=>'Ṏ','ṏ'=>'ṏ','Ṑ'=>'Ṑ','ṑ'=>'ṑ','Ṓ'=>'Ṓ','ṓ'=>'ṓ','Ṕ'=>'Ṕ','ṕ'=>'ṕ','Ṗ'=>'Ṗ','ṗ'=>'ṗ','Ṙ'=>'Ṙ','ṙ'=>'ṙ','Ṛ'=>'Ṛ','ṛ'=>'ṛ','Ṝ'=>'Ṝ','ṝ'=>'ṝ','Ṟ'=>'Ṟ','ṟ'=>'ṟ','Ṡ'=>'Ṡ','ṡ'=>'ṡ','Ṣ'=>'Ṣ','ṣ'=>'ṣ','Ṥ'=>'Ṥ','ṥ'=>'ṥ','Ṧ'=>'Ṧ','ṧ'=>'ṧ','Ṩ'=>'Ṩ','ṩ'=>'ṩ','Ṫ'=>'Ṫ','ṫ'=>'ṫ','Ṭ'=>'Ṭ','ṭ'=>'ṭ','Ṯ'=>'Ṯ','ṯ'=>'ṯ','Ṱ'=>'Ṱ','ṱ'=>'ṱ','Ṳ'=>'Ṳ','ṳ'=>'ṳ','Ṵ'=>'Ṵ','ṵ'=>'ṵ','Ṷ'=>'Ṷ','ṷ'=>'ṷ','Ṹ'=>'Ṹ','ṹ'=>'ṹ','Ṻ'=>'Ṻ','ṻ'=>'ṻ','Ṽ'=>'Ṽ','ṽ'=>'ṽ','Ṿ'=>'Ṿ','ṿ'=>'ṿ','Ẁ'=>'Ẁ','ẁ'=>'ẁ','Ẃ'=>'Ẃ','ẃ'=>'ẃ','Ẅ'=>'Ẅ','ẅ'=>'ẅ','Ẇ'=>'Ẇ','ẇ'=>'ẇ','Ẉ'=>'Ẉ','ẉ'=>'ẉ','Ẋ'=>'Ẋ','ẋ'=>'ẋ','Ẍ'=>'Ẍ','ẍ'=>'ẍ','Ẏ'=>'Ẏ','ẏ'=>'ẏ','Ẑ'=>'Ẑ','ẑ'=>'ẑ','Ẓ'=>'Ẓ','ẓ'=>'ẓ','Ẕ'=>'Ẕ','ẕ'=>'ẕ','ẖ'=>'ẖ','ẗ'=>'ẗ','ẘ'=>'ẘ','ẙ'=>'ẙ','ẛ'=>'ẛ','Ạ'=>'Ạ','ạ'=>'ạ','Ả'=>'Ả','ả'=>'ả','Ấ'=>'Ấ','ấ'=>'ấ','Ầ'=>'Ầ','ầ'=>'ầ','Ẩ'=>'Ẩ','ẩ'=>'ẩ','Ẫ'=>'Ẫ','ẫ'=>'ẫ','Ậ'=>'Ậ','ậ'=>'ậ','Ắ'=>'Ắ','ắ'=>'ắ','Ằ'=>'Ằ','ằ'=>'ằ','Ẳ'=>'Ẳ','ẳ'=>'ẳ','Ẵ'=>'Ẵ','ẵ'=>'ẵ','Ặ'=>'Ặ','ặ'=>'ặ','Ẹ'=>'Ẹ','ẹ'=>'ẹ','Ẻ'=>'Ẻ','ẻ'=>'ẻ','Ẽ'=>'Ẽ','ẽ'=>'ẽ','Ế'=>'Ế','ế'=>'ế','Ề'=>'Ề','ề'=>'ề','Ể'=>'Ể','ể'=>'ể','Ễ'=>'Ễ','ễ'=>'ễ','Ệ'=>'Ệ','ệ'=>'ệ','Ỉ'=>'Ỉ','ỉ'=>'ỉ','Ị'=>'Ị','ị'=>'ị','Ọ'=>'Ọ','ọ'=>'ọ','Ỏ'=>'Ỏ','ỏ'=>'ỏ','Ố'=>'Ố','ố'=>'ố','Ồ'=>'Ồ','ồ'=>'ồ','Ổ'=>'Ổ','ổ'=>'ổ','Ỗ'=>'Ỗ','ỗ'=>'ỗ','Ộ'=>'Ộ','ộ'=>'ộ','Ớ'=>'Ớ','ớ'=>'ớ','Ờ'=>'Ờ','ờ'=>'ờ','Ở'=>'Ở','ở'=>'ở','Ỡ'=>'Ỡ','ỡ'=>'ỡ','Ợ'=>'Ợ','ợ'=>'ợ','Ụ'=>'Ụ','ụ'=>'ụ','Ủ'=>'Ủ','ủ'=>'ủ','Ứ'=>'Ứ','ứ'=>'ứ','Ừ'=>'Ừ','ừ'=>'ừ','Ử'=>'Ử','ử'=>'ử','Ữ'=>'Ữ','ữ'=>'ữ','Ự'=>'Ự','ự'=>'ự','Ỳ'=>'Ỳ','ỳ'=>'ỳ','Ỵ'=>'Ỵ','ỵ'=>'ỵ','Ỷ'=>'Ỷ','ỷ'=>'ỷ','Ỹ'=>'Ỹ','ỹ'=>'ỹ','ἀ'=>'ἀ','ἁ'=>'ἁ','ἂ'=>'ἂ','ἃ'=>'ἃ','ἄ'=>'ἄ','ἅ'=>'ἅ','ἆ'=>'ἆ','ἇ'=>'ἇ','Ἀ'=>'Ἀ','Ἁ'=>'Ἁ','Ἂ'=>'Ἂ','Ἃ'=>'Ἃ','Ἄ'=>'Ἄ','Ἅ'=>'Ἅ','Ἆ'=>'Ἆ','Ἇ'=>'Ἇ','ἐ'=>'ἐ','ἑ'=>'ἑ','ἒ'=>'ἒ','ἓ'=>'ἓ','ἔ'=>'ἔ','ἕ'=>'ἕ','Ἐ'=>'Ἐ','Ἑ'=>'Ἑ','Ἒ'=>'Ἒ','Ἓ'=>'Ἓ','Ἔ'=>'Ἔ','Ἕ'=>'Ἕ','ἠ'=>'ἠ','ἡ'=>'ἡ','ἢ'=>'ἢ','ἣ'=>'ἣ','ἤ'=>'ἤ','ἥ'=>'ἥ','ἦ'=>'ἦ','ἧ'=>'ἧ','Ἠ'=>'Ἠ','Ἡ'=>'Ἡ','Ἢ'=>'Ἢ','Ἣ'=>'Ἣ','Ἤ'=>'Ἤ','Ἥ'=>'Ἥ','Ἦ'=>'Ἦ','Ἧ'=>'Ἧ','ἰ'=>'ἰ','ἱ'=>'ἱ','ἲ'=>'ἲ','ἳ'=>'ἳ','ἴ'=>'ἴ','ἵ'=>'ἵ','ἶ'=>'ἶ','ἷ'=>'ἷ','Ἰ'=>'Ἰ','Ἱ'=>'Ἱ','Ἲ'=>'Ἲ','Ἳ'=>'Ἳ','Ἴ'=>'Ἴ','Ἵ'=>'Ἵ','Ἶ'=>'Ἶ','Ἷ'=>'Ἷ','ὀ'=>'ὀ','ὁ'=>'ὁ','ὂ'=>'ὂ','ὃ'=>'ὃ','ὄ'=>'ὄ','ὅ'=>'ὅ','Ὀ'=>'Ὀ','Ὁ'=>'Ὁ','Ὂ'=>'Ὂ','Ὃ'=>'Ὃ','Ὄ'=>'Ὄ','Ὅ'=>'Ὅ','ὐ'=>'ὐ','ὑ'=>'ὑ','ὒ'=>'ὒ','ὓ'=>'ὓ','ὔ'=>'ὔ','ὕ'=>'ὕ','ὖ'=>'ὖ','ὗ'=>'ὗ','Ὑ'=>'Ὑ','Ὓ'=>'Ὓ','Ὕ'=>'Ὕ','Ὗ'=>'Ὗ','ὠ'=>'ὠ','ὡ'=>'ὡ','ὢ'=>'ὢ','ὣ'=>'ὣ','ὤ'=>'ὤ','ὥ'=>'ὥ','ὦ'=>'ὦ','ὧ'=>'ὧ','Ὠ'=>'Ὠ','Ὡ'=>'Ὡ','Ὢ'=>'Ὢ','Ὣ'=>'Ὣ','Ὤ'=>'Ὤ','Ὥ'=>'Ὥ','Ὦ'=>'Ὦ','Ὧ'=>'Ὧ','ὰ'=>'ὰ','ά'=>'ά','ὲ'=>'ὲ','έ'=>'έ','ὴ'=>'ὴ','ή'=>'ή','ὶ'=>'ὶ','ί'=>'ί','ὸ'=>'ὸ','ό'=>'ό','ὺ'=>'ὺ','ύ'=>'ύ','ὼ'=>'ὼ','ώ'=>'ώ','ᾀ'=>'ᾀ','ᾁ'=>'ᾁ','ᾂ'=>'ᾂ','ᾃ'=>'ᾃ','ᾄ'=>'ᾄ','ᾅ'=>'ᾅ','ᾆ'=>'ᾆ','ᾇ'=>'ᾇ','ᾈ'=>'ᾈ','ᾉ'=>'ᾉ','ᾊ'=>'ᾊ','ᾋ'=>'ᾋ','ᾌ'=>'ᾌ','ᾍ'=>'ᾍ','ᾎ'=>'ᾎ','ᾏ'=>'ᾏ','ᾐ'=>'ᾐ','ᾑ'=>'ᾑ','ᾒ'=>'ᾒ','ᾓ'=>'ᾓ','ᾔ'=>'ᾔ','ᾕ'=>'ᾕ','ᾖ'=>'ᾖ','ᾗ'=>'ᾗ','ᾘ'=>'ᾘ','ᾙ'=>'ᾙ','ᾚ'=>'ᾚ','ᾛ'=>'ᾛ','ᾜ'=>'ᾜ','ᾝ'=>'ᾝ','ᾞ'=>'ᾞ','ᾟ'=>'ᾟ','ᾠ'=>'ᾠ','ᾡ'=>'ᾡ','ᾢ'=>'ᾢ','ᾣ'=>'ᾣ','ᾤ'=>'ᾤ','ᾥ'=>'ᾥ','ᾦ'=>'ᾦ','ᾧ'=>'ᾧ','ᾨ'=>'ᾨ','ᾩ'=>'ᾩ','ᾪ'=>'ᾪ','ᾫ'=>'ᾫ','ᾬ'=>'ᾬ','ᾭ'=>'ᾭ','ᾮ'=>'ᾮ','ᾯ'=>'ᾯ','ᾰ'=>'ᾰ','ᾱ'=>'ᾱ','ᾲ'=>'ᾲ','ᾳ'=>'ᾳ','ᾴ'=>'ᾴ','ᾶ'=>'ᾶ','ᾷ'=>'ᾷ','Ᾰ'=>'Ᾰ','Ᾱ'=>'Ᾱ','Ὰ'=>'Ὰ','Ά'=>'Ά','ᾼ'=>'ᾼ','ι'=>'ι','῁'=>'῁','ῂ'=>'ῂ','ῃ'=>'ῃ','ῄ'=>'ῄ','ῆ'=>'ῆ','ῇ'=>'ῇ','Ὲ'=>'Ὲ','Έ'=>'Έ','Ὴ'=>'Ὴ','Ή'=>'Ή','ῌ'=>'ῌ','῍'=>'῍','῎'=>'῎','῏'=>'῏','ῐ'=>'ῐ','ῑ'=>'ῑ','ῒ'=>'ῒ','ΐ'=>'ΐ','ῖ'=>'ῖ','ῗ'=>'ῗ','Ῐ'=>'Ῐ','Ῑ'=>'Ῑ','Ὶ'=>'Ὶ','Ί'=>'Ί','῝'=>'῝','῞'=>'῞','῟'=>'῟','ῠ'=>'ῠ','ῡ'=>'ῡ','ῢ'=>'ῢ','ΰ'=>'ΰ','ῤ'=>'ῤ','ῥ'=>'ῥ','ῦ'=>'ῦ','ῧ'=>'ῧ','Ῠ'=>'Ῠ','Ῡ'=>'Ῡ','Ὺ'=>'Ὺ','Ύ'=>'Ύ','Ῥ'=>'Ῥ','῭'=>'῭','΅'=>'΅','`'=>'`','ῲ'=>'ῲ','ῳ'=>'ῳ','ῴ'=>'ῴ','ῶ'=>'ῶ','ῷ'=>'ῷ','Ὸ'=>'Ὸ','Ό'=>'Ό','Ὼ'=>'Ὼ','Ώ'=>'Ώ','ῼ'=>'ῼ','´'=>'´',' '=>' ',' '=>' ','Ω'=>'Ω','K'=>'K','Å'=>'Å','↚'=>'↚','↛'=>'↛','↮'=>'↮','⇍'=>'⇍','⇎'=>'⇎','⇏'=>'⇏','∄'=>'∄','∉'=>'∉','∌'=>'∌','∤'=>'∤','∦'=>'∦','≁'=>'≁','≄'=>'≄','≇'=>'≇','≉'=>'≉','≠'=>'≠','≢'=>'≢','≭'=>'≭','≮'=>'≮','≯'=>'≯','≰'=>'≰','≱'=>'≱','≴'=>'≴','≵'=>'≵','≸'=>'≸','≹'=>'≹','⊀'=>'⊀','⊁'=>'⊁','⊄'=>'⊄','⊅'=>'⊅','⊈'=>'⊈','⊉'=>'⊉','⊬'=>'⊬','⊭'=>'⊭','⊮'=>'⊮','⊯'=>'⊯','⋠'=>'⋠','⋡'=>'⋡','⋢'=>'⋢','⋣'=>'⋣','⋪'=>'⋪','⋫'=>'⋫','⋬'=>'⋬','⋭'=>'⋭','〈'=>'〈','〉'=>'〉','⫝̸'=>'⫝̸','が'=>'が','ぎ'=>'ぎ','ぐ'=>'ぐ','げ'=>'げ','ご'=>'ご','ざ'=>'ざ','じ'=>'じ','ず'=>'ず','ぜ'=>'ぜ','ぞ'=>'ぞ','だ'=>'だ','ぢ'=>'ぢ','づ'=>'づ','で'=>'で','ど'=>'ど','ば'=>'ば','ぱ'=>'ぱ','び'=>'び','ぴ'=>'ぴ','ぶ'=>'ぶ','ぷ'=>'ぷ','べ'=>'べ','ぺ'=>'ぺ','ぼ'=>'ぼ','ぽ'=>'ぽ','ゔ'=>'ゔ','ゞ'=>'ゞ','ガ'=>'ガ','ギ'=>'ギ','グ'=>'グ','ゲ'=>'ゲ','ゴ'=>'ゴ','ザ'=>'ザ','ジ'=>'ジ','ズ'=>'ズ','ゼ'=>'ゼ','ゾ'=>'ゾ','ダ'=>'ダ','ヂ'=>'ヂ','ヅ'=>'ヅ','デ'=>'デ','ド'=>'ド','バ'=>'バ','パ'=>'パ','ビ'=>'ビ','ピ'=>'ピ','ブ'=>'ブ','プ'=>'プ','ベ'=>'ベ','ペ'=>'ペ','ボ'=>'ボ','ポ'=>'ポ','ヴ'=>'ヴ','ヷ'=>'ヷ','ヸ'=>'ヸ','ヹ'=>'ヹ','ヺ'=>'ヺ','ヾ'=>'ヾ','豈'=>'豈','更'=>'更','車'=>'車','賈'=>'賈','滑'=>'滑','串'=>'串','句'=>'句','龜'=>'龜','龜'=>'龜','契'=>'契','金'=>'金','喇'=>'喇','奈'=>'奈','懶'=>'懶','癩'=>'癩','羅'=>'羅','蘿'=>'蘿','螺'=>'螺','裸'=>'裸','邏'=>'邏','樂'=>'樂','洛'=>'洛','烙'=>'烙','珞'=>'珞','落'=>'落','酪'=>'酪','駱'=>'駱','亂'=>'亂','卵'=>'卵','欄'=>'欄','爛'=>'爛','蘭'=>'蘭','鸞'=>'鸞','嵐'=>'嵐','濫'=>'濫','藍'=>'藍','襤'=>'襤','拉'=>'拉','臘'=>'臘','蠟'=>'蠟','廊'=>'廊','朗'=>'朗','浪'=>'浪','狼'=>'狼','郎'=>'郎','來'=>'來','冷'=>'冷','勞'=>'勞','擄'=>'擄','櫓'=>'櫓','爐'=>'爐','盧'=>'盧','老'=>'老','蘆'=>'蘆','虜'=>'虜','路'=>'路','露'=>'露','魯'=>'魯','鷺'=>'鷺','碌'=>'碌','祿'=>'祿','綠'=>'綠','菉'=>'菉','錄'=>'錄','鹿'=>'鹿','論'=>'論','壟'=>'壟','弄'=>'弄','籠'=>'籠','聾'=>'聾','牢'=>'牢','磊'=>'磊','賂'=>'賂','雷'=>'雷','壘'=>'壘','屢'=>'屢','樓'=>'樓','淚'=>'淚','漏'=>'漏','累'=>'累','縷'=>'縷','陋'=>'陋','勒'=>'勒','肋'=>'肋','凜'=>'凜','凌'=>'凌','稜'=>'稜','綾'=>'綾','菱'=>'菱','陵'=>'陵','讀'=>'讀','拏'=>'拏','樂'=>'樂','諾'=>'諾','丹'=>'丹','寧'=>'寧','怒'=>'怒','率'=>'率','異'=>'異','北'=>'北','磻'=>'磻','便'=>'便','復'=>'復','不'=>'不','泌'=>'泌','數'=>'數','索'=>'索','參'=>'參','塞'=>'塞','省'=>'省','葉'=>'葉','說'=>'說','殺'=>'殺','辰'=>'辰','沈'=>'沈','拾'=>'拾','若'=>'若','掠'=>'掠','略'=>'略','亮'=>'亮','兩'=>'兩','凉'=>'凉','梁'=>'梁','糧'=>'糧','良'=>'良','諒'=>'諒','量'=>'量','勵'=>'勵','呂'=>'呂','女'=>'女','廬'=>'廬','旅'=>'旅','濾'=>'濾','礪'=>'礪','閭'=>'閭','驪'=>'驪','麗'=>'麗','黎'=>'黎','力'=>'力','曆'=>'曆','歷'=>'歷','轢'=>'轢','年'=>'年','憐'=>'憐','戀'=>'戀','撚'=>'撚','漣'=>'漣','煉'=>'煉','璉'=>'璉','秊'=>'秊','練'=>'練','聯'=>'聯','輦'=>'輦','蓮'=>'蓮','連'=>'連','鍊'=>'鍊','列'=>'列','劣'=>'劣','咽'=>'咽','烈'=>'烈','裂'=>'裂','說'=>'說','廉'=>'廉','念'=>'念','捻'=>'捻','殮'=>'殮','簾'=>'簾','獵'=>'獵','令'=>'令','囹'=>'囹','寧'=>'寧','嶺'=>'嶺','怜'=>'怜','玲'=>'玲','瑩'=>'瑩','羚'=>'羚','聆'=>'聆','鈴'=>'鈴','零'=>'零','靈'=>'靈','領'=>'領','例'=>'例','禮'=>'禮','醴'=>'醴','隸'=>'隸','惡'=>'惡','了'=>'了','僚'=>'僚','寮'=>'寮','尿'=>'尿','料'=>'料','樂'=>'樂','燎'=>'燎','療'=>'療','蓼'=>'蓼','遼'=>'遼','龍'=>'龍','暈'=>'暈','阮'=>'阮','劉'=>'劉','杻'=>'杻','柳'=>'柳','流'=>'流','溜'=>'溜','琉'=>'琉','留'=>'留','硫'=>'硫','紐'=>'紐','類'=>'類','六'=>'六','戮'=>'戮','陸'=>'陸','倫'=>'倫','崙'=>'崙','淪'=>'淪','輪'=>'輪','律'=>'律','慄'=>'慄','栗'=>'栗','率'=>'率','隆'=>'隆','利'=>'利','吏'=>'吏','履'=>'履','易'=>'易','李'=>'李','梨'=>'梨','泥'=>'泥','理'=>'理','痢'=>'痢','罹'=>'罹','裏'=>'裏','裡'=>'裡','里'=>'里','離'=>'離','匿'=>'匿','溺'=>'溺','吝'=>'吝','燐'=>'燐','璘'=>'璘','藺'=>'藺','隣'=>'隣','鱗'=>'鱗','麟'=>'麟','林'=>'林','淋'=>'淋','臨'=>'臨','立'=>'立','笠'=>'笠','粒'=>'粒','狀'=>'狀','炙'=>'炙','識'=>'識','什'=>'什','茶'=>'茶','刺'=>'刺','切'=>'切','度'=>'度','拓'=>'拓','糖'=>'糖','宅'=>'宅','洞'=>'洞','暴'=>'暴','輻'=>'輻','行'=>'行','降'=>'降','見'=>'見','廓'=>'廓','兀'=>'兀','嗀'=>'嗀','塚'=>'塚','晴'=>'晴','凞'=>'凞','猪'=>'猪','益'=>'益','礼'=>'礼','神'=>'神','祥'=>'祥','福'=>'福','靖'=>'靖','精'=>'精','羽'=>'羽','蘒'=>'蘒','諸'=>'諸','逸'=>'逸','都'=>'都','飯'=>'飯','飼'=>'飼','館'=>'館','鶴'=>'鶴','侮'=>'侮','僧'=>'僧','免'=>'免','勉'=>'勉','勤'=>'勤','卑'=>'卑','喝'=>'喝','嘆'=>'嘆','器'=>'器','塀'=>'塀','墨'=>'墨','層'=>'層','屮'=>'屮','悔'=>'悔','慨'=>'慨','憎'=>'憎','懲'=>'懲','敏'=>'敏','既'=>'既','暑'=>'暑','梅'=>'梅','海'=>'海','渚'=>'渚','漢'=>'漢','煮'=>'煮','爫'=>'爫','琢'=>'琢','碑'=>'碑','社'=>'社','祉'=>'祉','祈'=>'祈','祐'=>'祐','祖'=>'祖','祝'=>'祝','禍'=>'禍','禎'=>'禎','穀'=>'穀','突'=>'突','節'=>'節','練'=>'練','縉'=>'縉','繁'=>'繁','署'=>'署','者'=>'者','臭'=>'臭','艹'=>'艹','艹'=>'艹','著'=>'著','褐'=>'褐','視'=>'視','謁'=>'謁','謹'=>'謹','賓'=>'賓','贈'=>'贈','辶'=>'辶','逸'=>'逸','難'=>'難','響'=>'響','頻'=>'頻','並'=>'並','况'=>'况','全'=>'全','侀'=>'侀','充'=>'充','冀'=>'冀','勇'=>'勇','勺'=>'勺','喝'=>'喝','啕'=>'啕','喙'=>'喙','嗢'=>'嗢','塚'=>'塚','墳'=>'墳','奄'=>'奄','奔'=>'奔','婢'=>'婢','嬨'=>'嬨','廒'=>'廒','廙'=>'廙','彩'=>'彩','徭'=>'徭','惘'=>'惘','慎'=>'慎','愈'=>'愈','憎'=>'憎','慠'=>'慠','懲'=>'懲','戴'=>'戴','揄'=>'揄','搜'=>'搜','摒'=>'摒','敖'=>'敖','晴'=>'晴','朗'=>'朗','望'=>'望','杖'=>'杖','歹'=>'歹','殺'=>'殺','流'=>'流','滛'=>'滛','滋'=>'滋','漢'=>'漢','瀞'=>'瀞','煮'=>'煮','瞧'=>'瞧','爵'=>'爵','犯'=>'犯','猪'=>'猪','瑱'=>'瑱','甆'=>'甆','画'=>'画','瘝'=>'瘝','瘟'=>'瘟','益'=>'益','盛'=>'盛','直'=>'直','睊'=>'睊','着'=>'着','磌'=>'磌','窱'=>'窱','節'=>'節','类'=>'类','絛'=>'絛','練'=>'練','缾'=>'缾','者'=>'者','荒'=>'荒','華'=>'華','蝹'=>'蝹','襁'=>'襁','覆'=>'覆','視'=>'視','調'=>'調','諸'=>'諸','請'=>'請','謁'=>'謁','諾'=>'諾','諭'=>'諭','謹'=>'謹','變'=>'變','贈'=>'贈','輸'=>'輸','遲'=>'遲','醙'=>'醙','鉶'=>'鉶','陼'=>'陼','難'=>'難','靖'=>'靖','韛'=>'韛','響'=>'響','頋'=>'頋','頻'=>'頻','鬒'=>'鬒','龜'=>'龜','𢡊'=>'𢡊','𢡄'=>'𢡄','𣏕'=>'𣏕','㮝'=>'㮝','䀘'=>'䀘','䀹'=>'䀹','𥉉'=>'𥉉','𥳐'=>'𥳐','𧻓'=>'𧻓','齃'=>'齃','龎'=>'龎','יִ'=>'יִ','ײַ'=>'ײַ','שׁ'=>'שׁ','שׂ'=>'שׂ','שּׁ'=>'שּׁ','שּׂ'=>'שּׂ','אַ'=>'אַ','אָ'=>'אָ','אּ'=>'אּ','בּ'=>'בּ','גּ'=>'גּ','דּ'=>'דּ','הּ'=>'הּ','וּ'=>'וּ','זּ'=>'זּ','טּ'=>'טּ','יּ'=>'יּ','ךּ'=>'ךּ','כּ'=>'כּ','לּ'=>'לּ','מּ'=>'מּ','נּ'=>'נּ','סּ'=>'סּ','ףּ'=>'ףּ','פּ'=>'פּ','צּ'=>'צּ','קּ'=>'קּ','רּ'=>'רּ','שּ'=>'שּ','תּ'=>'תּ','וֹ'=>'וֹ','בֿ'=>'בֿ','כֿ'=>'כֿ','פֿ'=>'פֿ','𝅗𝅥'=>'𝅗𝅥','𝅘𝅥'=>'𝅘𝅥','𝅘𝅥𝅮'=>'𝅘𝅥𝅮','𝅘𝅥𝅯'=>'𝅘𝅥𝅯','𝅘𝅥𝅰'=>'𝅘𝅥𝅰','𝅘𝅥𝅱'=>'𝅘𝅥𝅱','𝅘𝅥𝅲'=>'𝅘𝅥𝅲','𝆹𝅥'=>'𝆹𝅥','𝆺𝅥'=>'𝆺𝅥','𝆹𝅥𝅮'=>'𝆹𝅥𝅮','𝆺𝅥𝅮'=>'𝆺𝅥𝅮','𝆹𝅥𝅯'=>'𝆹𝅥𝅯','𝆺𝅥𝅯'=>'𝆺𝅥𝅯','丽'=>'丽','丸'=>'丸','乁'=>'乁','𠄢'=>'𠄢','你'=>'你','侮'=>'侮','侻'=>'侻','倂'=>'倂','偺'=>'偺','備'=>'備','僧'=>'僧','像'=>'像','㒞'=>'㒞','𠘺'=>'𠘺','免'=>'免','兔'=>'兔','兤'=>'兤','具'=>'具','𠔜'=>'𠔜','㒹'=>'㒹','內'=>'內','再'=>'再','𠕋'=>'𠕋','冗'=>'冗','冤'=>'冤','仌'=>'仌','冬'=>'冬','况'=>'况','𩇟'=>'𩇟','凵'=>'凵','刃'=>'刃','㓟'=>'㓟','刻'=>'刻','剆'=>'剆','割'=>'割','剷'=>'剷','㔕'=>'㔕','勇'=>'勇','勉'=>'勉','勤'=>'勤','勺'=>'勺','包'=>'包','匆'=>'匆','北'=>'北','卉'=>'卉','卑'=>'卑','博'=>'博','即'=>'即','卽'=>'卽','卿'=>'卿','卿'=>'卿','卿'=>'卿','𠨬'=>'𠨬','灰'=>'灰','及'=>'及','叟'=>'叟','𠭣'=>'𠭣','叫'=>'叫','叱'=>'叱','吆'=>'吆','咞'=>'咞','吸'=>'吸','呈'=>'呈','周'=>'周','咢'=>'咢','哶'=>'哶','唐'=>'唐','啓'=>'啓','啣'=>'啣','善'=>'善','善'=>'善','喙'=>'喙','喫'=>'喫','喳'=>'喳','嗂'=>'嗂','圖'=>'圖','嘆'=>'嘆','圗'=>'圗','噑'=>'噑','噴'=>'噴','切'=>'切','壮'=>'壮','城'=>'城','埴'=>'埴','堍'=>'堍','型'=>'型','堲'=>'堲','報'=>'報','墬'=>'墬','𡓤'=>'𡓤','売'=>'売','壷'=>'壷','夆'=>'夆','多'=>'多','夢'=>'夢','奢'=>'奢','𡚨'=>'𡚨','𡛪'=>'𡛪','姬'=>'姬','娛'=>'娛','娧'=>'娧','姘'=>'姘','婦'=>'婦','㛮'=>'㛮','㛼'=>'㛼','嬈'=>'嬈','嬾'=>'嬾','嬾'=>'嬾','𡧈'=>'𡧈','寃'=>'寃','寘'=>'寘','寧'=>'寧','寳'=>'寳','𡬘'=>'𡬘','寿'=>'寿','将'=>'将','当'=>'当','尢'=>'尢','㞁'=>'㞁','屠'=>'屠','屮'=>'屮','峀'=>'峀','岍'=>'岍','𡷤'=>'𡷤','嵃'=>'嵃','𡷦'=>'𡷦','嵮'=>'嵮','嵫'=>'嵫','嵼'=>'嵼','巡'=>'巡','巢'=>'巢','㠯'=>'㠯','巽'=>'巽','帨'=>'帨','帽'=>'帽','幩'=>'幩','㡢'=>'㡢','𢆃'=>'𢆃','㡼'=>'㡼','庰'=>'庰','庳'=>'庳','庶'=>'庶','廊'=>'廊','𪎒'=>'𪎒','廾'=>'廾','𢌱'=>'𢌱','𢌱'=>'𢌱','舁'=>'舁','弢'=>'弢','弢'=>'弢','㣇'=>'㣇','𣊸'=>'𣊸','𦇚'=>'𦇚','形'=>'形','彫'=>'彫','㣣'=>'㣣','徚'=>'徚','忍'=>'忍','志'=>'志','忹'=>'忹','悁'=>'悁','㤺'=>'㤺','㤜'=>'㤜','悔'=>'悔','𢛔'=>'𢛔','惇'=>'惇','慈'=>'慈','慌'=>'慌','慎'=>'慎','慌'=>'慌','慺'=>'慺','憎'=>'憎','憲'=>'憲','憤'=>'憤','憯'=>'憯','懞'=>'懞','懲'=>'懲','懶'=>'懶','成'=>'成','戛'=>'戛','扝'=>'扝','抱'=>'抱','拔'=>'拔','捐'=>'捐','𢬌'=>'𢬌','挽'=>'挽','拼'=>'拼','捨'=>'捨','掃'=>'掃','揤'=>'揤','𢯱'=>'𢯱','搢'=>'搢','揅'=>'揅','掩'=>'掩','㨮'=>'㨮','摩'=>'摩','摾'=>'摾','撝'=>'撝','摷'=>'摷','㩬'=>'㩬','敏'=>'敏','敬'=>'敬','𣀊'=>'𣀊','旣'=>'旣','書'=>'書','晉'=>'晉','㬙'=>'㬙','暑'=>'暑','㬈'=>'㬈','㫤'=>'㫤','冒'=>'冒','冕'=>'冕','最'=>'最','暜'=>'暜','肭'=>'肭','䏙'=>'䏙','朗'=>'朗','望'=>'望','朡'=>'朡','杞'=>'杞','杓'=>'杓','𣏃'=>'𣏃','㭉'=>'㭉','柺'=>'柺','枅'=>'枅','桒'=>'桒','梅'=>'梅','𣑭'=>'𣑭','梎'=>'梎','栟'=>'栟','椔'=>'椔','㮝'=>'㮝','楂'=>'楂','榣'=>'榣','槪'=>'槪','檨'=>'檨','𣚣'=>'𣚣','櫛'=>'櫛','㰘'=>'㰘','次'=>'次','𣢧'=>'𣢧','歔'=>'歔','㱎'=>'㱎','歲'=>'歲','殟'=>'殟','殺'=>'殺','殻'=>'殻','𣪍'=>'𣪍','𡴋'=>'𡴋','𣫺'=>'𣫺','汎'=>'汎','𣲼'=>'𣲼','沿'=>'沿','泍'=>'泍','汧'=>'汧','洖'=>'洖','派'=>'派','海'=>'海','流'=>'流','浩'=>'浩','浸'=>'浸','涅'=>'涅','𣴞'=>'𣴞','洴'=>'洴','港'=>'港','湮'=>'湮','㴳'=>'㴳','滋'=>'滋','滇'=>'滇','𣻑'=>'𣻑','淹'=>'淹','潮'=>'潮','𣽞'=>'𣽞','𣾎'=>'𣾎','濆'=>'濆','瀹'=>'瀹','瀞'=>'瀞','瀛'=>'瀛','㶖'=>'㶖','灊'=>'灊','災'=>'災','灷'=>'灷','炭'=>'炭','𠔥'=>'𠔥','煅'=>'煅','𤉣'=>'𤉣','熜'=>'熜','𤎫'=>'𤎫','爨'=>'爨','爵'=>'爵','牐'=>'牐','𤘈'=>'𤘈','犀'=>'犀','犕'=>'犕','𤜵'=>'𤜵','𤠔'=>'𤠔','獺'=>'獺','王'=>'王','㺬'=>'㺬','玥'=>'玥','㺸'=>'㺸','㺸'=>'㺸','瑇'=>'瑇','瑜'=>'瑜','瑱'=>'瑱','璅'=>'璅','瓊'=>'瓊','㼛'=>'㼛','甤'=>'甤','𤰶'=>'𤰶','甾'=>'甾','𤲒'=>'𤲒','異'=>'異','𢆟'=>'𢆟','瘐'=>'瘐','𤾡'=>'𤾡','𤾸'=>'𤾸','𥁄'=>'𥁄','㿼'=>'㿼','䀈'=>'䀈','直'=>'直','𥃳'=>'𥃳','𥃲'=>'𥃲','𥄙'=>'𥄙','𥄳'=>'𥄳','眞'=>'眞','真'=>'真','真'=>'真','睊'=>'睊','䀹'=>'䀹','瞋'=>'瞋','䁆'=>'䁆','䂖'=>'䂖','𥐝'=>'𥐝','硎'=>'硎','碌'=>'碌','磌'=>'磌','䃣'=>'䃣','𥘦'=>'𥘦','祖'=>'祖','𥚚'=>'𥚚','𥛅'=>'𥛅','福'=>'福','秫'=>'秫','䄯'=>'䄯','穀'=>'穀','穊'=>'穊','穏'=>'穏','𥥼'=>'𥥼','𥪧'=>'𥪧','𥪧'=>'𥪧','竮'=>'竮','䈂'=>'䈂','𥮫'=>'𥮫','篆'=>'篆','築'=>'築','䈧'=>'䈧','𥲀'=>'𥲀','糒'=>'糒','䊠'=>'䊠','糨'=>'糨','糣'=>'糣','紀'=>'紀','𥾆'=>'𥾆','絣'=>'絣','䌁'=>'䌁','緇'=>'緇','縂'=>'縂','繅'=>'繅','䌴'=>'䌴','𦈨'=>'𦈨','𦉇'=>'𦉇','䍙'=>'䍙','𦋙'=>'𦋙','罺'=>'罺','𦌾'=>'𦌾','羕'=>'羕','翺'=>'翺','者'=>'者','𦓚'=>'𦓚','𦔣'=>'𦔣','聠'=>'聠','𦖨'=>'𦖨','聰'=>'聰','𣍟'=>'𣍟','䏕'=>'䏕','育'=>'育','脃'=>'脃','䐋'=>'䐋','脾'=>'脾','媵'=>'媵','𦞧'=>'𦞧','𦞵'=>'𦞵','𣎓'=>'𣎓','𣎜'=>'𣎜','舁'=>'舁','舄'=>'舄','辞'=>'辞','䑫'=>'䑫','芑'=>'芑','芋'=>'芋','芝'=>'芝','劳'=>'劳','花'=>'花','芳'=>'芳','芽'=>'芽','苦'=>'苦','𦬼'=>'𦬼','若'=>'若','茝'=>'茝','荣'=>'荣','莭'=>'莭','茣'=>'茣','莽'=>'莽','菧'=>'菧','著'=>'著','荓'=>'荓','菊'=>'菊','菌'=>'菌','菜'=>'菜','𦰶'=>'𦰶','𦵫'=>'𦵫','𦳕'=>'𦳕','䔫'=>'䔫','蓱'=>'蓱','蓳'=>'蓳','蔖'=>'蔖','𧏊'=>'𧏊','蕤'=>'蕤','𦼬'=>'𦼬','䕝'=>'䕝','䕡'=>'䕡','𦾱'=>'𦾱','𧃒'=>'𧃒','䕫'=>'䕫','虐'=>'虐','虜'=>'虜','虧'=>'虧','虩'=>'虩','蚩'=>'蚩','蚈'=>'蚈','蜎'=>'蜎','蛢'=>'蛢','蝹'=>'蝹','蜨'=>'蜨','蝫'=>'蝫','螆'=>'螆','䗗'=>'䗗','蟡'=>'蟡','蠁'=>'蠁','䗹'=>'䗹','衠'=>'衠','衣'=>'衣','𧙧'=>'𧙧','裗'=>'裗','裞'=>'裞','䘵'=>'䘵','裺'=>'裺','㒻'=>'㒻','𧢮'=>'𧢮','𧥦'=>'𧥦','䚾'=>'䚾','䛇'=>'䛇','誠'=>'誠','諭'=>'諭','變'=>'變','豕'=>'豕','𧲨'=>'𧲨','貫'=>'貫','賁'=>'賁','贛'=>'贛','起'=>'起','𧼯'=>'𧼯','𠠄'=>'𠠄','跋'=>'跋','趼'=>'趼','跰'=>'跰','𠣞'=>'𠣞','軔'=>'軔','輸'=>'輸','𨗒'=>'𨗒','𨗭'=>'𨗭','邔'=>'邔','郱'=>'郱','鄑'=>'鄑','𨜮'=>'𨜮','鄛'=>'鄛','鈸'=>'鈸','鋗'=>'鋗','鋘'=>'鋘','鉼'=>'鉼','鏹'=>'鏹','鐕'=>'鐕','𨯺'=>'𨯺','開'=>'開','䦕'=>'䦕','閷'=>'閷','𨵷'=>'𨵷','䧦'=>'䧦','雃'=>'雃','嶲'=>'嶲','霣'=>'霣','𩅅'=>'𩅅','𩈚'=>'𩈚','䩮'=>'䩮','䩶'=>'䩶','韠'=>'韠','𩐊'=>'𩐊','䪲'=>'䪲','𩒖'=>'𩒖','頋'=>'頋','頋'=>'頋','頩'=>'頩','𩖶'=>'𩖶','飢'=>'飢','䬳'=>'䬳','餩'=>'餩','馧'=>'馧','駂'=>'駂','駾'=>'駾','䯎'=>'䯎','𩬰'=>'𩬰','鬒'=>'鬒','鱀'=>'鱀','鳽'=>'鳽','䳎'=>'䳎','䳭'=>'䳭','鵧'=>'鵧','𪃎'=>'𪃎','䳸'=>'䳸','𪄅'=>'𪄅','𪈎'=>'𪈎','𪊑'=>'𪊑','麻'=>'麻','䵖'=>'䵖','黹'=>'黹','黾'=>'黾','鼅'=>'鼅','鼏'=>'鼏','鼖'=>'鼖','鼻'=>'鼻','𪘀'=>'𪘀');
\ 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','À'=>'À','Á'=>'Á','Â'=>'Â','Ã'=>'Ã','Ä'=>'Ä','Å'=>'Å','Ç'=>'Ç','È'=>'È','É'=>'É','Ê'=>'Ê','Ë'=>'Ë','Ì'=>'Ì','Í'=>'Í','Î'=>'Î','Ï'=>'Ï','Ñ'=>'Ñ','Ò'=>'Ò','Ó'=>'Ó','Ô'=>'Ô','Õ'=>'Õ','Ö'=>'Ö','Ù'=>'Ù','Ú'=>'Ú','Û'=>'Û','Ü'=>'Ü','Ý'=>'Ý','à'=>'à','á'=>'á','â'=>'â','ã'=>'ã','ä'=>'ä','å'=>'å','ç'=>'ç','è'=>'è','é'=>'é','ê'=>'ê','ë'=>'ë','ì'=>'ì','í'=>'í','î'=>'î','ï'=>'ï','ñ'=>'ñ','ò'=>'ò','ó'=>'ó','ô'=>'ô','õ'=>'õ','ö'=>'ö','ù'=>'ù','ú'=>'ú','û'=>'û','ü'=>'ü','ý'=>'ý','ÿ'=>'ÿ','Ā'=>'Ā','ā'=>'ā','Ă'=>'Ă','ă'=>'ă','Ą'=>'Ą','ą'=>'ą','Ć'=>'Ć','ć'=>'ć','Ĉ'=>'Ĉ','ĉ'=>'ĉ','Ċ'=>'Ċ','ċ'=>'ċ','Č'=>'Č','č'=>'č','Ď'=>'Ď','ď'=>'ď','Ē'=>'Ē','ē'=>'ē','Ĕ'=>'Ĕ','ĕ'=>'ĕ','Ė'=>'Ė','ė'=>'ė','Ę'=>'Ę','ę'=>'ę','Ě'=>'Ě','ě'=>'ě','Ĝ'=>'Ĝ','ĝ'=>'ĝ','Ğ'=>'Ğ','ğ'=>'ğ','Ġ'=>'Ġ','ġ'=>'ġ','Ģ'=>'Ģ','ģ'=>'ģ','Ĥ'=>'Ĥ','ĥ'=>'ĥ','Ĩ'=>'Ĩ','ĩ'=>'ĩ','Ī'=>'Ī','ī'=>'ī','Ĭ'=>'Ĭ','ĭ'=>'ĭ','Į'=>'Į','į'=>'į','İ'=>'İ','IJ'=>'IJ','ij'=>'ij','Ĵ'=>'Ĵ','ĵ'=>'ĵ','Ķ'=>'Ķ','ķ'=>'ķ','Ĺ'=>'Ĺ','ĺ'=>'ĺ','Ļ'=>'Ļ','ļ'=>'ļ','Ľ'=>'Ľ','ľ'=>'ľ','Ŀ'=>'L·','ŀ'=>'l·','Ń'=>'Ń','ń'=>'ń','Ņ'=>'Ņ','ņ'=>'ņ','Ň'=>'Ň','ň'=>'ň','ʼn'=>'ʼn','Ō'=>'Ō','ō'=>'ō','Ŏ'=>'Ŏ','ŏ'=>'ŏ','Ő'=>'Ő','ő'=>'ő','Ŕ'=>'Ŕ','ŕ'=>'ŕ','Ŗ'=>'Ŗ','ŗ'=>'ŗ','Ř'=>'Ř','ř'=>'ř','Ś'=>'Ś','ś'=>'ś','Ŝ'=>'Ŝ','ŝ'=>'ŝ','Ş'=>'Ş','ş'=>'ş','Š'=>'Š','š'=>'š','Ţ'=>'Ţ','ţ'=>'ţ','Ť'=>'Ť','ť'=>'ť','Ũ'=>'Ũ','ũ'=>'ũ','Ū'=>'Ū','ū'=>'ū','Ŭ'=>'Ŭ','ŭ'=>'ŭ','Ů'=>'Ů','ů'=>'ů','Ű'=>'Ű','ű'=>'ű','Ų'=>'Ų','ų'=>'ų','Ŵ'=>'Ŵ','ŵ'=>'ŵ','Ŷ'=>'Ŷ','ŷ'=>'ŷ','Ÿ'=>'Ÿ','Ź'=>'Ź','ź'=>'ź','Ż'=>'Ż','ż'=>'ż','Ž'=>'Ž','ž'=>'ž','ſ'=>'s','Ơ'=>'Ơ','ơ'=>'ơ','Ư'=>'Ư','ư'=>'ư','DŽ'=>'DŽ','Dž'=>'Dž','dž'=>'dž','LJ'=>'LJ','Lj'=>'Lj','lj'=>'lj','NJ'=>'NJ','Nj'=>'Nj','nj'=>'nj','Ǎ'=>'Ǎ','ǎ'=>'ǎ','Ǐ'=>'Ǐ','ǐ'=>'ǐ','Ǒ'=>'Ǒ','ǒ'=>'ǒ','Ǔ'=>'Ǔ','ǔ'=>'ǔ','Ǖ'=>'Ǖ','ǖ'=>'ǖ','Ǘ'=>'Ǘ','ǘ'=>'ǘ','Ǚ'=>'Ǚ','ǚ'=>'ǚ','Ǜ'=>'Ǜ','ǜ'=>'ǜ','Ǟ'=>'Ǟ','ǟ'=>'ǟ','Ǡ'=>'Ǡ','ǡ'=>'ǡ','Ǣ'=>'Ǣ','ǣ'=>'ǣ','Ǧ'=>'Ǧ','ǧ'=>'ǧ','Ǩ'=>'Ǩ','ǩ'=>'ǩ','Ǫ'=>'Ǫ','ǫ'=>'ǫ','Ǭ'=>'Ǭ','ǭ'=>'ǭ','Ǯ'=>'Ǯ','ǯ'=>'ǯ','ǰ'=>'ǰ','DZ'=>'DZ','Dz'=>'Dz','dz'=>'dz','Ǵ'=>'Ǵ','ǵ'=>'ǵ','Ǹ'=>'Ǹ','ǹ'=>'ǹ','Ǻ'=>'Ǻ','ǻ'=>'ǻ','Ǽ'=>'Ǽ','ǽ'=>'ǽ','Ǿ'=>'Ǿ','ǿ'=>'ǿ','Ȁ'=>'Ȁ','ȁ'=>'ȁ','Ȃ'=>'Ȃ','ȃ'=>'ȃ','Ȅ'=>'Ȅ','ȅ'=>'ȅ','Ȇ'=>'Ȇ','ȇ'=>'ȇ','Ȉ'=>'Ȉ','ȉ'=>'ȉ','Ȋ'=>'Ȋ','ȋ'=>'ȋ','Ȍ'=>'Ȍ','ȍ'=>'ȍ','Ȏ'=>'Ȏ','ȏ'=>'ȏ','Ȑ'=>'Ȑ','ȑ'=>'ȑ','Ȓ'=>'Ȓ','ȓ'=>'ȓ','Ȕ'=>'Ȕ','ȕ'=>'ȕ','Ȗ'=>'Ȗ','ȗ'=>'ȗ','Ș'=>'Ș','ș'=>'ș','Ț'=>'Ț','ț'=>'ț','Ȟ'=>'Ȟ','ȟ'=>'ȟ','Ȧ'=>'Ȧ','ȧ'=>'ȧ','Ȩ'=>'Ȩ','ȩ'=>'ȩ','Ȫ'=>'Ȫ','ȫ'=>'ȫ','Ȭ'=>'Ȭ','ȭ'=>'ȭ','Ȯ'=>'Ȯ','ȯ'=>'ȯ','Ȱ'=>'Ȱ','ȱ'=>'ȱ','Ȳ'=>'Ȳ','ȳ'=>'ȳ','ʰ'=>'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ʾ','ẛ'=>'ṡ','Ạ'=>'Ạ','ạ'=>'ạ','Ả'=>'Ả','ả'=>'ả','Ấ'=>'Ấ','ấ'=>'ấ','Ầ'=>'Ầ','ầ'=>'ầ','Ẩ'=>'Ẩ','ẩ'=>'ẩ','Ẫ'=>'Ẫ','ẫ'=>'ẫ','Ậ'=>'Ậ','ậ'=>'ậ','Ắ'=>'Ắ','ắ'=>'ắ','Ằ'=>'Ằ','ằ'=>'ằ','Ẳ'=>'Ẳ','ẳ'=>'ẳ','Ẵ'=>'Ẵ','ẵ'=>'ẵ','Ặ'=>'Ặ','ặ'=>'ặ','Ẹ'=>'Ẹ','ẹ'=>'ẹ','Ẻ'=>'Ẻ','ẻ'=>'ẻ','Ẽ'=>'Ẽ','ẽ'=>'ẽ','Ế'=>'Ế','ế'=>'ế','Ề'=>'Ề','ề'=>'ề','Ể'=>'Ể','ể'=>'ể','Ễ'=>'Ễ','ễ'=>'ễ','Ệ'=>'Ệ','ệ'=>'ệ','Ỉ'=>'Ỉ','ỉ'=>'ỉ','Ị'=>'Ị','ị'=>'ị','Ọ'=>'Ọ','ọ'=>'ọ','Ỏ'=>'Ỏ','ỏ'=>'ỏ','Ố'=>'Ố','ố'=>'ố','Ồ'=>'Ồ','ồ'=>'ồ','Ổ'=>'Ổ','ổ'=>'ổ','Ỗ'=>'Ỗ','ỗ'=>'ỗ','Ộ'=>'Ộ','ộ'=>'ộ','Ớ'=>'Ớ','ớ'=>'ớ','Ờ'=>'Ờ','ờ'=>'ờ','Ở'=>'Ở','ở'=>'ở','Ỡ'=>'Ỡ','ỡ'=>'ỡ','Ợ'=>'Ợ','ợ'=>'ợ','Ụ'=>'Ụ','ụ'=>'ụ','Ủ'=>'Ủ','ủ'=>'ủ','Ứ'=>'Ứ','ứ'=>'ứ','Ừ'=>'Ừ','ừ'=>'ừ','Ử'=>'Ử','ử'=>'ử','Ữ'=>'Ữ','ữ'=>'ữ','Ự'=>'Ự','ự'=>'ự','Ỳ'=>'Ỳ','ỳ'=>'ỳ','Ỵ'=>'Ỵ','ỵ'=>'ỵ','Ỷ'=>'Ỷ','ỷ'=>'ỷ','Ỹ'=>'Ỹ','ỹ'=>'ỹ','ἀ'=>'ἀ','ἁ'=>'ἁ','ἂ'=>'ἂ','ἃ'=>'ἃ','ἄ'=>'ἄ','ἅ'=>'ἅ','ἆ'=>'ἆ','ἇ'=>'ἇ','Ἀ'=>'Ἀ','Ἁ'=>'Ἁ','Ἂ'=>'Ἂ','Ἃ'=>'Ἃ','Ἄ'=>'Ἄ','Ἅ'=>'Ἅ','Ἆ'=>'Ἆ','Ἇ'=>'Ἇ','ἐ'=>'ἐ','ἑ'=>'ἑ','ἒ'=>'ἒ','ἓ'=>'ἓ','ἔ'=>'ἔ','ἕ'=>'ἕ','Ἐ'=>'Ἐ','Ἑ'=>'Ἑ','Ἒ'=>'Ἒ','Ἓ'=>'Ἓ','Ἔ'=>'Ἔ','Ἕ'=>'Ἕ','ἠ'=>'ἠ','ἡ'=>'ἡ','ἢ'=>'ἢ','ἣ'=>'ἣ','ἤ'=>'ἤ','ἥ'=>'ἥ','ἦ'=>'ἦ','ἧ'=>'ἧ','Ἠ'=>'Ἠ','Ἡ'=>'Ἡ','Ἢ'=>'Ἢ','Ἣ'=>'Ἣ','Ἤ'=>'Ἤ','Ἥ'=>'Ἥ','Ἦ'=>'Ἦ','Ἧ'=>'Ἧ','ἰ'=>'ἰ','ἱ'=>'ἱ','ἲ'=>'ἲ','ἳ'=>'ἳ','ἴ'=>'ἴ','ἵ'=>'ἵ','ἶ'=>'ἶ','ἷ'=>'ἷ','Ἰ'=>'Ἰ','Ἱ'=>'Ἱ','Ἲ'=>'Ἲ','Ἳ'=>'Ἳ','Ἴ'=>'Ἴ','Ἵ'=>'Ἵ','Ἶ'=>'Ἶ','Ἷ'=>'Ἷ','ὀ'=>'ὀ','ὁ'=>'ὁ','ὂ'=>'ὂ','ὃ'=>'ὃ','ὄ'=>'ὄ','ὅ'=>'ὅ','Ὀ'=>'Ὀ','Ὁ'=>'Ὁ','Ὂ'=>'Ὂ','Ὃ'=>'Ὃ','Ὄ'=>'Ὄ','Ὅ'=>'Ὅ','ὐ'=>'ὐ','ὑ'=>'ὑ','ὒ'=>'ὒ','ὓ'=>'ὓ','ὔ'=>'ὔ','ὕ'=>'ὕ','ὖ'=>'ὖ','ὗ'=>'ὗ','Ὑ'=>'Ὑ','Ὓ'=>'Ὓ','Ὕ'=>'Ὕ','Ὗ'=>'Ὗ','ὠ'=>'ὠ','ὡ'=>'ὡ','ὢ'=>'ὢ','ὣ'=>'ὣ','ὤ'=>'ὤ','ὥ'=>'ὥ','ὦ'=>'ὦ','ὧ'=>'ὧ','Ὠ'=>'Ὠ','Ὡ'=>'Ὡ','Ὢ'=>'Ὢ','Ὣ'=>'Ὣ','Ὤ'=>'Ὤ','Ὥ'=>'Ὥ','Ὦ'=>'Ὦ','Ὧ'=>'Ὧ','ὰ'=>'ὰ','ά'=>'ά','ὲ'=>'ὲ','έ'=>'έ','ὴ'=>'ὴ','ή'=>'ή','ὶ'=>'ὶ','ί'=>'ί','ὸ'=>'ὸ','ό'=>'ό','ὺ'=>'ὺ','ύ'=>'ύ','ὼ'=>'ὼ','ώ'=>'ώ','ᾀ'=>'ᾀ','ᾁ'=>'ᾁ','ᾂ'=>'ᾂ','ᾃ'=>'ᾃ','ᾄ'=>'ᾄ','ᾅ'=>'ᾅ','ᾆ'=>'ᾆ','ᾇ'=>'ᾇ','ᾈ'=>'ᾈ','ᾉ'=>'ᾉ','ᾊ'=>'ᾊ','ᾋ'=>'ᾋ','ᾌ'=>'ᾌ','ᾍ'=>'ᾍ','ᾎ'=>'ᾎ','ᾏ'=>'ᾏ','ᾐ'=>'ᾐ','ᾑ'=>'ᾑ','ᾒ'=>'ᾒ','ᾓ'=>'ᾓ','ᾔ'=>'ᾔ','ᾕ'=>'ᾕ','ᾖ'=>'ᾖ','ᾗ'=>'ᾗ','ᾘ'=>'ᾘ','ᾙ'=>'ᾙ','ᾚ'=>'ᾚ','ᾛ'=>'ᾛ','ᾜ'=>'ᾜ','ᾝ'=>'ᾝ','ᾞ'=>'ᾞ','ᾟ'=>'ᾟ','ᾠ'=>'ᾠ','ᾡ'=>'ᾡ','ᾢ'=>'ᾢ','ᾣ'=>'ᾣ','ᾤ'=>'ᾤ','ᾥ'=>'ᾥ','ᾦ'=>'ᾦ','ᾧ'=>'ᾧ','ᾨ'=>'ᾨ','ᾩ'=>'ᾩ','ᾪ'=>'ᾪ','ᾫ'=>'ᾫ','ᾬ'=>'ᾬ','ᾭ'=>'ᾭ','ᾮ'=>'ᾮ','ᾯ'=>'ᾯ','ᾰ'=>'ᾰ','ᾱ'=>'ᾱ','ᾲ'=>'ᾲ','ᾳ'=>'ᾳ','ᾴ'=>'ᾴ','ᾶ'=>'ᾶ','ᾷ'=>'ᾷ','Ᾰ'=>'Ᾰ','Ᾱ'=>'Ᾱ','Ὰ'=>'Ὰ','Ά'=>'Ά','ᾼ'=>'ᾼ','᾽'=>' ̓','ι'=>'ι','᾿'=>' ̓','῀'=>' ͂','῁'=>' ̈͂','ῂ'=>'ῂ','ῃ'=>'ῃ','ῄ'=>'ῄ','ῆ'=>'ῆ','ῇ'=>'ῇ','Ὲ'=>'Ὲ','Έ'=>'Έ','Ὴ'=>'Ὴ','Ή'=>'Ή','ῌ'=>'ῌ','῍'=>' ̓̀','῎'=>' ̓́','῏'=>' ̓͂','ῐ'=>'ῐ','ῑ'=>'ῑ','ῒ'=>'ῒ','ΐ'=>'ΐ','ῖ'=>'ῖ','ῗ'=>'ῗ','Ῐ'=>'Ῐ','Ῑ'=>'Ῑ','Ὶ'=>'Ὶ','Ί'=>'Ί','῝'=>' ̔̀','῞'=>' ̔́','῟'=>' ̔͂','ῠ'=>'ῠ','ῡ'=>'ῡ','ῢ'=>'ῢ','ΰ'=>'ΰ','ῤ'=>'ῤ','ῥ'=>'ῥ','ῦ'=>'ῦ','ῧ'=>'ῧ','Ῠ'=>'Ῠ','Ῡ'=>'Ῡ','Ὺ'=>'Ὺ','Ύ'=>'Ύ','Ῥ'=>'Ῥ','῭'=>' ̈̀','΅'=>' ̈́','`'=>'`','ῲ'=>'ῲ','ῳ'=>'ῳ','ῴ'=>'ῴ','ῶ'=>'ῶ','ῷ'=>'ῷ','Ὸ'=>'Ὸ','Ό'=>'Ό','Ὼ'=>'Ὼ','Ώ'=>'Ώ','ῼ'=>'ῼ','´'=>' ́','῾'=>' ̔',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ','‑'=>'‐','‗'=>' ̳','․'=>'.','‥'=>'..','…'=>'...',' '=>' ','″'=>'′′','‴'=>'′′′','‶'=>'‵‵','‷'=>'‵‵‵','‼'=>'!!','‾'=>' ̅','⁇'=>'??','⁈'=>'?!','⁉'=>'!?','⁗'=>'′′′′',' '=>' ','⁰'=>'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','Å'=>'Å','ℬ'=>'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'=>'fi','fl'=>'fl','ffi'=>'ffi','ffl'=>'ffl','ſt'=>'st','st'=>'st','ﬓ'=>'մն','ﬔ'=>'մե','ﬕ'=>'մի','ﬖ'=>'վն','ﬗ'=>'մխ','יִ'=>'יִ','ײַ'=>'ײַ','ﬠ'=>'ע','ﬡ'=>'א','ﬢ'=>'ד','ﬣ'=>'ה','ﬤ'=>'כ','ﬥ'=>'ל','ﬦ'=>'ם','ﬧ'=>'ר','ﬨ'=>'ת','﬩'=>'+','שׁ'=>'שׁ','שׂ'=>'שׂ','שּׁ'=>'שּׁ','שּׂ'=>'שּׂ','אַ'=>'אַ','אָ'=>'אָ','אּ'=>'אּ','בּ'=>'בּ','גּ'=>'גּ','דּ'=>'דּ','הּ'=>'הּ','וּ'=>'וּ','זּ'=>'זּ','טּ'=>'טּ','יּ'=>'יּ','ךּ'=>'ךּ','כּ'=>'כּ','לּ'=>'לּ','מּ'=>'מּ','נּ'=>'נּ','סּ'=>'סּ','ףּ'=>'ףּ','פּ'=>'פּ','צּ'=>'צּ','קּ'=>'קּ','רּ'=>'רּ','שּ'=>'שּ','תּ'=>'תּ','וֹ'=>'וֹ','בֿ'=>'בֿ','כֿ'=>'כֿ','פֿ'=>'פֿ','ﭏ'=>'אל','ﭐ'=>'ٱ','ﭑ'=>'ٱ','ﭒ'=>'ٻ','ﭓ'=>'ٻ','ﭔ'=>'ٻ','ﭕ'=>'ٻ','ﭖ'=>'پ','ﭗ'=>'پ','ﭘ'=>'پ','ﭙ'=>'پ','ﭚ'=>'ڀ','ﭛ'=>'ڀ','ﭜ'=>'ڀ','ﭝ'=>'ڀ','ﭞ'=>'ٺ','ﭟ'=>'ٺ','ﭠ'=>'ٺ','ﭡ'=>'ٺ','ﭢ'=>'ٿ','ﭣ'=>'ٿ','ﭤ'=>'ٿ','ﭥ'=>'ٿ','ﭦ'=>'ٹ','ﭧ'=>'ٹ','ﭨ'=>'ٹ','ﭩ'=>'ٹ','ﭪ'=>'ڤ','ﭫ'=>'ڤ','ﭬ'=>'ڤ','ﭭ'=>'ڤ','ﭮ'=>'ڦ','ﭯ'=>'ڦ','ﭰ'=>'ڦ','ﭱ'=>'ڦ','ﭲ'=>'ڄ','ﭳ'=>'ڄ','ﭴ'=>'ڄ','ﭵ'=>'ڄ','ﭶ'=>'ڃ','ﭷ'=>'ڃ','ﭸ'=>'ڃ','ﭹ'=>'ڃ','ﭺ'=>'چ','ﭻ'=>'چ','ﭼ'=>'چ','ﭽ'=>'چ','ﭾ'=>'ڇ','ﭿ'=>'ڇ','ﮀ'=>'ڇ','ﮁ'=>'ڇ','ﮂ'=>'ڍ','ﮃ'=>'ڍ','ﮄ'=>'ڌ','ﮅ'=>'ڌ','ﮆ'=>'ڎ','ﮇ'=>'ڎ','ﮈ'=>'ڈ','ﮉ'=>'ڈ','ﮊ'=>'ژ','ﮋ'=>'ژ','ﮌ'=>'ڑ','ﮍ'=>'ڑ','ﮎ'=>'ک','ﮏ'=>'ک','ﮐ'=>'ک','ﮑ'=>'ک','ﮒ'=>'گ','ﮓ'=>'گ','ﮔ'=>'گ','ﮕ'=>'گ','ﮖ'=>'ڳ','ﮗ'=>'ڳ','ﮘ'=>'ڳ','ﮙ'=>'ڳ','ﮚ'=>'ڱ','ﮛ'=>'ڱ','ﮜ'=>'ڱ','ﮝ'=>'ڱ','ﮞ'=>'ں','ﮟ'=>'ں','ﮠ'=>'ڻ','ﮡ'=>'ڻ','ﮢ'=>'ڻ','ﮣ'=>'ڻ','ﮤ'=>'ۀ','ﮥ'=>'ۀ','ﮦ'=>'ہ','ﮧ'=>'ہ','ﮨ'=>'ہ','ﮩ'=>'ہ','ﮪ'=>'ھ','ﮫ'=>'ھ','ﮬ'=>'ھ','ﮭ'=>'ھ','ﮮ'=>'ے','ﮯ'=>'ے','ﮰ'=>'ۓ','ﮱ'=>'ۓ','ﯓ'=>'ڭ','ﯔ'=>'ڭ','ﯕ'=>'ڭ','ﯖ'=>'ڭ','ﯗ'=>'ۇ','ﯘ'=>'ۇ','ﯙ'=>'ۆ','ﯚ'=>'ۆ','ﯛ'=>'ۈ','ﯜ'=>'ۈ','ﯝ'=>'ۇٴ','ﯞ'=>'ۋ','ﯟ'=>'ۋ','ﯠ'=>'ۅ','ﯡ'=>'ۅ','ﯢ'=>'ۉ','ﯣ'=>'ۉ','ﯤ'=>'ې','ﯥ'=>'ې','ﯦ'=>'ې','ﯧ'=>'ې','ﯨ'=>'ى','ﯩ'=>'ى','ﯪ'=>'ئا','ﯫ'=>'ئا','ﯬ'=>'ئە','ﯭ'=>'ئە','ﯮ'=>'ئو','ﯯ'=>'ئو','ﯰ'=>'ئۇ','ﯱ'=>'ئۇ','ﯲ'=>'ئۆ','ﯳ'=>'ئۆ','ﯴ'=>'ئۈ','ﯵ'=>'ئۈ','ﯶ'=>'ئې','ﯷ'=>'ئې','ﯸ'=>'ئې','ﯹ'=>'ئى','ﯺ'=>'ئى','ﯻ'=>'ئى','ﯼ'=>'ی','ﯽ'=>'ی','ﯾ'=>'ی','ﯿ'=>'ی','ﰀ'=>'ئج','ﰁ'=>'ئح','ﰂ'=>'ئم','ﰃ'=>'ئى','ﰄ'=>'ئي','ﰅ'=>'بج','ﰆ'=>'بح','ﰇ'=>'بخ','ﰈ'=>'بم','ﰉ'=>'بى','ﰊ'=>'بي','ﰋ'=>'تج','ﰌ'=>'تح','ﰍ'=>'تخ','ﰎ'=>'تم','ﰏ'=>'تى','ﰐ'=>'تي','ﰑ'=>'ثج','ﰒ'=>'ثم','ﰓ'=>'ثى','ﰔ'=>'ثي','ﰕ'=>'جح','ﰖ'=>'جم','ﰗ'=>'حج','ﰘ'=>'حم','ﰙ'=>'خج','ﰚ'=>'خح','ﰛ'=>'خم','ﰜ'=>'سج','ﰝ'=>'سح','ﰞ'=>'سخ','ﰟ'=>'سم','ﰠ'=>'صح','ﰡ'=>'صم','ﰢ'=>'ضج','ﰣ'=>'ضح','ﰤ'=>'ضخ','ﰥ'=>'ضم','ﰦ'=>'طح','ﰧ'=>'طم','ﰨ'=>'ظم','ﰩ'=>'عج','ﰪ'=>'عم','ﰫ'=>'غج','ﰬ'=>'غم','ﰭ'=>'فج','ﰮ'=>'فح','ﰯ'=>'فخ','ﰰ'=>'فم','ﰱ'=>'فى','ﰲ'=>'في','ﰳ'=>'قح','ﰴ'=>'قم','ﰵ'=>'قى','ﰶ'=>'قي','ﰷ'=>'كا','ﰸ'=>'كج','ﰹ'=>'كح','ﰺ'=>'كخ','ﰻ'=>'كل','ﰼ'=>'كم','ﰽ'=>'كى','ﰾ'=>'كي','ﰿ'=>'لج','ﱀ'=>'لح','ﱁ'=>'لخ','ﱂ'=>'لم','ﱃ'=>'لى','ﱄ'=>'لي','ﱅ'=>'مج','ﱆ'=>'مح','ﱇ'=>'مخ','ﱈ'=>'مم','ﱉ'=>'مى','ﱊ'=>'مي','ﱋ'=>'نج','ﱌ'=>'نح','ﱍ'=>'نخ','ﱎ'=>'نم','ﱏ'=>'نى','ﱐ'=>'ني','ﱑ'=>'هج','ﱒ'=>'هم','ﱓ'=>'هى','ﱔ'=>'هي','ﱕ'=>'يج','ﱖ'=>'يح','ﱗ'=>'يخ','ﱘ'=>'يم','ﱙ'=>'يى','ﱚ'=>'يي','ﱛ'=>'ذٰ','ﱜ'=>'رٰ','ﱝ'=>'ىٰ','ﱞ'=>' ٌّ','ﱟ'=>' ٍّ','ﱠ'=>' َّ','ﱡ'=>' ُّ','ﱢ'=>' ِّ','ﱣ'=>' ّٰ','ﱤ'=>'ئر','ﱥ'=>'ئز','ﱦ'=>'ئم','ﱧ'=>'ئن','ﱨ'=>'ئى','ﱩ'=>'ئي','ﱪ'=>'بر','ﱫ'=>'بز','ﱬ'=>'بم','ﱭ'=>'بن','ﱮ'=>'بى','ﱯ'=>'بي','ﱰ'=>'تر','ﱱ'=>'تز','ﱲ'=>'تم','ﱳ'=>'تن','ﱴ'=>'تى','ﱵ'=>'تي','ﱶ'=>'ثر','ﱷ'=>'ثز','ﱸ'=>'ثم','ﱹ'=>'ثن','ﱺ'=>'ثى','ﱻ'=>'ثي','ﱼ'=>'فى','ﱽ'=>'في','ﱾ'=>'قى','ﱿ'=>'قي','ﲀ'=>'كا','ﲁ'=>'كل','ﲂ'=>'كم','ﲃ'=>'كى','ﲄ'=>'كي','ﲅ'=>'لم','ﲆ'=>'لى','ﲇ'=>'لي','ﲈ'=>'ما','ﲉ'=>'مم','ﲊ'=>'نر','ﲋ'=>'نز','ﲌ'=>'نم','ﲍ'=>'نن','ﲎ'=>'نى','ﲏ'=>'ني','ﲐ'=>'ىٰ','ﲑ'=>'ير','ﲒ'=>'يز','ﲓ'=>'يم','ﲔ'=>'ين','ﲕ'=>'يى','ﲖ'=>'يي','ﲗ'=>'ئج','ﲘ'=>'ئح','ﲙ'=>'ئخ','ﲚ'=>'ئم','ﲛ'=>'ئه','ﲜ'=>'بج','ﲝ'=>'بح','ﲞ'=>'بخ','ﲟ'=>'بم','ﲠ'=>'به','ﲡ'=>'تج','ﲢ'=>'تح','ﲣ'=>'تخ','ﲤ'=>'تم','ﲥ'=>'ته','ﲦ'=>'ثم','ﲧ'=>'جح','ﲨ'=>'جم','ﲩ'=>'حج','ﲪ'=>'حم','ﲫ'=>'خج','ﲬ'=>'خم','ﲭ'=>'سج','ﲮ'=>'سح','ﲯ'=>'سخ','ﲰ'=>'سم','ﲱ'=>'صح','ﲲ'=>'صخ','ﲳ'=>'صم','ﲴ'=>'ضج','ﲵ'=>'ضح','ﲶ'=>'ضخ','ﲷ'=>'ضم','ﲸ'=>'طح','ﲹ'=>'ظم','ﲺ'=>'عج','ﲻ'=>'عم','ﲼ'=>'غج','ﲽ'=>'غم','ﲾ'=>'فج','ﲿ'=>'فح','ﳀ'=>'فخ','ﳁ'=>'فم','ﳂ'=>'قح','ﳃ'=>'قم','ﳄ'=>'كج','ﳅ'=>'كح','ﳆ'=>'كخ','ﳇ'=>'كل','ﳈ'=>'كم','ﳉ'=>'لج','ﳊ'=>'لح','ﳋ'=>'لخ','ﳌ'=>'لم','ﳍ'=>'له','ﳎ'=>'مج','ﳏ'=>'مح','ﳐ'=>'مخ','ﳑ'=>'مم','ﳒ'=>'نج','ﳓ'=>'نح','ﳔ'=>'نخ','ﳕ'=>'نم','ﳖ'=>'نه','ﳗ'=>'هج','ﳘ'=>'هم','ﳙ'=>'هٰ','ﳚ'=>'يج','ﳛ'=>'يح','ﳜ'=>'يخ','ﳝ'=>'يم','ﳞ'=>'يه','ﳟ'=>'ئم','ﳠ'=>'ئه','ﳡ'=>'بم','ﳢ'=>'به','ﳣ'=>'تم','ﳤ'=>'ته','ﳥ'=>'ثم','ﳦ'=>'ثه','ﳧ'=>'سم','ﳨ'=>'سه','ﳩ'=>'شم','ﳪ'=>'شه','ﳫ'=>'كل','ﳬ'=>'كم','ﳭ'=>'لم','ﳮ'=>'نم','ﳯ'=>'نه','ﳰ'=>'يم','ﳱ'=>'يه','ﳲ'=>'ـَّ','ﳳ'=>'ـُّ','ﳴ'=>'ـِّ','ﳵ'=>'طى','ﳶ'=>'طي','ﳷ'=>'عى','ﳸ'=>'عي','ﳹ'=>'غى','ﳺ'=>'غي','ﳻ'=>'سى','ﳼ'=>'سي','ﳽ'=>'شى','ﳾ'=>'شي','ﳿ'=>'حى','ﴀ'=>'حي','ﴁ'=>'جى','ﴂ'=>'جي','ﴃ'=>'خى','ﴄ'=>'خي','ﴅ'=>'صى','ﴆ'=>'صي','ﴇ'=>'ضى','ﴈ'=>'ضي','ﴉ'=>'شج','ﴊ'=>'شح','ﴋ'=>'شخ','ﴌ'=>'شم','ﴍ'=>'شر','ﴎ'=>'سر','ﴏ'=>'صر','ﴐ'=>'ضر','ﴑ'=>'طى','ﴒ'=>'طي','ﴓ'=>'عى','ﴔ'=>'عي','ﴕ'=>'غى','ﴖ'=>'غي','ﴗ'=>'سى','ﴘ'=>'سي','ﴙ'=>'شى','ﴚ'=>'شي','ﴛ'=>'حى','ﴜ'=>'حي','ﴝ'=>'جى','ﴞ'=>'جي','ﴟ'=>'خى','ﴠ'=>'خي','ﴡ'=>'صى','ﴢ'=>'صي','ﴣ'=>'ضى','ﴤ'=>'ضي','ﴥ'=>'شج','ﴦ'=>'شح','ﴧ'=>'شخ','ﴨ'=>'شم','ﴩ'=>'شر','ﴪ'=>'سر','ﴫ'=>'صر','ﴬ'=>'ضر','ﴭ'=>'شج','ﴮ'=>'شح','ﴯ'=>'شخ','ﴰ'=>'شم','ﴱ'=>'سه','ﴲ'=>'شه','ﴳ'=>'طم','ﴴ'=>'سج','ﴵ'=>'سح','ﴶ'=>'سخ','ﴷ'=>'شج','ﴸ'=>'شح','ﴹ'=>'شخ','ﴺ'=>'طم','ﴻ'=>'ظم','ﴼ'=>'اً','ﴽ'=>'اً','ﵐ'=>'تجم','ﵑ'=>'تحج','ﵒ'=>'تحج','ﵓ'=>'تحم','ﵔ'=>'تخم','ﵕ'=>'تمج','ﵖ'=>'تمح','ﵗ'=>'تمخ','ﵘ'=>'جمح','ﵙ'=>'جمح','ﵚ'=>'حمي','ﵛ'=>'حمى','ﵜ'=>'سحج','ﵝ'=>'سجح','ﵞ'=>'سجى','ﵟ'=>'سمح','ﵠ'=>'سمح','ﵡ'=>'سمج','ﵢ'=>'سمم','ﵣ'=>'سمم','ﵤ'=>'صحح','ﵥ'=>'صحح','ﵦ'=>'صمم','ﵧ'=>'شحم','ﵨ'=>'شحم','ﵩ'=>'شجي','ﵪ'=>'شمخ','ﵫ'=>'شمخ','ﵬ'=>'شمم','ﵭ'=>'شمم','ﵮ'=>'ضحى','ﵯ'=>'ضخم','ﵰ'=>'ضخم','ﵱ'=>'طمح','ﵲ'=>'طمح','ﵳ'=>'طمم','ﵴ'=>'طمي','ﵵ'=>'عجم','ﵶ'=>'عمم','ﵷ'=>'عمم','ﵸ'=>'عمى','ﵹ'=>'غمم','ﵺ'=>'غمي','ﵻ'=>'غمى','ﵼ'=>'فخم','ﵽ'=>'فخم','ﵾ'=>'قمح','ﵿ'=>'قمم','ﶀ'=>'لحم','ﶁ'=>'لحي','ﶂ'=>'لحى','ﶃ'=>'لجج','ﶄ'=>'لجج','ﶅ'=>'لخم','ﶆ'=>'لخم','ﶇ'=>'لمح','ﶈ'=>'لمح','ﶉ'=>'محج','ﶊ'=>'محم','ﶋ'=>'محي','ﶌ'=>'مجح','ﶍ'=>'مجم','ﶎ'=>'مخج','ﶏ'=>'مخم','ﶒ'=>'مجخ','ﶓ'=>'همج','ﶔ'=>'همم','ﶕ'=>'نحم','ﶖ'=>'نحى','ﶗ'=>'نجم','ﶘ'=>'نجم','ﶙ'=>'نجى','ﶚ'=>'نمي','ﶛ'=>'نمى','ﶜ'=>'يمم','ﶝ'=>'يمم','ﶞ'=>'بخي','ﶟ'=>'تجي','ﶠ'=>'تجى','ﶡ'=>'تخي','ﶢ'=>'تخى','ﶣ'=>'تمي','ﶤ'=>'تمى','ﶥ'=>'جمي','ﶦ'=>'جحى','ﶧ'=>'جمى','ﶨ'=>'سخى','ﶩ'=>'صحي','ﶪ'=>'شحي','ﶫ'=>'ضحي','ﶬ'=>'لجي','ﶭ'=>'لمي','ﶮ'=>'يحي','ﶯ'=>'يجي','ﶰ'=>'يمي','ﶱ'=>'ممي','ﶲ'=>'قمي','ﶳ'=>'نحي','ﶴ'=>'قمح','ﶵ'=>'لحم','ﶶ'=>'عمي','ﶷ'=>'كمي','ﶸ'=>'نجح','ﶹ'=>'مخي','ﶺ'=>'لجم','ﶻ'=>'كمم','ﶼ'=>'لجم','ﶽ'=>'نجح','ﶾ'=>'جحي','ﶿ'=>'حجي','ﷀ'=>'مجي','ﷁ'=>'فمي','ﷂ'=>'بحي','ﷃ'=>'كمم','ﷄ'=>'عجم','ﷅ'=>'صمم','ﷆ'=>'سخي','ﷇ'=>'نجي','ﷰ'=>'صلے','ﷱ'=>'قلے','ﷲ'=>'الله','ﷳ'=>'اكبر','ﷴ'=>'محمد','ﷵ'=>'صلعم','ﷶ'=>'رسول','ﷷ'=>'عليه','ﷸ'=>'وسلم','ﷹ'=>'صلى','ﷺ'=>'صلى الله عليه وسلم','ﷻ'=>'جل جلاله','﷼'=>'ریال','︐'=>',','︑'=>'、','︒'=>'。','︓'=>':','︔'=>';','︕'=>'!','︖'=>'?','︗'=>'〖','︘'=>'〗','︙'=>'...','︰'=>'..','︱'=>'—','︲'=>'–','︳'=>'_','︴'=>'_','︵'=>'(','︶'=>')','︷'=>'{','︸'=>'}','︹'=>'〔','︺'=>'〕','︻'=>'【','︼'=>'】','︽'=>'《','︾'=>'》','︿'=>'〈','﹀'=>'〉','﹁'=>'「','﹂'=>'」','﹃'=>'『','﹄'=>'』','﹇'=>'[','﹈'=>']','﹉'=>' ̅','﹊'=>' ̅','﹋'=>' ̅','﹌'=>' ̅','﹍'=>'_','﹎'=>'_','﹏'=>'_','﹐'=>',','﹑'=>'、','﹒'=>'.','﹔'=>';','﹕'=>':','﹖'=>'?','﹗'=>'!','﹘'=>'—','﹙'=>'(','﹚'=>')','﹛'=>'{','﹜'=>'}','﹝'=>'〔','﹞'=>'〕','﹟'=>'#','﹠'=>'&','﹡'=>'*','﹢'=>'+','﹣'=>'-','﹤'=>'<','﹥'=>'>','﹦'=>'=','﹨'=>'\\','﹩'=>'$','﹪'=>'%','﹫'=>'@','ﹰ'=>' ً','ﹱ'=>'ـً','ﹲ'=>' ٌ','ﹴ'=>' ٍ','ﹶ'=>' َ','ﹷ'=>'ـَ','ﹸ'=>' ُ','ﹹ'=>'ـُ','ﹺ'=>' ِ','ﹻ'=>'ـِ','ﹼ'=>' ّ','ﹽ'=>'ـّ','ﹾ'=>' ْ','ﹿ'=>'ـْ','ﺀ'=>'ء','ﺁ'=>'آ','ﺂ'=>'آ','ﺃ'=>'أ','ﺄ'=>'أ','ﺅ'=>'ؤ','ﺆ'=>'ؤ','ﺇ'=>'إ','ﺈ'=>'إ','ﺉ'=>'ئ','ﺊ'=>'ئ','ﺋ'=>'ئ','ﺌ'=>'ئ','ﺍ'=>'ا','ﺎ'=>'ا','ﺏ'=>'ب','ﺐ'=>'ب','ﺑ'=>'ب','ﺒ'=>'ب','ﺓ'=>'ة','ﺔ'=>'ة','ﺕ'=>'ت','ﺖ'=>'ت','ﺗ'=>'ت','ﺘ'=>'ت','ﺙ'=>'ث','ﺚ'=>'ث','ﺛ'=>'ث','ﺜ'=>'ث','ﺝ'=>'ج','ﺞ'=>'ج','ﺟ'=>'ج','ﺠ'=>'ج','ﺡ'=>'ح','ﺢ'=>'ح','ﺣ'=>'ح','ﺤ'=>'ح','ﺥ'=>'خ','ﺦ'=>'خ','ﺧ'=>'خ','ﺨ'=>'خ','ﺩ'=>'د','ﺪ'=>'د','ﺫ'=>'ذ','ﺬ'=>'ذ','ﺭ'=>'ر','ﺮ'=>'ر','ﺯ'=>'ز','ﺰ'=>'ز','ﺱ'=>'س','ﺲ'=>'س','ﺳ'=>'س','ﺴ'=>'س','ﺵ'=>'ش','ﺶ'=>'ش','ﺷ'=>'ش','ﺸ'=>'ش','ﺹ'=>'ص','ﺺ'=>'ص','ﺻ'=>'ص','ﺼ'=>'ص','ﺽ'=>'ض','ﺾ'=>'ض','ﺿ'=>'ض','ﻀ'=>'ض','ﻁ'=>'ط','ﻂ'=>'ط','ﻃ'=>'ط','ﻄ'=>'ط','ﻅ'=>'ظ','ﻆ'=>'ظ','ﻇ'=>'ظ','ﻈ'=>'ظ','ﻉ'=>'ع','ﻊ'=>'ع','ﻋ'=>'ع','ﻌ'=>'ع','ﻍ'=>'غ','ﻎ'=>'غ','ﻏ'=>'غ','ﻐ'=>'غ','ﻑ'=>'ف','ﻒ'=>'ف','ﻓ'=>'ف','ﻔ'=>'ف','ﻕ'=>'ق','ﻖ'=>'ق','ﻗ'=>'ق','ﻘ'=>'ق','ﻙ'=>'ك','ﻚ'=>'ك','ﻛ'=>'ك','ﻜ'=>'ك','ﻝ'=>'ل','ﻞ'=>'ل','ﻟ'=>'ل','ﻠ'=>'ل','ﻡ'=>'م','ﻢ'=>'م','ﻣ'=>'م','ﻤ'=>'م','ﻥ'=>'ن','ﻦ'=>'ن','ﻧ'=>'ن','ﻨ'=>'ن','ﻩ'=>'ه','ﻪ'=>'ه','ﻫ'=>'ه','ﻬ'=>'ه','ﻭ'=>'و','ﻮ'=>'و','ﻯ'=>'ى','ﻰ'=>'ى','ﻱ'=>'ي','ﻲ'=>'ي','ﻳ'=>'ي','ﻴ'=>'ي','ﻵ'=>'لآ','ﻶ'=>'لآ','ﻷ'=>'لأ','ﻸ'=>'لأ','ﻹ'=>'لإ','ﻺ'=>'لإ','ﻻ'=>'لا','ﻼ'=>'لا','!'=>'!','"'=>'"','#'=>'#','$'=>'$','%'=>'%','&'=>'&','''=>'\'','('=>'(',')'=>')','*'=>'*','+'=>'+',','=>',','-'=>'-','.'=>'.','/'=>'/','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','{'=>'{','|'=>'|','}'=>'}','~'=>'~','⦅'=>'⦅','⦆'=>'⦆','。'=>'。','「'=>'「','」'=>'」','、'=>'、','・'=>'・','ヲ'=>'ヲ','ァ'=>'ァ','ィ'=>'ィ','ゥ'=>'ゥ','ェ'=>'ェ','ォ'=>'ォ','ャ'=>'ャ','ュ'=>'ュ','ョ'=>'ョ','ッ'=>'ッ','ー'=>'ー','ア'=>'ア','イ'=>'イ','ウ'=>'ウ','エ'=>'エ','オ'=>'オ','カ'=>'カ','キ'=>'キ','ク'=>'ク','ケ'=>'ケ','コ'=>'コ','サ'=>'サ','シ'=>'シ','ス'=>'ス','セ'=>'セ','ソ'=>'ソ','タ'=>'タ','チ'=>'チ','ツ'=>'ツ','テ'=>'テ','ト'=>'ト','ナ'=>'ナ','ニ'=>'ニ','ヌ'=>'ヌ','ネ'=>'ネ','ノ'=>'ノ','ハ'=>'ハ','ヒ'=>'ヒ','フ'=>'フ','ヘ'=>'ヘ','ホ'=>'ホ','マ'=>'マ','ミ'=>'ミ','ム'=>'ム','メ'=>'メ','モ'=>'モ','ヤ'=>'ヤ','ユ'=>'ユ','ヨ'=>'ヨ','ラ'=>'ラ','リ'=>'リ','ル'=>'ル','レ'=>'レ','ロ'=>'ロ','ワ'=>'ワ','ン'=>'ン','゙'=>'゙','゚'=>'゚','ᅠ'=>'ᅠ','ᄀ'=>'ᄀ','ᄁ'=>'ᄁ','ᆪ'=>'ᆪ','ᄂ'=>'ᄂ','ᆬ'=>'ᆬ','ᆭ'=>'ᆭ','ᄃ'=>'ᄃ','ᄄ'=>'ᄄ','ᄅ'=>'ᄅ','ᆰ'=>'ᆰ','ᆱ'=>'ᆱ','ᆲ'=>'ᆲ','ᆳ'=>'ᆳ','ᆴ'=>'ᆴ','ᆵ'=>'ᆵ','ᄚ'=>'ᄚ','ᄆ'=>'ᄆ','ᄇ'=>'ᄇ','ᄈ'=>'ᄈ','ᄡ'=>'ᄡ','ᄉ'=>'ᄉ','ᄊ'=>'ᄊ','ᄋ'=>'ᄋ','ᄌ'=>'ᄌ','ᄍ'=>'ᄍ','ᄎ'=>'ᄎ','ᄏ'=>'ᄏ','ᄐ'=>'ᄐ','ᄑ'=>'ᄑ','ᄒ'=>'ᄒ','ᅡ'=>'ᅡ','ᅢ'=>'ᅢ','ᅣ'=>'ᅣ','ᅤ'=>'ᅤ','ᅥ'=>'ᅥ','ᅦ'=>'ᅦ','ᅧ'=>'ᅧ','ᅨ'=>'ᅨ','ᅩ'=>'ᅩ','ᅪ'=>'ᅪ','ᅫ'=>'ᅫ','ᅬ'=>'ᅬ','ᅭ'=>'ᅭ','ᅮ'=>'ᅮ','ᅯ'=>'ᅯ','ᅰ'=>'ᅰ','ᅱ'=>'ᅱ','ᅲ'=>'ᅲ','ᅳ'=>'ᅳ','ᅴ'=>'ᅴ','ᅵ'=>'ᅵ','¢'=>'¢','£'=>'£','¬'=>'¬',' ̄'=>' ̄','¦'=>'¦','¥'=>'¥','₩'=>'₩','│'=>'│','←'=>'←','↑'=>'↑','→'=>'→','↓'=>'↓','■'=>'■','○'=>'○','𝅗𝅥'=>'𝅗𝅥','𝅘𝅥'=>'𝅘𝅥','𝅘𝅥𝅮'=>'𝅘𝅥𝅮','𝅘𝅥𝅯'=>'𝅘𝅥𝅯','𝅘𝅥𝅰'=>'𝅘𝅥𝅰','𝅘𝅥𝅱'=>'𝅘𝅥𝅱','𝅘𝅥𝅲'=>'𝅘𝅥𝅲','𝆹𝅥'=>'𝆹𝅥','𝆺𝅥'=>'𝆺𝅥','𝆹𝅥𝅮'=>'𝆹𝅥𝅮','𝆺𝅥𝅮'=>'𝆺𝅥𝅮','𝆹𝅥𝅯'=>'𝆹𝅥𝅯','𝆺𝅥𝅯'=>'𝆺𝅥𝅯','𝐀'=>'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,'DŽ'=>1,'Dž'=>1,'dž'=>1,'LJ'=>1,'Lj'=>1,'lj'=>1,'NJ'=>1,'Nj'=>1,'nj'=>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,'fi'=>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,'0'=>1,'1'=>1,'2'=>1,'3'=>1,'4'=>1,'5'=>1,'6'=>1,'7'=>1,'8'=>1,'9'=>1,':'=>1,';'=>1,'<'=>1,'='=>1,'>'=>1,'?'=>1,'@'=>1,'A'=>1,'B'=>1,'C'=>1,'D'=>1,'E'=>1,'F'=>1,'G'=>1,'H'=>1,'I'=>1,'J'=>1,'K'=>1,'L'=>1,'M'=>1,'N'=>1,'O'=>1,'P'=>1,'Q'=>1,'R'=>1,'S'=>1,'T'=>1,'U'=>1,'V'=>1,'W'=>1,'X'=>1,'Y'=>1,'Z'=>1,'['=>1,'\'=>1,']'=>1,'^'=>1,'_'=>1,'`'=>1,'a'=>1,'b'=>1,'c'=>1,'d'=>1,'e'=>1,'f'=>1,'g'=>1,'h'=>1,'i'=>1,'j'=>1,'k'=>1,'l'=>1,'m'=>1,'n'=>1,'o'=>1,'p'=>1,'q'=>1,'r'=>1,'s'=>1,'t'=>1,'u'=>1,'v'=>1,'w'=>1,'x'=>1,'y'=>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..0b567fad6b --- /dev/null +++ b/phpBB/includes/utf/utf_normalizer.php @@ -0,0 +1,1960 @@ +<?php +/** +* +* @package phpBB3 +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* 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"); + + +if (function_exists('utf8_normalize')) +{ + +//////////////////////////////////////////////////////////////////////////////// +// Wrapper for the utfnormal extension, ICU wrapper // +//////////////////////////////////////////////////////////////////////////////// + +define('UNORM_NONE', 1); +define('UNORM_NFD', 2); +define('UNORM_NFKD', 3); +define('UNORM_NFC', 4); +define('UNORM_NFKC', 5); +define('UNORM_FCD', 6); +define('UNORM_DEFAULT', UNORM_NFC); + +/** +* utf_normalizer class for the utfnormal extension +* +* @ignore +*/ +class utf_normalizer +{ + 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" + ); + + if (!isset($str[$pos])) + { + /** + * ASCII strings with no special chars return immediately + */ + return $str; + } + + /** + * Check if there is potentially a U+FFFE or U+FFFF char (UTF sequence + * 0xEFBFBE or 0xEFBFBF) and replace them + * + * Note: we start searching at position $pos + */ + if (is_int(strpos($str, "\xEF\xBF", $pos))) + { + $str = str_replace( + array("\xEF\xBF\xBE", "\xEF\xBF\xBF"), + array(UTF8_REPLACEMENT, UTF8_REPLACEMENT), + $str + ); + } + + /** + * 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 Unicode 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" + ); + + /** + * As per the original implementation, "the UnicodeString constructor fails + * if the string ends with a head byte". Therefore, if the string ends with + * a leading byte we replace it with 0xFF, which is illegal too and will be + * replaced with a Unicode replacement character + */ + if (substr($str, -1) >= "\xC0") + { + $str[strlen($str) - 1] = "\xFF"; + } + + return utf8_normalize($str, UNORM_NFC); + } + + function nfc($str) + { + return utf8_normalize($str, UNORM_NFC); + } + + function nfkc($str) + { + return utf8_normalize($str, UNORM_NFKC); + } + + function nfd($str) + { + return utf8_normalize($str, UNORM_NFD); + } + + function nfkd($str) + { + return utf8_normalize($str, UNORM_NFKD); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// End of the ICU wrapper // +//////////////////////////////////////////////////////////////////////////////// + + +} +else +{ + + +//////////////////////////////////////////////////////////////////////////////// +// This block will NOT be loaded if the utfnormal extension is // +//////////////////////////////////////////////////////////////////////////////// + +/** +* 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 phpBB3 +*/ +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 $str; + } + + /** + * 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); + } + + /** + * 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 + */ + return utf_normalizer::recompose( + 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" + ), + $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 $str; + } + + if (!isset($GLOBALS['utf_nfc_qc'])) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/utf/data/utf_nfc_qc.' . $phpEx); + } + + return 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 $str; + } + + 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_canonical_comp'])) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/utf/data/utf_canonical_comp.' . $phpEx); + } + + return 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 $str; + } + + if (!isset($GLOBALS['utf_canonical_decomp'])) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/utf/data/utf_canonical_decomp.' . $phpEx); + } + + return 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 $str; + } + + if (!isset($GLOBALS['utf_compatibility_decomp'])) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/utf/data/utf_compatibility_decomp.' . $phpEx); + } + + return utf_normalizer::decompose($str, $pos, $len, $GLOBALS['utf_compatibility_decomp']); + } + + + //////////////////////////////////////////////////////////////////////////// + // Internal functions // + //////////////////////////////////////////////////////////////////////////// + + /** + * 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; + include($phpbb_root_path . 'includes/utf/data/utf_normalizer_common.php'); + } + + /** + * Buffer the last ASCII char before the UTF-8 stuff if applicable + */ + $tmp = ''; + $i = $tmp_pos = $last_cc = 0; + + if ($pos) + { + $buffer = array(++$i => $str[$pos - 1]); + } + else + { + $buffer = 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 + */ + } + elseif (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] < "\xF8") + { + $trailing_bytes = 3; + } + elseif ($utf_char[0] < "\xFC") + { + $trailing_bytes = 4; + } + 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; + } + elseif ($utf_char[0] < "\xFC") + { + $trailing_bytes = 4; + } + elseif ($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; + } + } + } + + /** + * 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 = count($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 = count($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 + count($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]; + } + elseif (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, $utf_canonical_decomp, $phpbb_root_path; + + /** + * Load some commonly-used tables + */ + if (!isset($utf_combining_class)) + { + include($phpbb_root_path . 'includes/utf/data/utf_normalizer_common.php'); + } + + /** + * 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); + } + elseif (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; + } + } + } + } + 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 ($tIndex = $idx % UNICODE_HANGUL_TCOUNT) + { + if ($tIndex < 25) + { + $utf_char = "\xE1\x84\x00\xE1\x85\x00\xE1\x86\x00"; + $utf_char[8] = chr(0xA7 + $tIndex); + } + else + { + $utf_char = "\xE1\x84\x00\xE1\x85\x00\xE1\x87\x00"; + $utf_char[8] = chr(0x67 + $tIndex); + } + } + 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; + + } + elseif ($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..b3c3c5ed5e --- /dev/null +++ b/phpBB/includes/utf/utf_tools.php @@ -0,0 +1,217 @@ +<?php +/** +* +* @package phpBB3 +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* 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. +* +* If we go with UTF-8 in 3.2, we will also need a Unicode-aware replacement +* to strtolower() +* +* @package phpBB3 +*/ + +/** +* 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) +{ + if (function_exists('iconv_strlen')) + { + return iconv_strlen($text, 'utf-8'); + } + + if (function_exists('mb_strlen')) + { + return mb_strlen($text, 'utf-8'); + } + + return strlen(utf8_decode($text)); +} + +/** +* 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 +* @return string The string, encoded in UTF-8 +*/ +function utf8_recode($string, $encoding) +{ + $encoding = strtolower($encoding); + + if ($encoding == 'utf-8' || !is_string($string) || !isset($string[0])) + { + return $string; + } + + /** + * PHP has a built-in function for encoding from iso-8859-1, let's use that + */ + if ($encoding == 'iso-8859-1') + { + return utf8_encode($string); + } + + /** + * First, try iconv() + */ + if (function_exists('iconv')) + { + $ret = @iconv($encoding, 'utf-8', $string); + + if (isset($ret[0])) + { + return $ret; + } + } + + /** + * Try the mb_string extension + */ + if (function_exists('mb_convert_encoding')) + { + $ret = @mb_convert_encoding($string, 'utf-8', $encoding); + + if (isset($ret[0])) + { + return $ret; + } + } + + /** + * Try the recode extension + */ + if (function_exists('recode_string')) + { + $ret = @recode_string($encoding . '..utf-8', $string); + + if (isset($ret[0])) + { + 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); + } + + global $phpbb_root_path; + if (!file_exists($phpbb_root_path . 'includes/utf/data/')) + { + return $string; + } + + die('Finish me!! '.basename(__FILE__).' at line '.__LINE__); +} + +/** +* 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]+#', '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) +{ + switch (strlen($m[0])) + { + case 1: + return '&#' . ord($m[0]) . ';'; + + case 2: + return '&#' . (((ord($m[0][0]) & 0x1F) << 6) | (ord($m[0][1]) & 0x3F)) . ';'; + + case 3: + return '&#' . (((ord($m[0][0]) & 0x0F) << 12) | ((ord($m[0][1]) & 0x3F) << 6) | (ord($m[0][2]) & 0x3F)) . ';'; + + case 4: + return '&#' . (((ord($m[0][0]) & 0x07) << 18) | ((ord($m[0][1]) & 0x3F) << 12) | ((ord($m[0][2]) & 0x3F) << 6) | (ord($m[0][3]) & 0x3F)) . ';'; + + default: + return $m[0]; + } +} + +/** +* Convert Numeric Character References to UTF-8 chars +* +* Notes: +* - we do not convert NCRs recursively, if you pass &#38; it will return & +* - we DO NOT check for the existence of the Unicode characters, therefore an entity +* may be converted to an inexistent codepoint +* +* @param string $text String to convert, encoded in UTF-8 (no normal form required) +* @return string UTF-8 string where NCRs have been replaced with the actual chars +*/ +function utf8_decode_ncr($text) +{ + return preg_replace_callback('/&#([0-9]{1,6}|x[0-9A-F]{1,5});/i', 'utf8_decode_ncr_callback', $text); +} + +/** +* Callback used in decode_ncr() +* +* Takes a NCR (in decimal or hexadecimal) and returns a UTF-8 char. Attention, $m is an array. +* It will ignore most of invalid NCRs, but not all! +* +* @param array $m 0-based numerically indexed array passed by preg_replace_callback() +* @return string UTF-8 char +*/ +function utf8_decode_ncr_callback($m) +{ + $cp = (strncasecmp($m[1], 'x', 1)) ? $m[1] : hexdec(substr($m[1], 1)); + + if ($cp > 0xFFFF) + { + return chr(0xF0 | ($cp >> 18)) . chr(0x80 | (($cp >> 12) & 0x3F)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F)); + } + elseif ($cp > 0x7FF) + { + return chr(0xE0 | ($cp >> 12)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F)); + } + elseif ($cp > 0x7F) + { + return chr(0xC0 | ($cp >> 6)) . chr(0x80 | ($cp & 0x3F)); + } + else + { + return chr($cp); + } +} + +?>
\ No newline at end of file |
