diff options
Diffstat (limited to 'phpBB/includes')
74 files changed, 2424 insertions, 863 deletions
diff --git a/phpBB/includes/acp/acp_attachments.php b/phpBB/includes/acp/acp_attachments.php index c62fefae46..4295aa9d9f 100644 --- a/phpBB/includes/acp/acp_attachments.php +++ b/phpBB/includes/acp/acp_attachments.php @@ -1159,7 +1159,7 @@ class acp_attachments // Issue warning message if files stats are inaccurate if (($num_files != $num_files_real) || ($total_size != $total_size_real)) { - $error[] = sprintf($user->lang['FILES_STATS_WRONG'], $num_files_real, get_formatted_filesize($total_size_real)); + $error[] = $user->lang('FILES_STATS_WRONG', (int) $num_files_real, get_formatted_filesize($total_size_real)); $template->assign_vars(array( 'S_ACTION_OPTIONS' => ($auth->acl_get('a_board')) ? true : false, @@ -1244,8 +1244,7 @@ class acp_attachments $row['extension'] = strtolower(trim((string) $row['extension'])); $comment = ($row['attach_comment'] && !$row['in_message']) ? str_replace(array("\n", "\r"), array('<br />', "\n"), $row['attach_comment']) : ''; $display_cat = $extensions[$row['extension']]['display_cat']; - $l_downloaded_viewed = ($display_cat == ATTACHMENT_CATEGORY_NONE) ? 'DOWNLOAD_COUNT' : 'VIEWED_COUNT'; - $l_download_count = (!isset($row['download_count']) || (int) $row['download_count'] == 0) ? $user->lang[$l_downloaded_viewed . '_NONE'] : (((int) $row['download_count'] == 1) ? sprintf($user->lang[$l_downloaded_viewed], $row['download_count']) : sprintf($user->lang[$l_downloaded_viewed . 'S'], $row['download_count'])); + $l_downloaded_viewed = ($display_cat == ATTACHMENT_CATEGORY_NONE) ? 'DOWNLOAD_COUNTS' : 'VIEWED_COUNTS'; $template->assign_block_vars('attachments', array( 'ATTACHMENT_POSTER' => get_username_string('full', (int) $row['poster_id'], (string) $row['username'], (string) $row['user_colour'], (string) $row['username']), @@ -1261,7 +1260,7 @@ class acp_attachments 'TOPIC_ID' => (int) $row['topic_id'], 'POST_IDS' => (!empty($post_ids[$row['attach_id']])) ? (int) $post_ids[$row['attach_id']] : '', - 'L_DOWNLOAD_COUNT' => $l_download_count, + 'L_DOWNLOAD_COUNT' => $user->lang($l_downloaded_viewed, (int) $row['download_count']), 'S_IN_MESSAGE' => (bool) $row['in_message'], diff --git a/phpBB/includes/acp/acp_ban.php b/phpBB/includes/acp/acp_ban.php index 00e68367fd..d881fc6bdc 100644 --- a/phpBB/includes/acp/acp_ban.php +++ b/phpBB/includes/acp/acp_ban.php @@ -175,12 +175,21 @@ class acp_ban } $result = $db->sql_query($sql); - $banned_options = ''; + $banned_options = $excluded_options = array(); $ban_length = $ban_reasons = $ban_give_reasons = array(); while ($row = $db->sql_fetchrow($result)) { - $banned_options .= '<option' . (($row['ban_exclude']) ? ' class="sep"' : '') . ' value="' . $row['ban_id'] . '">' . $row[$field] . '</option>'; + $option = '<option value="' . $row['ban_id'] . '">' . $row[$field] . '</option>'; + + if ($row['ban_exclude']) + { + $excluded_options[] = $option; + } + else + { + $banned_options[] = $option; + } $time_length = ($row['ban_end']) ? ($row['ban_end'] - $row['ban_start']) / 60 : 0; @@ -241,10 +250,25 @@ class acp_ban } } + $options = ''; + if ($excluded_options) + { + $options .= '<optgroup label="' . $user->lang['OPTIONS_EXCLUDED'] . '">'; + $options .= implode('', $excluded_options); + $options .= '</optgroup>'; + } + + if ($banned_options) + { + $options .= '<optgroup label="' . $user->lang['OPTIONS_BANNED'] . '">'; + $options .= implode('', $banned_options); + $options .= '</optgroup>'; + } + $template->assign_vars(array( 'S_BAN_END_OPTIONS' => $ban_end_options, - 'S_BANNED_OPTIONS' => ($banned_options) ? true : false, - 'BANNED_OPTIONS' => $banned_options) - ); + 'S_BANNED_OPTIONS' => ($banned_options || $excluded_options) ? true : false, + 'BANNED_OPTIONS' => $options, + )); } } diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index f27a133eb5..c99541ea7a 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -99,6 +99,7 @@ class acp_board 'load_cpf_pm' => array('lang' => 'LOAD_CPF_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), 'load_cpf_viewprofile' => array('lang' => 'LOAD_CPF_VIEWPROFILE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), 'load_cpf_viewtopic' => array('lang' => 'LOAD_CPF_VIEWTOPIC', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'load_jquery_cdn' => array('lang' => 'LOAD_JQUERY_CDN', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'legend3' => 'ACP_SUBMIT_CHANGES', ) @@ -189,7 +190,7 @@ class acp_board 'hot_threshold' => array('lang' => 'HOT_THRESHOLD', 'validate' => 'int:0', 'type' => 'text:3:4', 'explain' => true), 'max_poll_options' => array('lang' => 'MAX_POLL_OPTIONS', 'validate' => 'int:2:127', 'type' => 'text:4:4', 'explain' => false), 'max_post_chars' => array('lang' => 'CHAR_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:6', 'explain' => true), - 'min_post_chars' => array('lang' => 'MIN_CHAR_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:6', 'explain' => true), + 'min_post_chars' => array('lang' => 'MIN_CHAR_LIMIT', 'validate' => 'int:1', 'type' => 'text:4:6', 'explain' => true), 'max_post_smilies' => array('lang' => 'SMILIES_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true), 'max_post_urls' => array('lang' => 'MAX_POST_URLS', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true), 'max_post_font_size' => array('lang' => 'MAX_POST_FONT_SIZE', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' %'), @@ -235,7 +236,7 @@ class acp_board 'max_name_chars' => array('lang' => 'USERNAME_LENGTH', 'validate' => 'int:8:180', 'type' => false, 'method' => false, 'explain' => false,), 'max_pass_chars' => array('lang' => 'PASSWORD_LENGTH', 'validate' => 'int:8:255', 'type' => false, 'method' => false, 'explain' => false,), - 'require_activation' => array('lang' => 'ACC_ACTIVATION', 'validate' => 'int', 'type' => 'custom', 'method' => 'select_acc_activation', 'explain' => true), + 'require_activation' => array('lang' => 'ACC_ACTIVATION', 'validate' => 'int', 'type' => 'select', 'method' => 'select_acc_activation', 'explain' => true), 'new_member_post_limit' => array('lang' => 'NEW_MEMBER_POST_LIMIT', 'validate' => 'int:0:255', 'type' => 'text:4:4', 'explain' => true, 'append' => ' ' . $user->lang['POSTS']), 'new_member_group_default'=> array('lang' => 'NEW_MEMBER_GROUP_DEFAULT', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'min_name_chars' => array('lang' => 'USERNAME_LENGTH', 'validate' => 'int:1', 'type' => 'custom:5:180', 'method' => 'username_length', 'explain' => true), @@ -771,24 +772,28 @@ class acp_board /** * Select account activation method */ - function select_acc_activation($value, $key = '') + function select_acc_activation($selected_value, $value) { global $user, $config; - $radio_ary = array( - USER_ACTIVATION_DISABLE => 'ACC_DISABLE', - USER_ACTIVATION_NONE => 'ACC_NONE', + $act_ary = array( + 'ACC_DISABLE' => USER_ACTIVATION_DISABLE, + 'ACC_NONE' => USER_ACTIVATION_NONE, ); - if ($config['email_enable']) { - $radio_ary[USER_ACTIVATION_SELF] = 'ACC_USER'; - $radio_ary[USER_ACTIVATION_ADMIN] = 'ACC_ADMIN'; - } + $act_ary['ACC_USER'] = USER_ACTIVATION_SELF; + $act_ary['ACC_ADMIN'] = USER_ACTIVATION_ADMIN; + } + $act_options = ''; - $radio_text = h_radio('config[require_activation]', $radio_ary, $value, 'require_activation', $key, '<br />'); + foreach ($act_ary as $key => $value) + { + $selected = ($selected_value == $value) ? ' selected="selected"' : ''; + $act_options .= '<option value="' . $value . '"' . $selected . '>' . $user->lang[$key] . '</option>'; + } - return $radio_text; + return $act_options; } /** diff --git a/phpBB/includes/acp/acp_captcha.php b/phpBB/includes/acp/acp_captcha.php index bef8ae0ea9..f051781547 100644 --- a/phpBB/includes/acp/acp_captcha.php +++ b/phpBB/includes/acp/acp_captcha.php @@ -104,13 +104,13 @@ class acp_captcha foreach ($captchas['available'] as $value => $title) { $current = ($selected !== false && $value == $selected) ? ' selected="selected"' : ''; - $captcha_select .= '<option value="' . $value . '"' . $current . '>' . $user->lang[$title] . '</option>'; + $captcha_select .= '<option value="' . $value . '"' . $current . '>' . $user->lang($title) . '</option>'; } foreach ($captchas['unavailable'] as $value => $title) { $current = ($selected !== false && $value == $selected) ? ' selected="selected"' : ''; - $captcha_select .= '<option value="' . $value . '"' . $current . ' class="disabled-option">' . $user->lang[$title] . '</option>'; + $captcha_select .= '<option value="' . $value . '"' . $current . ' class="disabled-option">' . $user->lang($title) . '</option>'; } $demo_captcha = phpbb_captcha_factory::get_instance($selected); diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php index 632578ef2d..38d4d3c8e4 100644 --- a/phpBB/includes/acp/acp_database.php +++ b/phpBB/includes/acp/acp_database.php @@ -221,6 +221,7 @@ class acp_database case 'submit': $delete = request_var('delete', ''); $file = request_var('file', ''); + $download = request_var('download', ''); if (!preg_match('#^backup_\d{10,}_[a-z\d]{16}\.(sql(?:\.(?:gz|bz2))?)$#', $file, $matches)) { @@ -247,10 +248,8 @@ class acp_database confirm_box(false, $user->lang['DELETE_SELECTED_BACKUP'], build_hidden_fields(array('delete' => $delete, 'file' => $file))); } } - else + else if ($download || confirm_box(true)) { - $download = request_var('download', ''); - if ($download) { $name = $matches[0]; @@ -411,6 +410,10 @@ class acp_database trigger_error($user->lang['RESTORE_SUCCESS'] . adm_back_link($this->u_action)); break; } + else if (!$download) + { + confirm_box(false, $user->lang['RESTORE_SELECTED_BACKUP'], build_hidden_fields(array('file' => $file))); + } default: $methods = array('sql'); diff --git a/phpBB/includes/acp/acp_email.php b/phpBB/includes/acp/acp_email.php index b4755d3984..8812302601 100644 --- a/phpBB/includes/acp/acp_email.php +++ b/phpBB/includes/acp/acp_email.php @@ -136,8 +136,9 @@ class acp_email $i = $j = 0; - // Send with BCC, no more than 50 recipients for one mail (to not exceed the limit) - $max_chunk_size = 50; + // Send with BCC + // Maximum number of bcc recipients + $max_chunk_size = (int) $config['email_max_chunk_size']; $email_list = array(); $old_lang = $row['user_lang']; $old_notify_type = $row['user_notify_type']; @@ -194,10 +195,7 @@ class acp_email $messenger->template('admin_send_email', $used_lang); - $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); - $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); - $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); - $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + $messenger->anti_abuse_headers($config, $user); $messenger->subject(htmlspecialchars_decode($subject)); $messenger->set_mail_priority($priority); diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php index 854f262a0b..7fe8915ad1 100644 --- a/phpBB/includes/acp/acp_forums.php +++ b/phpBB/includes/acp/acp_forums.php @@ -212,15 +212,11 @@ class acp_forums $message = ($action == 'add') ? $user->lang['FORUM_CREATED'] : $user->lang['FORUM_UPDATED']; - // Redirect to permissions - if ($auth->acl_get('a_fauth') && !$copied_permissions) - { - $message .= '<br /><br />' . sprintf($user->lang['REDIRECT_ACL'], '<a href="' . append_sid("{$phpbb_admin_path}index.$phpEx", 'i=permissions' . $acl_url) . '">', '</a>'); - } - // redirect directly to permission settings screen if authed if ($action == 'add' && !$copied_permissions && $auth->acl_get('a_fauth')) { + $message .= '<br /><br />' . sprintf($user->lang['REDIRECT_ACL'], '<a href="' . append_sid("{$phpbb_admin_path}index.$phpEx", 'i=permissions' . $acl_url) . '">', '</a>'); + meta_refresh(4, append_sid("{$phpbb_admin_path}index.$phpEx", 'i=permissions' . $acl_url)); } diff --git a/phpBB/includes/acp/acp_groups.php b/phpBB/includes/acp/acp_groups.php index 221dea2345..98b0e4dc56 100644 --- a/phpBB/includes/acp/acp_groups.php +++ b/phpBB/includes/acp/acp_groups.php @@ -371,7 +371,7 @@ class acp_groups { if ($data['width'] > $config['avatar_max_width'] || $data['height'] > $config['avatar_max_height']) { - $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $data['width'], $data['height']); + $error[] = phpbb_avatar_error_wrong_size($data['width'], $data['height']); } } @@ -381,7 +381,7 @@ class acp_groups { if ($data['width'] < $config['avatar_min_width'] || $data['height'] < $config['avatar_min_height']) { - $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $data['width'], $data['height']); + $error[] = phpbb_avatar_error_wrong_size($data['width'], $data['height']); } } } @@ -627,7 +627,7 @@ class acp_groups 'U_BACK' => $u_back, 'U_SWATCH' => append_sid("{$phpbb_admin_path}swatch.$phpEx", 'form=settings&name=group_colour'), 'U_ACTION' => "{$this->u_action}&action=$action&g=$group_id", - 'L_AVATAR_EXPLAIN' => sprintf($user->lang['AVATAR_EXPLAIN'], $config['avatar_max_width'], $config['avatar_max_height'], round($config['avatar_filesize'] / 1024)), + 'L_AVATAR_EXPLAIN' => phpbb_avatar_explanation_string(), )); return; @@ -835,7 +835,7 @@ class acp_groups case 'set_config_teampage': set_config('teampage_forums', request_var('teampage_forums', 0)); - set_config('teampage_multiple', request_var('teampage_multiple', 0)); + set_config('teampage_memberships', request_var('teampage_memberships', 0)); break; case 'add': @@ -916,11 +916,11 @@ class acp_groups 'U_ACTION_LEGEND' => $this->u_action . '&field=legend', 'U_ACTION_TEAMPAGE' => $this->u_action . '&field=teampage', - 'S_GROUP_SELECT_LEGEND' => $s_group_select_legend, - 'S_GROUP_SELECT_TEAMPAGE' => $s_group_select_teampage, - 'DISPLAY_FORUMS' => ($config['teampage_forums']) ? true : false, - 'DISPLAY_MULTIPLE' => ($config['teampage_multiple']) ? true : false, - 'LEGEND_SORT_GROUPNAME' => ($config['legend_sort_groupname']) ? true : false, + 'S_GROUP_SELECT_LEGEND' => $s_group_select_legend, + 'S_GROUP_SELECT_TEAMPAGE' => $s_group_select_teampage, + 'DISPLAY_FORUMS' => ($config['teampage_forums']) ? true : false, + 'DISPLAY_MEMBERSHIPS' => $config['teampage_memberships'], + 'LEGEND_SORT_GROUPNAME' => ($config['legend_sort_groupname']) ? true : false, )); } } diff --git a/phpBB/includes/acp/acp_icons.php b/phpBB/includes/acp/acp_icons.php index c848039c66..e02124fb42 100644 --- a/phpBB/includes/acp/acp_icons.php +++ b/phpBB/includes/acp/acp_icons.php @@ -379,7 +379,7 @@ class acp_icons if ($smiley_count + $addable_smileys_count > SMILEY_LIMIT) { - trigger_error(sprintf($user->lang['TOO_MANY_SMILIES'], SMILEY_LIMIT) . adm_back_link($this->u_action), E_USER_WARNING); + trigger_error($user->lang('TOO_MANY_SMILIES', SMILEY_LIMIT) . adm_back_link($this->u_action), E_USER_WARNING); } } @@ -487,21 +487,7 @@ class acp_icons $cache->destroy('_icons'); $cache->destroy('sql', $table); - $level = E_USER_NOTICE; - switch ($icons_updated) - { - case 0: - $suc_lang = "{$lang}_NONE"; - $level = E_USER_WARNING; - break; - - case 1: - $suc_lang = "{$lang}_ONE"; - break; - - default: - $suc_lang = $lang; - } + $level = ($icons_updated) ? E_USER_NOTICE : E_USER_WARNING; $errormsgs = ''; foreach ($errors as $img => $error) { @@ -509,11 +495,11 @@ class acp_icons } if ($action == 'modify') { - trigger_error($user->lang[$suc_lang . '_EDITED'] . $errormsgs . adm_back_link($this->u_action), $level); + trigger_error($user->lang($lang . '_EDITED', $icons_updated) . $errormsgs . adm_back_link($this->u_action), $level); } else { - trigger_error($user->lang[$suc_lang . '_ADDED'] . $errormsgs . adm_back_link($this->u_action), $level); + trigger_error($user->lang($lang . '_ADDED', $icons_updated) . $errormsgs . adm_back_link($this->u_action), $level); } break; @@ -599,7 +585,7 @@ class acp_icons $smiley_count = $this->item_count($table); if ($smiley_count + sizeof($pak_ary) > SMILEY_LIMIT) { - trigger_error(sprintf($user->lang['TOO_MANY_SMILIES'], SMILEY_LIMIT) . adm_back_link($this->u_action), E_USER_WARNING); + trigger_error($user->lang('TOO_MANY_SMILIES', SMILEY_LIMIT) . adm_back_link($this->u_action), E_USER_WARNING); } } diff --git a/phpBB/includes/acp/acp_inactive.php b/phpBB/includes/acp/acp_inactive.php index 0e4801f630..8df11f053a 100644 --- a/phpBB/includes/acp/acp_inactive.php +++ b/phpBB/includes/acp/acp_inactive.php @@ -118,10 +118,7 @@ class acp_inactive $messenger->to($row['user_email'], $row['username']); - $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); - $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); - $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); - $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + $messenger->anti_abuse_headers($config, $user); $messenger->assign_vars(array( 'USERNAME' => htmlspecialchars_decode($row['username'])) @@ -209,10 +206,7 @@ class acp_inactive $messenger->to($row['user_email'], $row['username']); $messenger->im($row['user_jabber'], $row['username']); - $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); - $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); - $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); - $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + $messenger->anti_abuse_headers($config, $user); $messenger->assign_vars(array( 'USERNAME' => htmlspecialchars_decode($row['username']), diff --git a/phpBB/includes/acp/acp_language.php b/phpBB/includes/acp/acp_language.php index ffa8df1848..91b48f013e 100644 --- a/phpBB/includes/acp/acp_language.php +++ b/phpBB/includes/acp/acp_language.php @@ -869,6 +869,9 @@ class acp_language $default_lang_id = (int) $db->sql_fetchfield('lang_id'); $db->sql_freeresult($result); + // We want to notify the admin that custom profile fields need to be updated for the new language. + $notify_cpf_update = false; + // From the mysql documentation: // Prior to MySQL 4.0.14, the target table of the INSERT statement cannot appear in the FROM clause of the SELECT part of the query. This limitation is lifted in 4.0.14. // Due to this we stay on the safe side if we do the insertion "the manual way" @@ -882,6 +885,7 @@ class acp_language { $row['lang_id'] = $lang_id; $db->sql_query('INSERT INTO ' . PROFILE_LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $row)); + $notify_cpf_update = true; } $db->sql_freeresult($result); @@ -894,12 +898,15 @@ class acp_language { $row['lang_id'] = $lang_id; $db->sql_query('INSERT INTO ' . PROFILE_FIELDS_LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $row)); + $notify_cpf_update = true; } $db->sql_freeresult($result); add_log('admin', 'LOG_LANGUAGE_PACK_INSTALLED', $lang_pack['name']); - trigger_error(sprintf($user->lang['LANGUAGE_PACK_INSTALLED'], $lang_pack['name']) . adm_back_link($this->u_action)); + $message = sprintf($user->lang['LANGUAGE_PACK_INSTALLED'], $lang_pack['name']); + $message .= ($notify_cpf_update) ? '<br /><br />' . $user->lang['LANGUAGE_PACK_CPF_UPDATE'] : ''; + trigger_error($message . adm_back_link($this->u_action)); break; diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index a922ef570c..6304ff9d47 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -600,6 +600,17 @@ class acp_main $template->assign_var('S_WRITABLE_CONFIG', (bool) (@fileperms($phpbb_root_path . 'config.' . $phpEx) & 0x0002)); } + if (extension_loaded('mbstring')) + { + $template->assign_vars(array( + 'S_MBSTRING_LOADED' => true, + 'S_MBSTRING_FUNC_OVERLOAD_FAIL' => (intval(@ini_get('mbstring.func_overload')) & (MB_OVERLOAD_MAIL | MB_OVERLOAD_STRING)), + 'S_MBSTRING_ENCODING_TRANSLATION_FAIL' => (@ini_get('mbstring.encoding_translation') != 0), + 'S_MBSTRING_HTTP_INPUT_FAIL' => (@ini_get('mbstring.http_input') != 'pass'), + 'S_MBSTRING_HTTP_OUTPUT_FAIL' => (@ini_get('mbstring.http_output') != 'pass'), + )); + } + // Fill dbms version if not yet filled if (empty($config['dbms_version'])) { diff --git a/phpBB/includes/acp/acp_modules.php b/phpBB/includes/acp/acp_modules.php index 52033b590c..e51b440d4d 100644 --- a/phpBB/includes/acp/acp_modules.php +++ b/phpBB/includes/acp/acp_modules.php @@ -111,7 +111,7 @@ class acp_modules } break; - + case 'enable': case 'disable': if (!$module_id) @@ -170,7 +170,7 @@ class acp_modules add_log('admin', 'LOG_MODULE_' . strtoupper($action), $this->lang_name($row['module_langname']), $move_module_name); $this->remove_cache_file(); } - + break; case 'quickadd': @@ -207,7 +207,7 @@ class acp_modules if (!sizeof($errors)) { $this->remove_cache_file(); - + trigger_error($user->lang['MODULE_ADDED'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); } } @@ -231,7 +231,7 @@ class acp_modules { trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); } - + $module_row = $this->get_module_row($module_id); // no break @@ -250,7 +250,7 @@ class acp_modules 'module_auth' => '', ); } - + $module_data = array(); $module_data['module_basename'] = request_var('module_basename', (string) $module_row['module_basename']); @@ -295,7 +295,7 @@ class acp_modules if (!sizeof($errors)) { $this->remove_cache_file(); - + trigger_error((($action == 'add') ? $user->lang['MODULE_ADDED'] : $user->lang['MODULE_EDITED']) . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); } } @@ -316,7 +316,7 @@ class acp_modules } // Name options - $s_name_options .= '<option value="' . $option . '"' . (($option == $module_data['module_basename']) ? ' selected="selected"' : '') . '>' . $this->lang_name($values['title']) . ' [' . $this->module_class . '_' . $option . ']</option>'; + $s_name_options .= '<option value="' . $option . '"' . (($option == $module_data['module_basename']) ? ' selected="selected"' : '') . '>' . $this->lang_name($values['title']) . ' [' . $option . ']</option>'; $template->assign_block_vars('m_names', array('NAME' => $option, 'A_NAME' => addslashes($option))); @@ -327,7 +327,7 @@ class acp_modules { $s_mode_options .= '<option value="' . $m_mode . '"' . (($m_mode == $module_data['module_mode']) ? ' selected="selected"' : '') . '>' . $this->lang_name($m_values['title']) . '</option>'; } - + $template->assign_block_vars('m_names.modes', array( 'OPTION' => $m_mode, 'VALUE' => $this->lang_name($m_values['title']), @@ -336,7 +336,7 @@ class acp_modules ); } } - + $s_cat_option = '<option value="0"' . (($module_data['parent_id'] == 0) ? ' selected="selected"' : '') . '>' . $user->lang['NO_PARENT'] . '</option>'; $template->assign_vars(array_merge(array( @@ -349,7 +349,7 @@ class acp_modules 'U_EDIT_ACTION' => $this->u_action . '&parent_id=' . $this->parent_id, 'L_TITLE' => $user->lang[strtoupper($action) . '_MODULE'], - + 'MODULENAME' => $this->lang_name($module_data['module_langname']), 'ACTION' => $action, 'MODULE_ID' => $module_id, @@ -480,7 +480,7 @@ class acp_modules foreach ($module_infos as $option => $values) { // Name options - $s_install_options .= '<optgroup label="' . $this->lang_name($values['title']) . ' [' . $this->module_class . '_' . $option . ']">'; + $s_install_options .= '<optgroup label="' . $this->lang_name($values['title']) . ' [' . $option . ']">'; // Build module modes foreach ($values['modes'] as $m_mode => $m_values) @@ -516,7 +516,7 @@ class acp_modules $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - + if (!$row) { trigger_error($user->lang['NO_MODULE'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); @@ -524,14 +524,14 @@ class acp_modules return $row; } - + /** * Get available module information from module files */ function get_module_infos($module = '', $module_class = false) { global $phpbb_root_path, $phpEx; - + $module_class = ($module_class === false) ? $this->module_class : $module_class; $directory = $phpbb_root_path . 'includes/' . $module_class . '/info/'; @@ -539,57 +539,72 @@ class acp_modules if (!$module) { - $dh = @opendir($directory); + global $phpbb_extension_manager; - if (!$dh) - { - return $fileinfo; - } + $finder = $phpbb_extension_manager->get_finder(); + + $modules = $finder + ->extension_suffix('_module') + ->extension_directory("/$module_class") + ->core_path("includes/$module_class/info/") + ->core_prefix($module_class . '_') + ->get_classes(); - while (($file = readdir($dh)) !== false) + foreach ($modules as $module) { - // Is module? - if (preg_match('/^' . $module_class . '_.+\.' . $phpEx . '$/', $file)) - { - $class = str_replace(".$phpEx", '', $file) . '_info'; + $info_class = preg_replace('/_module$/', '_info', $module); - if (!class_exists($class)) + // If the class does not exist it might be following the old + // format. phpbb_acp_info_acp_foo needs to be turned into + // acp_foo_info and the respective file has to be included + // manually because it does not support auto loading + if (!class_exists($info_class)) + { + $info_class = str_replace("phpbb_{$module_class}_info_", '', $module) . '_info'; + if (file_exists($directory . $info_class . '.' . $phpEx)) { - include($directory . $file); + include($directory . $info_class . '.' . $phpEx); } + } - // Get module title tag - if (class_exists($class)) - { - $c_class = new $class(); - $module_info = $c_class->module(); - $fileinfo[str_replace($module_class . '_', '', $module_info['filename'])] = $module_info; - } + if (class_exists($info_class)) + { + $info = new $info_class(); + $module_info = $info->module(); + + $main_class = (isset($module_info['filename'])) ? $module_info['filename'] : $module; + + $fileinfo[$main_class] = $module_info; } } - closedir($dh); ksort($fileinfo); } else { - $filename = $module_class . '_' . basename($module); - $class = $module_class . '_' . basename($module) . '_info'; + $info_class = preg_replace('/_module$/', '_info', $module); - if (!class_exists($class)) + if (!class_exists($info_class)) { - include($directory . $filename . '.' . $phpEx); + if (file_exists($directory . $module . '.' . $phpEx)) + { + include($directory . $module . '.' . $phpEx); + } + $info_class = $module . '_info'; } // Get module title tag - if (class_exists($class)) + if (class_exists($info_class)) { - $c_class = new $class(); - $module_info = $c_class->module(); - $fileinfo[str_replace($module_class . '_', '', $module_info['filename'])] = $module_info; + $info = new $info_class(); + $module_info = $info->module(); + + $main_class = (isset($module_info['filename'])) ? $module_info['filename'] : $module; + + $fileinfo[$main_class] = $module_info; } } - + return $fileinfo; } @@ -721,7 +736,7 @@ class acp_modules // Sanitise for future path use, it's escaped as appropriate for queries $p_class = str_replace(array('.', '/', '\\'), '', basename($this->module_class)); - + $cache->destroy('_modules_' . $p_class); // Additionally remove sql cache diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index a3061ae2da..2de76187d5 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -77,7 +77,8 @@ class acp_search continue; } - $name = ucfirst(strtolower(str_replace('_', ' ', $type))); + $name = $search->get_name(); + $selected = ($config['search_type'] == $type) ? ' selected="selected"' : ''; $search_options .= '<option value="' . $type . '"' . $selected . '>' . $name . '</option>'; @@ -275,7 +276,7 @@ class acp_search { trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); } - $name = ucfirst(strtolower(str_replace('_', ' ', $this->state[0]))); + $name = $this->search->get_name(); $action = &$this->state[1]; @@ -337,7 +338,7 @@ class acp_search $totaltime = $mtime[0] + $mtime[1] - $starttime; $rows_per_second = $row_count / $totaltime; meta_refresh(1, append_sid($this->u_action . '&action=delete&skip_rows=' . $post_counter)); - trigger_error(sprintf($user->lang['SEARCH_INDEX_DELETE_REDIRECT'], $post_counter, $row_count, $rows_per_second)); + trigger_error($user->lang('SEARCH_INDEX_DELETE_REDIRECT', (int) $row_count, $post_counter, $rows_per_second)); } } @@ -427,7 +428,7 @@ class acp_search $totaltime = $mtime[0] + $mtime[1] - $starttime; $rows_per_second = $row_count / $totaltime; meta_refresh(1, append_sid($this->u_action . '&action=create&skip_rows=' . $post_counter)); - trigger_error(sprintf($user->lang['SEARCH_INDEX_CREATE_REDIRECT'], $post_counter, $row_count, $rows_per_second)); + trigger_error($user->lang('SEARCH_INDEX_CREATE_REDIRECT', (int) $row_count, $post_counter) . $user->lang('SEARCH_INDEX_CREATE_REDIRECT_RATE', $rows_per_second)); } } @@ -454,7 +455,7 @@ class acp_search continue; } - $name = ucfirst(strtolower(str_replace('_', ' ', $type))); + $name = $search->get_name(); $data = array(); if (method_exists($search, 'index_stats')) @@ -553,27 +554,15 @@ class acp_search function get_search_types() { - global $phpbb_root_path, $phpEx; - - $search_types = array(); - - $dp = @opendir($phpbb_root_path . 'includes/search'); - - if ($dp) - { - while (($file = readdir($dp)) !== false) - { - if ((preg_match('#\.' . $phpEx . '$#', $file)) && ($file != "search.$phpEx")) - { - $search_types[] = preg_replace('#^(.*?)\.' . $phpEx . '$#', '\1', $file); - } - } - closedir($dp); + global $phpbb_root_path, $phpEx, $phpbb_extension_manager; - sort($search_types); - } + $finder = $phpbb_extension_manager->get_finder(); - return $search_types; + return $finder + ->extension_suffix('_backend') + ->extension_directory('/search') + ->core_path('includes/search/') + ->get_classes(); } function get_max_post_id() @@ -610,15 +599,7 @@ class acp_search { global $phpbb_root_path, $phpEx, $user; - if (!preg_match('#^\w+$#', $type) || !file_exists("{$phpbb_root_path}includes/search/$type.$phpEx")) - { - $error = $user->lang['NO_SUCH_SEARCH_MODULE']; - return $error; - } - - include_once("{$phpbb_root_path}includes/search/$type.$phpEx"); - - if (!class_exists($type)) + if (!class_exists($type) || !method_exists($type, 'get_name')) { $error = $user->lang['NO_SUCH_SEARCH_MODULE']; return $error; diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 9bcf1b20db..c1ad28ca14 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -348,10 +348,7 @@ class acp_users $messenger->to($user_row['user_email'], $user_row['username']); - $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); - $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); - $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); - $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + $messenger->anti_abuse_headers($config, $user); $messenger->assign_vars(array( 'WELCOME_MSG' => htmlspecialchars_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename'])), @@ -406,10 +403,7 @@ class acp_users $messenger->to($user_row['user_email'], $user_row['username']); - $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); - $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); - $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); - $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + $messenger->anti_abuse_headers($config, $user); $messenger->assign_vars(array( 'USERNAME' => htmlspecialchars_decode($user_row['username'])) @@ -818,7 +812,7 @@ class acp_users // Which updates do we need to do? $update_username = ($user_row['username'] != $data['username']) ? $data['username'] : false; - $update_password = ($data['new_password'] && !phpbb_check_hash($user_row['user_password'], $data['new_password'])) ? true : false; + $update_password = ($data['new_password'] && !phpbb_check_hash($data['new_password'], $user_row['user_password'])) ? true : false; $update_email = ($data['email'] != $user_row['user_email']) ? $data['email'] : false; if (!sizeof($error)) @@ -1016,8 +1010,8 @@ class acp_users $db->sql_freeresult($result); $template->assign_vars(array( - 'L_NAME_CHARS_EXPLAIN' => sprintf($user->lang[$config['allow_name_chars'] . '_EXPLAIN'], $config['min_name_chars'], $config['max_name_chars']), - 'L_CHANGE_PASSWORD_EXPLAIN' => sprintf($user->lang[$config['pass_complex'] . '_EXPLAIN'], $config['min_pass_chars'], $config['max_pass_chars']), + 'L_NAME_CHARS_EXPLAIN' => $user->lang($config['allow_name_chars'] . '_EXPLAIN', $user->lang('CHARACTERS', (int) $config['min_name_chars']), $user->lang('CHARACTERS', (int) $config['max_name_chars'])), + 'L_CHANGE_PASSWORD_EXPLAIN' => $user->lang($config['pass_complex'] . '_EXPLAIN', $user->lang('CHARACTERS', (int) $config['min_pass_chars']), $user->lang('CHARACTERS', (int) $config['max_pass_chars'])), 'L_POSTS_IN_QUEUE' => $user->lang('NUM_POSTS_IN_QUEUE', $user_row['posts_in_queue']), 'S_FOUNDER' => ($user->data['user_type'] == USER_FOUNDER) ? true : false, @@ -1754,8 +1748,8 @@ class acp_users 'USER_AVATAR_WIDTH' => $user_row['user_avatar_width'], 'USER_AVATAR_HEIGHT' => $user_row['user_avatar_height'], - 'L_AVATAR_EXPLAIN' => sprintf($user->lang['AVATAR_EXPLAIN'], $config['avatar_max_width'], $config['avatar_max_height'], round($config['avatar_filesize'] / 1024))) - ); + 'L_AVATAR_EXPLAIN' => phpbb_avatar_explanation_string(), + )); break; @@ -1887,7 +1881,7 @@ class acp_users 'FLASH_STATUS' => ($config['allow_sig_flash']) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], 'URL_STATUS' => ($config['allow_sig_links']) ? $user->lang['URL_IS_ON'] : $user->lang['URL_IS_OFF'], - 'L_SIGNATURE_EXPLAIN' => sprintf($user->lang['SIGNATURE_EXPLAIN'], $config['max_sig_chars']), + 'L_SIGNATURE_EXPLAIN' => $user->lang('SIGNATURE_EXPLAIN', (int) $config['max_sig_chars']), 'S_BBCODE_ALLOWED' => $config['allow_sig_bbcode'], 'S_SMILIES_ALLOWED' => $config['allow_sig_smilies'], diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php index c3367fbd46..929ea45c9b 100644 --- a/phpBB/includes/bbcode.php +++ b/phpBB/includes/bbcode.php @@ -127,14 +127,15 @@ class bbcode */ function bbcode_cache_init() { - global $phpbb_root_path, $phpEx, $config, $user; + global $phpbb_root_path, $phpEx, $config, $user, $phpbb_extension_manager; if (empty($this->template_filename)) { $this->template_bitfield = new bitfield($user->theme['bbcode_bitfield']); $template_locator = new phpbb_template_locator(); - $template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $template_locator); + $template_path_provider = new phpbb_template_extension_path_provider($phpbb_extension_manager, new phpbb_template_path_provider()); + $template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $template_locator, $template_path_provider); $template->set_template(); $template_locator->set_filenames(array('bbcode.html' => 'bbcode.html')); $this->template_filename = $template_locator->get_source_file_for_handle('bbcode.html'); diff --git a/phpBB/includes/captcha/captcha_factory.php b/phpBB/includes/captcha/captcha_factory.php index c2ec8c5bda..e039e92054 100644 --- a/phpBB/includes/captcha/captcha_factory.php +++ b/phpBB/includes/captcha/captcha_factory.php @@ -59,38 +59,38 @@ class phpbb_captcha_factory */ function get_captcha_types() { - global $phpbb_root_path, $phpEx; + global $phpbb_root_path, $phpEx, $phpbb_extension_manager; $captchas = array( 'available' => array(), 'unavailable' => array(), ); - $dp = @opendir($phpbb_root_path . 'includes/captcha/plugins'); + $finder = $phpbb_extension_manager->get_finder(); + $captcha_plugin_classes = $finder + ->extension_directory('/captcha') + ->suffix('_plugin') + ->core_path('includes/captcha/plugins/') + ->get_classes(); - if ($dp) + foreach ($captcha_plugin_classes as $class) { - while (($file = readdir($dp)) !== false) + // check if this class needs to be loaded in legacy mode + $old_class = preg_replace('/^phpbb_captcha_plugins_/', '', $class); + if (file_exists($phpbb_root_path . "includes/captcha/plugins/$old_class.$phpEx") && !class_exists($old_class)) { - if ((preg_match('#_plugin\.' . $phpEx . '$#', $file))) - { - $name = preg_replace('#^(.*?)_plugin\.' . $phpEx . '$#', '\1', $file); - if (!class_exists($name)) - { - include($phpbb_root_path . "includes/captcha/plugins/$file"); - } + include($phpbb_root_path . "includes/captcha/plugins/$old_class.$phpEx"); + $class = preg_replace('/_plugin$/', '', $old_class); + } - if (call_user_func(array($name, 'is_available'))) - { - $captchas['available'][$name] = call_user_func(array($name, 'get_name')); - } - else - { - $captchas['unavailable'][$name] = call_user_func(array($name, 'get_name')); - } - } + if (call_user_func(array($class, 'is_available'))) + { + $captchas['available'][$class] = call_user_func(array($class, 'get_name')); + } + else + { + $captchas['unavailable'][$class] = call_user_func(array($class, 'get_name')); } - closedir($dp); } return $captchas; diff --git a/phpBB/includes/captcha/plugins/captcha_abstract.php b/phpBB/includes/captcha/plugins/captcha_abstract.php index aea39b3123..07a0ea1279 100644 --- a/phpBB/includes/captcha/plugins/captcha_abstract.php +++ b/phpBB/includes/captcha/plugins/captcha_abstract.php @@ -22,7 +22,7 @@ if (!defined('IN_PHPBB')) * * @package VC */ -class phpbb_default_captcha +class phpbb_captcha_plugins_captcha_abstract { var $confirm_id; var $confirm_code; @@ -364,3 +364,10 @@ class phpbb_default_captcha } } + +/** +* Old class name for legacy use. The new class name is auto loadable. +*/ +class phpbb_default_captcha extends phpbb_captcha_plugins_captcha_abstract +{ +} diff --git a/phpBB/includes/class_loader.php b/phpBB/includes/class_loader.php index a28d745983..bc268d342e 100644 --- a/phpBB/includes/class_loader.php +++ b/phpBB/includes/class_loader.php @@ -31,22 +31,32 @@ if (!defined('IN_PHPBB')) */ class phpbb_class_loader { - private $phpbb_root_path; + private $prefix; + private $path; private $php_ext; private $cache; + + /** + * A map of looked up class names to paths relative to $this->path. + * This map is stored in cache and looked up if the cache is available. + * + * @var array + */ private $cached_paths = array(); /** * Creates a new phpbb_class_loader, which loads files with the given - * file extension from the given phpbb root path. + * file extension from the given path. * - * @param string $phpbb_root_path phpBB's root directory containing includes/ - * @param string $php_ext The file extension for PHP files + * @param string $prefix Required class name prefix for files to be loaded + * @param string $path Directory to load files from + * @param string $php_ext The file extension for PHP files * @param phpbb_cache_driver_interface $cache An implementation of the phpBB cache interface. */ - public function __construct($phpbb_root_path, $php_ext = '.php', phpbb_cache_driver_interface $cache = null) + public function __construct($prefix, $path, $php_ext = '.php', phpbb_cache_driver_interface $cache = null) { - $this->phpbb_root_path = $phpbb_root_path; + $this->prefix = $prefix; + $this->path = $path; $this->php_ext = $php_ext; $this->set_cache($cache); @@ -63,7 +73,7 @@ class phpbb_class_loader { if ($cache) { - $this->cached_paths = $cache->get('class_loader'); + $this->cached_paths = $cache->get('class_loader_' . $this->prefix); if ($this->cached_paths === false) { @@ -100,23 +110,21 @@ class phpbb_class_loader */ public function resolve_path($class) { - $path_prefix = $this->phpbb_root_path . 'includes/'; - if (isset($this->cached_paths[$class])) { - return $path_prefix . $this->cached_paths[$class] . $this->php_ext; + return $this->path . $this->cached_paths[$class] . $this->php_ext; } - if (!preg_match('/phpbb_[a-zA-Z0-9_]+/', $class)) + if (!preg_match('/^' . $this->prefix . '[a-zA-Z0-9_]+$/', $class)) { return false; } - $parts = explode('_', substr($class, 6)); + $parts = explode('_', substr($class, strlen($this->prefix))); $dirs = ''; - for ($i = 0, $n = sizeof($parts); $i < $n && is_dir($path_prefix . $dirs . $parts[$i]); $i++) + for ($i = 0, $n = sizeof($parts); $i < $n && is_dir($this->path . $dirs . $parts[$i]); $i++) { $dirs .= $parts[$i] . '/'; } @@ -129,7 +137,7 @@ class phpbb_class_loader $relative_path = $dirs . implode(array_slice($parts, $i, sizeof($parts) - $i), '_'); - if (!file_exists($path_prefix . $relative_path . $this->php_ext)) + if (!file_exists($this->path . $relative_path . $this->php_ext)) { return false; } @@ -137,10 +145,10 @@ class phpbb_class_loader if ($this->cache) { $this->cached_paths[$class] = $relative_path; - $this->cache->put('class_loader', $this->cached_paths); + $this->cache->put('class_loader_' . $this->prefix, $this->cached_paths); } - return $path_prefix . $relative_path . $this->php_ext; + return $this->path . $relative_path . $this->php_ext; } /** @@ -150,7 +158,7 @@ class phpbb_class_loader */ public function load_class($class) { - if (substr($class, 0, 6) === 'phpbb_') + if (substr($class, 0, strlen($this->prefix)) === $this->prefix) { $path = $this->resolve_path($class); diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index 8ef1a4655d..d5b398b7bf 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -226,6 +226,7 @@ define('CONFIG_TABLE', $table_prefix . 'config'); define('CONFIRM_TABLE', $table_prefix . 'confirm'); define('DISALLOW_TABLE', $table_prefix . 'disallow'); define('DRAFTS_TABLE', $table_prefix . 'drafts'); +define('EXT_TABLE', $table_prefix . 'ext'); define('EXTENSIONS_TABLE', $table_prefix . 'extensions'); define('EXTENSION_GROUPS_TABLE', $table_prefix . 'extension_groups'); define('FORUMS_TABLE', $table_prefix . 'forums'); diff --git a/phpBB/includes/cron/manager.php b/phpBB/includes/cron/manager.php index 31be1a69cb..a0bf018b33 100644 --- a/phpBB/includes/cron/manager.php +++ b/phpBB/includes/cron/manager.php @@ -33,137 +33,24 @@ class phpbb_cron_manager protected $tasks = array(); /** - * Path to the root of directory tree with tasks. - * For bundled phpBB tasks, this is the path to includes/cron/tasks - * under phpBB root. - * @var string - */ - protected $task_path; - - /** - * PHP file extension - * @var string - */ - protected $phpEx; - - /** - * Cache driver - * @var phpbb_cache_driver_interface - */ - protected $cache; - - /** * Constructor. Loads all available tasks. * - * Tasks will be looked up in directory tree rooted at $task_path. - * Task classes will be autoloaded and must be named according to - * autoloading naming conventions. To load cron tasks shipped with - * phpbb, pass $phpbb_root_path . 'includes/cron/task' as $task_path. - * - * If $cache is given, names of found cron tasks will be cached in it - * for one hour. Note that the cron task names are stored without - * namespacing; if two different phbb_cron_manager instances are - * constructed with different $task_path arguments but the same $cache, - * the second instance will use task names found by the first instance. - * - * @param string $task_path Directory containing cron tasks - * @param string $phpEx PHP file extension - * @param phpbb_cache_driver_interface $cache Cache for task names (optional) - * @return void + * @param array|Traversable $task_names Provides an iterable set of task names */ - public function __construct($task_path, $phpEx, phpbb_cache_driver_interface $cache = null) + public function __construct($task_names) { - if (DIRECTORY_SEPARATOR != '/') - { - // Need this on some platforms since the code elsewhere uses / - // to separate directory components, but PHP iterators return - // paths with platform-specific directory separators. - $task_path = str_replace('/', DIRECTORY_SEPARATOR, $task_path); - } - - $this->task_path = $task_path; - $this->phpEx = $phpEx; - $this->cache = $cache; - - $task_names = $this->find_cron_task_names(); $this->load_tasks($task_names); } /** - * Finds cron task names. - * - * A cron task file must follow the naming convention: - * includes/cron/task/$mod/$name.php. - * $mod is core for tasks that are part of phpbb. - * Modifications should use their name as $mod. - * $name is the name of the cron task. - * Cron task is expected to be a class named phpbb_cron_task_${mod}_${name}. - * - * @return array List of task names - */ - public function find_cron_task_names() - { - if ($this->cache) - { - $task_names = $this->cache->get('_cron_tasks'); - - if ($task_names !== false) - { - return $task_names; - } - } - - $task_names = array(); - $ext = '.' . $this->phpEx; - $ext_length = strlen($ext); - - $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->task_path)); - - foreach ($iterator as $fileinfo) - { - $file = preg_replace('#^' . preg_quote($this->task_path, '#') . '#', '', $fileinfo->getPathname()); - - // skip directories and files direclty in the task root path - if ($fileinfo->isFile() && strpos($file, DIRECTORY_SEPARATOR) !== false) - { - $task_name = str_replace(DIRECTORY_SEPARATOR, '_', substr($file, 0, -$ext_length)); - if (substr($file, -$ext_length) == $ext && $this->is_valid_name($task_name)) - { - $task_names[] = 'phpbb_cron_task_' . $task_name; - } - } - } - - if ($this->cache) - { - $this->cache->put('_cron_tasks', $task_names, 3600); - } - - return $task_names; - } - - /** - * Checks whether $name is a valid identifier, and - * therefore part of valid cron task class name. - * - * @param string $name Name to check - * - * @return bool - */ - public function is_valid_name($name) - { - return (bool) preg_match('/^[a-zA-Z][a-zA-Z0-9_]*$/', $name); - } - - /** * Loads tasks given by name, wraps them * and puts them into $this->tasks. * - * @param array $task_names Array of strings + * @param array|Traversable $task_names Array of strings * * @return void */ - public function load_tasks(array $task_names) + public function load_tasks($task_names) { foreach ($task_names as $task_name) { diff --git a/phpBB/includes/cron/task/provider.php b/phpBB/includes/cron/task/provider.php new file mode 100644 index 0000000000..e6ae0f75ec --- /dev/null +++ b/phpBB/includes/cron/task/provider.php @@ -0,0 +1,48 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Provides cron manager with tasks +* +* Finds installed cron tasks and makes them available to the cron manager. +* +* @package phpBB3 +*/ +class phpbb_cron_task_provider extends phpbb_extension_provider +{ + /** + * Finds cron task names using the extension manager. + * + * All PHP files in includes/cron/task/core/ are considered tasks. Tasks + * in extensions have to be located in a directory called cron or a subdir + * of a directory called cron. The class and filename must end in a _task + * suffix. Additionally all PHP files in includes/cron/task/core/ are + * tasks. + * + * @return array List of task names + */ + protected function find() + { + $finder = $this->extension_manager->get_finder(); + + return $finder + ->extension_suffix('_task') + ->extension_directory('/cron') + ->core_path('includes/cron/task/core/') + ->get_classes(); + } +} diff --git a/phpBB/includes/db/dbal.php b/phpBB/includes/db/dbal.php index a61dc5f58a..4f33a22a09 100644 --- a/phpBB/includes/db/dbal.php +++ b/phpBB/includes/db/dbal.php @@ -631,7 +631,7 @@ class dbal } } - $sql .= $this->_sql_custom_build('FROM', implode(', ', $table_array)); + $sql .= $this->_sql_custom_build('FROM', implode(' CROSS JOIN ', $table_array)); if (!empty($array['LEFT_JOIN'])) { diff --git a/phpBB/includes/extension/base.php b/phpBB/includes/extension/base.php new file mode 100644 index 0000000000..d9159d57d2 --- /dev/null +++ b/phpBB/includes/extension/base.php @@ -0,0 +1,57 @@ +<?php +/** +* +* @package extension +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* A base class for extensions without custom enable/disable/purge code. +* +* @package extension +*/ +class phpbb_extension_base implements phpbb_extension_interface +{ + /** + * Single enable step that does nothing + * + * @param mixed $old_state State returned by previous call of this method + * @return false Indicates no further steps are required + */ + public function enable_step($old_state) + { + return false; + } + + /** + * Single disable step that does nothing + * + * @param mixed $old_state State returned by previous call of this method + * @return false Indicates no further steps are required + */ + public function disable_step($old_state) + { + return false; + } + + /** + * Single purge step that does nothing + * + * @param mixed $old_state State returned by previous call of this method + * @return false Indicates no further steps are required + */ + public function purge_step($old_state) + { + return false; + } +} diff --git a/phpBB/includes/extension/finder.php b/phpBB/includes/extension/finder.php new file mode 100644 index 0000000000..f4a0b7a371 --- /dev/null +++ b/phpBB/includes/extension/finder.php @@ -0,0 +1,422 @@ +<?php +/** +* +* @package extension +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* The extension finder provides a simple way to locate files in active extensions +* +* @package extension +*/ +class phpbb_extension_finder +{ + protected $extension_manager; + protected $phpbb_root_path; + protected $cache; + protected $phpEx; + + /** + * The cache variable name used to store $this->cached_queries in $this->cache. + * + * Allows the use of multiple differently configured finders with the same cache. + * @var string + */ + protected $cache_name; + + /** + * An associative array, containing all search parameters set in methods. + * @var array + */ + protected $query; + + /** + * A map from md5 hashes of serialized queries to their previously retrieved + * results. + * @var array + */ + protected $cached_queries; + + /** + * Creates a new finder instance with its dependencies + * + * @param phpbb_extension_manager $extension_manager An extension manager + * instance that provides the finder with a list of active + * extensions and their locations + * @param string $phpbb_root_path Path to the phpbb root directory + * @param phpbb_cache_driver_interface $cache A cache instance or null + * @param string $phpEx php file extension + * @param string $cache_name The name of the cache variable, defaults to + * _ext_finder + */ + public function __construct(phpbb_extension_manager $extension_manager, $phpbb_root_path = '', phpbb_cache_driver_interface $cache = null, $phpEx = '.php', $cache_name = '_ext_finder') + { + $this->extension_manager = $extension_manager; + $this->phpbb_root_path = $phpbb_root_path; + $this->cache = $cache; + $this->phpEx = $phpEx; + $this->cache_name = $cache_name; + + $this->query = array( + 'core_path' => false, + 'core_suffix' => false, + 'core_prefix' => false, + 'core_directory' => false, + 'extension_suffix' => false, + 'extension_prefix' => false, + 'extension_directory' => false, + ); + + $this->cached_queries = ($this->cache) ? $this->cache->get($this->cache_name) : false; + } + + /** + * Sets a core path to be searched in addition to extensions + * + * @param string $core_path The path relative to phpbb_root_path + * @return phpbb_extension_finder This object for chaining calls + */ + public function core_path($core_path) + { + $this->query['core_path'] = $core_path; + return $this; + } + + /** + * Sets the suffix all files found in extensions and core must match. + * + * There is no default file extension, so to find PHP files only, you will + * have to specify .php as a suffix. However when using get_classes, the .php + * file extension is automatically added to suffixes. + * + * @param string $suffix A filename suffix + * @return phpbb_extension_finder This object for chaining calls + */ + public function suffix($suffix) + { + $this->core_suffix($suffix); + $this->extension_suffix($suffix); + return $this; + } + + /** + * Sets a suffix all files found in extensions must match + * + * There is no default file extension, so to find PHP files only, you will + * have to specify .php as a suffix. However when using get_classes, the .php + * file extension is automatically added to suffixes. + * + * @param string $extension_suffix A filename suffix + * @return phpbb_extension_finder This object for chaining calls + */ + public function extension_suffix($extension_suffix) + { + $this->query['extension_suffix'] = $extension_suffix; + return $this; + } + + /** + * Sets a suffix all files found in the core path must match + * + * There is no default file extension, so to find PHP files only, you will + * have to specify .php as a suffix. However when using get_classes, the .php + * file extension is automatically added to suffixes. + * + * @param string $core_suffix A filename suffix + * @return phpbb_extension_finder This object for chaining calls + */ + public function core_suffix($core_suffix) + { + $this->query['core_suffix'] = $core_suffix; + return $this; + } + + /** + * Sets the prefix all files found in extensions and core must match + * + * @param string $prefix A filename prefix + * @return phpbb_extension_finder This object for chaining calls + */ + public function prefix($prefix) + { + $this->core_prefix($prefix); + $this->extension_prefix($prefix); + return $this; + } + + /** + * Sets a prefix all files found in extensions must match + * + * @param string $extension_prefix A filename prefix + * @return phpbb_extension_finder This object for chaining calls + */ + public function extension_prefix($extension_prefix) + { + $this->query['extension_prefix'] = $extension_prefix; + return $this; + } + + /** + * Sets a prefix all files found in the core path must match + * + * @param string $core_prefix A filename prefix + * @return phpbb_extension_finder This object for chaining calls + */ + public function core_prefix($core_prefix) + { + $this->query['core_prefix'] = $core_prefix; + return $this; + } + + /** + * Sets a directory all files found in extensions and core must be contained in + * + * Automatically sets the core_directory if its value does not differ from + * the current directory. + * + * @param string $directory + * @return phpbb_extension_finder This object for chaining calls + */ + public function directory($directory) + { + $this->core_directory($directory); + $this->extension_directory($directory); + return $this; + } + + /** + * Sets a directory all files found in extensions must be contained in + * + * @param string $extension_directory + * @return phpbb_extension_finder This object for chaining calls + */ + public function extension_directory($extension_directory) + { + $this->query['extension_directory'] = $this->sanitise_directory($extension_directory); + return $this; + } + + /** + * Sets a directory all files found in the core path must be contained in + * + * @param string $core_directory + * @return phpbb_extension_finder This object for chaining calls + */ + public function core_directory($core_directory) + { + $this->query['core_directory'] = $this->sanitise_directory($core_directory); + return $this; + } + + /** + * Removes occurances of /./ and makes sure path ends without trailing slash + * + * @param string $directory A directory pattern + * @return string A cleaned up directory pattern + */ + protected function sanitise_directory($directory) + { + $directory = preg_replace('#(?:^|/)\./#', '/', $directory); + $dir_len = strlen($directory); + + if ($dir_len > 1 && $directory[$dir_len - 1] === '/') + { + $directory = substr($directory, 0, -1); + } + + return $directory; + } + + /** + * Finds classes matching the configured options if they follow phpBB naming rules. + * + * The php file extension is automatically added to suffixes. + * + * Note: If a file is matched but contains a class name not following the + * phpBB naming rules an incorrect class name will be returned. + * + * @param bool $cache Whether the result should be cached + * @return array An array of found class names + */ + public function get_classes($cache = true) + { + $this->query['extension_suffix'] .= $this->phpEx; + $this->query['core_suffix'] .= $this->phpEx; + + $files = $this->find($cache, false); + + $classes = array(); + foreach ($files as $file => $ext_name) + { + $file = preg_replace('#^includes/#', '', $file); + + $classes[] = 'phpbb_' . str_replace('/', '_', substr($file, 0, -strlen($this->phpEx))); + } + return $classes; + } + + /** + * Finds all directories matching the configured options + * + * @param bool $cache Whether the result should be cached + * @return array An array of paths to found directories + */ + public function get_directories($cache = true) + { + return $this->find_with_root_path($cache, true); + } + + /** + * Finds all files matching the configured options. + * + * @param bool $cache Whether the result should be cached + * @return array An array of paths to found files + */ + public function get_files($cache = true) + { + return $this->find_with_root_path($cache, false); + } + + /** + * A wrapper around the general find which prepends a root path to results + * + * @param bool $cache Whether the result should be cached + * @param bool $is_dir Directories will be returned when true, only files + * otherwise + * @return array An array of paths to found items + */ + protected function find_with_root_path($cache = true, $is_dir = false) + { + $items = $this->find($cache, $is_dir); + + $result = array(); + foreach ($items as $item => $ext_name) + { + $result[] = $this->phpbb_root_path . $item; + } + + return $result; + } + + /** + * Finds all file system entries matching the configured options + * + * @param bool $cache Whether the result should be cached + * @param bool $is_dir Directories will be returned when true, only files + * otherwise + * @return array An array of paths to found items + */ + public function find($cache = true, $is_dir = false) + { + $this->query['is_dir'] = $is_dir; + $query = md5(serialize($this->query)); + + if (!defined('DEBUG') && $cache && isset($this->cached_queries[$query])) + { + return $this->cached_queries[$query]; + } + + $files = array(); + + $extensions = $this->extension_manager->all_enabled(); + + if ($this->query['core_path']) + { + $extensions['/'] = $this->phpbb_root_path . $this->query['core_path']; + } + + foreach ($extensions as $name => $path) + { + $ext_name = $name; + + if (!file_exists($path)) + { + continue; + } + + if ($name === '/') + { + $location = $this->query['core_path']; + $name = ''; + $suffix = $this->query['core_suffix']; + $prefix = $this->query['core_prefix']; + $directory = $this->query['core_directory']; + } + else + { + $location = 'ext/'; + $name .= '/'; + $suffix = $this->query['extension_suffix']; + $prefix = $this->query['extension_prefix']; + $directory = $this->query['extension_directory']; + } + + // match only first directory if leading slash is given + if ($directory === '/') + { + $directory_pattern = '^' . preg_quote(DIRECTORY_SEPARATOR, '#'); + } + else if ($directory && $directory[0] === '/') + { + $directory_pattern = '^' . preg_quote(str_replace('/', DIRECTORY_SEPARATOR, $directory) . DIRECTORY_SEPARATOR, '#'); + } + else + { + $directory_pattern = preg_quote(DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $directory) . DIRECTORY_SEPARATOR, '#'); + } + $directory_pattern = '#' . $directory_pattern . '#'; + + $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST); + foreach ($iterator as $file_info) + { + $filename = $file_info->getFilename(); + if ($filename == '.' || $filename == '..') + { + continue; + } + + if ($file_info->isDir() == $is_dir) + { + if ($is_dir) + { + $relative_path = $iterator->getInnerIterator()->getSubPath() . DIRECTORY_SEPARATOR . basename($filename) . DIRECTORY_SEPARATOR; + if ($relative_path[0] !== DIRECTORY_SEPARATOR) + { + $relative_path = DIRECTORY_SEPARATOR . $relative_path; + } + } + else + { + $relative_path = DIRECTORY_SEPARATOR . $iterator->getInnerIterator()->getSubPathname(); + } + + if ((!$suffix || substr($relative_path, -strlen($suffix)) === $suffix) && + (!$prefix || substr($filename, 0, strlen($prefix)) === $prefix) && + (!$directory || preg_match($directory_pattern, $relative_path))) + { + $files[str_replace(DIRECTORY_SEPARATOR, '/', $location . $name . substr($relative_path, 1))] = $ext_name; + } + } + } + } + + if ($cache && $this->cache) + { + $this->cached_queries[$query] = $files; + $this->cache->put($this->cache_name, $this->cached_queries); + } + + return $files; + } +} diff --git a/phpBB/includes/extension/interface.php b/phpBB/includes/extension/interface.php new file mode 100644 index 0000000000..b37cd24d77 --- /dev/null +++ b/phpBB/includes/extension/interface.php @@ -0,0 +1,65 @@ +<?php +/** +* +* @package extension +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* The interface extension meta classes have to implement to run custom code +* on enable/disable/purge. +* +* @package extension +*/ +interface phpbb_extension_interface +{ + /** + * enable_step is executed on enabling an extension until it returns false. + * + * Calls to this function can be made in subsequent requests, when the + * function is invoked through a webserver with a too low max_execution_time. + * + * @param mixed $old_state The return value of the previous call + * of this method, or false on the first call + * @return mixed Returns false after last step, otherwise + * temporary state which is passed as an + * argument to the next step + */ + public function enable_step($old_state); + + /** + * Disables the extension. + * + * Calls to this function can be made in subsequent requests, when the + * function is invoked through a webserver with a too low max_execution_time. + * + * @param mixed $old_state The return value of the previous call + * of this method, or false on the first call + * @return null + */ + public function disable_step($old_state); + + /** + * purge_step is executed on purging an extension until it returns false. + * + * Calls to this function can be made in subsequent requests, when the + * function is invoked through a webserver with a too low max_execution_time. + * + * @param mixed $old_state The return value of the previous call + * of this method, or false on the first call + * @return mixed Returns false after last step, otherwise + * temporary state which is passed as an + * argument to the next step + */ + public function purge_step($old_state); +} diff --git a/phpBB/includes/extension/manager.php b/phpBB/includes/extension/manager.php new file mode 100644 index 0000000000..bcdd21f7f1 --- /dev/null +++ b/phpBB/includes/extension/manager.php @@ -0,0 +1,415 @@ +<?php +/** +* +* @package extension +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* The extension manager provides means to activate/deactivate extensions. +* +* @package extension +*/ +class phpbb_extension_manager +{ + protected $cache; + protected $phpEx; + protected $extensions; + protected $extension_table; + protected $phpbb_root_path; + protected $cache_name; + + /** + * Creates a manager and loads information from database + * + * @param dbal $db A database connection + * @param string $extension_table The name of the table holding extensions + * @param string $phpbb_root_path Path to the phpbb includes directory. + * @param string $phpEx php file extension + * @param phpbb_cache_driver_interface $cache A cache instance or null + * @param string $cache_name The name of the cache variable, defaults to _ext + */ + public function __construct(dbal $db, $extension_table, $phpbb_root_path, $phpEx = '.php', phpbb_cache_driver_interface $cache = null, $cache_name = '_ext') + { + $this->phpbb_root_path = $phpbb_root_path; + $this->db = $db; + $this->cache = $cache; + $this->phpEx = $phpEx; + $this->extension_table = $extension_table; + $this->cache_name = $cache_name; + + $this->extensions = ($this->cache) ? $this->cache->get($this->cache_name) : false; + + if ($this->extensions === false) + { + $this->load_extensions(); + } + } + + /** + * Loads all extension information from the database + * + * @return null + */ + protected function load_extensions() + { + $sql = 'SELECT * + FROM ' . $this->extension_table; + + $result = $this->db->sql_query($sql); + $extensions = $this->db->sql_fetchrowset($result); + $this->db->sql_freeresult($result); + + $this->extensions = array(); + foreach ($extensions as $extension) + { + $extension['ext_path'] = $this->get_extension_path($extension['ext_name']); + $this->extensions[$extension['ext_name']] = $extension; + } + + ksort($this->extensions); + + if ($this->cache) + { + $this->cache->put($this->cache_name, $this->extensions); + } + } + + /** + * Generates the path to an extension + * + * @param string $name The name of the extension + * @param bool $phpbb_relative Whether the path should be relative to phpbb root + * @return string Path to an extension + */ + public function get_extension_path($name, $phpbb_relative = false) + { + $name = str_replace('.', '', $name); + + return (($phpbb_relative) ? $this->phpbb_root_path : '') . 'ext/' . $name . '/'; + } + + /** + * Instantiates the extension meta class for the extension with the given name + * + * @param string $name The extension name + * @return phpbb_extension_interface Instance of the extension meta class or + * phpbb_extension_base if the class does not exist + */ + public function get_extension($name) + { + $extension_class_name = 'phpbb_ext_' . str_replace('/', '_', $name) . '_ext'; + + if (class_exists($extension_class_name)) + { + return new $extension_class_name; + } + else + { + return new phpbb_extension_base; + } + } + + /** + * Runs a step of the extension enabling process. + * + * Allows the exentension to enable in a long running script that works + * in multiple steps across requests. State is kept for the extension + * in the extensions table. + * + * @param string $name The extension's name + * @return bool False if enabling is finished, true otherwise + */ + public function enable_step($name) + { + // ignore extensions that are already enabled + if (isset($this->extensions[$name]) && $this->extensions[$name]['ext_active']) + { + return false; + } + + $old_state = (isset($this->extensions[$name]['ext_state'])) ? unserialize($this->extensions[$name]['ext_state']) : false; + + $extension = $this->get_extension($name); + $state = $extension->enable_step($old_state); + + $active = ($state === false); + + $extension_data = array( + 'ext_name' => $name, + 'ext_active' => $active, + 'ext_state' => serialize($state), + ); + + $this->extensions[$name] = $extension_data; + $this->extensions[$name]['ext_path'] = $this->get_extension_path($extension_data['ext_name']); + ksort($this->extensions); + + $sql = 'UPDATE ' . $this->extension_table . ' + SET ' . $this->db->sql_build_array('UPDATE', $extension_data) . " + WHERE ext_name = '" . $this->db->sql_escape($name) . "'"; + $this->db->sql_query($sql); + + if (!$this->db->sql_affectedrows()) + { + $sql = 'INSERT INTO ' . $this->extension_table . ' + ' . $this->db->sql_build_array('INSERT', $extension_data); + $this->db->sql_query($sql); + } + + return !$active; + } + + /** + * Enables an extension + * + * This method completely enables an extension. But it could be long running + * so never call this in a script that has a max_execution time. + * + * @param string $name The extension's name + * @return null + */ + public function enable($name) + { + while ($this->enable_step($name)); + } + + /** + * Disables an extension + * + * Calls the disable method on the extension's meta class to allow it to + * process the event. + * + * @param string $name The extension's name + * @return bool False if disabling is finished, true otherwise + */ + public function disable_step($name) + { + // ignore extensions that are already disabled + if (!isset($this->extensions[$name]) || !$this->extensions[$name]['ext_active']) + { + return false; + } + + $old_state = unserialize($this->extensions[$name]['ext_state']); + + $extension = $this->get_extension($name); + $state = $extension->disable_step($old_state); + + // continue until the state is false + if ($state !== false) + { + $extension_data = array( + 'ext_state' => serialize($state), + ); + $this->extensions[$name]['ext_state'] = serialize($state); + + $sql = 'UPDATE ' . $this->extension_table . ' + SET ' . $this->db->sql_build_array('UPDATE', $extension_data) . " + WHERE ext_name = '" . $this->db->sql_escape($name) . "'"; + $this->db->sql_query($sql); + + return true; + } + + $extension_data = array( + 'ext_active' => false, + 'ext_state' => serialize(false), + ); + $this->extensions[$name]['ext_active'] = false; + $this->extensions[$name]['ext_state'] = serialize(false); + + $sql = 'UPDATE ' . $this->extension_table . ' + SET ' . $this->db->sql_build_array('UPDATE', $extension_data) . " + WHERE ext_name = '" . $this->db->sql_escape($name) . "'"; + $this->db->sql_query($sql); + + return false; + } + + /** + * Disables an extension + * + * Disables an extension completely at once. This process could run for a + * while so never call this in a script that has a max_execution time. + * + * @param string $name The extension's name + * @return null + */ + public function disable($name) + { + while ($this->disable_step($name)); + } + + /** + * Purge an extension + * + * Disables the extension first if active, and then calls purge on the + * extension's meta class to delete the extension's database content. + * + * @param string $name The extension's name + * @return bool False if purging is finished, true otherwise + */ + public function purge_step($name) + { + // ignore extensions that do not exist + if (!isset($this->extensions[$name])) + { + return false; + } + + // disable first if necessary + if ($this->extensions[$name]['ext_active']) + { + $this->disable($name); + } + + $old_state = unserialize($this->extensions[$name]['ext_state']); + + $extension = $this->get_extension($name); + $state = $extension->purge_step($old_state); + + // continue until the state is false + if ($state !== false) + { + $extension_data = array( + 'ext_state' => serialize($state), + ); + $this->extensions[$name]['ext_state'] = serialize($state); + + $sql = 'UPDATE ' . $this->extension_table . ' + SET ' . $this->db->sql_build_array('UPDATE', $extension_data) . " + WHERE ext_name = '" . $this->db->sql_escape($name) . "'"; + $this->db->sql_query($sql); + + return true; + } + + unset($this->extensions[$name]); + + $sql = 'DELETE FROM ' . $this->extension_table . " + WHERE ext_name = '" . $this->db->sql_escape($name) . "'"; + $this->db->sql_query($sql); + + return false; + } + + /** + * Purge an extension + * + * Purges an extension completely at once. This process could run for a while + * so never call this in a script that has a max_execution time. + * + * @param string $name The extension's name + * @return null + */ + public function purge($name) + { + while ($this->purge_step($name)); + } + + /** + * Retrieves a list of all available extensions on the filesystem + * + * @return array An array with extension names as keys and paths to the + * extension as values + */ + public function all_available() + { + $available = array(); + + $iterator = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($this->phpbb_root_path . 'ext/')); + foreach ($iterator as $file_info) + { + if ($file_info->isFile() && $file_info->getFilename() == 'ext' . $this->phpEx) + { + $ext_name = $iterator->getInnerIterator()->getSubPath(); + + $ext_name = str_replace(DIRECTORY_SEPARATOR, '/', $ext_name); + + $available[$ext_name] = $this->phpbb_root_path . 'ext/' . $ext_name . '/'; + } + } + ksort($available); + return $available; + } + + /** + * Retrieves all configured extensions. + * + * All enabled and disabled extensions are considered configured. A purged + * extension that is no longer in the database is not configured. + * + * @return array An array with extension names as keys and and the + * database stored extension information as values + */ + public function all_configured() + { + $configured = array(); + foreach ($this->extensions as $name => $data) + { + $data['ext_path'] = $this->phpbb_root_path . $data['ext_path']; + $configured[$name] = $data; + } + return $configured; + } + + /** + * Retrieves all enabled extensions. + * + * @return array An array with extension names as keys and and the + * database stored extension information as values + */ + public function all_enabled() + { + $enabled = array(); + foreach ($this->extensions as $name => $data) + { + if ($data['ext_active']) + { + $enabled[$name] = $this->phpbb_root_path . $data['ext_path']; + } + } + return $enabled; + } + + /** + * Retrieves all disabled extensions. + * + * @return array An array with extension names as keys and and the + * database stored extension information as values + */ + public function all_disabled() + { + $disabled = array(); + foreach ($this->extensions as $name => $data) + { + if (!$data['ext_active']) + { + $disabled[$name] = $this->phpbb_root_path . $data['ext_path']; + } + } + return $disabled; + } + + /** + * Instantiates a phpbb_extension_finder. + * + * @return phpbb_extension_finder An extension finder instance + */ + public function get_finder() + { + return new phpbb_extension_finder($this, $this->phpbb_root_path, $this->cache, $this->phpEx, $this->cache_name . '_finder'); + } +} diff --git a/phpBB/includes/extension/provider.php b/phpBB/includes/extension/provider.php new file mode 100644 index 0000000000..3939c2ef07 --- /dev/null +++ b/phpBB/includes/extension/provider.php @@ -0,0 +1,68 @@ +<?php +/** +* +* @package extension +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Provides a set of items found in extensions +* +* @package extension +*/ +abstract class phpbb_extension_provider implements IteratorAggregate +{ + /** + * Array holding all found items + * @var array|null + */ + protected $items = null; + + /** + * An extension manager to search for items in extensions + * @var phpbb_extension_manager + */ + protected $extension_manager; + + /** + * Constructor. Loads all available items. + * + * @param phpbb_extension_manager $extension_manager phpBB extension manager + */ + public function __construct(phpbb_extension_manager $extension_manager) + { + $this->extension_manager = $extension_manager; + } + + /** + * Finds template paths using the extension manager. + * + * @return array List of task names + */ + abstract protected function find(); + + /** + * Retrieve an iterator over all items + * + * @return ArrayIterator An iterator for the array of template paths + */ + public function getIterator() + { + if ($this->items === null) + { + $this->items = $this->find(); + } + + return new ArrayIterator($this->items); + } +} diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 688c7f2000..86bd21b1fc 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -1654,7 +1654,7 @@ function get_unread_topics($user_id = false, $sql_extra = '', $sql_sort = '', $s */ 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, $request; + global $db, $tracking_topics, $user, $config, $auth, $request; // Determine the users last forum mark time if not given. if ($mark_time_forum === false) @@ -1677,6 +1677,10 @@ function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_ti } } + // Handle update of unapproved topics info. + // Only update for moderators having m_approve permission for the forum. + $sql_update_unapproved = ($auth->acl_get('m_approve', $forum_id)) ? '': 'AND t.topic_approved = 1'; + // 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']) @@ -1692,7 +1696,8 @@ function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_ti 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 t.topic_moved_id = 0 ' . + $sql_update_unapproved . ' AND (tt.topic_id IS NULL OR tt.mark_time < t.topic_last_post_time) GROUP BY t.forum_id'; $result = $db->sql_query_limit($sql, 1); @@ -1712,11 +1717,12 @@ function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_ti } 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'; + $sql = 'SELECT t.topic_id + FROM ' . TOPICS_TABLE . ' t + WHERE t.forum_id = ' . $forum_id . ' + AND t.topic_last_post_time > ' . $mark_time_forum . ' + AND t.topic_moved_id = 0 ' . + $sql_update_unapproved; $result = $db->sql_query($sql); $check_forum = $tracking_topics['tf'][$forum_id]; @@ -3256,6 +3262,10 @@ function get_preg_expression($mode) $inline = ($mode == 'relative_url') ? ')' : ''; return "(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})*(?:/(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?"; break; + + case 'table_prefix': + return '#^[a-zA-Z][a-zA-Z0-9_]*$#'; + break; } return ''; @@ -4110,59 +4120,26 @@ function obtain_users_online_string($online_users, $item_id = 0, $item = 'forum' } else if ($config['load_online_guests']) { - $l_online = ($online_users['guests_online'] === 1) ? $user->lang['BROWSING_' . $item_caps . '_GUEST'] : $user->lang['BROWSING_' . $item_caps . '_GUESTS']; - $online_userlist = sprintf($l_online, $online_userlist, $online_users['guests_online']); + $online_userlist = $user->lang('BROWSING_' . $item_caps . '_GUESTS', $online_users['guests_online'], $online_userlist); } else { $online_userlist = sprintf($user->lang['BROWSING_' . $item_caps], $online_userlist); } // Build online listing - $vars_online = array( - 'ONLINE' => array('total_online', 'l_t_user_s', 0), - 'REG' => array('visible_online', 'l_r_user_s', !$config['load_online_guests']), - 'HIDDEN' => array('hidden_online', 'l_h_user_s', $config['load_online_guests']), - 'GUEST' => array('guests_online', 'l_g_user_s', 0) - ); + $visible_online = $user->lang('REG_USERS_TOTAL', (int) $online_users['visible_online']); + $hidden_online = $user->lang('HIDDEN_USERS_TOTAL', (int) $online_users['hidden_online']); - foreach ($vars_online as $l_prefix => $var_ary) + if ($config['load_online_guests']) { - if ($var_ary[2]) - { - $l_suffix = '_AND'; - } - else - { - $l_suffix = ''; - } - switch ($online_users[$var_ary[0]]) - { - case 0: - ${$var_ary[1]} = $user->lang[$l_prefix . '_USERS_ZERO_TOTAL' . $l_suffix]; - break; - - case 1: - ${$var_ary[1]} = $user->lang[$l_prefix . '_USER_TOTAL' . $l_suffix]; - break; - - default: - ${$var_ary[1]} = $user->lang[$l_prefix . '_USERS_TOTAL' . $l_suffix]; - break; - } + $guests_online = $user->lang('GUEST_USERS_TOTAL', (int) $online_users['guests_online']); + $l_online_users = $user->lang('ONLINE_USERS_TOTAL_GUESTS', (int) $online_users['total_online'], $visible_online, $hidden_online, $guests_online); } - unset($vars_online); - - $l_online_users = sprintf($l_t_user_s, $online_users['total_online']); - $l_online_users .= sprintf($l_r_user_s, $online_users['visible_online']); - $l_online_users .= sprintf($l_h_user_s, $online_users['hidden_online']); - - if ($config['load_online_guests']) + else { - $l_online_users .= sprintf($l_g_user_s, $online_users['guests_online']); + $l_online_users = $user->lang('ONLINE_USERS_TOTAL', (int) $online_users['total_online'], $visible_online, $hidden_online); } - - return array( 'online_userlist' => $online_userlist, 'l_online_users' => $l_online_users, @@ -4205,6 +4182,178 @@ function phpbb_optionset($bit, $set, $data) } /** +* Determine which plural form we should use. +* For some languages this is not as simple as for English. +* +* @param $rule int ID of the plural rule we want to use, see http://wiki.phpbb.com/Plural_Rules#Plural_Rules +* @param $number int|float The number we want to get the plural case for. Float numbers are floored. +* @return int The plural-case we need to use for the number plural-rule combination +*/ +function phpbb_get_plural_form($rule, $number) +{ + $number = (int) $number; + + if ($rule > 15 || $rule < 0) + { + trigger_error('INVALID_PLURAL_RULE'); + } + + /** + * The following plural rules are based on a list published by the Mozilla Developer Network + * https://developer.mozilla.org/en/Localization_and_Plurals + */ + switch ($rule) + { + case 0: + /** + * Families: Asian (Chinese, Japanese, Korean, Vietnamese), Persian, Turkic/Altaic (Turkish), Thai, Lao + * 1 - everything: 0, 1, 2, ... + */ + return 1; + + case 1: + /** + * Families: Germanic (Danish, Dutch, English, Faroese, Frisian, German, Norwegian, Swedish), Finno-Ugric (Estonian, Finnish, Hungarian), Language isolate (Basque), Latin/Greek (Greek), Semitic (Hebrew), Romanic (Italian, Portuguese, Spanish, Catalan) + * 1 - 1 + * 2 - everything else: 0, 2, 3, ... + */ + return ($number == 1) ? 1 : 2; + + case 2: + /** + * Families: Romanic (French, Brazilian Portuguese) + * 1 - 0, 1 + * 2 - everything else: 2, 3, ... + */ + return (($number == 0) || ($number == 1)) ? 1 : 2; + + case 3: + /** + * Families: Baltic (Latvian) + * 1 - 0 + * 2 - ends in 1, not 11: 1, 21, ... 101, 121, ... + * 3 - everything else: 2, 3, ... 10, 11, 12, ... 20, 22, ... + */ + return ($number == 0) ? 1 : ((($number % 10 == 1) && ($number % 100 != 11)) ? 2 : 3); + + case 4: + /** + * Families: Celtic (Scottish Gaelic) + * 1 - is 1 or 11: 1, 11 + * 2 - is 2 or 12: 2, 12 + * 3 - others between 3 and 19: 3, 4, ... 10, 13, ... 18, 19 + * 4 - everything else: 0, 20, 21, ... + */ + return ($number == 1 || $number == 11) ? 1 : (($number == 2 || $number == 12) ? 2 : (($number >= 3 && $number <= 19) ? 3 : 4)); + + case 5: + /** + * Families: Romanic (Romanian) + * 1 - 1 + * 2 - is 0 or ends in 01-19: 0, 2, 3, ... 19, 101, 102, ... 119, 201, ... + * 3 - everything else: 20, 21, ... + */ + return ($number == 1) ? 1 : ((($number == 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 2 : 3); + + case 6: + /** + * Families: Baltic (Lithuanian) + * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, ... + * 2 - ends in 0 or ends in 10-20: 0, 10, 11, 12, ... 19, 20, 30, 40, ... + * 3 - everything else: 2, 3, ... 8, 9, 22, 23, ... 29, 32, 33, ... + */ + return (($number % 10 == 1) && ($number % 100 != 11)) ? 1 : ((($number % 10 < 2) || (($number % 100 >= 10) && ($number % 100 < 20))) ? 2 : 3); + + case 7: + /** + * Families: Slavic (Croatian, Serbian, Russian, Ukrainian) + * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, ... + * 2 - ends in 2-4, not 12-14: 2, 3, 4, 22, 23, 24, 32, ... + * 3 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 26, ... + */ + return (($number % 10 == 1) && ($number % 100 != 11)) ? 1 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 2 : 3); + + case 8: + /** + * Families: Slavic (Slovak, Czech) + * 1 - 1 + * 2 - 2, 3, 4 + * 3 - everything else: 0, 5, 6, 7, ... + */ + return ($number == 1) ? 1 : ((($number >= 2) && ($number <= 4)) ? 2 : 3); + + case 9: + /** + * Families: Slavic (Polish) + * 1 - 1 + * 2 - ends in 2-4, not 12-14: 2, 3, 4, 22, 23, 24, 32, ... 104, 122, ... + * 3 - everything else: 0, 5, 6, ... 11, 12, 13, 14, 15, ... 20, 21, 25, ... + */ + return ($number == 1) ? 1 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 2 : 3); + + case 10: + /** + * Families: Slavic (Slovenian, Sorbian) + * 1 - ends in 01: 1, 101, 201, ... + * 2 - ends in 02: 2, 102, 202, ... + * 3 - ends in 03-04: 3, 4, 103, 104, 203, 204, ... + * 4 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, ... + */ + return ($number % 100 == 1) ? 1 : (($number % 100 == 2) ? 2 : ((($number % 100 == 3) || ($number % 100 == 4)) ? 3 : 4)); + + case 11: + /** + * Families: Celtic (Irish Gaeilge) + * 1 - 1 + * 2 - 2 + * 3 - is 3-6: 3, 4, 5, 6 + * 4 - is 7-10: 7, 8, 9, 10 + * 5 - everything else: 0, 11, 12, ... + */ + return ($number == 1) ? 1 : (($number == 2) ? 2 : (($number >= 3 && $number <= 6) ? 3 : (($number >= 7 && $number <= 10) ? 4 : 5))); + + case 12: + /** + * Families: Semitic (Arabic) + * 1 - 1 + * 2 - 2 + * 3 - ends in 03-10: 3, 4, ... 10, 103, 104, ... 110, 203, 204, ... + * 4 - ends in 11-99: 11, ... 99, 111, 112, ... + * 5 - everything else: 100, 101, 102, 200, 201, 202, ... + * 6 - 0 + */ + return ($number == 1) ? 1 : (($number == 2) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : (($number != 0) ? 5 : 6)))); + + case 13: + /** + * Families: Semitic (Maltese) + * 1 - 1 + * 2 - is 0 or ends in 01-10: 0, 2, 3, ... 9, 10, 101, 102, ... + * 3 - ends in 11-19: 11, 12, ... 18, 19, 111, 112, ... + * 4 - everything else: 20, 21, ... + */ + return ($number == 1) ? 1 : ((($number == 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 2 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 3 : 4)); + + case 14: + /** + * Families: Slavic (Macedonian) + * 1 - ends in 1: 1, 11, 21, ... + * 2 - ends in 2: 2, 12, 22, ... + * 3 - everything else: 0, 3, 4, ... 10, 13, 14, ... 20, 23, ... + */ + return ($number % 10 == 1) ? 1 : (($number % 10 == 2) ? 2 : 3); + + case 15: + /** + * Families: Icelandic + * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, 131, ... + * 2 - everything else: 0, 2, 3, ... 10, 11, 12, ... 20, 22, ... + */ + return (($number % 10 == 1) && ($number % 100 != 11)) ? 1 : 2; + } +} + +/** * Login using http authenticate. * * @param array $param Parameter array, see $param_defaults array. @@ -4312,7 +4461,7 @@ function phpbb_http_login($param) */ function page_header($page_title = '', $display_online_list = true, $item_id = 0, $item = 'forum') { - global $db, $config, $template, $SID, $_SID, $user, $auth, $phpEx, $phpbb_root_path; + global $db, $config, $template, $SID, $_SID, $_EXTRA_URL, $user, $auth, $phpEx, $phpbb_root_path; if (defined('HEADER_INC')) { @@ -4383,10 +4532,9 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 set_config('record_online_date', time(), true); } - $l_online_record = sprintf($user->lang['RECORD_ONLINE_USERS'], $config['record_online_users'], $user->format_date($config['record_online_date'], false, true)); + $l_online_record = $user->lang('RECORD_ONLINE_USERS', (int) $config['record_online_users'], $user->format_date($config['record_online_date'], false, true)); - $l_online_time = ($config['load_online_time'] == 1) ? 'VIEW_ONLINE_TIME' : 'VIEW_ONLINE_TIMES'; - $l_online_time = sprintf($user->lang[$l_online_time], $config['load_online_time']); + $l_online_time = $user->lang('VIEW_ONLINE_TIMES', (int) $config['load_online_time']); } $l_privmsgs_text = $l_privmsgs_text_unread = ''; @@ -4397,8 +4545,7 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 { if ($user->data['user_new_privmsg']) { - $l_message_new = ($user->data['user_new_privmsg'] == 1) ? $user->lang['NEW_PM'] : $user->lang['NEW_PMS']; - $l_privmsgs_text = sprintf($l_message_new, $user->data['user_new_privmsg']); + $l_privmsgs_text = $user->lang('NEW_PMS', (int) $user->data['user_new_privmsg']); if (!$user->data['user_last_privmsg'] || $user->data['user_last_privmsg'] > $user->data['session_last_visit']) { @@ -4416,7 +4563,7 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 } else { - $l_privmsgs_text = $user->lang['NO_NEW_PM']; + $l_privmsgs_text = $user->lang('NEW_PMS', 0); $s_privmsg_new = false; } @@ -4424,8 +4571,7 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 if ($user->data['user_unread_privmsg'] && $user->data['user_unread_privmsg'] != $user->data['user_new_privmsg']) { - $l_message_unread = ($user->data['user_unread_privmsg'] == 1) ? $user->lang['UNREAD_PM'] : $user->lang['UNREAD_PMS']; - $l_privmsgs_text_unread = sprintf($l_message_unread, $user->data['user_unread_privmsg']); + $l_privmsgs_text_unread = $user->lang('UNREAD_PMS', (int) $user->data['user_unread_privmsg']); } } @@ -4465,6 +4611,15 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 $s_search_hidden_fields['sid'] = $_SID; } + if (!empty($_EXTRA_URL)) + { + foreach ($_EXTRA_URL as $url_param) + { + $url_param = explode('=', $url_param, 2); + $s_hidden_fields[$url_param[0]] = $url_param[1]; + } + } + // The following assigns all _common_ variables that may be used at any point in a template. $template->assign_vars(array( 'SITENAME' => $config['sitename'], @@ -4570,6 +4725,8 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 'T_STYLESHEET_LINK' => "{$web_path}styles/" . $user->theme['theme_path'] . '/theme/stylesheet.css', 'T_STYLESHEET_LANG_LINK' => "{$web_path}styles/" . $user->theme['theme_path'] . '/theme/' . $user->lang_name . '/stylesheet.css', 'T_STYLESHEET_NAME' => $user->theme['theme_name'], + 'T_JQUERY_LINK' => ($config['load_jquery_cdn'] && !empty($config['load_jquery_url'])) ? $config['load_jquery_url'] : "{$web_path}assets/javascript/jquery.js", + 'S_JQUERY_FALLBACK' => ($config['load_jquery_cdn']) ? true : false, 'T_THEME_NAME' => $user->theme['theme_path'], 'T_THEME_LANG_NAME' => $user->data['user_lang'], diff --git a/phpBB/includes/functions_acp.php b/phpBB/includes/functions_acp.php index 36e22e069f..4702f9939d 100644 --- a/phpBB/includes/functions_acp.php +++ b/phpBB/includes/functions_acp.php @@ -124,6 +124,8 @@ function adm_page_footer($copyright_html = true) 'DEBUG_OUTPUT' => (defined('DEBUG')) ? $debug_output : '', 'TRANSLATION_INFO' => (!empty($user->lang['TRANSLATION_INFO'])) ? $user->lang['TRANSLATION_INFO'] : '', 'S_COPYRIGHT_HTML' => $copyright_html, + 'T_JQUERY_LINK' => ($config['load_jquery_cdn'] && !empty($config['load_jquery_url'])) ? $config['load_jquery_url'] : "{$phpbb_root_path}assets/javascript/jquery.js", + 'S_JQUERY_FALLBACK' => ($config['load_jquery_cdn']) ? true : false, 'VERSION' => $config['version']) ); diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 3f9e517fdf..f6378e331e 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -2295,41 +2295,6 @@ function auto_prune($forum_id, $prune_mode, $prune_flags, $prune_days, $prune_fr } /** -* remove_comments will strip the sql comment lines out of an uploaded sql file -* specifically for mssql and postgres type files in the install.... -*/ -function remove_comments(&$output) -{ - $lines = explode("\n", $output); - $output = ''; - - // try to keep mem. use down - $linecount = sizeof($lines); - - $in_comment = false; - for ($i = 0; $i < $linecount; $i++) - { - if (trim($lines[$i]) == '/*') - { - $in_comment = true; - } - - if (!$in_comment) - { - $output .= $lines[$i] . "\n"; - } - - if (trim($lines[$i]) == '*/') - { - $in_comment = false; - } - } - - unset($lines); - return $output; -} - -/** * Cache moderators, called whenever permissions are changed via admin_permissions. Changes of username * and group names must be carried through for the moderators table */ @@ -2366,7 +2331,7 @@ function cache_moderators() $ug_id_ary = array_keys($hold_ary); // Remove users who have group memberships with DENY moderator permissions - $sql = $db->sql_build_query('SELECT', array( + $sql_ary = array( 'SELECT' => 'a.forum_id, ug.user_id, g.group_id', 'FROM' => array( @@ -2379,8 +2344,8 @@ function cache_moderators() 'LEFT_JOIN' => array( array( 'FROM' => array(ACL_ROLES_DATA_TABLE => 'r'), - 'ON' => 'a.auth_role_id = r.role_id' - ) + 'ON' => 'a.auth_role_id = r.role_id', + ), ), 'WHERE' => '(o.auth_option_id = a.auth_option_id OR o.auth_option_id = r.auth_option_id) @@ -2392,7 +2357,8 @@ function cache_moderators() AND ' . $db->sql_in_set('ug.user_id', $ug_id_ary) . " AND ug.user_pending = 0 AND o.auth_option " . $db->sql_like_expression('m_' . $db->any_char), - )); + ); + $sql = $db->sql_build_query('SELECT', $sql_ary); $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) @@ -2610,7 +2576,11 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id $db->sql_freeresult($result); } - if ($log_count == 0) + // $log_count may be false here if false was passed in for it, + // because in this case we did not run the COUNT() query above. + // If we ran the COUNT() query and it returned zero rows, return; + // otherwise query for logs below. + if ($log_count === 0) { // Save the queries, because there are no logs to display return 0; @@ -2792,18 +2762,18 @@ function update_foes($group_id = false, $user_id = false) if (is_array($group_id) && sizeof($group_id)) { // Grab group settings... - $sql = $db->sql_build_query('SELECT', array( + $sql_ary = array( 'SELECT' => 'a.group_id', 'FROM' => array( ACL_OPTIONS_TABLE => 'ao', - ACL_GROUPS_TABLE => 'a' + ACL_GROUPS_TABLE => 'a', ), 'LEFT_JOIN' => array( array( 'FROM' => array(ACL_ROLES_DATA_TABLE => 'r'), - 'ON' => 'a.auth_role_id = r.role_id' + 'ON' => 'a.auth_role_id = r.role_id', ), ), @@ -2811,8 +2781,9 @@ function update_foes($group_id = false, $user_id = false) AND ' . $db->sql_in_set('a.group_id', $group_id) . " AND ao.auth_option IN ('a_', 'm_')", - 'GROUP_BY' => 'a.group_id' - )); + 'GROUP_BY' => 'a.group_id', + ); + $sql = $db->sql_build_query('SELECT', $sql_ary); $result = $db->sql_query($sql); $groups = array(); diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php index b1294a2f14..894e261c12 100644 --- a/phpBB/includes/functions_content.php +++ b/phpBB/includes/functions_content.php @@ -938,12 +938,12 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count, } $download_link = append_sid("{$phpbb_root_path}download/file.$phpEx", 'id=' . $attachment['attach_id']); + $l_downloaded_viewed = 'VIEWED_COUNTS'; switch ($display_cat) { // Images case ATTACHMENT_CATEGORY_IMAGE: - $l_downloaded_viewed = 'VIEWED_COUNT'; $inline_link = append_sid("{$phpbb_root_path}download/file.$phpEx", 'id=' . $attachment['attach_id']); $download_link .= '&mode=view'; @@ -957,7 +957,6 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count, // Images, but display Thumbnail case ATTACHMENT_CATEGORY_THUMB: - $l_downloaded_viewed = 'VIEWED_COUNT'; $thumbnail_link = append_sid("{$phpbb_root_path}download/file.$phpEx", 'id=' . $attachment['attach_id'] . '&t=1'); $download_link .= '&mode=view'; @@ -971,7 +970,6 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count, // Windows Media Streams case ATTACHMENT_CATEGORY_WM: - $l_downloaded_viewed = 'VIEWED_COUNT'; // Giving the filename directly because within the wm object all variables are in local context making it impossible // to validate against a valid session (all params can differ) @@ -990,7 +988,6 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count, // Real Media Streams case ATTACHMENT_CATEGORY_RM: case ATTACHMENT_CATEGORY_QUICKTIME: - $l_downloaded_viewed = 'VIEWED_COUNT'; $block_array += array( 'S_RM_FILE' => ($display_cat == ATTACHMENT_CATEGORY_RM) ? true : false, @@ -1007,8 +1004,6 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count, case ATTACHMENT_CATEGORY_FLASH: list($width, $height) = @getimagesize($filename); - $l_downloaded_viewed = 'VIEWED_COUNT'; - $block_array += array( 'S_FLASH_FILE' => true, 'WIDTH' => $width, @@ -1021,7 +1016,7 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count, break; default: - $l_downloaded_viewed = 'DOWNLOAD_COUNT'; + $l_downloaded_viewed = 'DOWNLOAD_COUNTS'; $block_array += array( 'S_FILE' => true, @@ -1029,11 +1024,14 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count, break; } - $l_download_count = (!isset($attachment['download_count']) || $attachment['download_count'] == 0) ? $user->lang[$l_downloaded_viewed . '_NONE'] : (($attachment['download_count'] == 1) ? sprintf($user->lang[$l_downloaded_viewed], $attachment['download_count']) : sprintf($user->lang[$l_downloaded_viewed . 'S'], $attachment['download_count'])); + if (!isset($attachment['download_count'])) + { + $attachment['download_count'] = 0; + } $block_array += array( 'U_DOWNLOAD_LINK' => $download_link, - 'L_DOWNLOAD_COUNT' => $l_download_count + 'L_DOWNLOAD_COUNT' => $user->lang($l_downloaded_viewed, (int) $attachment['download_count']), ); } diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php index 4e8d8f7d34..2ec34e1084 100644 --- a/phpBB/includes/functions_display.php +++ b/phpBB/includes/functions_display.php @@ -110,7 +110,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod $sql_array['SELECT'] .= ', fa.user_id'; } - $sql = $db->sql_build_query('SELECT', array( + $sql_ary = array( 'SELECT' => $sql_array['SELECT'], 'FROM' => $sql_array['FROM'], 'LEFT_JOIN' => $sql_array['LEFT_JOIN'], @@ -118,8 +118,9 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod 'WHERE' => $sql_where, 'ORDER_BY' => 'f.left_id', - )); + ); + $sql = $db->sql_build_query('SELECT', $sql_ary); $result = $db->sql_query($sql); $forum_tracking_info = array(); @@ -446,6 +447,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod 'S_NO_CAT' => $catless && !$last_catless, 'S_IS_LINK' => ($row['forum_type'] == FORUM_LINK) ? true : false, 'S_UNREAD_FORUM' => $forum_unread, + 'S_AUTH_READ' => $auth->acl_get('f_read', $row['forum_id']), 'S_LOCKED_FORUM' => ($row['forum_status'] == ITEM_LOCKED) ? true : false, 'S_LIST_SUBFORUMS' => ($row['display_subforum_list']) ? true : false, 'S_SUBFORUMS' => (sizeof($subforums_list)) ? true : false, @@ -1041,10 +1043,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_POSTS' => $user->lang('USER_POSTS', (int) $active_f_count), 'ACTIVE_FORUM_PCT' => sprintf($l_active_pct, $active_f_pct), 'ACTIVE_TOPIC' => censor_text($active_t_name), - 'ACTIVE_TOPIC_POSTS' => ($active_t_count == 1) ? sprintf($user->lang['USER_POST'], 1) : sprintf($user->lang['USER_POSTS'], $active_t_count), + 'ACTIVE_TOPIC_POSTS' => $user->lang('USER_POSTS', (int) $active_t_count), 'ACTIVE_TOPIC_PCT' => sprintf($l_active_pct, $active_t_pct), 'U_ACTIVE_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $active_f_id), 'U_ACTIVE_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", 't=' . $active_t_id), @@ -1065,6 +1067,7 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id, $match_id = ($mode == 'forum') ? $forum_id : $topic_id; $u_url = "uid={$user->data['user_id']}"; $u_url .= ($mode == 'forum') ? '&f' : '&f=' . $forum_id . '&t'; + $is_watching = 0; // Is user watching this thread? if ($user_id != ANONYMOUS) @@ -1090,9 +1093,9 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id, $uid = request_var('uid', 0); $token = request_var('hash', ''); - if (($token && check_link_hash($token, "{$mode}_$match_id")) || confirm_box(true)) + if ($token && check_link_hash($token, "{$mode}_$match_id") || confirm_box(true)) { - if (($uid != $user_id) || ($request->variable('unwatch', '', false, phpbb_request_interface::GET) != $mode)) + if ($uid != $user_id || $request->variable('unwatch', '', false, phpbb_request_interface::GET) != $mode) { $redirect_url = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&start=$start"); $message = $user->lang['ERR_UNWATCHING'] . '<br /><br />' . sprintf($user->lang['RETURN_' . strtoupper($mode)], '<a href="' . $redirect_url . '">', '</a>'); @@ -1105,7 +1108,8 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id, $db->sql_query($sql); $redirect_url = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&start=$start"); - $message = $user->lang['NOT_WATCHING_' . strtoupper($mode)] . '<br /><br />' . sprintf($user->lang['RETURN_' . strtoupper($mode)], '<a href="' . $redirect_url . '">', '</a>'); + $message = $user->lang['NOT_WATCHING_' . strtoupper($mode)] . '<br /><br />'; + $message .= sprintf($user->lang['RETURN_' . strtoupper($mode)], '<a href="' . $redirect_url . '">', '</a>'); meta_refresh(3, $redirect_url); trigger_error($message); } @@ -1122,7 +1126,14 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id, $s_hidden_fields['t'] = $topic_id; } - $confirm_box_message = (($item_title == '') ? 'UNWATCH_' . strtoupper($mode) : $user->lang('UNWATCH_' . strtoupper($mode) . '_DETAILED', $item_title)); + if ($item_title == '') + { + $confirm_box_message = 'UNWATCH_' . strtoupper($mode); + } + else + { + $confirm_box_message = $user->lang('UNWATCH_' . strtoupper($mode) . '_DETAILED', $item_title); + } confirm_box(false, $confirm_box_message, build_hidden_fields($s_hidden_fields)); } } @@ -1147,9 +1158,9 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id, $uid = request_var('uid', 0); $token = request_var('hash', ''); - if (($token && check_link_hash($token, "{$mode}_$match_id")) || confirm_box(true)) + if ($token && check_link_hash($token, "{$mode}_$match_id") || confirm_box(true)) { - if (($uid != $user_id) || ($request->variable('watch', '', false, phpbb_request_interface::GET) != $mode)) + if ($uid != $user_id || $request->variable('watch', '', false, phpbb_request_interface::GET) != $mode) { $redirect_url = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&start=$start"); $message = $user->lang['ERR_WATCHING'] . '<br /><br />' . sprintf($user->lang['RETURN_' . strtoupper($mode)], '<a href="' . $redirect_url . '">', '</a>'); diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php index 7a99bca0e2..b0d8fb6720 100644 --- a/phpBB/includes/functions_install.php +++ b/phpBB/includes/functions_install.php @@ -50,7 +50,6 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'firebird', 'MODULE' => 'interbase', 'DELIM' => ';;', - 'COMMENTS' => 'remove_remarks', 'DRIVER' => 'firebird', 'AVAILABLE' => true, '2.0.x' => false, @@ -60,7 +59,6 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'mysql_41', 'MODULE' => 'mysqli', 'DELIM' => ';', - 'COMMENTS' => 'remove_remarks', 'DRIVER' => 'mysqli', 'AVAILABLE' => true, '2.0.x' => true, @@ -70,7 +68,6 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'mysql', 'MODULE' => 'mysql', 'DELIM' => ';', - 'COMMENTS' => 'remove_remarks', 'DRIVER' => 'mysql', 'AVAILABLE' => true, '2.0.x' => true, @@ -80,7 +77,6 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'mssql', 'MODULE' => 'mssql', 'DELIM' => 'GO', - 'COMMENTS' => 'remove_comments', 'DRIVER' => 'mssql', 'AVAILABLE' => true, '2.0.x' => true, @@ -90,7 +86,6 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'mssql', 'MODULE' => 'odbc', 'DELIM' => 'GO', - 'COMMENTS' => 'remove_comments', 'DRIVER' => 'mssql_odbc', 'AVAILABLE' => true, '2.0.x' => true, @@ -100,7 +95,6 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'mssql', 'MODULE' => 'sqlsrv', 'DELIM' => 'GO', - 'COMMENTS' => 'remove_comments', 'DRIVER' => 'mssqlnative', 'AVAILABLE' => true, '2.0.x' => false, @@ -110,7 +104,6 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'oracle', 'MODULE' => 'oci8', 'DELIM' => '/', - 'COMMENTS' => 'remove_comments', 'DRIVER' => 'oracle', 'AVAILABLE' => true, '2.0.x' => false, @@ -120,7 +113,6 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'postgres', 'MODULE' => 'pgsql', 'DELIM' => ';', - 'COMMENTS' => 'remove_comments', 'DRIVER' => 'postgres', 'AVAILABLE' => true, '2.0.x' => true, @@ -130,7 +122,6 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'sqlite', 'MODULE' => 'sqlite', 'DELIM' => ';', - 'COMMENTS' => 'remove_remarks', 'DRIVER' => 'sqlite', 'AVAILABLE' => true, '2.0.x' => false, @@ -473,11 +464,17 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix, } /** -* remove_remarks will strip the sql comment lines out of an uploaded sql file +* Removes comments from schema files */ -function remove_remarks(&$sql) +function remove_comments($sql) { + // Remove /* */ comments (http://ostermiller.org/findcomment.html) + $sql = preg_replace('#/\*(.|[\r\n])*?\*/#', "\n", $sql); + + // Remove # style comments $sql = preg_replace('/\n{2,}/', "\n", preg_replace('/^#.*$/m', "\n", $sql)); + + return $sql; } /** diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index b94957a85f..4797da5398 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -163,6 +163,22 @@ class messenger } /** + * Adds X-AntiAbuse headers + * + * @param array $config Configuration array + * @param user $user A user object + * + * @return null + */ + function anti_abuse_headers($config, $user) + { + $this->headers('X-AntiAbuse: Board servername - ' . mail_encode($config['server_name'])); + $this->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); + $this->headers('X-AntiAbuse: Username - ' . mail_encode($user->data['username'])); + $this->headers('X-AntiAbuse: User IP - ' . $user->ip); + } + + /** * Set the email priority */ function set_mail_priority($priority = MAIL_NORMAL_PRIORITY) @@ -175,7 +191,7 @@ class messenger */ function template($template_file, $template_lang = '', $template_path = '') { - global $config, $phpbb_root_path, $phpEx, $user; + global $config, $phpbb_root_path, $phpEx, $user, $phpbb_extension_manager; if (!trim($template_file)) { @@ -194,7 +210,8 @@ class messenger if (!isset($this->tpl_msg[$template_lang . $template_file])) { $template_locator = new phpbb_template_locator(); - $this->tpl_msg[$template_lang . $template_file] = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $template_locator); + $template_path_provider = new phpbb_template_extension_path_provider($phpbb_extension_manager, new phpbb_template_path_provider()); + $this->tpl_msg[$template_lang . $template_file] = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $template_locator, $template_path_provider); $tpl = &$this->tpl_msg[$template_lang . $template_file]; $fallback_template_path = false; diff --git a/phpBB/includes/functions_module.php b/phpBB/includes/functions_module.php index 09c54422b0..1f451d392d 100644 --- a/phpBB/includes/functions_module.php +++ b/phpBB/includes/functions_module.php @@ -221,13 +221,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_basename'] . '_url'; + $short_name = $this->get_short_name($row['module_basename']); + + $url_func = '_module_' . $short_name . '_url'; // Function for building the language name - $lang_func = '_module_' . $row['module_basename'] . '_lang'; + $lang_func = '_module_' . $short_name . '_lang'; // Custom function for calling parameters on module init (for example assigning template variables) - $custom_func = '_module_' . $row['module_basename']; + $custom_func = '_module_' . $short_name; $names[$row['module_basename'] . '_' . $row['module_mode']][] = true; @@ -275,6 +277,11 @@ class p_master */ function loaded($module_basename, $module_mode = false) { + if (!$this->is_full_class($module_basename)) + { + $module_basename = $this->p_class . '_' . $module_basename; + } + if (empty($this->loaded_cache)) { $this->loaded_cache = array(); @@ -381,6 +388,11 @@ class p_master $id = request_var('icat', ''); } + if ($id && !is_numeric($id) && !$this->is_full_class($id)) + { + $id = $this->p_class . '_' . $id; + } + $category = false; foreach ($this->module_ary as $row_id => $item_ary) { @@ -389,9 +401,9 @@ class p_master // If this is a module and no mode selected, select first mode // If no category or module selected, go active for first module in first category if ( - (($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && (($item_ary['mode'] == $mode && !$item_ary['cat']) || ($icat && $item_ary['cat']))) || + (($item_ary['name'] === $id || $item_ary['name'] === $this->p_class . '_' . $id || $item_ary['id'] === (int) $id) && (($item_ary['mode'] == $mode && !$item_ary['cat']) || ($icat && $item_ary['cat']))) || ($item_ary['parent'] === $category && !$item_ary['cat'] && !$icat && $item_ary['display']) || - (($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && !$mode && !$item_ary['cat']) || + (($item_ary['name'] === $id || $item_ary['name'] === $this->p_class . '_' . $id || $item_ary['id'] === (int) $id) && !$mode && !$item_ary['cat']) || (!$id && !$mode && !$item_ary['cat'] && $item_ary['display']) ) { @@ -440,75 +452,74 @@ class p_master trigger_error('Module not accessible', E_USER_ERROR); } - if (!class_exists("{$this->p_class}_$this->p_name")) + // new modules use the full class names, old ones are always called <type>_<name>, e.g. acp_board + if (!class_exists($this->p_name)) { - if (!file_exists("$module_path/{$this->p_class}_$this->p_name.$phpEx")) + if (!file_exists("$module_path/{$this->p_name}.$phpEx")) { - trigger_error("Cannot find module $module_path/{$this->p_class}_$this->p_name.$phpEx", E_USER_ERROR); + trigger_error("Cannot find module $module_path/{$this->p_name}.$phpEx", E_USER_ERROR); } - include("$module_path/{$this->p_class}_$this->p_name.$phpEx"); + include("$module_path/{$this->p_name}.$phpEx"); - if (!class_exists("{$this->p_class}_$this->p_name")) + if (!class_exists($this->p_name)) { - trigger_error("Module file $module_path/{$this->p_class}_$this->p_name.$phpEx does not contain correct class [{$this->p_class}_$this->p_name]", E_USER_ERROR); + trigger_error("Module file $module_path/{$this->p_name}.$phpEx does not contain correct class [{$this->p_name}]", E_USER_ERROR); } + } - if (!empty($mode)) - { - $this->p_mode = $mode; - } + if (!empty($mode)) + { + $this->p_mode = $mode; + } - // Create a new instance of the desired module ... if it has a - // constructor it will of course be executed - $instance = "{$this->p_class}_$this->p_name"; + // Create a new instance of the desired module ... + $class_name = $this->p_name; - $this->module = new $instance($this); + $this->module = new $class_name($this); - // We pre-define the action parameter we are using all over the place - if (defined('IN_ADMIN')) + // We pre-define the action parameter we are using all over the place + if (defined('IN_ADMIN')) + { + // Is first module automatically enabled a duplicate and the category not passed yet? + if (!$icat && $this->module_ary[$this->active_module_row_id]['is_duplicate']) { - // Is first module automatically enabled a duplicate and the category not passed yet? - if (!$icat && $this->module_ary[$this->active_module_row_id]['is_duplicate']) - { - $icat = $this->module_ary[$this->active_module_row_id]['parent']; - } + $icat = $this->module_ary[$this->active_module_row_id]['parent']; + } - // Not being able to overwrite ;) - $this->module->u_action = append_sid("{$phpbb_admin_path}index.$phpEx", "i={$this->p_name}") . (($icat) ? '&icat=' . $icat : '') . "&mode={$this->p_mode}"; + // Not being able to overwrite ;) + $this->module->u_action = append_sid("{$phpbb_admin_path}index.$phpEx", "i={$this->p_name}") . (($icat) ? '&icat=' . $icat : '') . "&mode={$this->p_mode}"; + } + else + { + // If user specified the module url we will use it... + if ($module_url !== false) + { + $this->module->u_action = $module_url; } else { - // If user specified the module url we will use it... - if ($module_url !== false) - { - $this->module->u_action = $module_url; - } - else - { - $this->module->u_action = $phpbb_root_path . (($user->page['page_dir']) ? $user->page['page_dir'] . '/' : '') . $user->page['page_name']; - } - - $this->module->u_action = append_sid($this->module->u_action, "i={$this->p_name}") . (($icat) ? '&icat=' . $icat : '') . "&mode={$this->p_mode}"; + $this->module->u_action = $phpbb_root_path . (($user->page['page_dir']) ? $user->page['page_dir'] . '/' : '') . $user->page['page_name']; } - // Add url_extra parameter to u_action url - if (!empty($this->module_ary) && $this->active_module !== false && $this->module_ary[$this->active_module_row_id]['url_extra']) - { - $this->module->u_action .= $this->module_ary[$this->active_module_row_id]['url_extra']; - } + $this->module->u_action = append_sid($this->module->u_action, "i={$this->p_name}") . (($icat) ? '&icat=' . $icat : '') . "&mode={$this->p_mode}"; + } - // Assign the module path for re-usage - $this->module->module_path = $module_path . '/'; + // Add url_extra parameter to u_action url + if (!empty($this->module_ary) && $this->active_module !== false && $this->module_ary[$this->active_module_row_id]['url_extra']) + { + $this->module->u_action .= $this->module_ary[$this->active_module_row_id]['url_extra']; + } - // Execute the main method for the new instance, we send the module id and mode as parameters - // Users are able to call the main method after this function to be able to assign additional parameters manually - if ($execute_module) - { - $this->module->main($this->p_name, $this->p_mode); - } + // Assign the module path for re-usage + $this->module->module_path = $module_path . '/'; - return; + // Execute the main method for the new instance, we send the module id and mode as parameters + // Users are able to call the main method after this function to be able to assign additional parameters manually + if ($execute_module) + { + $short_name = preg_replace("#^{$this->p_class}_#", '', $this->p_name); + $this->module->main($short_name, $this->p_mode); } } @@ -547,7 +558,7 @@ class p_master // If we find a name by this id and being enabled we have our active one... foreach ($this->module_ary as $row_id => $item_ary) { - if (($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && $item_ary['display']) + if (($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && $item_ary['display'] || $item_ary['name'] === $this->p_class . '_' . $id) { if ($mode === false || $mode === $item_ary['mode']) { @@ -841,7 +852,7 @@ class p_master { foreach ($this->module_ary as $row_id => $item_ary) { - if (($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && (!$mode || $item_ary['mode'] === $mode)) + if (($item_ary['name'] === $id || $item_ary['name'] === $this->p_class . '_' . $id || $item_ary['id'] === (int) $id) && (!$mode || $item_ary['mode'] === $mode)) { $this->module_ary[$row_id]['display'] = (int) $display; } @@ -855,28 +866,49 @@ class p_master { global $user, $phpEx; - if (file_exists($user->lang_path . $user->lang_name . '/mods')) - { - $add_files = array(); + global $phpbb_extension_manager; - $dir = @opendir($user->lang_path . $user->lang_name . '/mods'); + $finder = $phpbb_extension_manager->get_finder(); - if ($dir) - { - while (($entry = readdir($dir)) !== false) - { - if (strpos($entry, 'info_' . strtolower($module_class) . '_') === 0 && substr(strrchr($entry, '.'), 1) == $phpEx) - { - $add_files[] = 'mods/' . substr(basename($entry), 0, -(strlen($phpEx) + 1)); - } - } - closedir($dir); - } + $lang_files = $finder + ->prefix('info_' . strtolower($module_class) . '_') + ->suffix(".$phpEx") + ->extension_directory('/language/' . $user->lang_name) + ->core_path('language/' . $user->lang_name . '/mods/') + ->find(); - if (sizeof($add_files)) - { - $user->add_lang($add_files); - } + foreach ($lang_files as $lang_file => $ext_name) + { + $user->add_lang_ext($ext_name, $lang_file); } } + + /** + * Retrieve shortened module basename for legacy basenames (with xcp_ prefix) + * + * @param string $basename A module basename + * @return string The basename if it starts with phpbb_ or the basename with + * the current p_class (e.g. acp_) stripped. + */ + protected function get_short_name($basename) + { + if (substr($basename, 0, 6) === 'phpbb_') + { + return $basename; + } + + // strip xcp_ prefix from old classes + return substr($basename, strlen($this->p_class) + 1); + } + + /** + * Checks whether the given module basename is a correct class name + * + * @param string $basename A module basename + * @return bool True if the basename starts with phpbb_ or (x)cp_, false otherwise + */ + protected function is_full_class($basename) + { + return (substr($basename, 0, 6) === 'phpbb_' || substr($basename, 0, strlen($this->p_class) + 1) === $this->p_class . '_'); + } } diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 4ca76344de..960359b936 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -1005,7 +1005,7 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id $mode = 'post_review'; } - $sql = $db->sql_build_query('SELECT', array( + $sql_ary = array( 'SELECT' => 'u.username, u.user_id, u.user_colour, p.*, z.friend, z.foe', 'FROM' => array( @@ -1016,14 +1016,15 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id 'LEFT_JOIN' => array( array( 'FROM' => array(ZEBRA_TABLE => 'z'), - 'ON' => 'z.user_id = ' . $user->data['user_id'] . ' AND z.zebra_id = p.poster_id' - ) + 'ON' => 'z.user_id = ' . $user->data['user_id'] . ' AND z.zebra_id = p.poster_id', + ), ), 'WHERE' => $db->sql_in_set('p.post_id', $post_list) . ' - AND u.user_id = p.poster_id' - )); + AND u.user_id = p.poster_id', + ); + $sql = $db->sql_build_query('SELECT', $sql_ary); $result = $db->sql_query($sql); $bbcode_bitfield = ''; @@ -1855,9 +1856,9 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u case 'edit_topic': case 'edit_first_post': - if (isset($poll['poll_options']) && !empty($poll['poll_options'])) + if (isset($poll['poll_options'])) { - $poll_start = ($poll['poll_start']) ? $poll['poll_start'] : $current_time; + $poll_start = ($poll['poll_start'] || empty($poll['poll_options'])) ? $poll['poll_start'] : $current_time; $poll_length = $poll['poll_length'] * 86400; if ($poll_length < 0) { @@ -2005,11 +2006,11 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u } // Update Poll Tables - if (isset($poll['poll_options']) && !empty($poll['poll_options'])) + if (isset($poll['poll_options'])) { $cur_poll_options = array(); - if ($poll['poll_start'] && $mode == 'edit') + if ($mode == 'edit') { $sql = 'SELECT * FROM ' . POLL_OPTIONS_TABLE . ' @@ -2350,16 +2351,11 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u if ($update_search_index && $data['enable_indexing']) { // Select the search method and do some additional checks to ensure it can actually be utilised - $search_type = basename($config['search_type']); - - if (!file_exists($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx)) - { - trigger_error('NO_SUCH_SEARCH_MODULE'); - } + $search_type = $config['search_type']; if (!class_exists($search_type)) { - include("{$phpbb_root_path}includes/search/$search_type.$phpEx"); + trigger_error('NO_SUCH_SEARCH_MODULE'); } $error = false; diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index 32b57a9f2e..76f25da977 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -1330,7 +1330,7 @@ function get_folder_status($folder_id, $folder) 'percent' => ($user->data['message_limit']) ? (($user->data['message_limit'] > 0) ? round(($folder['num_messages'] / $user->data['message_limit']) * 100) : 100) : 0, ); - $return['message'] = sprintf($user->lang['FOLDER_STATUS_MSG'], $return['percent'], $return['cur'], $return['max']); + $return['message'] = $user->lang('FOLDER_STATUS_MSG', (int) $return['max'], $return['cur'], $return['percent']); return $return; } @@ -1652,7 +1652,7 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) // Send Notifications if ($mode != 'edit') { - pm_notification($mode, $data['from_username'], $recipients, $subject, $data['message']); + pm_notification($mode, $data['from_username'], $recipients, $subject, $data['message'], $data['msg_id']); } return $data['msg_id']; @@ -1661,7 +1661,7 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) /** * PM Notification */ -function pm_notification($mode, $author, $recipients, $subject, $message) +function pm_notification($mode, $author, $recipients, $subject, $message, $msg_id) { global $db, $user, $config, $phpbb_root_path, $phpEx, $auth; @@ -1733,8 +1733,9 @@ function pm_notification($mode, $author, $recipients, $subject, $message) 'AUTHOR_NAME' => htmlspecialchars_decode($author), 'USERNAME' => htmlspecialchars_decode($addr['name']), - 'U_INBOX' => generate_board_url() . "/ucp.$phpEx?i=pm&folder=inbox") - ); + 'U_INBOX' => generate_board_url() . "/ucp.$phpEx?i=pm&folder=inbox", + 'U_VIEW_MESSAGE' => generate_board_url() . "/ucp.$phpEx?i=pm&mode=view&p=$msg_id", + )); $messenger->send($addr['method']); } diff --git a/phpBB/includes/functions_profile_fields.php b/phpBB/includes/functions_profile_fields.php index ec29a1732d..130a4dcae8 100644 --- a/phpBB/includes/functions_profile_fields.php +++ b/phpBB/includes/functions_profile_fields.php @@ -315,32 +315,32 @@ class custom_profile case 'FIELD_INVALID_DATE': case 'FIELD_INVALID_VALUE': case 'FIELD_REQUIRED': - $error = sprintf($user->lang[$cp_result], $row['lang_name']); + $error = $user->lang($cp_result, $row['lang_name']); break; case 'FIELD_TOO_SHORT': case 'FIELD_TOO_SMALL': - $error = sprintf($user->lang[$cp_result], $row['lang_name'], $row['field_minlen']); + $error = $user->lang($cp_result, (int) $row['field_minlen'], $row['lang_name']); break; case 'FIELD_TOO_LONG': case 'FIELD_TOO_LARGE': - $error = sprintf($user->lang[$cp_result], $row['lang_name'], $row['field_maxlen']); + $error = $user->lang($cp_result, (int) $row['field_maxlen'], $row['lang_name']); break; case 'FIELD_INVALID_CHARS': switch ($row['field_validation']) { case '[0-9]+': - $error = sprintf($user->lang[$cp_result . '_NUMBERS_ONLY'], $row['lang_name']); + $error = $user->lang($cp_result . '_NUMBERS_ONLY', $row['lang_name']); break; case '[\w]+': - $error = sprintf($user->lang[$cp_result . '_ALPHA_ONLY'], $row['lang_name']); + $error = $user->lang($cp_result . '_ALPHA_ONLY', $row['lang_name']); break; case '[\w_\+\. \-\[\]]+': - $error = sprintf($user->lang[$cp_result . '_SPACERS_ONLY'], $row['lang_name']); + $error = $user->lang($cp_result . '_SPACERS_ONLY', $row['lang_name']); break; } break; diff --git a/phpBB/includes/functions_upload.php b/phpBB/includes/functions_upload.php index f648c585f6..2322aa77bf 100644 --- a/phpBB/includes/functions_upload.php +++ b/phpBB/includes/functions_upload.php @@ -427,7 +427,13 @@ class filespec if (!$this->upload->valid_dimensions($this)) { - $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'WRONG_SIZE'], $this->upload->min_width, $this->upload->min_height, $this->upload->max_width, $this->upload->max_height, $this->width, $this->height); + $this->error[] = $user->lang($this->upload->error_prefix . 'WRONG_SIZE', + $user->lang('PIXELS', (int) $this->upload->min_width), + $user->lang('PIXELS', (int) $this->upload->min_height), + $user->lang('PIXELS', (int) $this->upload->max_width), + $user->lang('PIXELS', (int) $this->upload->max_height), + $user->lang('PIXELS', (int) $this->width), + $user->lang('PIXELS', (int) $this->height)); return false; } diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index 930cd4625f..5631928f96 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -2039,7 +2039,7 @@ function avatar_remote($data, &$error) { if ($width > $config['avatar_max_width'] || $height > $config['avatar_max_height']) { - $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $width, $height); + $error[] = phpbb_avatar_error_wrong_size($width, $height); return false; } } @@ -2048,7 +2048,7 @@ function avatar_remote($data, &$error) { if ($width < $config['avatar_min_width'] || $height < $config['avatar_min_height']) { - $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $width, $height); + $error[] = phpbb_avatar_error_wrong_size($width, $height); return false; } } @@ -2388,7 +2388,7 @@ function avatar_process_user(&$error, $custom_userdata = false, $can_upload = nu { if ($data['width'] > $config['avatar_max_width'] || $data['height'] > $config['avatar_max_height']) { - $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $data['width'], $data['height']); + $error[] = phpbb_avatar_error_wrong_size($data['width'], $data['height']); } } @@ -2398,7 +2398,7 @@ function avatar_process_user(&$error, $custom_userdata = false, $can_upload = nu { if ($data['width'] < $config['avatar_min_width'] || $data['height'] < $config['avatar_min_height']) { - $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $data['width'], $data['height']); + $error[] = phpbb_avatar_error_wrong_size($data['width'], $data['height']); } } } @@ -2444,6 +2444,41 @@ function avatar_process_user(&$error, $custom_userdata = false, $can_upload = nu return (sizeof($error)) ? false : true; } +/** +* Returns a language string with the avatar size of the new avatar and the allowed maximum and minimum +* +* @param $width int The width of the new uploaded/selected avatar +* @param $height int The height of the new uploaded/selected avatar +* @return string +*/ +function phpbb_avatar_error_wrong_size($width, $height) +{ + global $config, $user; + + return $user->lang('AVATAR_WRONG_SIZE', + $user->lang('PIXELS', (int) $config['avatar_min_width']), + $user->lang('PIXELS', (int) $config['avatar_min_height']), + $user->lang('PIXELS', (int) $config['avatar_max_width']), + $user->lang('PIXELS', (int) $config['avatar_max_height']), + $user->lang('PIXELS', (int) $width), + $user->lang('PIXELS', (int) $height)); +} + +/** +* Returns an explanation string with maximum avatar settings +* +* @return string +*/ +function phpbb_avatar_explanation_string() +{ + global $config, $user; + + return $user->lang('AVATAR_EXPLAIN', + $user->lang('PIXELS', (int) $config['avatar_max_width']), + $user->lang('PIXELS', (int) $config['avatar_max_height']), + round($config['avatar_filesize'] / 1024)); +} + // // Usergroup functions // diff --git a/phpBB/includes/mcp/mcp_forum.php b/phpBB/includes/mcp/mcp_forum.php index 8206a183f3..c823e0a0ee 100644 --- a/phpBB/includes/mcp/mcp_forum.php +++ b/phpBB/includes/mcp/mcp_forum.php @@ -132,7 +132,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info) 'PAGINATION' => generate_pagination($url . "&i=$id&action=$action&mode=$mode&sd=$sort_dir&sk=$sort_key&st=$sort_days" . (($merge_select) ? $selected_ids : ''), $forum_topics, $topics_per_page, $start), 'PAGE_NUMBER' => on_page($forum_topics, $topics_per_page, $start), - 'TOTAL_TOPICS' => ($forum_topics == 1) ? $user->lang['VIEW_FORUM_TOPIC'] : sprintf($user->lang['VIEW_FORUM_TOPICS'], $forum_topics), + 'TOTAL_TOPICS' => $user->lang('VIEW_FORUM_TOPICS', (int) $forum_topics), )); // Grab icons diff --git a/phpBB/includes/mcp/mcp_front.php b/phpBB/includes/mcp/mcp_front.php index eca67c5ac1..4ae46f98a2 100644 --- a/phpBB/includes/mcp/mcp_front.php +++ b/phpBB/includes/mcp/mcp_front.php @@ -79,7 +79,7 @@ function mcp_front_view($id, $mode, $action) if ($total) { - $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.username, u.username_clean, u.user_colour, t.topic_id, t.topic_title, t.topic_first_post_id, p.forum_id + $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.post_attachment, p.poster_id, p.post_username, u.username, u.username_clean, u.user_colour, t.topic_id, t.topic_title, t.topic_first_post_id, p.forum_id FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t, ' . USERS_TABLE . ' u WHERE ' . $db->sql_in_set('p.post_id', $post_list) . ' AND t.topic_id = p.topic_id @@ -105,8 +105,9 @@ function mcp_front_view($id, $mode, $action) 'POST_ID' => $row['post_id'], 'TOPIC_TITLE' => $row['topic_title'], 'SUBJECT' => ($row['post_subject']) ? $row['post_subject'] : $user->lang['NO_SUBJECT'], - 'POST_TIME' => $user->format_date($row['post_time'])) - ); + 'POST_TIME' => $user->format_date($row['post_time']), + 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']) && $row['post_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', + )); } $db->sql_freeresult($result); } @@ -118,22 +119,9 @@ function mcp_front_view($id, $mode, $action) $template->assign_vars(array( 'S_HIDDEN_FIELDS' => $s_hidden_fields, 'S_MCP_QUEUE_ACTION' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=queue"), + 'L_UNAPPROVED_TOTAL' => $user->lang('UNAPPROVED_POSTS_TOTAL', (int) $total), + 'S_HAS_UNAPPROVED_POSTS'=> ($total != 0), )); - - if ($total == 0) - { - $template->assign_vars(array( - 'L_UNAPPROVED_TOTAL' => $user->lang['UNAPPROVED_POSTS_ZERO_TOTAL'], - 'S_HAS_UNAPPROVED_POSTS' => false) - ); - } - else - { - $template->assign_vars(array( - 'L_UNAPPROVED_TOTAL' => ($total == 1) ? $user->lang['UNAPPROVED_POST_TOTAL'] : sprintf($user->lang['UNAPPROVED_POSTS_TOTAL'], $total), - 'S_HAS_UNAPPROVED_POSTS' => true) - ); - } } } @@ -158,22 +146,22 @@ function mcp_front_view($id, $mode, $action) if ($total) { - $sql = $db->sql_build_query('SELECT', array( - 'SELECT' => 'r.report_time, p.post_id, p.post_subject, p.post_time, u.username, u.username_clean, u.user_colour, u.user_id, u2.username as author_name, u2.username_clean as author_name_clean, u2.user_colour as author_colour, u2.user_id as author_id, t.topic_id, t.topic_title, f.forum_id, f.forum_name', + $sql_ary = array( + 'SELECT' => 'r.report_time, p.post_id, p.post_subject, p.post_time, p.post_attachment, u.username, u.username_clean, u.user_colour, u.user_id, u2.username as author_name, u2.username_clean as author_name_clean, u2.user_colour as author_colour, u2.user_id as author_id, t.topic_id, t.topic_title, f.forum_id, f.forum_name', 'FROM' => array( REPORTS_TABLE => 'r', REPORTS_REASONS_TABLE => 'rr', TOPICS_TABLE => 't', USERS_TABLE => array('u', 'u2'), - POSTS_TABLE => 'p' + POSTS_TABLE => 'p', ), 'LEFT_JOIN' => array( array( 'FROM' => array(FORUMS_TABLE => 'f'), - 'ON' => 'f.forum_id = p.forum_id' - ) + 'ON' => 'f.forum_id = p.forum_id', + ), ), 'WHERE' => 'r.post_id = p.post_id @@ -185,8 +173,9 @@ function mcp_front_view($id, $mode, $action) AND p.poster_id = u2.user_id AND ' . $db->sql_in_set('p.forum_id', $forum_list), - 'ORDER_BY' => 'p.post_time DESC' - )); + 'ORDER_BY' => 'p.post_time DESC', + ); + $sql = $db->sql_build_query('SELECT', $sql_ary); $result = $db->sql_query_limit($sql, 5); while ($row = $db->sql_fetchrow($result)) @@ -213,24 +202,15 @@ function mcp_front_view($id, $mode, $action) 'SUBJECT' => ($row['post_subject']) ? $row['post_subject'] : $user->lang['NO_SUBJECT'], 'REPORT_TIME' => $user->format_date($row['report_time']), 'POST_TIME' => $user->format_date($row['post_time']), + 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']) && $row['post_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', )); } } - if ($total == 0) - { - $template->assign_vars(array( - 'L_REPORTS_TOTAL' => $user->lang['REPORTS_ZERO_TOTAL'], - 'S_HAS_REPORTS' => false) - ); - } - else - { - $template->assign_vars(array( - 'L_REPORTS_TOTAL' => ($total == 1) ? $user->lang['REPORT_TOTAL'] : sprintf($user->lang['REPORTS_TOTAL'], $total), - 'S_HAS_REPORTS' => true) - ); - } + $template->assign_vars(array( + 'L_REPORTS_TOTAL' => $user->lang('REPORTS_TOTAL', (int) $total), + 'S_HAS_REPORTS' => ($total != 0), + )); } } @@ -253,14 +233,14 @@ function mcp_front_view($id, $mode, $action) { include($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx); - $sql = $db->sql_build_query('SELECT', array( - 'SELECT' => 'r.report_id, r.report_time, p.msg_id, p.message_subject, p.message_time, p.to_address, p.bcc_address, u.username, u.username_clean, u.user_colour, u.user_id, u2.username as author_name, u2.username_clean as author_name_clean, u2.user_colour as author_colour, u2.user_id as author_id', + $sql_ary = array( + 'SELECT' => 'r.report_id, r.report_time, p.msg_id, p.message_subject, p.message_time, p.to_address, p.bcc_address, p.message_attachment, u.username, u.username_clean, u.user_colour, u.user_id, u2.username as author_name, u2.username_clean as author_name_clean, u2.user_colour as author_colour, u2.user_id as author_id', 'FROM' => array( REPORTS_TABLE => 'r', REPORTS_REASONS_TABLE => 'rr', USERS_TABLE => array('u', 'u2'), - PRIVMSGS_TABLE => 'p' + PRIVMSGS_TABLE => 'p', ), 'WHERE' => 'r.pm_id = p.msg_id @@ -270,8 +250,9 @@ function mcp_front_view($id, $mode, $action) AND r.user_id = u.user_id AND p.author_id = u2.user_id', - 'ORDER_BY' => 'p.message_time DESC' - )); + 'ORDER_BY' => 'p.message_time DESC', + ); + $sql_ary = $db->sql_build_query('SELECT', $sql_ary); $result = $db->sql_query_limit($sql, 5); $pm_by_id = $pm_list = array(); @@ -304,24 +285,15 @@ function mcp_front_view($id, $mode, $action) 'REPORT_TIME' => $user->format_date($row['report_time']), 'PM_TIME' => $user->format_date($row['message_time']), 'RECIPIENTS' => implode(', ', $address_list[$row['msg_id']]), + 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $row['message_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', )); } } - if ($total == 0) - { - $template->assign_vars(array( - 'L_PM_REPORTS_TOTAL' => $user->lang['PM_REPORTS_ZERO_TOTAL'], - 'S_HAS_PM_REPORTS' => false) - ); - } - else - { - $template->assign_vars(array( - 'L_PM_REPORTS_TOTAL' => ($total == 1) ? $user->lang['PM_REPORT_TOTAL'] : sprintf($user->lang['PM_REPORTS_TOTAL'], $total), - 'S_HAS_PM_REPORTS' => true) - ); - } + $template->assign_vars(array( + 'L_PM_REPORTS_TOTAL' => $user->lang('PM_REPORTS_TOTAL', (int) $total), + 'S_HAS_PM_REPORTS' => ($total != 0), + )); } // Latest 5 logs diff --git a/phpBB/includes/mcp/mcp_logs.php b/phpBB/includes/mcp/mcp_logs.php index dc05ba4110..52f8259acf 100644 --- a/phpBB/includes/mcp/mcp_logs.php +++ b/phpBB/includes/mcp/mcp_logs.php @@ -174,7 +174,7 @@ class mcp_logs $template->assign_vars(array( 'PAGE_NUMBER' => on_page($log_count, $config['topics_per_page'], $start), - 'TOTAL' => ($log_count == 1) ? $user->lang['TOTAL_LOG'] : sprintf($user->lang['TOTAL_LOGS'], $log_count), + 'TOTAL' => $user->lang('TOTAL_LOGS', (int) $log_count), 'PAGINATION' => generate_pagination($this->u_action . "&$u_sort_param$keywords_param", $log_count, $config['topics_per_page'], $start), 'L_TITLE' => $user->lang['MCP_LOGS'], diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index 6c6c5a5532..e0a1357213 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -286,14 +286,6 @@ function change_topic_type($action, $topic_ids) { global $auth, $user, $db, $phpEx, $phpbb_root_path; - // For changing topic types, we only allow operations in one forum. - $forum_id = check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('f_announce', 'f_sticky', 'm_'), true); - - if ($forum_id === false) - { - return; - } - switch ($action) { case 'make_announce': @@ -316,11 +308,18 @@ function change_topic_type($action, $topic_ids) default: $new_topic_type = POST_NORMAL; - $check_acl = ''; + $check_acl = false; $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_NORMAL' : 'MCP_MAKE_NORMALS'; break; } + $forum_id = check_ids($topic_ids, TOPICS_TABLE, 'topic_id', $check_acl, true); + + if ($forum_id === false) + { + return; + } + $redirect = request_var('redirect', build_url(array('action', 'quickmod'))); $s_hidden_fields = array( diff --git a/phpBB/includes/mcp/mcp_notes.php b/phpBB/includes/mcp/mcp_notes.php index dfb6ed3b68..1432e96a48 100644 --- a/phpBB/includes/mcp/mcp_notes.php +++ b/phpBB/includes/mcp/mcp_notes.php @@ -228,7 +228,7 @@ class mcp_notes 'PAGE_NUMBER' => on_page($log_count, $config['topics_per_page'], $start), 'PAGINATION' => generate_pagination($this->u_action . "&$u_sort_param$keywords_param", $log_count, $config['topics_per_page'], $start), - 'TOTAL_REPORTS' => ($log_count == 1) ? $user->lang['LIST_REPORT'] : sprintf($user->lang['LIST_REPORTS'], $log_count), + 'TOTAL_REPORTS' => $user->lang('LIST_REPORTS', (int) $log_count), 'RANK_TITLE' => $rank_title, 'JOINED' => $user->format_date($userrow['user_regdate']), diff --git a/phpBB/includes/mcp/mcp_pm_reports.php b/phpBB/includes/mcp/mcp_pm_reports.php index e61e8390c9..6bba71f0d9 100644 --- a/phpBB/includes/mcp/mcp_pm_reports.php +++ b/phpBB/includes/mcp/mcp_pm_reports.php @@ -293,6 +293,7 @@ class mcp_pm_reports 'REPORT_TIME' => $user->format_date($row['report_time']), 'RECIPIENTS' => implode(', ', $address_list[$row['msg_id']]), + 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $row['message_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', )); } } @@ -310,7 +311,7 @@ class mcp_pm_reports 'PAGINATION' => generate_pagination($this->u_action . "&st=$sort_days&sk=$sort_key&sd=$sort_dir", $total, $config['topics_per_page'], $start), 'PAGE_NUMBER' => on_page($total, $config['topics_per_page'], $start), 'TOTAL' => $total, - 'TOTAL_REPORTS' => ($total == 1) ? $user->lang['LIST_REPORT'] : sprintf($user->lang['LIST_REPORTS'], $total), + 'TOTAL_REPORTS' => $user->lang('LIST_REPORTS', (int) $total), ) ); diff --git a/phpBB/includes/mcp/mcp_post.php b/phpBB/includes/mcp/mcp_post.php index 4e0aae1870..2abded4483 100644 --- a/phpBB/includes/mcp/mcp_post.php +++ b/phpBB/includes/mcp/mcp_post.php @@ -246,7 +246,7 @@ function mcp_post_details($id, $mode, $action) } // Get Reports - if ($auth->acl_get('m_', $post_info['forum_id'])) + if ($auth->acl_get('m_report', $post_info['forum_id'])) { $sql = 'SELECT r.*, re.*, u.user_id, u.username FROM ' . REPORTS_TABLE . ' r, ' . USERS_TABLE . ' u, ' . REPORTS_REASONS_TABLE . " re diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php index 0630f55b12..692d29dabb 100644 --- a/phpBB/includes/mcp/mcp_queue.php +++ b/phpBB/includes/mcp/mcp_queue.php @@ -216,6 +216,7 @@ class mcp_queue 'POST_IP' => $post_info['poster_ip'], 'POST_IPADDR' => ($auth->acl_get('m_info', $post_info['forum_id']) && request_var('lookup', '')) ? @gethostbyaddr($post_info['poster_ip']) : '', 'POST_ID' => $post_info['post_id'], + 'S_FIRST_POST' => ($post_info['topic_first_post_id'] == $post_id), 'U_LOOKUP_IP' => ($auth->acl_get('m_info', $post_info['forum_id'])) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=queue&mode=approve_details&f=' . $post_info['forum_id'] . '&p=' . $post_id . '&lookup=' . $post_info['poster_ip']) . '#ip' : '', )); @@ -331,7 +332,7 @@ class mcp_queue if (sizeof($post_ids)) { - $sql = 'SELECT t.topic_id, t.topic_title, t.forum_id, p.post_id, p.post_subject, p.post_username, p.poster_id, p.post_time, u.username, u.username_clean, u.user_colour + $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, p.post_attachment, u.username, u.username_clean, u.user_colour FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t, ' . USERS_TABLE . ' u WHERE ' . $db->sql_in_set('p.post_id', $post_ids) . ' AND t.topic_id = p.topic_id @@ -360,7 +361,7 @@ class mcp_queue } else { - $sql = 'SELECT t.forum_id, t.topic_id, t.topic_title, t.topic_title AS post_subject, t.topic_time AS post_time, t.topic_poster AS poster_id, t.topic_first_post_id AS post_id, t.topic_first_poster_name AS username, t.topic_first_poster_colour AS user_colour + $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_attachment AS post_attachment, t.topic_first_poster_name AS username, t.topic_first_poster_colour AS user_colour FROM ' . TOPICS_TABLE . " t WHERE " . $db->sql_in_set('forum_id', $forum_list) . " AND topic_approved = 0 @@ -415,8 +416,9 @@ class mcp_queue 'FORUM_NAME' => $forum_names[$row['forum_id']], 'POST_SUBJECT' => ($row['post_subject'] != '') ? $row['post_subject'] : $user->lang['NO_SUBJECT'], 'TOPIC_TITLE' => $row['topic_title'], - 'POST_TIME' => $user->format_date($row['post_time'])) - ); + 'POST_TIME' => $user->format_date($row['post_time']), + 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']) && $row['post_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', + )); } unset($rowset, $forum_names); @@ -434,7 +436,7 @@ class mcp_queue 'PAGINATION' => generate_pagination($this->u_action . "&f=$forum_id&st=$sort_days&sk=$sort_key&sd=$sort_dir", $total, $config['topics_per_page'], $start), 'PAGE_NUMBER' => on_page($total, $config['topics_per_page'], $start), 'TOPIC_ID' => $topic_id, - 'TOTAL' => ($total == 1) ? (($mode == 'unapproved_posts') ? $user->lang['VIEW_TOPIC_POST'] : $user->lang['VIEW_FORUM_TOPIC']) : sprintf((($mode == 'unapproved_posts') ? $user->lang['VIEW_TOPIC_POSTS'] : $user->lang['VIEW_FORUM_TOPICS']), $total), + 'TOTAL' => $user->lang((($mode == 'unapproved_posts') ? 'VIEW_TOPIC_POSTS' : 'VIEW_FORUM_TOPICS'), (int) $total), )); $this->tpl_name = 'mcp_queue'; @@ -754,7 +756,10 @@ function disapprove_post($post_id_list, $id, $mode) if (!$row || (!$reason && strtolower($row['reason_title']) == 'other')) { $additional_msg = $user->lang['NO_REASON_DISAPPROVAL']; + $request->overwrite('confirm', null, phpbb_request_interface::POST); + $request->overwrite('confirm_key', null, phpbb_request_interface::POST); + $request->overwrite('confirm_key', null, phpbb_request_interface::REQUEST); } else { diff --git a/phpBB/includes/mcp/mcp_reports.php b/phpBB/includes/mcp/mcp_reports.php index a7275382e6..eb2b655dd3 100644 --- a/phpBB/includes/mcp/mcp_reports.php +++ b/phpBB/includes/mcp/mcp_reports.php @@ -148,6 +148,7 @@ class mcp_reports $message = bbcode_nl2br($message); $message = smiley_text($message); + $report['report_text'] = make_clickable(bbcode_nl2br($report['report_text'])); if ($post_info['post_attachment'] && $auth->acl_get('u_download') && $auth->acl_get('f_download', $post_info['forum_id'])) { @@ -367,7 +368,7 @@ class mcp_reports if (sizeof($report_ids)) { - $sql = 'SELECT t.forum_id, t.topic_id, t.topic_title, p.post_id, p.post_subject, p.post_username, p.poster_id, p.post_time, u.username, u.username_clean, u.user_colour, r.user_id as reporter_id, ru.username as reporter_name, ru.user_colour as reporter_colour, r.report_time, r.report_id + $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, p.post_attachment, u.username, u.username_clean, u.user_colour, r.user_id as reporter_id, ru.username as reporter_name, ru.user_colour as reporter_colour, r.report_time, r.report_id FROM ' . REPORTS_TABLE . ' r, ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t, ' . USERS_TABLE . ' u, ' . USERS_TABLE . ' ru WHERE ' . $db->sql_in_set('r.report_id', $report_ids) . ' AND t.topic_id = p.topic_id @@ -402,8 +403,9 @@ class mcp_reports 'POST_TIME' => $user->format_date($row['post_time']), 'REPORT_ID' => $row['report_id'], 'REPORT_TIME' => $user->format_date($row['report_time']), - 'TOPIC_TITLE' => $row['topic_title']) - ); + 'TOPIC_TITLE' => $row['topic_title'], + 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']) && $row['post_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', + )); } $db->sql_freeresult($result); unset($report_ids, $row); @@ -423,7 +425,7 @@ class mcp_reports 'PAGE_NUMBER' => on_page($total, $config['topics_per_page'], $start), 'TOPIC_ID' => $topic_id, 'TOTAL' => $total, - 'TOTAL_REPORTS' => ($total == 1) ? $user->lang['LIST_REPORT'] : sprintf($user->lang['LIST_REPORTS'], $total), + 'TOTAL_REPORTS' => $user->lang('LIST_REPORTS', (int) $total), ) ); diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php index 8a8ef11289..463dd5868d 100644 --- a/phpBB/includes/mcp/mcp_topic.php +++ b/phpBB/includes/mcp/mcp_topic.php @@ -239,8 +239,8 @@ function mcp_topic_view($id, $mode, $action) 'MINI_POST_IMG' => ($post_unread) ? $user->img('icon_post_target_unread', 'UNREAD_POST') : $user->img('icon_post_target', 'POST'), - 'S_POST_REPORTED' => ($row['post_reported']) ? true : false, - 'S_POST_UNAPPROVED' => ($row['post_approved']) ? false : true, + 'S_POST_REPORTED' => ($row['post_reported'] && $auth->acl_get('m_report', $topic_info['forum_id'])), + 'S_POST_UNAPPROVED' => (!$row['post_approved'] && $auth->acl_get('m_approve', $topic_info['forum_id'])), 'S_CHECKED' => (($submitted_id_list && !in_array(intval($row['post_id']), $submitted_id_list)) || in_array(intval($row['post_id']), $checked_ids)) ? true : false, 'S_HAS_ATTACHMENTS' => (!empty($attachments[$row['post_id']])) ? true : false, @@ -336,7 +336,7 @@ function mcp_topic_view($id, $mode, $action) 'PAGE_NUMBER' => on_page($total, $posts_per_page, $start), 'PAGINATION' => (!$posts_per_page) ? '' : generate_pagination(append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&t={$topic_info['topic_id']}&mode=$mode&action=$action&to_topic_id=$to_topic_id&posts_per_page=$posts_per_page&st=$sort_days&sk=$sort_key&sd=$sort_dir"), $total, $posts_per_page, $start), - 'TOTAL_POSTS' => ($total == 1) ? $user->lang['VIEW_TOPIC_POST'] : sprintf($user->lang['VIEW_TOPIC_POSTS'], $total), + 'TOTAL_POSTS' => $user->lang('VIEW_TOPIC_POSTS', (int) $total), )); } diff --git a/phpBB/includes/mcp/mcp_warn.php b/phpBB/includes/mcp/mcp_warn.php index 9339389ea4..8cf435c293 100644 --- a/phpBB/includes/mcp/mcp_warn.php +++ b/phpBB/includes/mcp/mcp_warn.php @@ -185,7 +185,7 @@ class mcp_warn 'PAGE_NUMBER' => on_page($user_count, $config['topics_per_page'], $start), 'PAGINATION' => generate_pagination(append_sid("{$phpbb_root_path}mcp.$phpEx", "i=warn&mode=list&st=$st&sk=$sk&sd=$sd"), $user_count, $config['topics_per_page'], $start), - 'TOTAL_USERS' => ($user_count == 1) ? $user->lang['LIST_USER'] : sprintf($user->lang['LIST_USERS'], $user_count), + 'TOTAL_USERS' => $user->lang('LIST_USERS', (int) $user_count), )); } diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index b3a48112ea..5e8732e94d 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -210,7 +210,7 @@ class bbcode_firstpass extends bbcode if ($config['max_' . $this->mode . '_font_size'] && $config['max_' . $this->mode . '_font_size'] < $stx) { - $this->warn_msg[] = sprintf($user->lang['MAX_FONT_SIZE_EXCEEDED'], $config['max_' . $this->mode . '_font_size']); + $this->warn_msg[] = $user->lang('MAX_FONT_SIZE_EXCEEDED', (int) $config['max_' . $this->mode . '_font_size']); return '[size=' . $stx . ']' . $in . '[/size]'; } @@ -319,13 +319,13 @@ class bbcode_firstpass extends bbcode if ($config['max_' . $this->mode . '_img_height'] && $config['max_' . $this->mode . '_img_height'] < $stats[1]) { $error = true; - $this->warn_msg[] = sprintf($user->lang['MAX_IMG_HEIGHT_EXCEEDED'], $config['max_' . $this->mode . '_img_height']); + $this->warn_msg[] = $user->lang('MAX_IMG_HEIGHT_EXCEEDED', (int) $config['max_' . $this->mode . '_img_height']); } if ($config['max_' . $this->mode . '_img_width'] && $config['max_' . $this->mode . '_img_width'] < $stats[0]) { $error = true; - $this->warn_msg[] = sprintf($user->lang['MAX_IMG_WIDTH_EXCEEDED'], $config['max_' . $this->mode . '_img_width']); + $this->warn_msg[] = $user->lang('MAX_IMG_WIDTH_EXCEEDED', (int) $config['max_' . $this->mode . '_img_width']); } } } @@ -374,13 +374,13 @@ class bbcode_firstpass extends bbcode if ($config['max_' . $this->mode . '_img_height'] && $config['max_' . $this->mode . '_img_height'] < $height) { $error = true; - $this->warn_msg[] = sprintf($user->lang['MAX_FLASH_HEIGHT_EXCEEDED'], $config['max_' . $this->mode . '_img_height']); + $this->warn_msg[] = $user->lang('MAX_FLASH_HEIGHT_EXCEEDED', (int) $config['max_' . $this->mode . '_img_height']); } if ($config['max_' . $this->mode . '_img_width'] && $config['max_' . $this->mode . '_img_width'] < $width) { $error = true; - $this->warn_msg[] = sprintf($user->lang['MAX_FLASH_WIDTH_EXCEEDED'], $config['max_' . $this->mode . '_img_width']); + $this->warn_msg[] = $user->lang('MAX_FLASH_WIDTH_EXCEEDED', (int) $config['max_' . $this->mode . '_img_width']); } } @@ -772,7 +772,7 @@ class bbcode_firstpass extends bbcode if ($config['max_quote_depth'] && sizeof($close_tags) >= $config['max_quote_depth']) { // there are too many nested quotes - $error_ary['quote_depth'] = sprintf($user->lang['QUOTE_DEPTH_EXCEEDED'], $config['max_quote_depth']); + $error_ary['quote_depth'] = $user->lang('QUOTE_DEPTH_EXCEEDED', (int) $config['max_quote_depth']); $out .= $buffer . $tok; $tok = '[]'; @@ -1117,7 +1117,7 @@ class parse_message extends bbcode_firstpass // Maximum message length check. 0 disables this check completely. if ((int) $config['max_' . $mode . '_chars'] > 0 && $message_length > (int) $config['max_' . $mode . '_chars']) { - $this->warn_msg[] = sprintf($user->lang['TOO_MANY_CHARS_' . strtoupper($mode)], $message_length, (int) $config['max_' . $mode . '_chars']); + $this->warn_msg[] = $user->lang('TOO_MANY_CHARS_' . strtoupper($mode), $message_length, (int) $config['max_' . $mode . '_chars']); return (!$update_this_message) ? $return_message : $this->warn_msg; } @@ -1126,7 +1126,7 @@ class parse_message extends bbcode_firstpass { if (!$message_length || $message_length < (int) $config['min_post_chars']) { - $this->warn_msg[] = (!$message_length) ? $user->lang['TOO_FEW_CHARS'] : sprintf($user->lang['TOO_FEW_CHARS_LIMIT'], $message_length, (int) $config['min_post_chars']); + $this->warn_msg[] = (!$message_length) ? $user->lang['TOO_FEW_CHARS'] : $user->lang('TOO_FEW_CHARS_LIMIT', $message_length, (int) $config['min_post_chars']); return (!$update_this_message) ? $return_message : $this->warn_msg; } } @@ -1445,7 +1445,7 @@ class parse_message extends bbcode_firstpass } else { - $error[] = sprintf($user->lang['TOO_MANY_ATTACHMENTS'], $cfg['max_attachments']); + $error[] = $user->lang('TOO_MANY_ATTACHMENTS', (int) $cfg['max_attachments']); } } @@ -1536,7 +1536,7 @@ class parse_message extends bbcode_firstpass } else { - $error[] = sprintf($user->lang['TOO_MANY_ATTACHMENTS'], $cfg['max_attachments']); + $error[] = $user->lang('TOO_MANY_ATTACHMENTS', (int) $cfg['max_attachments']); } } } diff --git a/phpBB/includes/search/search.php b/phpBB/includes/search/base.php index 7c34ce9ff6..bb63957aba 100644 --- a/phpBB/includes/search/search.php +++ b/phpBB/includes/search/base.php @@ -24,12 +24,12 @@ define('SEARCH_RESULT_IN_CACHE', 1); define('SEARCH_RESULT_INCOMPLETE', 2); /** -* search_backend +* phpbb_search_base * optional base class for search plugins providing simple caching based on ACM * and functions to retrieve ignore_words and synonyms * @package search */ -class search_backend +class phpbb_search_base { var $ignore_words = array(); var $match_synonym = array(); diff --git a/phpBB/includes/search/fulltext_mysql.php b/phpBB/includes/search/fulltext_mysql.php index 827205f20d..4214de3d97 100644 --- a/phpBB/includes/search/fulltext_mysql.php +++ b/phpBB/includes/search/fulltext_mysql.php @@ -17,16 +17,11 @@ if (!defined('IN_PHPBB')) } /** -* @ignore -*/ -include_once($phpbb_root_path . 'includes/search/search.' . $phpEx); - -/** * fulltext_mysql * Fulltext search for MySQL * @package search */ -class fulltext_mysql extends search_backend +class phpbb_search_fulltext_mysql extends phpbb_search_base { var $stats = array(); var $word_length = array(); @@ -36,7 +31,7 @@ class fulltext_mysql extends search_backend var $pcre_properties = false; var $mbstring_regex = false; - function fulltext_mysql(&$error) + public function __construct(&$error) { global $config; @@ -58,6 +53,16 @@ class fulltext_mysql extends search_backend } /** + * Returns the name of this search backend to be displayed to administrators + * + * @return string Name + */ + public function get_name() + { + return 'MySQL Fulltext'; + } + + /** * Checks for correct MySQL version and stores min/max word length in the config */ function init() diff --git a/phpBB/includes/search/fulltext_native.php b/phpBB/includes/search/fulltext_native.php index e749e86f68..a335ddab6e 100644 --- a/phpBB/includes/search/fulltext_native.php +++ b/phpBB/includes/search/fulltext_native.php @@ -17,16 +17,11 @@ if (!defined('IN_PHPBB')) } /** -* @ignore -*/ -include_once($phpbb_root_path . 'includes/search/search.' . $phpEx); - -/** * fulltext_native * phpBB's own db driven fulltext search, version 2 * @package search */ -class fulltext_native extends search_backend +class phpbb_search_fulltext_native extends phpbb_search_base { var $stats = array(); var $word_length = array(); @@ -41,10 +36,8 @@ class fulltext_native extends search_backend * 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) + public function __construct(&$error) { global $phpbb_root_path, $phpEx, $config; @@ -58,11 +51,20 @@ class fulltext_native extends search_backend include($phpbb_root_path . 'includes/utf/utf_normalizer.' . $phpEx); } - $error = false; } /** + * Returns the name of this search backend to be displayed to administrators + * + * @return string Name + */ + public function get_name() + { + return 'phpBB Native Fulltext'; + } + + /** * 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 diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php index bd2257c139..fcbe8aed2c 100644 --- a/phpBB/includes/session.php +++ b/phpBB/includes/session.php @@ -1821,6 +1821,9 @@ class user extends session * This function/functionality is inspired by SHS` and Ashe. * * Example call: <samp>$user->lang('NUM_POSTS_IN_QUEUE', 1);</samp> + * + * If the first parameter is an array, the elements are used as keys and subkeys to get the language entry: + * Example: <samp>$user->lang(array('datetime', 'AGO'), 1)</samp> uses $user->lang['datetime']['AGO'] as language entry. */ function lang() { @@ -1859,6 +1862,11 @@ class user extends session $args[0] = $lang; return call_user_func_array('sprintf', $args); } + else if (sizeof($lang) == 0) + { + // If the language entry is an empty array, we just return the language key + return $args[0]; + } // It is an array... now handle different nullar/singular/plural forms $key_found = false; @@ -1866,20 +1874,40 @@ class user extends session // We now get the first number passed and will select the key based upon this number for ($i = 1, $num_args = sizeof($args); $i < $num_args; $i++) { - if (is_int($args[$i])) + if (is_int($args[$i]) || is_float($args[$i])) { - $numbers = array_keys($lang); - - foreach ($numbers as $num) + if ($args[$i] == 0 && isset($lang[0])) + { + // We allow each translation using plural forms to specify a version for the case of 0 things, + // so that "0 users" may be displayed as "No users". + $key_found = 0; + break; + } + else { - if ($num > $args[$i]) + $use_plural_form = $this->get_plural_form($args[$i]); + if (isset($lang[$use_plural_form])) { - break; + // The key we should use exists, so we use it. + $key_found = $use_plural_form; } + else + { + // If the key we need to use does not exist, we fall back to the previous one. + $numbers = array_keys($lang); - $key_found = $num; + foreach ($numbers as $num) + { + if ($num > $use_plural_form) + { + break; + } + + $key_found = $num; + } + } + break; } - break; } } @@ -1896,11 +1924,31 @@ class user extends session } /** + * Determine which plural form we should use. + * For some languages this is not as simple as for English. + * + * @param $number int|float The number we want to get the plural case for. Float numbers are floored. + * @param $force_rule mixed False to use the plural rule of the language package + * or an integer to force a certain plural rule + * @return int The plural-case we need to use for the number plural-rule combination + */ + function get_plural_form($number, $force_rule = false) + { + $number = (int) $number; + + // Default to English system + $plural_rule = ($force_rule !== false) ? $force_rule : ((isset($this->lang['PLURAL_RULE'])) ? $this->lang['PLURAL_RULE'] : 1); + + return phpbb_get_plural_form($plural_rule, $number); + } + + /** * Add Language Items - use_db and use_help are assigned where needed (only use them to force inclusion) * * @param mixed $lang_set specifies the language entries to include * @param bool $use_db internal variable for recursion, do not use * @param bool $use_help internal variable for recursion, do not use + * @param string $ext_name The extension to load language from, or empty for core files * * Examples: * <code> @@ -1911,7 +1959,7 @@ class user extends session * $lang_set = array('help' => 'faq', 'db' => array('help:faq', 'posting')) * </code> */ - function add_lang($lang_set, $use_db = false, $use_help = false) + function add_lang($lang_set, $use_db = false, $use_help = false, $ext_name = '') { global $phpEx; @@ -1925,36 +1973,54 @@ class user extends session if ($key == 'db') { - $this->add_lang($lang_file, true, $use_help); + $this->add_lang($lang_file, true, $use_help, $ext_name); } else if ($key == 'help') { - $this->add_lang($lang_file, $use_db, true); + $this->add_lang($lang_file, $use_db, true, $ext_name); } else if (!is_array($lang_file)) { - $this->set_lang($this->lang, $this->help, $lang_file, $use_db, $use_help); + $this->set_lang($this->lang, $this->help, $lang_file, $use_db, $use_help, $ext_name); } else { - $this->add_lang($lang_file, $use_db, $use_help); + $this->add_lang($lang_file, $use_db, $use_help, $ext_name); } } unset($lang_set); } else if ($lang_set) { - $this->set_lang($this->lang, $this->help, $lang_set, $use_db, $use_help); + $this->set_lang($this->lang, $this->help, $lang_set, $use_db, $use_help, $ext_name); } } /** + * Add Language Items from an extension - use_db and use_help are assigned where needed (only use them to force inclusion) + * + * @param string $ext_name The extension to load language from, or empty for core files + * @param mixed $lang_set specifies the language entries to include + * @param bool $use_db internal variable for recursion, do not use + * @param bool $use_help internal variable for recursion, do not use + */ + function add_lang_ext($ext_name, $lang_set, $use_db = false, $use_help = false) + { + if ($ext_name === '/') + { + $ext_name = ''; + } + + $this->add_lang($lang_set, $use_db, $use_help, $ext_name); + } + + /** * Set language entry (called by add_lang) * @access private */ - function set_lang(&$lang, &$help, $lang_file, $use_db = false, $use_help = false) + function set_lang(&$lang, &$help, $lang_file, $use_db = false, $use_help = false, $ext_name = '') { - global $phpEx; + global $phpbb_root_path, $phpEx; // Make sure the language name is set (if the user setup did not happen it is not set) if (!$this->lang_name) @@ -1970,11 +2036,32 @@ class user extends session { if ($use_help && strpos($lang_file, '/') !== false) { - $language_filename = $this->lang_path . $this->lang_name . '/' . substr($lang_file, 0, stripos($lang_file, '/') + 1) . 'help_' . substr($lang_file, stripos($lang_file, '/') + 1) . '.' . $phpEx; + $filename = dirname($lang_file) . '/help_' . basename($lang_file); + } + else + { + $filename = (($use_help) ? 'help_' : '') . $lang_file; + } + + if ($ext_name) + { + global $phpbb_extension_manager; + $ext_path = $phpbb_extension_manager->get_extension_path($ext_name, true); + + $lang_path = $ext_path . 'language/'; + } + else + { + $lang_path = $this->lang_path; + } + + if (strpos($phpbb_root_path . $filename, $lang_path . $this->lang_name . '/') === 0) + { + $language_filename = $phpbb_root_path . $filename; } else { - $language_filename = $this->lang_path . $this->lang_name . '/' . (($use_help) ? 'help_' : '') . $lang_file . '.' . $phpEx; + $language_filename = $lang_path . $this->lang_name . '/' . $filename . '.' . $phpEx; } if (!file_exists($language_filename)) @@ -1984,24 +2071,24 @@ class user extends session if ($this->lang_name == 'en') { // The user's selected language is missing the file, the board default's language is missing the file, and the file doesn't exist in /en. - $language_filename = str_replace($this->lang_path . 'en', $this->lang_path . $this->data['user_lang'], $language_filename); + $language_filename = str_replace($lang_path . 'en', $lang_path . $this->data['user_lang'], $language_filename); trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR); } else if ($this->lang_name == basename($config['default_lang'])) { // Fall back to the English Language $this->lang_name = 'en'; - $this->set_lang($lang, $help, $lang_file, $use_db, $use_help); + $this->set_lang($lang, $help, $lang_file, $use_db, $use_help, $ext_name); } else if ($this->lang_name == $this->data['user_lang']) { // Fall back to the board default language $this->lang_name = basename($config['default_lang']); - $this->set_lang($lang, $help, $lang_file, $use_db, $use_help); + $this->set_lang($lang, $help, $lang_file, $use_db, $use_help, $ext_name); } // Reset the lang name - $this->lang_name = (file_exists($this->lang_path . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']); + $this->lang_name = (file_exists($lang_path . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']); return; } @@ -2059,9 +2146,9 @@ class user extends session // Zone offset $zone_offset = $this->timezone + $this->dst; - // Show date <= 1 hour ago as 'xx min ago' but not greater than 60 seconds in the future + // Show date < 1 hour ago as 'xx min ago' but not greater than 60 seconds in the future // A small tolerence is given for times in the future but in the same minute are displayed as '< than a minute ago' - if ($delta <= 3600 && $delta > -60 && ($delta >= -5 || (($now / 60) % 60) == (($gmepoch / 60) % 60)) && $date_cache[$format]['is_short'] !== false && !$forcedate && isset($this->lang['datetime']['AGO'])) + if ($delta < 3600 && $delta > -60 && ($delta >= -5 || (($now / 60) % 60) == (($gmepoch / 60) % 60)) && $date_cache[$format]['is_short'] !== false && !$forcedate && isset($this->lang['datetime']['AGO'])) { return $this->lang(array('datetime', 'AGO'), max(0, (int) floor($delta / 60))); } diff --git a/phpBB/includes/startup.php b/phpBB/includes/startup.php index ca9665da29..bbe2f127f1 100644 --- a/phpBB/includes/startup.php +++ b/phpBB/includes/startup.php @@ -97,8 +97,8 @@ function deregister_globals() unset($input); } -// If we are on PHP >= 6.0.0 we do not need some code -if (version_compare(PHP_VERSION, '6.0.0-dev', '>=')) +// Register globals and magic quotes have been dropped in PHP 5.4 +if (version_compare(PHP_VERSION, '5.4.0-dev', '>=')) { /** * @ignore diff --git a/phpBB/includes/template/extension_path_provider.php b/phpBB/includes/template/extension_path_provider.php new file mode 100644 index 0000000000..0feeaafed0 --- /dev/null +++ b/phpBB/includes/template/extension_path_provider.php @@ -0,0 +1,130 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Provides a template locator with core template paths and extension template paths +* +* Finds installed template paths and makes them available to the locator. +* +* @package phpBB3 +*/ +class phpbb_template_extension_path_provider extends phpbb_extension_provider implements phpbb_template_path_provider_interface +{ + /** + * Optional prefix for template paths searched within extensions. + * + * Empty by default. Relative to the extension directory. As an example, it + * could be adm/ for admin templates. + * + * @var string + */ + protected $ext_dir_prefix = ''; + + /** + * A provider of paths to be searched for templates + * @var phpbb_template_path_provider + */ + protected $base_path_provider; + + /** + * Constructor stores extension manager + * + * @param phpbb_extension_manager $extension_manager phpBB extension manager + * @param phpbb_template_path_provider $base_path_provider A simple path provider + * to provide paths to be located in extensions + */ + public function __construct(phpbb_extension_manager $extension_manager, phpbb_template_path_provider $base_path_provider) + { + parent::__construct($extension_manager); + $this->base_path_provider = $base_path_provider; + } + + /** + * Sets a prefix for template paths searched within extensions. + * + * The prefix is inserted between the extension's path e.g. ext/foo/ and + * the looked up template path, e.g. styles/bar/template/some.html. So it + * should not have a leading slash, but should have a trailing slash. + * + * @param string $ext_dir_prefix The prefix including trailing slash + * @return null + */ + public function set_ext_dir_prefix($ext_dir_prefix) + { + $this->ext_dir_prefix = $ext_dir_prefix; + } + + /** + * Finds template paths using the extension manager + * + * Locates a path (e.g. styles/prosilver/template/) in all active extensions. + * Then appends the core template paths based in the current working + * directory. + * + * @return array List of template paths + */ + public function find() + { + $directories = array(); + + $finder = $this->extension_manager->get_finder(); + foreach ($this->base_path_provider as $path) + { + if ($path && !phpbb_is_absolute($path)) + { + $directories = array_merge($directories, $finder + ->directory('/' . $this->ext_dir_prefix . $path) + ->get_directories() + ); + } + } + + foreach ($this->base_path_provider as $path) + { + $directories[] = $path; + } + + return $directories; + } + + /** + * Overwrites the current template names and paths + * + * @param array $templates An associative map from template names to paths. + * The first element is the main template. + * If the path is false, it will be generated from + * the supplied name. + * @param string $style_root_path The root directory for styles identified + * by name only. + * @return null + */ + public function set_templates(array $templates, $style_root_path) + { + $this->base_path_provider->set_templates($templates, $style_root_path); + $this->items = null; + } + + /** + * Retrieves the path to the main template passed into set_templates() + * + * @return string Main template path + */ + public function get_main_template_path() + { + return $this->base_path_provider->get_main_template_path(); + } +} diff --git a/phpBB/includes/template/locator.php b/phpBB/includes/template/locator.php index 35e33bb9e6..ee9bfa7d48 100644 --- a/phpBB/includes/template/locator.php +++ b/phpBB/includes/template/locator.php @@ -28,62 +28,70 @@ if (!defined('IN_PHPBB')) class phpbb_template_locator { /** - * @var string Path to directory that templates are stored in. + * Paths to directories that templates are stored in. + * @var array */ - private $root = ''; + private $roots = array(); /** - * @var string Path to parent/fallback template directory. + * Index of the main template in the roots array + * @var int */ - private $inherit_root = ''; + private $main_root_id = 0; /** - * @var array Map from handles to source template file paths. + * Map from root index to handles to source template file paths. * Normally it only contains paths for handles that are used * (or are likely to be used) by the page being rendered and not * all templates that exist on the filesystem. + * @var array */ private $files = array(); /** - * @var array Map from handles to source template file names. + * Map from handles to source template file names. * Covers the same data as $files property but maps to basenames * instead of paths. + * @var array */ private $filenames = array(); /** - * @var array Map from handles to parent/fallback source template - * file paths. Covers the same data as $files. + * Set main template location (must have been added through set_paths first). + * + * @param string $template_path Path to template directory + * @return null */ - private $files_inherit = array(); + public function set_main_template($template) + { + $this->main_root_id = array_search($template, $this->roots, true); + } /** - * Set custom template location (able to use directory outside of phpBB). + * Sets the list of template paths * - * Note: Templates are still compiled to phpBB's cache directory. + * These paths will be searched for template files in the provided order. + * Paths may be outside of phpBB, but templates loaded from these paths + * will still be cached. * - * @param string $template_path Path to template directory - * @param string|bool $fallback_template_path Path to fallback template, or false to disable fallback + * @param array $template_paths An array of paths to template directories + * @return null */ - public function set_custom_template($template_path, $fallback_template_path = false) + public function set_paths($template_paths) { - // Make sure $template_path has no ending slash - if (substr($template_path, -1) == '/') - { - $template_path = substr($template_path, 0, -1); - } - - $this->root = $template_path; + $this->roots = array(); + $this->files = array(); + $this->filenames = array(); + $this->main_root_id = 0; - if ($fallback_template_path !== false) + foreach ($template_paths as $path) { - if (substr($fallback_template_path, -1) == '/') + // Make sure $path has no ending slash + if (substr($path, -1) === '/') { - $fallback_template_path = substr($fallback_template_path, 0, -1); + $path = substr($path, 0, -1); } - - $this->inherit_root = $fallback_template_path; + $this->roots[] = $path; } } @@ -103,11 +111,10 @@ class phpbb_template_locator } $this->filename[$handle] = $filename; - $this->files[$handle] = $this->root . '/' . $filename; - if ($this->inherit_root) + foreach ($this->roots as $root_index => $root) { - $this->files_inherit[$handle] = $this->inherit_root . '/' . $filename; + $this->files[$root_index][$handle] = $root . '/' . $filename; } } } @@ -154,12 +161,12 @@ class phpbb_template_locator public function get_virtual_source_file_for_handle($handle) { // If we don't have a file assigned to this handle, die. - if (!isset($this->files[$handle])) + if (!isset($this->files[$this->main_root_id][$handle])) { trigger_error("template locator: No file specified for handle $handle", E_USER_ERROR); } - $source_file = $this->files[$handle]; + $source_file = $this->files[$this->main_root_id][$handle]; return $source_file; } @@ -182,30 +189,26 @@ class phpbb_template_locator public function get_source_file_for_handle($handle) { // If we don't have a file assigned to this handle, die. - if (!isset($this->files[$handle])) + if (!isset($this->files[$this->main_root_id][$handle])) { trigger_error("template locator: No file specified for handle $handle", E_USER_ERROR); } - $source_file = $this->files[$handle]; + // locate a source file that exists + $source_file = $this->files[0][$handle]; + $tried = $source_file; + for ($i = 1, $n = count($this->roots); $i < $n && !file_exists($source_file); $i++) + { + $source_file = $this->files[$i][$handle]; + $tried .= ', ' . $source_file; + } - // Try and open template for reading + // search failed if (!file_exists($source_file)) { - if (isset($this->files_inherit[$handle]) && $this->files_inherit[$handle]) - { - $parent_source_file = $this->files_inherit[$handle]; - if (!file_exists($parent_source_file)) - { - trigger_error("template locator: Neither $source_file nor $parent_source_file exist", E_USER_ERROR); - } - $source_file = $parent_source_file; - } - else - { - trigger_error("template locator: File $source_file does not exist", E_USER_ERROR); - } + trigger_error("template locator: File for handle $handle does not exist. Could not find: $tried", E_USER_ERROR); } + return $source_file; } } diff --git a/phpBB/includes/template/path_provider.php b/phpBB/includes/template/path_provider.php new file mode 100644 index 0000000000..c243d1b115 --- /dev/null +++ b/phpBB/includes/template/path_provider.php @@ -0,0 +1,102 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Provides a template locator with paths +* +* Finds installed template paths and makes them available to the locator. +* +* @package phpBB3 +*/ +class phpbb_template_path_provider implements IteratorAggregate, phpbb_template_path_provider_interface +{ + protected $main_template_name = ''; + protected $paths = array(); + + /** + * Ignores the extension dir prefix + * + * @param string $ext_dir_prefix The prefix including trailing slash + * @return null + */ + public function set_ext_dir_prefix($ext_dir_prefix) + { + } + + /** + * Overwrites the current template names and paths + * + * The first element of the passed templates map, is considered the main + * template and can be retrieved through get_main_template_path(). + * + * @param array $templates An associative map from template names to paths. + * The first element is the main template. + * If the path is false, it will be generated from + * the supplied name. + * @param string $style_root_path The root directory for styles identified + * by name only. + * @return null + */ + public function set_templates(array $templates, $style_root_path) + { + $this->paths = array(); + + foreach ($templates as $name => $path) + { + if (!$path) + { + $path = $style_root_path . $this->template_root_for_style($name); + } + + $this->paths[] = $path; + } + + $this->main_template_path = $this->paths[0]; + } + + /** + * Retrieves the path to the main template passed into set_templates() + * + * @return string Main template path + */ + public function get_main_template_path() + { + return $this->main_template_path; + } + + /** + * Converts a style name to relative (to board root or extension) path to + * the style's template files. + * + * @param $style_name string Style name + * @return string Path to style template files + */ + private function template_root_for_style($style_name) + { + return 'styles/' . $style_name . '/template'; + } + + /** + * Retrieve an iterator over all template paths + * + * @return ArrayIterator An iterator for the array of template paths + */ + public function getIterator() + { + return new ArrayIterator($this->paths); + } +} diff --git a/phpBB/includes/template/path_provider_interface.php b/phpBB/includes/template/path_provider_interface.php new file mode 100644 index 0000000000..822393a91e --- /dev/null +++ b/phpBB/includes/template/path_provider_interface.php @@ -0,0 +1,54 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Provides a template locator with paths +* +* Finds installed template paths and makes them available to the locator. +* +* @package phpBB3 +*/ +interface phpbb_template_path_provider_interface extends Traversable +{ + /** + * Defines a prefix to use for template paths in extensions + * + * @param string $ext_dir_prefix The prefix including trailing slash + * @return null + */ + public function set_ext_dir_prefix($ext_dir_prefix); + + /** + * Overwrites the current template names and paths + * + * @param array $templates An associative map from template names to paths. + * The first element is the main template. + * If the path is false, it will be generated from + * the supplied name. + * @param string $style_root_path The root directory for styles identified + * by name only. + * @return null + */ + public function set_templates(array $templates, $style_root_path); + + /** + * Retrieves the path to the main template passed into set_templates() + * + * @return string Main template path + */ + public function get_main_template_path(); +} diff --git a/phpBB/includes/template/template.php b/phpBB/includes/template/template.php index ec5fbe2829..228ea93513 100644 --- a/phpBB/includes/template/template.php +++ b/phpBB/includes/template/template.php @@ -63,24 +63,33 @@ class phpbb_template private $user; /** - * @var locator template locator + * Template locator + * @var phpbb_template_locator */ private $locator; /** + * Template path provider + * @var phpbb_template_path_provider + */ + private $provider; + + /** * Constructor. * * @param string $phpbb_root_path phpBB root path * @param user $user current user * @param phpbb_template_locator $locator template locator + * @param phpbb_template_path_provider $provider template path provider */ - public function __construct($phpbb_root_path, $phpEx, $config, $user, phpbb_template_locator $locator) + public function __construct($phpbb_root_path, $phpEx, $config, $user, phpbb_template_locator $locator, phpbb_template_path_provider_interface $provider) { $this->phpbb_root_path = $phpbb_root_path; $this->phpEx = $phpEx; $this->config = $config; $this->user = $user; $this->locator = $locator; + $this->provider = $provider; } /** @@ -88,25 +97,21 @@ class phpbb_template */ public function set_template() { - $style_name = $this->user->theme['template_path']; + $template_name = $this->user->theme['template_path']; + $fallback_name = ($this->user->theme['template_inherits_id']) ? $this->user->theme['template_inherit_path'] : false; - $relative_template_root = $this->relative_template_root_for_style($style_name); - $template_root = $this->phpbb_root_path . $relative_template_root; - if (!file_exists($template_root)) - { - trigger_error('template locator: Template path could not be found: ' . $relative_template_root, E_USER_ERROR); - } - - if ($this->user->theme['template_inherits_id']) - { - $fallback_template_path = $this->phpbb_root_path . $this->relative_template_root_for_style($this->user->theme['template_inherit_path']); - } - else - { - $fallback_template_path = null; - } + return $this->set_custom_template(false, $template_name, false, $fallback_name); + } - return $this->set_custom_template($template_root, $style_name, $fallback_template_path); + /** + * Defines a prefix to use for template paths in extensions + * + * @param string $ext_dir_prefix The prefix including trailing slash + * @return null + */ + public function set_ext_dir_prefix($ext_dir_prefix) + { + $this->provider->set_ext_dir_prefix($ext_dir_prefix); } /** @@ -117,12 +122,22 @@ class phpbb_template * @param string $template_path Path to template directory * @param string $template_name Name of template * @param string $fallback_template_path Path to fallback template + * @param string $fallback_template_name Name of fallback template */ - public function set_custom_template($template_path, $style_name, $fallback_template_path = false) + public function set_custom_template($template_path, $template_name, $fallback_template_path = false, $fallback_template_name = false) { - $this->locator->set_custom_template($template_path, $fallback_template_path); + $templates = array($template_name => $template_path); + + if ($fallback_template_path !== false) + { + $templates[$fallback_template_name] = $fallback_template_path; + } + + $this->provider->set_templates($templates, $this->phpbb_root_path); + $this->locator->set_paths($this->provider); + $this->locator->set_main_template($this->provider->get_main_template_path()); - $this->cachepath = $this->phpbb_root_path . 'cache/tpl_' . str_replace('_', '-', $style_name) . '_'; + $this->cachepath = $this->phpbb_root_path . 'cache/tpl_' . str_replace('_', '-', $template_name) . '_'; $this->context = new phpbb_template_context(); @@ -130,18 +145,6 @@ class phpbb_template } /** - * Converts a style name to relative (to board root) path to - * the style's template files. - * - * @param $style_name string Style name - * @return string Path to style template files - */ - private function relative_template_root_for_style($style_name) - { - return 'styles/' . $style_name . '/template'; - } - - /** * Sets the template filenames for handles. * * @param array $filname_array Should be a hash of handle => filename pairs. diff --git a/phpBB/includes/ucp/ucp_activate.php b/phpBB/includes/ucp/ucp_activate.php index 34b0b6d879..e19451191c 100644 --- a/phpBB/includes/ucp/ucp_activate.php +++ b/phpBB/includes/ucp/ucp_activate.php @@ -117,10 +117,7 @@ class ucp_activate $messenger->to($user_row['user_email'], $user_row['username']); - $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); - $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); - $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); - $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + $messenger->anti_abuse_headers($config, $user); $messenger->assign_vars(array( 'USERNAME' => htmlspecialchars_decode($user_row['username'])) diff --git a/phpBB/includes/ucp/ucp_groups.php b/phpBB/includes/ucp/ucp_groups.php index 676c0a8ef0..f2e2e616b7 100644 --- a/phpBB/includes/ucp/ucp_groups.php +++ b/phpBB/includes/ucp/ucp_groups.php @@ -194,47 +194,43 @@ class ucp_groups if ($group_row[$group_id]['group_type'] == GROUP_FREE) { group_user_add($group_id, $user->data['user_id']); - - $email_template = 'group_added'; } else { group_user_add($group_id, $user->data['user_id'], false, false, false, 0, 1); - $email_template = 'group_request'; - } + include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); + $messenger = new messenger(); - include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - $messenger = new messenger(); + $sql = 'SELECT u.username, u.username_clean, u.user_email, u.user_notify_type, u.user_jabber, u.user_lang + FROM ' . USER_GROUP_TABLE . ' ug, ' . USERS_TABLE . " u + WHERE ug.user_id = u.user_id + AND ug.group_leader = 1 + AND ug.group_id = $group_id"; + $result = $db->sql_query($sql); - $sql = 'SELECT u.username, u.username_clean, u.user_email, u.user_notify_type, u.user_jabber, u.user_lang - FROM ' . USER_GROUP_TABLE . ' ug, ' . USERS_TABLE . ' u - WHERE ug.user_id = u.user_id - AND ' . (($group_row[$group_id]['group_type'] == GROUP_FREE) ? "ug.user_id = {$user->data['user_id']}" : 'ug.group_leader = 1') . " - AND ug.group_id = $group_id"; - $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + $messenger->template('group_request', $row['user_lang']); - while ($row = $db->sql_fetchrow($result)) - { - $messenger->template($email_template, $row['user_lang']); + $messenger->to($row['user_email'], $row['username']); + $messenger->im($row['user_jabber'], $row['username']); - $messenger->to($row['user_email'], $row['username']); - $messenger->im($row['user_jabber'], $row['username']); + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($row['username']), + 'GROUP_NAME' => htmlspecialchars_decode($group_row[$group_id]['group_name']), + 'REQUEST_USERNAME' => $user->data['username'], - $messenger->assign_vars(array( - 'USERNAME' => htmlspecialchars_decode($row['username']), - 'GROUP_NAME' => htmlspecialchars_decode($group_row[$group_id]['group_name']), - 'REQUEST_USERNAME' => $user->data['username'], + 'U_PENDING' => generate_board_url() . "/ucp.$phpEx?i=groups&mode=manage&action=list&g=$group_id", + 'U_GROUP' => generate_board_url() . "/memberlist.$phpEx?mode=group&g=$group_id") + ); - 'U_PENDING' => generate_board_url() . "/ucp.$phpEx?i=groups&mode=manage&action=list&g=$group_id", - 'U_GROUP' => generate_board_url() . "/memberlist.$phpEx?mode=group&g=$group_id") - ); + $messenger->send($row['user_notify_type']); + } + $db->sql_freeresult($result); - $messenger->send($row['user_notify_type']); + $messenger->save_queue(); } - $db->sql_freeresult($result); - - $messenger->save_queue(); add_log('user', $user->data['user_id'], 'LOG_USER_GROUP_JOIN' . (($group_row[$group_id]['group_type'] == GROUP_FREE) ? '' : '_PENDING'), $group_row[$group_id]['group_name']); @@ -565,7 +561,7 @@ class ucp_groups { if ($data['width'] > $config['avatar_max_width'] || $data['height'] > $config['avatar_max_height']) { - $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $data['width'], $data['height']); + $error[] = phpbb_avatar_error_wrong_size($data['width'], $data['height']); } } @@ -575,7 +571,7 @@ class ucp_groups { if ($data['width'] < $config['avatar_min_width'] || $data['height'] < $config['avatar_min_height']) { - $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $data['width'], $data['height']); + $error[] = phpbb_avatar_error_wrong_size($data['width'], $data['height']); } } } @@ -736,7 +732,7 @@ class ucp_groups 'U_SWATCH' => append_sid("{$phpbb_root_path}adm/swatch.$phpEx", 'form=ucp&name=group_colour'), 'S_UCP_ACTION' => $this->u_action . "&action=$action&g=$group_id", - 'L_AVATAR_EXPLAIN' => sprintf($user->lang['AVATAR_EXPLAIN'], $config['avatar_max_width'], $config['avatar_max_height'], $config['avatar_filesize'] / 1024), + 'L_AVATAR_EXPLAIN' => phpbb_avatar_explanation_string(), )); break; @@ -1072,7 +1068,7 @@ class ucp_groups 'mode' => $mode, 'action' => $action ); - confirm_box(false, sprintf($user->lang['GROUP_CONFIRM_ADD_USER' . ((sizeof($name_ary) == 1) ? '' : 'S')], implode(', ', $name_ary)), build_hidden_fields($s_hidden_fields)); + confirm_box(false, $user->lang('GROUP_CONFIRM_ADD_USERS', sizeof($name_ary), implode(', ', $name_ary)), build_hidden_fields($s_hidden_fields)); } trigger_error($user->lang['NO_USERS_ADDED'] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $this->u_action . '&action=list&g=' . $group_id . '">', '</a>')); diff --git a/phpBB/includes/ucp/ucp_main.php b/phpBB/includes/ucp/ucp_main.php index 738da62158..2b8f662bb4 100644 --- a/phpBB/includes/ucp/ucp_main.php +++ b/phpBB/includes/ucp/ucp_main.php @@ -194,8 +194,8 @@ class ucp_main 'VISITED' => (empty($last_visit)) ? ' - ' : $user->format_date($last_visit), 'WARNINGS' => ($user->data['user_warnings']) ? $user->data['user_warnings'] : 0, 'POSTS' => ($user->data['user_posts']) ? $user->data['user_posts'] : 0, - 'POSTS_DAY' => sprintf($user->lang['POST_DAY'], $posts_per_day), - 'POSTS_PCT' => sprintf($user->lang['POST_PCT'], $percentage), + 'POSTS_DAY' => $user->lang('POST_DAY', $posts_per_day), + 'POSTS_PCT' => $user->lang('POST_PCT', $percentage), 'OCCUPATION' => (!empty($row['user_occ'])) ? $row['user_occ'] : '', 'INTERESTS' => (!empty($row['user_interests'])) ? $row['user_interests'] : '', @@ -674,8 +674,8 @@ class ucp_main $template->assign_vars(array( 'PAGINATION' => generate_pagination($this->u_action, $topics_count, $config['topics_per_page'], $start), 'PAGE_NUMBER' => on_page($topics_count, $config['topics_per_page'], $start), - 'TOTAL_TOPICS' => ($topics_count == 1) ? $user->lang['VIEW_FORUM_TOPIC'] : sprintf($user->lang['VIEW_FORUM_TOPICS'], $topics_count)) - ); + 'TOTAL_TOPICS' => $user->lang('VIEW_FORUM_TOPICS', (int) $topics_count), + )); } if ($mode == 'subscribed') diff --git a/phpBB/includes/ucp/ucp_pm.php b/phpBB/includes/ucp/ucp_pm.php index 87d51ca613..6dbf092604 100644 --- a/phpBB/includes/ucp/ucp_pm.php +++ b/phpBB/includes/ucp/ucp_pm.php @@ -243,7 +243,7 @@ class ucp_pm $num_not_moved = $num_removed = 0; $release = request_var('release', 0); - if ($user->data['user_new_privmsg'] && $action == 'view_folder') + if ($user->data['user_new_privmsg'] && ($action == 'view_folder' || $action == 'view_message')) { $return = place_pm_into_folder($global_privmsgs_rules, $release); $num_not_moved = $return['not_moved']; @@ -345,8 +345,8 @@ class ucp_pm 'NUM_NOT_MOVED' => $num_not_moved, 'NUM_REMOVED' => $num_removed, 'RELEASE_MESSAGE_INFO' => sprintf($user->lang['RELEASE_MESSAGES'], '<a href="' . $this->u_action . '&folder=' . $folder_id . '&release=1">', '</a>'), - 'NOT_MOVED_MESSAGES' => ($num_not_moved == 1) ? $user->lang['NOT_MOVED_MESSAGE'] : sprintf($user->lang['NOT_MOVED_MESSAGES'], $num_not_moved), - 'RULE_REMOVED_MESSAGES' => ($num_removed == 1) ? $user->lang['RULE_REMOVED_MESSAGE'] : sprintf($user->lang['RULE_REMOVED_MESSAGES'], $num_removed), + 'NOT_MOVED_MESSAGES' => $user->lang('NOT_MOVED_MESSAGES', (int) $num_not_moved), + 'RULE_REMOVED_MESSAGES' => $user->lang('RULE_REMOVED_MESSAGES', (int) $num_removed), 'S_FOLDER_OPTIONS' => $s_folder_options, 'S_TO_FOLDER_OPTIONS' => $s_to_folder_options, diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php index 92297c1490..981c95a748 100644 --- a/phpBB/includes/ucp/ucp_pm_compose.php +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -1053,7 +1053,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $template->assign_vars(array( 'L_POST_A' => $page_title, 'L_ICON' => $user->lang['PM_ICON'], - 'L_MESSAGE_BODY_EXPLAIN' => (intval($config['max_post_chars'])) ? sprintf($user->lang['MESSAGE_BODY_EXPLAIN'], intval($config['max_post_chars'])) : '', + 'L_MESSAGE_BODY_EXPLAIN' => $user->lang('MESSAGE_BODY_EXPLAIN', (int) $config['max_post_chars']), 'SUBJECT' => (isset($message_subject)) ? $message_subject : '', 'MESSAGE' => $message_text, diff --git a/phpBB/includes/ucp/ucp_pm_options.php b/phpBB/includes/ucp/ucp_pm_options.php index 49c727847a..7f854e422f 100644 --- a/phpBB/includes/ucp/ucp_pm_options.php +++ b/phpBB/includes/ucp/ucp_pm_options.php @@ -231,7 +231,7 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit // Something went wrong, only partially moved? if ($num_moved != $folder_row['pm_count']) { - trigger_error(sprintf($user->lang['MOVE_PM_ERROR'], $num_moved, $folder_row['pm_count'])); + trigger_error($user->lang('MOVE_PM_ERROR', (int) $folder_row['pm_count'], $num_moved)); } break; @@ -409,7 +409,7 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit $folder[PRIVMSGS_INBOX] = array( 'folder_name' => $user->lang['PM_INBOX'], - 'message_status' => sprintf($user->lang['FOLDER_MESSAGE_STATUS'], $num_messages, $user->data['message_limit']) + 'message_status' => $user->lang('FOLDER_MESSAGE_STATUS', (int) $user->data['message_limit'], $num_messages), ); $sql = 'SELECT folder_id, folder_name, pm_count @@ -423,7 +423,7 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit $num_user_folder++; $folder[$row['folder_id']] = array( 'folder_name' => $row['folder_name'], - 'message_status' => sprintf($user->lang['FOLDER_MESSAGE_STATUS'], $row['pm_count'], $user->data['message_limit']) + 'message_status' => $user->lang('FOLDER_MESSAGE_STATUS', (int) $user->data['message_limit'], $row['pm_count']), ); } $db->sql_freeresult($result); diff --git a/phpBB/includes/ucp/ucp_pm_viewfolder.php b/phpBB/includes/ucp/ucp_pm_viewfolder.php index c74574f361..7b850cb436 100644 --- a/phpBB/includes/ucp/ucp_pm_viewfolder.php +++ b/phpBB/includes/ucp/ucp_pm_viewfolder.php @@ -455,7 +455,7 @@ function get_pm_from($folder_id, $folder, $user_id) $template->assign_vars(array( 'PAGINATION' => generate_pagination(append_sid("{$phpbb_root_path}ucp.$phpEx", "i=pm&mode=view&action=view_folder&f=$folder_id&$u_sort_param"), $pm_count, $config['topics_per_page'], $start), 'PAGE_NUMBER' => on_page($pm_count, $config['topics_per_page'], $start), - 'TOTAL_MESSAGES' => (($pm_count == 1) ? $user->lang['VIEW_PM_MESSAGE'] : sprintf($user->lang['VIEW_PM_MESSAGES'], $pm_count)), + 'TOTAL_MESSAGES' => $user->lang('VIEW_PM_MESSAGES', (int) $pm_count), 'POST_IMG' => (!$auth->acl_get('u_sendpm')) ? $user->img('button_topic_locked', 'POST_PM_LOCKED') : $user->img('button_pm_new', 'POST_NEW_PM'), diff --git a/phpBB/includes/ucp/ucp_pm_viewmessage.php b/phpBB/includes/ucp/ucp_pm_viewmessage.php index c9451bd202..0458ff6579 100644 --- a/phpBB/includes/ucp/ucp_pm_viewmessage.php +++ b/phpBB/includes/ucp/ucp_pm_viewmessage.php @@ -22,7 +22,7 @@ if (!defined('IN_PHPBB')) function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) { global $user, $template, $auth, $db, $cache; - global $phpbb_root_path, $phpEx, $config; + global $phpbb_root_path, $request, $phpEx, $config; $user->add_lang(array('viewtopic', 'memberlist')); diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index 4572dfd25d..6eb11e6e59 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -79,14 +79,14 @@ class ucp_profile $error = validate_data($data, $check_ary); - if ($auth->acl_get('u_chgpasswd') && $data['new_password'] && $data['password_confirm'] != $data['new_password']) + if ($auth->acl_get('u_chgemail') && $data['email'] != $user->data['user_email'] && $data['email_confirm'] != $data['email']) { - $error[] = 'NEW_PASSWORD_ERROR'; + $error[] = ($data['email_confirm']) ? 'NEW_EMAIL_ERROR' : 'NEW_EMAIL_CONFIRM_EMPTY'; } - if (($data['new_password'] || ($auth->acl_get('u_chgemail') && $data['email'] != $user->data['user_email']) || ($data['username'] != $user->data['username'] && $auth->acl_get('u_chgname') && $config['allow_namechange'])) && !phpbb_check_hash($data['cur_password'], $user->data['user_password'])) + if ($auth->acl_get('u_chgpasswd') && $data['new_password'] && $data['password_confirm'] != $data['new_password']) { - $error[] = 'CUR_PASSWORD_ERROR'; + $error[] = ($data['password_confirm']) ? 'NEW_PASSWORD_ERROR' : 'NEW_PASSWORD_CONFIRM_EMPTY'; } // Only check the new password against the previous password if there have been no errors @@ -95,9 +95,9 @@ class ucp_profile $error[] = 'SAME_PASSWORD_ERROR'; } - if ($auth->acl_get('u_chgemail') && $data['email'] != $user->data['user_email'] && $data['email_confirm'] != $data['email']) + if (!phpbb_check_hash($data['cur_password'], $user->data['user_password'])) { - $error[] = 'NEW_EMAIL_ERROR'; + $error[] = ($data['cur_password']) ? 'CUR_PASSWORD_ERROR' : 'CUR_PASSWORD_EMPTY'; } if (!check_form_key('ucp_reg_details')) @@ -151,10 +151,7 @@ class ucp_profile $messenger->to($data['email'], $data['username']); - $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); - $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); - $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); - $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + $messenger->anti_abuse_headers($config, $user); $messenger->assign_vars(array( 'USERNAME' => htmlspecialchars_decode($data['username']), @@ -251,8 +248,8 @@ class ucp_profile 'NEW_PASSWORD' => $data['new_password'], 'CUR_PASSWORD' => '', - 'L_USERNAME_EXPLAIN' => sprintf($user->lang[$config['allow_name_chars'] . '_EXPLAIN'], $config['min_name_chars'], $config['max_name_chars']), - 'L_CHANGE_PASSWORD_EXPLAIN' => sprintf($user->lang[$config['pass_complex'] . '_EXPLAIN'], $config['min_pass_chars'], $config['max_pass_chars']), + 'L_USERNAME_EXPLAIN' => $user->lang($config['allow_name_chars'] . '_EXPLAIN', $user->lang('CHARACTERS', (int) $config['min_name_chars']), $user->lang('CHARACTERS', (int) $config['max_name_chars'])), + 'L_CHANGE_PASSWORD_EXPLAIN' => $user->lang($config['pass_complex'] . '_EXPLAIN', $user->lang('CHARACTERS', (int) $config['min_pass_chars']), $user->lang('CHARACTERS', (int) $config['max_pass_chars'])), 'S_FORCE_PASSWORD' => ($auth->acl_get('u_chgpasswd') && $config['chg_passforce'] && $user->data['user_passchg'] < time() - ($config['chg_passforce'] * 86400)) ? true : false, 'S_CHANGE_USERNAME' => ($config['allow_namechange'] && $auth->acl_get('u_chgname')) ? true : false, @@ -540,7 +537,7 @@ class ucp_profile 'URL_STATUS' => ($config['allow_sig_links']) ? $user->lang['URL_IS_ON'] : $user->lang['URL_IS_OFF'], 'MAX_FONT_SIZE' => (int) $config['max_sig_font_size'], - 'L_SIGNATURE_EXPLAIN' => sprintf($user->lang['SIGNATURE_EXPLAIN'], $config['max_sig_chars']), + 'L_SIGNATURE_EXPLAIN' => $user->lang('SIGNATURE_EXPLAIN', (int) $config['max_sig_chars']), 'S_BBCODE_ALLOWED' => $config['allow_sig_bbcode'], 'S_SMILIES_ALLOWED' => $config['allow_sig_smilies'], @@ -605,7 +602,7 @@ class ucp_profile 'S_FORM_ENCTYPE' => ($can_upload && ($config['allow_avatar_upload'] || $config['allow_avatar_remote_upload'])) ? ' enctype="multipart/form-data"' : '', - 'L_AVATAR_EXPLAIN' => sprintf($user->lang['AVATAR_EXPLAIN'], $config['avatar_max_width'], $config['avatar_max_height'], $config['avatar_filesize'] / 1024), + 'L_AVATAR_EXPLAIN' => phpbb_avatar_explanation_string(), )); if ($config['allow_avatar'] && $display_gallery && $auth->acl_get('u_chgavatar') && $config['allow_avatar_local']) diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php index 3781fc6b1c..fe09d0a9fe 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -366,10 +366,7 @@ class ucp_register $messenger->to($data['email'], $data['username']); - $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); - $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); - $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); - $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + $messenger->anti_abuse_headers($config, $user); $messenger->assign_vars(array( 'WELCOME_MSG' => htmlspecialchars_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename'])), @@ -478,8 +475,8 @@ class ucp_register 'EMAIL_CONFIRM' => $data['email_confirm'], 'L_REG_COND' => $l_reg_cond, - 'L_USERNAME_EXPLAIN' => sprintf($user->lang[$config['allow_name_chars'] . '_EXPLAIN'], $config['min_name_chars'], $config['max_name_chars']), - 'L_PASSWORD_EXPLAIN' => sprintf($user->lang[$config['pass_complex'] . '_EXPLAIN'], $config['min_pass_chars'], $config['max_pass_chars']), + 'L_USERNAME_EXPLAIN' => $user->lang($config['allow_name_chars'] . '_EXPLAIN', $user->lang('CHARACTERS', (int) $config['min_name_chars']), $user->lang('CHARACTERS', (int) $config['max_name_chars'])), + 'L_PASSWORD_EXPLAIN' => $user->lang($config['pass_complex'] . '_EXPLAIN', $user->lang('CHARACTERS', (int) $config['min_pass_chars']), $user->lang('CHARACTERS', (int) $config['max_pass_chars'])), 'S_LANG_OPTIONS' => language_select($data['lang']), 'S_TZ_OPTIONS' => tz_select($data['tz']), diff --git a/phpBB/includes/ucp/ucp_resend.php b/phpBB/includes/ucp/ucp_resend.php index 66677b9a4f..ab4f699668 100644 --- a/phpBB/includes/ucp/ucp_resend.php +++ b/phpBB/includes/ucp/ucp_resend.php @@ -94,10 +94,7 @@ class ucp_resend $messenger->template(($coppa) ? 'coppa_resend_inactive' : 'user_resend_inactive', $user_row['user_lang']); $messenger->to($user_row['user_email'], $user_row['username']); - $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); - $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); - $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); - $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + $messenger->anti_abuse_headers($config, $user); $messenger->assign_vars(array( 'WELCOME_MSG' => htmlspecialchars_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename'])), @@ -133,10 +130,7 @@ class ucp_resend $messenger->to($row['user_email'], $row['username']); $messenger->im($row['user_jabber'], $row['username']); - $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); - $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); - $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); - $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + $messenger->anti_abuse_headers($config, $user); $messenger->assign_vars(array( 'USERNAME' => htmlspecialchars_decode($user_row['username']), |
