diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index 8dbf70ccb1..84cc8ddd1c 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -347,6 +347,10 @@ class acp_board $this->new_config = $config; $cfg_array = (isset($_REQUEST['config'])) ? request_var('config', array('' => ''), true) : $this->new_config; + if (isset($_REQUEST['config'])) + { + utf8_normalize_nfc(&$cfg_array); + } $error = array(); // We validate the complete config if whished diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 0cba781542..30c4e27b63 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -985,11 +985,13 @@ class acp_users 'website' => request_var('website', $user_row['user_website']), 'location' => request_var('location', $user_row['user_from'], true), 'occupation' => request_var('occupation', $user_row['user_occ'], true), - 'interests' => request_var('interests', $user_row['user_interests']), + 'interests' => request_var('interests', $user_row['user_interests'], true), 'bday_day' => 0, 'bday_month' => 0, 'bday_year' => 0, ); + + utf8_normalize_nfc(array(&$data['location'], &$data['occupation'], &$data['interests'])); if ($user_row['user_birthday']) { @@ -1551,6 +1553,8 @@ class acp_users $enable_urls = request_var('enable_urls', true); $signature = request_var('signature', $user_row['user_sig'], true); + utf8_normalize_nfc(&$signature); + $preview = (isset($_POST['preview'])) ? true : false; if ($submit || $preview) diff --git a/phpBB/includes/acp/acp_words.php b/phpBB/includes/acp/acp_words.php index dc5a694d0a..8fe99b8c80 100644 --- a/phpBB/includes/acp/acp_words.php +++ b/phpBB/includes/acp/acp_words.php @@ -71,6 +71,8 @@ class acp_words $word_id = request_var('id', 0); $word = request_var('word', '', true); $replacement = request_var('replacement', '', true); + + utf8_normalize_nfc(array(&$word, &$replacement)); if (!$word || !$replacement) { diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 48b64f8092..17c15fda30 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -2085,7 +2085,7 @@ function bump_topic_allowed($forum_id, $topic_bumped, $last_post_time, $topic_po * Generates a text with approx. the specified length which contains the specified words and their context * * @param string $text The full text from which context shall be extracted -* @param string $words An array of words which should be contained in the result, * is allowed as a wildcard +* @param string $words An array of words which should be contained in the result, has to be a valid part of a PCRE pattern (escape with preg_quote!) * @param int $length The desired length of the resulting text, however the result might be shorter or longer than this value * * @return string Context of the specified words seperated by "..." @@ -2102,7 +2102,7 @@ function get_context($text, $words, $length = 400) // find the starting indizes of all words foreach ($words as $word) { - if (preg_match('#(?:[^\w]|^)(' . str_replace('\*', '\w*?', preg_quote($word, '#')) . ')(?:[^\w]|$)#i', $text, $match)) + if (preg_match('#(?:[^\w]|^)(' . $word . ')(?:[^\w]|$)#i', $text, $match)) { $pos = strpos($text, $match[1]); if ($pos !== false) diff --git a/phpBB/includes/functions_profile_fields.php b/phpBB/includes/functions_profile_fields.php index ca2bf690b6..b35781e198 100644 --- a/phpBB/includes/functions_profile_fields.php +++ b/phpBB/includes/functions_profile_fields.php @@ -576,6 +576,11 @@ class custom_profile else { $value = (isset($_REQUEST[$profile_row['field_ident']])) ? request_var($profile_row['field_ident'], $default_value, true) : ((!isset($user->profile_fields[$user_ident]) || $preview) ? $default_value : $user->profile_fields[$user_ident]); + + if (gettype($value) == 'string') + { + utf8_normalize_nfc(&$value); + } } switch ($field_validation) @@ -861,6 +866,7 @@ class custom_profile case FIELD_STRING: case FIELD_TEXT: $var = request_var($var_name, $profile_row['field_default_value'], true); + utf8_normalize_nfc(&$var); break; case FIELD_INT: diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php index 2452e19512..3b674139e9 100644 --- a/phpBB/includes/mcp/mcp_topic.php +++ b/phpBB/includes/mcp/mcp_topic.php @@ -37,6 +37,8 @@ function mcp_topic_view($id, $mode, $action) $to_topic_id = request_var('to_topic_id', 0); $to_forum_id = request_var('to_forum_id', 0); $post_id_list = request_var('post_id_list', array(0)); + + utf8_normalize_nfc(&$subject); // Split Topic? if ($action == 'split_all' || $action == 'split_beyond') diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index ab5ee46824..6538bd7721 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -1139,6 +1139,7 @@ class parse_message extends bbcode_firstpass $num_attachments = sizeof($this->attachment_data); $this->filename_data['filecomment'] = request_var('filecomment', '', true); + utf8_normalize_nfc(&$this->filename_data['filecomment']); $upload_file = (isset($_FILES[$form_name]) && $_FILES[$form_name]['name'] != 'none' && trim($_FILES[$form_name]['name'])) ? true : false; $add_file = (isset($_POST['add_file'])) ? true : false; @@ -1256,6 +1257,7 @@ class parse_message extends bbcode_firstpass if ($edit_comment) { $actual_comment_list = request_var('comment_list', array(''), true); + utf8_normalize_nfc(&$actual_comment_list); $edit_comment = request_var('edit_comment', array(0 => '')); $edit_comment = key($edit_comment); @@ -1321,6 +1323,7 @@ class parse_message extends bbcode_firstpass global $user, $db, $phpbb_root_path, $phpEx, $config; $this->filename_data['filecomment'] = request_var('filecomment', '', true); + utf8_normalize_nfc(&$this->filename_data['filecomment']); $attachment_data = (isset($_POST['attachment_data'])) ? $_POST['attachment_data'] : array(); $this->attachment_data = array(); diff --git a/phpBB/includes/ucp/ucp_main.php b/phpBB/includes/ucp/ucp_main.php index 997f8884f5..67e1c4d155 100644 --- a/phpBB/includes/ucp/ucp_main.php +++ b/phpBB/includes/ucp/ucp_main.php @@ -662,6 +662,8 @@ class ucp_main { $draft_subject = request_var('subject', '', true); $draft_message = request_var('message', '', true); + + utf8_normalize_nfc(array(&$draft_subject, &$draft_message)); if ($draft_message && $draft_subject) { diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php index 6c20c89459..98aa35117b 100644 --- a/phpBB/includes/ucp/ucp_pm_compose.php +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -399,6 +399,8 @@ function compose_pm($id, $mode, $action) $subject = request_var('subject', '', true); $subject = (!$subject && $action != 'post') ? $user->lang['NEW_MESSAGE'] : $subject; $message = request_var('message', '', true); + + utf8_normalize_nfc(array(&$subject, &$message)); if ($subject && $message) { @@ -476,6 +478,8 @@ function compose_pm($id, $mode, $action) { $subject = request_var('subject', '', true); $message_parser->message = request_var('message', '', true); + + utf8_normalize_nfc(array(&$subject, &$message_parser->message)); $icon_id = request_var('icon', 0); diff --git a/phpBB/includes/ucp/ucp_pm_options.php b/phpBB/includes/ucp/ucp_pm_options.php index 256e781f1f..9b86553569 100644 --- a/phpBB/includes/ucp/ucp_pm_options.php +++ b/phpBB/includes/ucp/ucp_pm_options.php @@ -250,6 +250,8 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit $rule_string = ($cond_option != 'none') ? request_var('rule_string', '', true) : ''; $rule_user_id = ($cond_option != 'none') ? request_var('rule_user_id', 0) : 0; $rule_group_id = ($cond_option != 'none') ? request_var('rule_group_id', 0) : 0; + + utf8_normalize_nfc(&$rule_string); $action = (int) $action_option[0]; $folder_id = (int) $action_option[1]; @@ -639,6 +641,8 @@ function define_cond_option($hardcoded, $cond_option, $rule_option, $global_rule { case 'text': $rule_string = request_var('rule_string', '', true); + + utf8_normalize_nfc(&$rule_string); $template->assign_vars(array( 'S_TEXT_CONDITION' => true, @@ -653,6 +657,8 @@ function define_cond_option($hardcoded, $cond_option, $rule_option, $global_rule case 'user': $rule_user_id = request_var('rule_user_id', 0); $rule_string = request_var('rule_string', '', true); + + utf8_normalize_nfc(&$rule_string); if ($rule_string && !$rule_user_id) { @@ -696,6 +702,8 @@ function define_cond_option($hardcoded, $cond_option, $rule_option, $global_rule case 'group': $rule_group_id = request_var('rule_group_id', 0); $rule_string = request_var('rule_string', '', true); + + utf8_normalize_nfc(&$rule_string); $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_type diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index 7aab239f39..f8a23869b2 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -252,11 +252,13 @@ class ucp_profile 'website' => request_var('website', $user->data['user_website']), 'location' => request_var('location', $user->data['user_from'], true), 'occupation' => request_var('occupation', $user->data['user_occ'], true), - 'interests' => request_var('interests', $user->data['user_interests']), + 'interests' => request_var('interests', $user->data['user_interests'], true), 'bday_day' => 0, 'bday_month' => 0, 'bday_year' => 0, ); + + utf8_normalize_nfc(array(&$data['location'], &$data['occupation'], &$data['interests'])) if ($user->data['user_birthday']) { @@ -412,6 +414,8 @@ class ucp_profile $enable_urls = request_var('enable_urls', true); $signature = request_var('signature', (string) $user->data['user_sig'], true); + utf8_normalize_nfc(&$signature); + if ($submit || $preview) { include($phpbb_root_path . 'includes/message_parser.'.$phpEx); diff --git a/phpBB/includes/utf/utf_tools.php b/phpBB/includes/utf/utf_tools.php index d90590e813..b91fd51c20 100644 --- a/phpBB/includes/utf/utf_tools.php +++ b/phpBB/includes/utf/utf_tools.php @@ -930,15 +930,52 @@ function utf8_case_fold($text, $option = 'full') } /** -* @todo needs documenting +* A wrapper function for the normalizer which takes care of including the class if required and modifies the passed strings +* to be in NFC (Normalization Form Composition). +* +* @param mixed $strings Either an array of references to strings, a reference to an array of strings or a reference to a single string +*/ +function utf8_normalize_nfc($strings) +{ + if (!is_array($strings) || (sizeof($strings) > 0)) + { + if (!class_exists('utf_normalizer')) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx); + } + + if (is_array($strings)) + { + foreach ($strings as $key => $string) + { + $strings[$key] = utf_normalizer::nfc($strings[$key]); + } + } + else + { + $strings = utf_normalizer::nfc($strings); + } + } +} + +/** +* This function is used to generate a "clean" version of a string. +* Clean means that it is a case insensitive form (case folding) and that it is normalized (NFC). +* Additionally a homographs of one character are transformed into one specific character (preferably ASCII +* if it is an ASCII character). * * Please be aware that if you change something within this function or within -* functions used here you need to rebuild/update the complete users table. +* functions used here you need to rebuild/update the username_clean column in the users table. And all other +* columns that store a clean string otherwise you will break this functionality. +* +* @param $text An unclean string, mabye user input (has to be valid UTF-8!) +* @return Cleaned up version of the input string */ function utf8_clean_string($text) { $text = utf8_case_fold($text); - + if (!class_exists('utf_normalizer')) { global $phpbb_root_path, $phpEx; @@ -963,6 +1000,8 @@ function utf8_clean_string($text) // greek "\xCE\xB1" => "\x61", "\xCE\xBF" => "\x6F", + // other + "\xC2\xA1" => "\x69", ); $text = strtr($text, $homographs); diff --git a/phpBB/posting.php b/phpBB/posting.php index aa79f31167..d2d9ef0e27 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -448,6 +448,8 @@ if ($save && $user->data['is_registered'] && $auth->acl_get('u_savedrafts')) $subject = request_var('subject', '', true); $subject = (!$subject && $mode != 'post') ? $post_data['topic_title'] : $subject; $message = request_var('message', '', true); + + utf8_normalize_nfc(array(&$subject, &$message)); if ($subject && $message) { @@ -532,6 +534,8 @@ if ($submit || $preview || $refresh) $post_data['username'] = request_var('username', $post_data['username'], true); $post_data['post_edit_reason'] = (!empty($_POST['edit_reason']) && $mode == 'edit' && $auth->acl_get('m_edit', $forum_id)) ? request_var('edit_reason', '', true) : ''; + + utf8_normalize_nfc(array(&$post_data['post_subject'], &$message_parser->message, &$post_data['username'], &$post_data['post_edit_reason'])); $post_data['topic_type'] = request_var('topic_type', (($mode != 'post') ? (int) $post_data['topic_type'] : POST_NORMAL)); $post_data['topic_time_limit'] = request_var('topic_time_limit', (($mode != 'post') ? (int) $post_data['topic_time_limit'] : 0)); @@ -604,6 +608,8 @@ if ($submit || $preview || $refresh) $post_data['poll_option_text'] = request_var('poll_option_text', '', true); $post_data['poll_max_options'] = request_var('poll_max_options', 1); $post_data['poll_vote_change'] = ($auth->acl_get('f_votechg', $forum_id) && isset($_POST['poll_vote_change'])) ? 1 : 0; + + utf8_normalize_nfc(array(&$post_data['poll_title'], &$post_data['poll_option_text'])); } // If replying/quoting and last post id has changed diff --git a/phpBB/report.php b/phpBB/report.php index 9679e23d6c..348b2e91b6 100644 --- a/phpBB/report.php +++ b/phpBB/report.php @@ -22,10 +22,13 @@ $user->session_begin(); $auth->acl($user->data); $user->setup('mcp'); -$forum_id = request_var('f', 0); -$post_id = request_var('p', 0); -$reason_id = request_var('reason_id', 0); -$report_text = request_var('report_text', '', true); +$forum_id = request_var('f', 0); +$post_id = request_var('p', 0); +$reason_id = request_var('reason_id', 0); +$report_text = request_var('report_text', '', true); + +utf8_normalize_nfc(&$report_text); + $user_notify = (isset($_POST['notify']) && $user->data['is_registered']) ? true : false; $submit = (isset($_POST['submit'])) ? true : false;