From c2866f52453ac8bdfcdde6b541bbba60f1c71d02 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 2 Aug 2011 16:50:17 +0200 Subject: [PATCH 01/93] [ticket/10300] Always set group attributes for teampage and legend The code in acp_groups.php removes unchanged attributes from the group_attributes array, to prevent issues with reapplying avatar/rank and more. This code causes problems with the new teampage/legend feature, because when the attribute is not set, the group is removed from the feature. Therefore I added an array with the keys that need to be set, when calling the function. PHPBB3-10300 --- phpBB/includes/acp/acp_groups.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/phpBB/includes/acp/acp_groups.php b/phpBB/includes/acp/acp_groups.php index dde556c19e..221dea2345 100644 --- a/phpBB/includes/acp/acp_groups.php +++ b/phpBB/includes/acp/acp_groups.php @@ -415,6 +415,9 @@ class acp_groups // Only set the rank, colour, etc. if it's changed or if we're adding a new // group. This prevents existing group members being updated if no changes // were made. + // However there are some attributes that need to be set everytime, + // otherwise the group gets removed from the feature. + $set_attributes = array('legend', 'teampage'); $group_attributes = array(); $test_variables = array( @@ -435,7 +438,7 @@ class acp_groups foreach ($test_variables as $test => $type) { - if (isset($submit_ary[$test]) && ($action == 'add' || $group_row['group_' . $test] != $submit_ary[$test])) + if (isset($submit_ary[$test]) && ($action == 'add' || $group_row['group_' . $test] != $submit_ary[$test] || in_array($test, $set_attributes))) { settype($submit_ary[$test], $type); $group_attributes['group_' . $test] = $group_row['group_' . $test] = $submit_ary[$test]; From 2ffdf56bfe8ad35ac648a22a838b1ef01905b2d4 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Thu, 25 Aug 2011 20:14:49 +0200 Subject: [PATCH 02/93] [ticket/10278] Also set timeout on stream in get_remote_file(). From the PHP manual for fsockopen(): If you need to set a timeout for reading/writing data over the socket, use stream_set_timeout(), as the timeout parameter to fsockopen() only applies while connecting the socket. http://www.php.net/manual/en/function.fsockopen.php PHPBB3-10278 --- phpBB/includes/functions_admin.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index f7e19f3e7d..ee146ca214 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -3140,6 +3140,8 @@ function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port @fputs($fsock, "HOST: $host\r\n"); @fputs($fsock, "Connection: close\r\n\r\n"); + stream_set_timeout($fsock, $timeout); + $file_info = ''; $get_info = false; From 29a23ae217efed86e6b5afff4c9a0b1271eb20f4 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Thu, 25 Aug 2011 20:34:01 +0200 Subject: [PATCH 03/93] [ticket/10278] Return with a timeout error when fread() or fgets() time out. PHPBB3-10278 --- phpBB/includes/functions_admin.php | 8 ++++++++ phpBB/language/en/common.php | 1 + 2 files changed, 9 insertions(+) diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index ee146ca214..8b9b80b23d 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -3164,6 +3164,14 @@ function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port return false; } } + + $stream_meta_data = stream_get_meta_data($fsock); + + if (!empty($stream_meta_data['timed_out'])) + { + $errstr = $user->lang['FSOCK_TIMEOUT']; + return false; + } } @fclose($fsock); } diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php index 1c96818346..2eca49d3e0 100644 --- a/phpBB/language/en/common.php +++ b/phpBB/language/en/common.php @@ -200,6 +200,7 @@ $lang = array_merge($lang, array( 'FORUM_RULES_LINK' => 'Please click here to view the forum rules', 'FROM' => 'from', 'FSOCK_DISABLED' => 'The operation could not be completed because the fsockopen function has been disabled or the server being queried could not be found.', + 'FSOCK_TIMEOUT' => 'A timeout occurred while reading from the network stream.', 'FTP_FSOCK_HOST' => 'FTP host', 'FTP_FSOCK_HOST_EXPLAIN' => 'FTP server used to connect your site.', From c0507c6a9e26ba250596530f501bf6843250ed36 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Thu, 25 Aug 2011 20:38:53 +0200 Subject: [PATCH 04/93] [ticket/10278] Decrease default timeout of get_remote_file() to 6 seconds. PHPBB3-10278 --- phpBB/includes/functions_admin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 8b9b80b23d..bcd477d855 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -3130,7 +3130,7 @@ function get_database_size() /** * Retrieve contents from remotely stored file */ -function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port = 80, $timeout = 10) +function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port = 80, $timeout = 6) { global $user; From 138d1050fcfa910eb8819e91034741ed74baf4f3 Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Sat, 24 Sep 2011 22:05:40 +0100 Subject: [PATCH 05/93] [ticket/9307] Remove hardcoded chunk size of mass emails. The new config option is 'email_max_chunk_size' I have not added an interface option to change this. PHPBB3-9307 --- phpBB/includes/acp/acp_email.php | 5 +++-- phpBB/install/database_update.php | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/phpBB/includes/acp/acp_email.php b/phpBB/includes/acp/acp_email.php index 133fe47e09..e98b7a19a5 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']; diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php index a167e79308..21246a215e 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -1994,6 +1994,11 @@ function change_database_data(&$no_updates, $version) // No changes from 3.0.9-RC4 to 3.0.9 case '3.0.9-RC4': break; + + // Changes from 3.0.9 to 3.0.10-RC1 + case '3.0.9': + set_config('email_max_chunk_size', '50'); + break; } } From e0869b39a37a2db4ba88070d52e58307e721b336 Mon Sep 17 00:00:00 2001 From: rxu Date: Sun, 25 Sep 2011 10:59:41 +0800 Subject: [PATCH 06/93] [ticket/9008] Incorrect unread topic tracking for unapproved topics PHPBB3-9008 --- phpBB/includes/functions.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 628f8ee123..c0581c1b1b 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -1880,7 +1880,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; + global $db, $tracking_topics, $user, $config, $auth; // Determine the users last forum mark time if not given. if ($mark_time_forum === false) @@ -1903,6 +1903,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']) @@ -1918,7 +1922,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); @@ -1942,7 +1947,8 @@ function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_ti FROM ' . TOPICS_TABLE . ' WHERE forum_id = ' . $forum_id . ' AND topic_last_post_time > ' . $mark_time_forum . ' - AND topic_moved_id = 0'; + AND topic_moved_id = 0 ' . + $sql_update_unapproved; $result = $db->sql_query($sql); $check_forum = $tracking_topics['tf'][$forum_id]; From 81f9385477e1a6b050f447c9659faaf0bc7e871a Mon Sep 17 00:00:00 2001 From: Chris Smith Date: Sun, 25 Sep 2011 22:13:43 +0100 Subject: [PATCH 07/93] [ticket/9307] Add config variable to installation schema. PHPBB3-9307 --- phpBB/install/schemas/schema_data.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index 153ac61157..84b25d676e 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -94,6 +94,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('delete_time', '0') INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_check_mx', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_enable', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_function_name', 'mail'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_max_chunk_size', '50'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('email_package_size', '20'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_confirm', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('enable_pm_icons', '1'); From 6fce68b9b6f1f47f9f51f8ef1a043b78ac046a3f Mon Sep 17 00:00:00 2001 From: Cullen Walsh Date: Sun, 18 Sep 2011 19:40:04 -0700 Subject: [PATCH 08/93] [ticket/9661] Remove eval() from functions_privmsgs.php Tested by sending messages to myself on a test board. PHPBB3-9661 --- phpBB/includes/functions_privmsgs.php | 113 ++++++++++++++++++-------- 1 file changed, 79 insertions(+), 34 deletions(-) diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index 9787bdfbc4..32b57a9f2e 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -19,7 +19,8 @@ if (!defined('IN_PHPBB')) Ability to simply add own rules by doing three things: 1) Add an appropriate constant 2) Add a new check array to the global_privmsgs_rules variable and the condition array (if one is required) - 3) Add a new language variable to ucp.php + 3) Implement the rule logic in the check_rule() function + 4) Add a new language variable to ucp.php The user is then able to select the new rule. It will be checked against and handled as specified. To add new actions (yes, checks can be added here too) to the rule management, the core code has to be modified. @@ -57,42 +58,42 @@ define('CHECK_TO', 5); */ $global_privmsgs_rules = array( CHECK_SUBJECT => array( - RULE_IS_LIKE => array('check0' => 'message_subject', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0})'), - RULE_IS_NOT_LIKE => array('check0' => 'message_subject', 'function' => '!(preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0}))'), - RULE_IS => array('check0' => 'message_subject', 'function' => '{CHECK0} == {STRING}'), - RULE_IS_NOT => array('check0' => 'message_subject', 'function' => '{CHECK0} != {STRING}'), - RULE_BEGINS_WITH => array('check0' => 'message_subject', 'function' => 'preg_match("/^" . preg_quote({STRING}, "/") . "/i", {CHECK0})'), - RULE_ENDS_WITH => array('check0' => 'message_subject', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "$/i", {CHECK0})'), + RULE_IS_LIKE => array('check0' => 'message_subject'), + RULE_IS_NOT_LIKE => array('check0' => 'message_subject'), + RULE_IS => array('check0' => 'message_subject'), + RULE_IS_NOT => array('check0' => 'message_subject'), + RULE_BEGINS_WITH => array('check0' => 'message_subject'), + RULE_ENDS_WITH => array('check0' => 'message_subject'), ), CHECK_SENDER => array( - RULE_IS_LIKE => array('check0' => 'username', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0})'), - RULE_IS_NOT_LIKE => array('check0' => 'username', 'function' => '!(preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0}))'), - RULE_IS => array('check0' => 'username', 'function' => '{CHECK0} == {STRING}'), - RULE_IS_NOT => array('check0' => 'username', 'function' => '{CHECK0} != {STRING}'), - RULE_BEGINS_WITH => array('check0' => 'username', 'function' => 'preg_match("/^" . preg_quote({STRING}, "/") . "/i", {CHECK0})'), - RULE_ENDS_WITH => array('check0' => 'username', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "$/i", {CHECK0})'), - RULE_IS_FRIEND => array('check0' => 'friend', 'function' => '{CHECK0} == 1'), - RULE_IS_FOE => array('check0' => 'foe', 'function' => '{CHECK0} == 1'), - RULE_IS_USER => array('check0' => 'author_id', 'function' => '{CHECK0} == {USER_ID}'), - RULE_IS_GROUP => array('check0' => 'author_in_group', 'function' => 'in_array({GROUP_ID}, {CHECK0})'), + RULE_IS_LIKE => array('check0' => 'username'), + RULE_IS_NOT_LIKE => array('check0' => 'username'), + RULE_IS => array('check0' => 'username'), + RULE_IS_NOT => array('check0' => 'username'), + RULE_BEGINS_WITH => array('check0' => 'username'), + RULE_ENDS_WITH => array('check0' => 'username'), + RULE_IS_FRIEND => array('check0' => 'friend'), + RULE_IS_FOE => array('check0' => 'foe'), + RULE_IS_USER => array('check0' => 'author_id'), + RULE_IS_GROUP => array('check0' => 'author_in_group'), ), CHECK_MESSAGE => array( - RULE_IS_LIKE => array('check0' => 'message_text', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0})'), - RULE_IS_NOT_LIKE => array('check0' => 'message_text', 'function' => '!(preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0}))'), - RULE_IS => array('check0' => 'message_text', 'function' => '{CHECK0} == {STRING}'), - RULE_IS_NOT => array('check0' => 'message_text', 'function' => '{CHECK0} != {STRING}'), + RULE_IS_LIKE => array('check0' => 'message_text'), + RULE_IS_NOT_LIKE => array('check0' => 'message_text'), + RULE_IS => array('check0' => 'message_text'), + RULE_IS_NOT => array('check0' => 'message_text'), ), CHECK_STATUS => array( - RULE_ANSWERED => array('check0' => 'pm_replied', 'function' => '{CHECK0} == 1'), - RULE_FORWARDED => array('check0' => 'pm_forwarded', 'function' => '{CHECK0} == 1'), + RULE_ANSWERED => array('check0' => 'pm_replied'), + RULE_FORWARDED => array('check0' => 'pm_forwarded'), ), CHECK_TO => array( - RULE_TO_GROUP => array('check0' => 'to', 'check1' => 'bcc', 'check2' => 'user_in_group', 'function' => 'in_array("g_" . {CHECK2}, {CHECK0}) || in_array("g_" . {CHECK2}, {CHECK1})'), - RULE_TO_ME => array('check0' => 'to', 'check1' => 'bcc', 'function' => 'in_array("u_" . $user_id, {CHECK0}) || in_array("u_" . $user_id, {CHECK1})'), + RULE_TO_GROUP => array('check0' => 'to', 'check1' => 'bcc', 'check2' => 'user_in_group'), + RULE_TO_ME => array('check0' => 'to', 'check1' => 'bcc'), ) ); @@ -260,16 +261,60 @@ function check_rule(&$rules, &$rule_row, &$message_row, $user_id) $check_ary = $rules[$rule_row['rule_check']][$rule_row['rule_connection']]; - // Replace Check Literals - $evaluate = $check_ary['function']; - $evaluate = preg_replace('/{(CHECK[0-9])}/', '$message_row[$check_ary[strtolower("\1")]]', $evaluate); - - // Replace Rule Literals - $evaluate = preg_replace('/{(STRING|USER_ID|GROUP_ID)}/', '$rule_row["rule_" . strtolower("\1")]', $evaluate); - - // Evil Statement $result = false; - eval('$result = (' . $evaluate . ') ? true : false;'); + + $check0 = $message_row[$check_ary['check0']]; + + switch ($rule_row['rule_connection']) + { + case RULE_IS_LIKE: + $result = preg_match("/" . preg_quote($rule_row['rule_string'], '/') . '/i', $check0); + break; + + case RULE_IS_NOT_LIKE: + $result = !preg_match("/" . preg_quote($rule_row['rule_string'], '/') . '/i', $check0); + break; + + case RULE_IS: + $result = ($check0 == $rule_row['rule_string']); + break; + + case RULE_IS_NOT: + $result = ($check0 != $rule_row['rule_string']); + break; + + case RULE_BEGINS_WITH: + $result = preg_match("/^" . preg_quote($rule_row['rule_string'], '/') . '/i', $check0); + break; + + case RULE_ENDS_WITH: + $result = preg_match("/" . preg_quote($rule_row['rule_string'], '/') . '$/i', $check0); + break; + + case RULE_IS_FRIEND: + case RULE_IS_FOE: + case RULE_ANSWERED: + case RULE_FORWARDED: + $result = ($check0 == 1); + break; + + case RULE_IS_USER: + $result = ($check0 == $rule_row['rule_user_id']); + break; + + case RULE_IS_GROUP: + $result = in_array($rule_row['rule_group_id'], $check0); + break; + + case RULE_TO_GROUP: + $result = (in_array('g_' . $message_row[$check_ary['check2']], $check0) || in_array('g_' . $message_row[$check_ary['check2']], $message_row[$check_ary['check1']])); + break; + + case RULE_TO_ME: + $result = (in_array('u_' . $user_id, $check0) || in_array('u_' . $user_id, $message_row[$check_ary['check1']])); + break; + } + if (!$result) { From 56c6476233646e7c735aa4e3b98c4a6b62df5c7d Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Sun, 25 Sep 2011 15:12:56 -0700 Subject: [PATCH 09/93] [ticket/10390] Allow option for jQuery to be hosted by a remote CDN Add an option to the ACP so admins can choose to host jQuery from the local version shipped with phpBB, or via a popular CDN. PHPBB3-10390 --- phpBB/adm/style/install_footer.html | 3 +- phpBB/adm/style/overall_footer.html | 3 +- phpBB/adm/style/simple_footer.html | 3 +- phpBB/includes/acp/acp_board.php | 11 +++++++ phpBB/includes/constants.php | 1 + phpBB/includes/functions.php | 29 +++++++++++++++++++ phpBB/includes/functions_acp.php | 2 ++ phpBB/install/database_update.php | 1 + phpBB/install/schemas/schema_data.sql | 1 + phpBB/language/en/acp/board.php | 10 +++++++ .../prosilver/template/overall_footer.html | 3 +- .../prosilver/template/simple_footer.html | 3 +- .../subsilver2/template/overall_footer.html | 3 +- .../subsilver2/template/simple_footer.html | 3 +- 14 files changed, 69 insertions(+), 7 deletions(-) diff --git a/phpBB/adm/style/install_footer.html b/phpBB/adm/style/install_footer.html index 1b3134b5e1..a3b2294025 100644 --- a/phpBB/adm/style/install_footer.html +++ b/phpBB/adm/style/install_footer.html @@ -12,7 +12,8 @@ - + + diff --git a/phpBB/adm/style/overall_footer.html b/phpBB/adm/style/overall_footer.html index dc03d2cfb5..f05e9c56c5 100644 --- a/phpBB/adm/style/overall_footer.html +++ b/phpBB/adm/style/overall_footer.html @@ -20,7 +20,8 @@ - + + diff --git a/phpBB/adm/style/simple_footer.html b/phpBB/adm/style/simple_footer.html index 272fd5e3fb..0d697aec1d 100644 --- a/phpBB/adm/style/simple_footer.html +++ b/phpBB/adm/style/simple_footer.html @@ -16,7 +16,8 @@ - + + diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index f27a133eb5..45b6f219ac 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_host' => array('lang' => 'JQUERY_HOST', 'validate' => 'string', 'type' => 'select', 'method' => 'jquery_host_select', 'explain' => true), 'legend3' => 'ACP_SUBMIT_CHANGES', ) @@ -997,4 +998,14 @@ class acp_board $cache->destroy('sql', FORUMS_TABLE); } + function jquery_host_select($value, $key = '') + { + global $user; + + return ' + + + '; + } + } diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index 8ef1a4655d..c3af3d29e1 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -210,6 +210,7 @@ define('CAPTCHA_MAX_CHARS', 7); // Additional constants define('VOTE_CONVERTED', 127); +define('JQUERY_VERSION', '1.6.2'); // Important follow jQuery versioning, ie: 1.6, 1.6.1, 1.6.2 // Table names define('ACL_GROUPS_TABLE', $table_prefix . 'acl_groups'); diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 5ccb9edd07..af07938879 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -4569,6 +4569,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' => (!empty($config['load_jquery_host']) && $config['load_jquery_host'] != 'localhost') ? remote_jquery_url($config['load_jquery_host']) : "{$web_path}assets/javascript/jquery.js", + 'S_JQUERY_FALLBACK' => (!empty($config['load_jquery_host']) && $config['load_jquery_host'] != 'localhost') ? true : false, 'T_THEME_NAME' => $user->theme['theme_path'], 'T_THEME_LANG_NAME' => $user->data['user_lang'], @@ -4767,3 +4769,30 @@ function phpbb_pcre_utf8_support() } return $utf8_pcre_properties; } + +/** +* Build jQuery URL for remote CDNs +* Reference: http://docs.jquery.com/Downloading_jQuery#CDN_Hosted_jQuery +* +* @return string Returns url to a jQuery library +*/ +function remote_jquery_url($host) +{ + switch($host) + { + case 'google': + // Google uses a 1.5.0, 1.5.1 format (it is always a three numbered version) + return '//ajax.googleapis.com/ajax/libs/jquery/' . ((strlen(JQUERY_VERSION) == 3) ? JQUERY_VERSION . '.0' : JQUERY_VERSION) . '/jquery.min.js'; + break; + + case 'microsoft': + // Microsoft uses a 1.5, 1.5.1 format + return 'http://ajax.aspnetcdn.com/ajax/jQuery/jquery-' . JQUERY_VERSION . '.min.js'; + break; + + case 'jquery': + // jQuery uses a 1.5, 1.5.1 format + return 'http://code.jquery.com/jquery-' . JQUERY_VERSION . '.min.js'; + break; + } +} diff --git a/phpBB/includes/functions_acp.php b/phpBB/includes/functions_acp.php index c3806dc786..4f9fa0db5e 100644 --- a/phpBB/includes/functions_acp.php +++ b/phpBB/includes/functions_acp.php @@ -126,6 +126,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' => (!empty($config['load_jquery_host']) && $config['load_jquery_host'] != 'localhost') ? remote_jquery_url($config['load_jquery_host']) : "{$phpbb_root_path}assets/javascript/jquery.js", + 'S_JQUERY_FALLBACK' => (!empty($config['load_jquery_host']) && $config['load_jquery_host'] != 'localhost') ? true : false, 'VERSION' => $config['version']) ); diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php index 18741191d8..1a47e2a656 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -2090,6 +2090,7 @@ function change_database_data(&$no_updates, $version) // Changes from 3.1.0-dev to 3.1.0-A1 case '3.1.0-dev': + set_config('load_jquery_host', 'localhost'); set_config('use_system_cron', 0); $sql = 'UPDATE ' . GROUPS_TABLE . ' diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index 5506922e17..865189f345 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -165,6 +165,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_cpf_viewprofi INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_cpf_viewtopic', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_db_lastread', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_db_track', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_jquery_host', 'localhost'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_jumpbox', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_moderators', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_online', '1'); diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index abf346137d..4da069f68f 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -549,3 +549,13 @@ $lang = array_merge($lang, array( 'JAB_USERNAME' => 'Jabber username or JID', 'JAB_USERNAME_EXPLAIN' => 'Specify a registered username or a valid JID. The username will not be checked for validity. If you only specify a username, then your JID will be the username and the server you specified above. Else, specify a valid JID, for example user@jabber.org.', )); + +// jQuery settings +$lang = array_merge($lang, array( + 'JQUERY_HOST' => 'jQuery server', + 'JQUERY_HOST_EXPLAIN' => 'Load jQuery from your local server, or choose a remote copy hosted on a CDN (Content Delivery Network). If the CDN fails, phpBB will fall back to the local copy.', + 'JQUERY_HOST_LOCAL' => 'Localhost', + 'JQUERY_HOST_GOOGLE' => 'Google Ajax API CDN', + 'JQUERY_HOST_JQUERY' => 'jQuery CDN', + 'JQUERY_HOST_MS' => 'Microsoft CDN', +)); diff --git a/phpBB/styles/prosilver/template/overall_footer.html b/phpBB/styles/prosilver/template/overall_footer.html index 275e018f43..4456d6b37d 100644 --- a/phpBB/styles/prosilver/template/overall_footer.html +++ b/phpBB/styles/prosilver/template/overall_footer.html @@ -33,7 +33,8 @@ {RUN_CRON_TASK} - + + diff --git a/phpBB/styles/prosilver/template/simple_footer.html b/phpBB/styles/prosilver/template/simple_footer.html index 5899da0b7a..3458d02495 100644 --- a/phpBB/styles/prosilver/template/simple_footer.html +++ b/phpBB/styles/prosilver/template/simple_footer.html @@ -6,7 +6,8 @@ - + + diff --git a/phpBB/styles/subsilver2/template/overall_footer.html b/phpBB/styles/subsilver2/template/overall_footer.html index 3cdd071211..9b0b95372e 100644 --- a/phpBB/styles/subsilver2/template/overall_footer.html +++ b/phpBB/styles/subsilver2/template/overall_footer.html @@ -8,7 +8,8 @@
[ {DEBUG_OUTPUT} ] - + + diff --git a/phpBB/styles/subsilver2/template/simple_footer.html b/phpBB/styles/subsilver2/template/simple_footer.html index f03d1094f2..b51be3ac4c 100644 --- a/phpBB/styles/subsilver2/template/simple_footer.html +++ b/phpBB/styles/subsilver2/template/simple_footer.html @@ -5,7 +5,8 @@ Powered by phpBB® Forum Software © phpBB Group - + + From 39840ef36d4b074478de080caddd3e880bdba663 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Sun, 25 Sep 2011 18:15:42 -0700 Subject: [PATCH 10/93] [ticket/10390] Move jQuery version definition Move jQuery version definition to its own block PHPBB3-10390 --- phpBB/includes/constants.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index c3af3d29e1..06cbc7120c 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -30,6 +30,9 @@ define('PHPBB_VERSION', '3.1.0-dev'); // QA-related // define('PHPBB_QA', 1); +// jQuery Version +define('JQUERY_VERSION', '1.6.2'); // Important follow jQuery versioning, ie: 1.6, 1.6.1, 1.6.2 + // User related define('ANONYMOUS', 1); @@ -210,7 +213,6 @@ define('CAPTCHA_MAX_CHARS', 7); // Additional constants define('VOTE_CONVERTED', 127); -define('JQUERY_VERSION', '1.6.2'); // Important follow jQuery versioning, ie: 1.6, 1.6.1, 1.6.2 // Table names define('ACL_GROUPS_TABLE', $table_prefix . 'acl_groups'); From abb0f3f96d2fecfe2af2bde539a2b9d3a577e421 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Sun, 25 Sep 2011 18:16:25 -0700 Subject: [PATCH 11/93] [ticket/10390] Improve the jQuery CDN url generation function Per p's comments, return the remote url from a variable instead of using multiple returns. Also put the logic for creating Google's version on its own line, and count the version number's dots instead of length so it will be less likely to break if jQuery goes to version 1.10. PHPBB3-10390 --- phpBB/includes/functions.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index af07938879..83cadf426d 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -4781,18 +4781,21 @@ function remote_jquery_url($host) switch($host) { case 'google': - // Google uses a 1.5.0, 1.5.1 format (it is always a three numbered version) - return '//ajax.googleapis.com/ajax/libs/jquery/' . ((strlen(JQUERY_VERSION) == 3) ? JQUERY_VERSION . '.0' : JQUERY_VERSION) . '/jquery.min.js'; + // Google uses a 1.5.0, 1.5.1 format (it adds a .0 to new 1.X releases) + $version = (substr_count(JQUERY_VERSION, '.') == 1) ? JQUERY_VERSION . '.0' : JQUERY_VERSION; + // HTTP protocol intentionally omitted - its the best way to reference third party content that is available via both HTTP and HTTPS + $url = '//ajax.googleapis.com/ajax/libs/jquery/' . $version . '/jquery.min.js'; break; case 'microsoft': // Microsoft uses a 1.5, 1.5.1 format - return 'http://ajax.aspnetcdn.com/ajax/jQuery/jquery-' . JQUERY_VERSION . '.min.js'; + $url = 'http://ajax.aspnetcdn.com/ajax/jQuery/jquery-' . JQUERY_VERSION . '.min.js'; break; case 'jquery': // jQuery uses a 1.5, 1.5.1 format - return 'http://code.jquery.com/jquery-' . JQUERY_VERSION . '.min.js'; + $url = 'http://code.jquery.com/jquery-' . JQUERY_VERSION . '.min.js'; break; } + return $url; } From d4fe81f8f0458b46b1bfe086c5a34af38e5af618 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Sun, 25 Sep 2011 18:16:46 -0700 Subject: [PATCH 12/93] [ticket/10390] Fix a type-o - captialize AJAX AJAX should be capitalized where it appears in the ACP as the option: "Google AJAX API CDN" PHPBB3-10390 --- phpBB/language/en/acp/board.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index 4da069f68f..1bab87b37f 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -555,7 +555,7 @@ $lang = array_merge($lang, array( 'JQUERY_HOST' => 'jQuery server', 'JQUERY_HOST_EXPLAIN' => 'Load jQuery from your local server, or choose a remote copy hosted on a CDN (Content Delivery Network). If the CDN fails, phpBB will fall back to the local copy.', 'JQUERY_HOST_LOCAL' => 'Localhost', - 'JQUERY_HOST_GOOGLE' => 'Google Ajax API CDN', + 'JQUERY_HOST_GOOGLE' => 'Google AJAX API CDN', 'JQUERY_HOST_JQUERY' => 'jQuery CDN', 'JQUERY_HOST_MS' => 'Microsoft CDN', )); From 81e8faecbcc4f8c22a1dafdefe848ac548a6c77a Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Sun, 25 Sep 2011 19:09:29 -0700 Subject: [PATCH 13/93] [ticket/10390] Reword the language for jQuery host/server options Reword some of the language used for the description and pull-down options to try and make it more clear to users that they have the option to use jQuery from their own server with the copy included with phpBB, or from one of the remote CDN servers. PHPBB3-10390 --- phpBB/language/en/acp/board.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index 1bab87b37f..7a028b4064 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -552,10 +552,10 @@ $lang = array_merge($lang, array( // jQuery settings $lang = array_merge($lang, array( - 'JQUERY_HOST' => 'jQuery server', - 'JQUERY_HOST_EXPLAIN' => 'Load jQuery from your local server, or choose a remote copy hosted on a CDN (Content Delivery Network). If the CDN fails, phpBB will fall back to the local copy.', - 'JQUERY_HOST_LOCAL' => 'Localhost', - 'JQUERY_HOST_GOOGLE' => 'Google AJAX API CDN', - 'JQUERY_HOST_JQUERY' => 'jQuery CDN', - 'JQUERY_HOST_MS' => 'Microsoft CDN', + 'JQUERY_HOST' => 'Load jQuery from your server or a hosted CDN', + 'JQUERY_HOST_EXPLAIN' => 'Load jQuery from the copy included with phpBB on your local server, or choose a remote copy hosted on a CDN (Content Delivery Network). If the CDN fails, phpBB will fall back to the copy included with phpBB.', + 'JQUERY_HOST_LOCAL' => 'Included with phpBB on my server', + 'JQUERY_HOST_GOOGLE' => 'Hosted CDN: Google AJAX API', + 'JQUERY_HOST_JQUERY' => 'Hosted CDN: jQuery', + 'JQUERY_HOST_MS' => 'Hosted CDN: Microsoft', )); From c6a2d81bd359711aeb9dc36478977e779d3bdfe9 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Mon, 26 Sep 2011 11:13:16 -0700 Subject: [PATCH 14/93] [ticket/10390] Drop http protocol for Microsoft's CDN option Like Google, Microsoft supports both http and https protocols, so we can drop the protocol alltogether from the url so the Microsoft CDN will work on both HTTP or HTTPS sites without issue. Also I cleaned up some of the comments here. PHPBB3-10390 --- phpBB/includes/functions.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 83cadf426d..8cdafbd95e 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -4773,6 +4773,8 @@ function phpbb_pcre_utf8_support() /** * Build jQuery URL for remote CDNs * Reference: http://docs.jquery.com/Downloading_jQuery#CDN_Hosted_jQuery +* HTTP protocols intentionally omitted for Google and Microsoft - its the best +* way to reference third party content that is available via both HTTP and HTTPS * * @return string Returns url to a jQuery library */ @@ -4781,15 +4783,14 @@ function remote_jquery_url($host) switch($host) { case 'google': - // Google uses a 1.5.0, 1.5.1 format (it adds a .0 to new 1.X releases) + // Google uses a 1.5.0, 1.5.1 format (we need to add a .0 to new 1.X releases) $version = (substr_count(JQUERY_VERSION, '.') == 1) ? JQUERY_VERSION . '.0' : JQUERY_VERSION; - // HTTP protocol intentionally omitted - its the best way to reference third party content that is available via both HTTP and HTTPS $url = '//ajax.googleapis.com/ajax/libs/jquery/' . $version . '/jquery.min.js'; break; case 'microsoft': // Microsoft uses a 1.5, 1.5.1 format - $url = 'http://ajax.aspnetcdn.com/ajax/jQuery/jquery-' . JQUERY_VERSION . '.min.js'; + $url = '//ajax.aspnetcdn.com/ajax/jQuery/jquery-' . JQUERY_VERSION . '.min.js'; break; case 'jquery': From 2a28b6fc401e4481a3a4eb6085b45b9bd7746f43 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Mon, 26 Sep 2011 20:21:14 -0700 Subject: [PATCH 15/93] [ticket/10390] Use simpler HTML5 compliant js for the jQuery fallback HTML5 styles (ACP / Prosilver) do not need to use escaped javascript wrapped in an unescape function, so we can simplify it! Only subsilver2 will use the escaped version of the fallback code, because it is still XHTML. PHPBB3-10390 --- phpBB/adm/style/install_footer.html | 2 +- phpBB/adm/style/overall_footer.html | 2 +- phpBB/adm/style/simple_footer.html | 2 +- phpBB/styles/prosilver/template/overall_footer.html | 2 +- phpBB/styles/prosilver/template/simple_footer.html | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/phpBB/adm/style/install_footer.html b/phpBB/adm/style/install_footer.html index a3b2294025..342d8d4151 100644 --- a/phpBB/adm/style/install_footer.html +++ b/phpBB/adm/style/install_footer.html @@ -13,7 +13,7 @@ - + diff --git a/phpBB/adm/style/overall_footer.html b/phpBB/adm/style/overall_footer.html index f05e9c56c5..a190b2299a 100644 --- a/phpBB/adm/style/overall_footer.html +++ b/phpBB/adm/style/overall_footer.html @@ -21,7 +21,7 @@ - + diff --git a/phpBB/adm/style/simple_footer.html b/phpBB/adm/style/simple_footer.html index 0d697aec1d..5632d3fc9c 100644 --- a/phpBB/adm/style/simple_footer.html +++ b/phpBB/adm/style/simple_footer.html @@ -17,7 +17,7 @@ - + diff --git a/phpBB/styles/prosilver/template/overall_footer.html b/phpBB/styles/prosilver/template/overall_footer.html index 4456d6b37d..67f1b922a4 100644 --- a/phpBB/styles/prosilver/template/overall_footer.html +++ b/phpBB/styles/prosilver/template/overall_footer.html @@ -34,7 +34,7 @@ - + diff --git a/phpBB/styles/prosilver/template/simple_footer.html b/phpBB/styles/prosilver/template/simple_footer.html index 3458d02495..75b7480aa7 100644 --- a/phpBB/styles/prosilver/template/simple_footer.html +++ b/phpBB/styles/prosilver/template/simple_footer.html @@ -7,7 +7,7 @@ - + From 2dca3c3c278e99cfd6cdbea7149063d160e4cc11 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Mon, 26 Sep 2011 20:26:32 -0700 Subject: [PATCH 16/93] [ticket/10390] Serve jQuery from Google CDN Yes/No button in ACP jQuery will now be available via remote CDN from Google. Microsoft and jQuery CDNs have been removed, so we can simplify this option for the user. Default mode is NO so the copy of jQuery included with phpBB is served by default. PHPBB3-10390 --- phpBB/includes/acp/acp_board.php | 12 +-------- phpBB/includes/constants.php | 3 --- phpBB/includes/functions.php | 35 ++------------------------- phpBB/includes/functions_acp.php | 4 +-- phpBB/install/database_update.php | 3 ++- phpBB/install/schemas/schema_data.sql | 3 ++- phpBB/language/en/acp/board.php | 12 ++------- 7 files changed, 11 insertions(+), 61 deletions(-) diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index 45b6f219ac..352f1abc33 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -99,7 +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_host' => array('lang' => 'JQUERY_HOST', 'validate' => 'string', 'type' => 'select', 'method' => 'jquery_host_select', 'explain' => true), + 'load_jquery_cdn' => array('lang' => 'LOAD_JQUERY_CDN', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'legend3' => 'ACP_SUBMIT_CHANGES', ) @@ -998,14 +998,4 @@ class acp_board $cache->destroy('sql', FORUMS_TABLE); } - function jquery_host_select($value, $key = '') - { - global $user; - - return ' - - - '; - } - } diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index 06cbc7120c..8ef1a4655d 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -30,9 +30,6 @@ define('PHPBB_VERSION', '3.1.0-dev'); // QA-related // define('PHPBB_QA', 1); -// jQuery Version -define('JQUERY_VERSION', '1.6.2'); // Important follow jQuery versioning, ie: 1.6, 1.6.1, 1.6.2 - // User related define('ANONYMOUS', 1); diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 8cdafbd95e..d769ce0374 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -4569,8 +4569,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' => (!empty($config['load_jquery_host']) && $config['load_jquery_host'] != 'localhost') ? remote_jquery_url($config['load_jquery_host']) : "{$web_path}assets/javascript/jquery.js", - 'S_JQUERY_FALLBACK' => (!empty($config['load_jquery_host']) && $config['load_jquery_host'] != 'localhost') ? true : false, + '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'], @@ -4769,34 +4769,3 @@ function phpbb_pcre_utf8_support() } return $utf8_pcre_properties; } - -/** -* Build jQuery URL for remote CDNs -* Reference: http://docs.jquery.com/Downloading_jQuery#CDN_Hosted_jQuery -* HTTP protocols intentionally omitted for Google and Microsoft - its the best -* way to reference third party content that is available via both HTTP and HTTPS -* -* @return string Returns url to a jQuery library -*/ -function remote_jquery_url($host) -{ - switch($host) - { - case 'google': - // Google uses a 1.5.0, 1.5.1 format (we need to add a .0 to new 1.X releases) - $version = (substr_count(JQUERY_VERSION, '.') == 1) ? JQUERY_VERSION . '.0' : JQUERY_VERSION; - $url = '//ajax.googleapis.com/ajax/libs/jquery/' . $version . '/jquery.min.js'; - break; - - case 'microsoft': - // Microsoft uses a 1.5, 1.5.1 format - $url = '//ajax.aspnetcdn.com/ajax/jQuery/jquery-' . JQUERY_VERSION . '.min.js'; - break; - - case 'jquery': - // jQuery uses a 1.5, 1.5.1 format - $url = 'http://code.jquery.com/jquery-' . JQUERY_VERSION . '.min.js'; - break; - } - return $url; -} diff --git a/phpBB/includes/functions_acp.php b/phpBB/includes/functions_acp.php index 4f9fa0db5e..142be083a7 100644 --- a/phpBB/includes/functions_acp.php +++ b/phpBB/includes/functions_acp.php @@ -126,8 +126,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' => (!empty($config['load_jquery_host']) && $config['load_jquery_host'] != 'localhost') ? remote_jquery_url($config['load_jquery_host']) : "{$phpbb_root_path}assets/javascript/jquery.js", - 'S_JQUERY_FALLBACK' => (!empty($config['load_jquery_host']) && $config['load_jquery_host'] != 'localhost') ? true : false, + '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/install/database_update.php b/phpBB/install/database_update.php index 1a47e2a656..1fa01a534d 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -2090,7 +2090,8 @@ function change_database_data(&$no_updates, $version) // Changes from 3.1.0-dev to 3.1.0-A1 case '3.1.0-dev': - set_config('load_jquery_host', 'localhost'); + set_config('load_jquery_cdn', 0); + set_config('load_jquery_url', '//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js'); set_config('use_system_cron', 0); $sql = 'UPDATE ' . GROUPS_TABLE . ' diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index 865189f345..843d6daaa7 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -165,7 +165,8 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_cpf_viewprofi INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_cpf_viewtopic', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_db_lastread', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_db_track', '1'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_jquery_host', 'localhost'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_jquery_cdn', '0'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_jquery_url', '//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_jumpbox', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_moderators', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('load_online', '1'); diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index 7a028b4064..07102d4db3 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -356,6 +356,8 @@ $lang = array_merge($lang, array( 'LOAD_CPF_PM' => 'Display custom profile fields in private messages', 'LOAD_CPF_VIEWPROFILE' => 'Display custom profile fields in user profiles', 'LOAD_CPF_VIEWTOPIC' => 'Display custom profile fields on topic pages', + 'LOAD_JQUERY_CDN' => 'Serve jQuery using Google’s CDN', + 'LOAD_JQUERY_CDN_EXPLAIN' => 'If this setting is enabled, jQuery will be served from Google’s AJAX API CDN instead of the copy included with phpBB on your server. If the CDN fails, phpBB will attempt to fallback to the copy included with phpBB.', 'LOAD_USER_ACTIVITY' => 'Show user’s activity', 'LOAD_USER_ACTIVITY_EXPLAIN' => 'Displays active topic/forum in user profiles and user control panel. It is recommended to disable this on boards with more than one million posts.', 'RECOMPILE_STYLES' => 'Recompile stale style components', @@ -549,13 +551,3 @@ $lang = array_merge($lang, array( 'JAB_USERNAME' => 'Jabber username or JID', 'JAB_USERNAME_EXPLAIN' => 'Specify a registered username or a valid JID. The username will not be checked for validity. If you only specify a username, then your JID will be the username and the server you specified above. Else, specify a valid JID, for example user@jabber.org.', )); - -// jQuery settings -$lang = array_merge($lang, array( - 'JQUERY_HOST' => 'Load jQuery from your server or a hosted CDN', - 'JQUERY_HOST_EXPLAIN' => 'Load jQuery from the copy included with phpBB on your local server, or choose a remote copy hosted on a CDN (Content Delivery Network). If the CDN fails, phpBB will fall back to the copy included with phpBB.', - 'JQUERY_HOST_LOCAL' => 'Included with phpBB on my server', - 'JQUERY_HOST_GOOGLE' => 'Hosted CDN: Google AJAX API', - 'JQUERY_HOST_JQUERY' => 'Hosted CDN: jQuery', - 'JQUERY_HOST_MS' => 'Hosted CDN: Microsoft', -)); From 9bea7c327846c7281dd5d1f78322ac0016c4dfc9 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Tue, 27 Sep 2011 20:15:41 -0700 Subject: [PATCH 17/93] [ticket/10390] Fix wording: fallback should be fall back PHPBB3-10390 --- phpBB/language/en/acp/board.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index 07102d4db3..7ead6c6628 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -357,7 +357,7 @@ $lang = array_merge($lang, array( 'LOAD_CPF_VIEWPROFILE' => 'Display custom profile fields in user profiles', 'LOAD_CPF_VIEWTOPIC' => 'Display custom profile fields on topic pages', 'LOAD_JQUERY_CDN' => 'Serve jQuery using Google’s CDN', - 'LOAD_JQUERY_CDN_EXPLAIN' => 'If this setting is enabled, jQuery will be served from Google’s AJAX API CDN instead of the copy included with phpBB on your server. If the CDN fails, phpBB will attempt to fallback to the copy included with phpBB.', + 'LOAD_JQUERY_CDN_EXPLAIN' => 'If this setting is enabled, jQuery will be served from Google’s AJAX API CDN instead of the copy included with phpBB on your server. If the CDN fails, phpBB will attempt to fall back to the copy included with phpBB.', 'LOAD_USER_ACTIVITY' => 'Show user’s activity', 'LOAD_USER_ACTIVITY_EXPLAIN' => 'Displays active topic/forum in user profiles and user control panel. It is recommended to disable this on boards with more than one million posts.', 'RECOMPILE_STYLES' => 'Recompile stale style components', From 12882084d4ce686fe43f3935f16078c4e818cde3 Mon Sep 17 00:00:00 2001 From: Vjacheslav Trushkin Date: Tue, 4 Oct 2011 11:55:25 +0300 Subject: [PATCH 18/93] [ticket/10397] Pagination inconsistency fix Fixing inconsistency in code generated by generate_pagination() PHPBB3-10397 --- phpBB/includes/functions.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index c2b099d48a..8017c379f3 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -2127,7 +2127,7 @@ function generate_pagination($base_url, $num_items, $per_page, $start_item, $add $start_cnt = min(max(1, $on_page - 4), $total_pages - 5); $end_cnt = max(min($total_pages, $on_page + 4), 6); - $page_string .= ($start_cnt > 1) ? ' ... ' : $seperator; + $page_string .= ($start_cnt > 1) ? ' ... ' : $seperator; for ($i = $start_cnt + 1; $i < $end_cnt; $i++) { @@ -2138,7 +2138,7 @@ function generate_pagination($base_url, $num_items, $per_page, $start_item, $add } } - $page_string .= ($end_cnt < $total_pages) ? ' ... ' : $seperator; + $page_string .= ($end_cnt < $total_pages) ? ' ... ' : $seperator; } else { From b38fbc6d25d1f76683acec83627238ed5b5dbf8c Mon Sep 17 00:00:00 2001 From: Vjacheslav Trushkin Date: Tue, 4 Oct 2011 12:24:42 +0300 Subject: [PATCH 19/93] [ticket/10397] Pagination inconsistency fix Fixing topic_generate_pagination() PHPBB3-10397 --- phpBB/includes/functions_display.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php index 14d0c44dcf..86eabc419c 100644 --- a/phpBB/includes/functions_display.php +++ b/phpBB/includes/functions_display.php @@ -674,7 +674,7 @@ function topic_generate_pagination($replies, $url) $pagination .= '' . $times . ''; if ($times == 1 && $total_pages > 5) { - $pagination .= ' ... '; + $pagination .= ' ... '; // Display the last three pages $times = $total_pages - 3; From 2d0f96e8cc48ba6eed06f99efb33193fc495eab7 Mon Sep 17 00:00:00 2001 From: Matt Friedman Date: Wed, 5 Oct 2011 21:24:34 -0700 Subject: [PATCH 20/93] [ticket/10390] Revert back to escaped script tags inside document.write Revert all script tags inside a document.write back to the escaped version so they won't trip up any XML parsers. PHPBB3-10390 --- phpBB/adm/style/install_footer.html | 2 +- phpBB/adm/style/overall_footer.html | 2 +- phpBB/adm/style/simple_footer.html | 2 +- phpBB/styles/prosilver/template/overall_footer.html | 2 +- phpBB/styles/prosilver/template/simple_footer.html | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/phpBB/adm/style/install_footer.html b/phpBB/adm/style/install_footer.html index 342d8d4151..a3b2294025 100644 --- a/phpBB/adm/style/install_footer.html +++ b/phpBB/adm/style/install_footer.html @@ -13,7 +13,7 @@ - + diff --git a/phpBB/adm/style/overall_footer.html b/phpBB/adm/style/overall_footer.html index a190b2299a..f05e9c56c5 100644 --- a/phpBB/adm/style/overall_footer.html +++ b/phpBB/adm/style/overall_footer.html @@ -21,7 +21,7 @@ - + diff --git a/phpBB/adm/style/simple_footer.html b/phpBB/adm/style/simple_footer.html index 5632d3fc9c..0d697aec1d 100644 --- a/phpBB/adm/style/simple_footer.html +++ b/phpBB/adm/style/simple_footer.html @@ -17,7 +17,7 @@ - + diff --git a/phpBB/styles/prosilver/template/overall_footer.html b/phpBB/styles/prosilver/template/overall_footer.html index 67f1b922a4..4456d6b37d 100644 --- a/phpBB/styles/prosilver/template/overall_footer.html +++ b/phpBB/styles/prosilver/template/overall_footer.html @@ -34,7 +34,7 @@ - + diff --git a/phpBB/styles/prosilver/template/simple_footer.html b/phpBB/styles/prosilver/template/simple_footer.html index 75b7480aa7..3458d02495 100644 --- a/phpBB/styles/prosilver/template/simple_footer.html +++ b/phpBB/styles/prosilver/template/simple_footer.html @@ -7,7 +7,7 @@ - + From cacb9f2ec514f028ef7ccf35a3fa04b38bdac7ac Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 7 Oct 2011 09:44:31 +0200 Subject: [PATCH 21/93] [ticket/10400] Allow forum name to be '0' PHPBB3-10400 --- phpBB/includes/acp/acp_forums.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php index 4d9b9f01e0..27bec3f1ea 100644 --- a/phpBB/includes/acp/acp_forums.php +++ b/phpBB/includes/acp/acp_forums.php @@ -875,7 +875,7 @@ class acp_forums $errors = array(); - if (!$forum_data['forum_name']) + if ($forum_data['forum_name'] == '') { $errors[] = $user->lang['FORUM_NAME_EMPTY']; } From d4bbfae0d54a3726ac6080dcf399aee8187af19f Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Thu, 13 Oct 2011 11:52:35 +0200 Subject: [PATCH 22/93] [ticket/9898] Encourage patches in README PHPBB3-9898 --- phpBB/docs/README.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/docs/README.html b/phpBB/docs/README.html index 7a0a42b34f..7ceb698ac4 100644 --- a/phpBB/docs/README.html +++ b/phpBB/docs/README.html @@ -263,7 +263,7 @@

The relevant database type/version is listed within the administration control panel

-

Please also be as detailed as you can in your report, if possible list the steps required to duplicate the problem. If you have a fix which you are VERY SURE works (and is consistent with our coding guidelines) and does not introduce further problems or incompatibilities please let us know. However only include it in the bug report if you really must, if we need it we'll ask you for it.

+

Please also be as detailed as you can in your report, if possible list the steps required to duplicate the problem. If you have a patch that fixes the issue, please attach it to the ticket or submit a pull request on GitHub.

Once a bug has been submitted you will be emailed any follow up comments added to it. Please if you are requested to supply additional information, do so! It is frustrating for us to receive bug reports, ask for additional information but get nothing. In these cases we have a policy of closing the bug, which may leave a very real problem in place. Obviously we would rather not have this situation arise.

From f94f872624bd0a4987bef17cd5ac4d26d6bceee4 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 13 Oct 2011 13:59:39 +0200 Subject: [PATCH 23/93] [ticket/10304] Fix URL for ICQ while view private messages PHPBB3-10304 --- phpBB/includes/ucp/ucp_pm_viewmessage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/ucp/ucp_pm_viewmessage.php b/phpBB/includes/ucp/ucp_pm_viewmessage.php index d0cfa1ffd2..82a095dd9c 100644 --- a/phpBB/includes/ucp/ucp_pm_viewmessage.php +++ b/phpBB/includes/ucp/ucp_pm_viewmessage.php @@ -208,7 +208,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) 'U_PM' => ($config['allow_privmsg'] && $auth->acl_get('u_sendpm') && ($user_info['user_allow_pm'] || $auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_'))) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&mode=compose&u=' . $author_id) : '', 'U_WWW' => (!empty($user_info['user_website'])) ? $user_info['user_website'] : '', - 'U_ICQ' => ($user_info['user_icq']) ? 'http://www.icq.com/people' . urlencode($user_info['user_icq']) . '/' : '', + 'U_ICQ' => ($user_info['user_icq']) ? 'http://www.icq.com/people/' . urlencode($user_info['user_icq']) . '/' : '', 'U_AIM' => ($user_info['user_aim'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=aim&u=' . $author_id) : '', 'U_YIM' => ($user_info['user_yim']) ? 'http://edit.yahoo.com/config/send_webmesg?.target=' . urlencode($user_info['user_yim']) . '&.src=pg' : '', 'U_MSN' => ($user_info['user_msnm'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=msnm&u=' . $author_id) : '', From 88aacd0f2cffdf75af71d749c6ea602ed3912651 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 13 Oct 2011 15:52:12 +0200 Subject: [PATCH 24/93] [ticket/10408] Layout of topics/attachments list is broken in UCP and MCP PHPBB3-10408 --- phpBB/styles/prosilver/template/ucp_attachments.html | 4 ++-- phpBB/styles/prosilver/theme/content.css | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/phpBB/styles/prosilver/template/ucp_attachments.html b/phpBB/styles/prosilver/template/ucp_attachments.html index 8052fdc435..c76316d93e 100644 --- a/phpBB/styles/prosilver/template/ucp_attachments.html +++ b/phpBB/styles/prosilver/template/ucp_attachments.html @@ -20,7 +20,7 @@
  • -
    {L_FILENAME}
    +
    {L_FILENAME}
    {L_DOWNLOADS}
    {L_POST_TIME}
    {L_MARK}
    @@ -32,7 +32,7 @@
  • -
    {attachrow.FILENAME} ({attachrow.SIZE})
    +
    {attachrow.FILENAME} ({attachrow.SIZE})
    {L_PM}: {L_TOPIC}: {attachrow.TOPIC_TITLE}
    {attachrow.DOWNLOAD_COUNT}
    {attachrow.POST_TIME}
    diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css index 2dad706bf5..58247883e5 100644 --- a/phpBB/styles/prosilver/theme/content.css +++ b/phpBB/styles/prosilver/theme/content.css @@ -184,7 +184,7 @@ dd.extra { dd.mark { float: right !important; - width: 9%; + width: 90px; text-align: center; line-height: 200%; font-size: 1.2em; From 6698a9cbd62be1e77f329a7e8843fafbc18a1025 Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Thu, 13 Oct 2011 16:25:41 +0200 Subject: [PATCH 25/93] [ticket/8094] Remove ambiguity of "phpBB has no categories" PHPBB3-8094 --- phpBB/language/en/acp/forums.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/language/en/acp/forums.php b/phpBB/language/en/acp/forums.php index eab027f295..b99a0724be 100644 --- a/phpBB/language/en/acp/forums.php +++ b/phpBB/language/en/acp/forums.php @@ -72,7 +72,7 @@ $lang = array_merge($lang, array( 'ENABLE_TOPIC_ICONS' => 'Enable topic icons', 'FORUM_ADMIN' => 'Forum administration', - 'FORUM_ADMIN_EXPLAIN' => 'In phpBB3 there are no categories, everything is forum based. Each forum can have an unlimited number of sub-forums and you can determine whether each may be posted to or not (i.e. whether it acts like an old category). Here you can add, edit, delete, lock, unlock individual forums as well as set certain additional controls. If your posts and topics have got out of sync you can also resynchronise a forum. You need to copy or set appropriate permissions for newly created forums to have them displayed.', + 'FORUM_ADMIN_EXPLAIN' => 'In phpBB3 everything is forum based. A category is just a special type of forum. Each forum can have an unlimited number of sub-forums and you can determine whether each may be posted to or not (i.e. whether it acts like an old category). Here you can add, edit, delete, lock, unlock individual forums as well as set certain additional controls. If your posts and topics have got out of sync you can also resynchronise a forum. You need to copy or set appropriate permissions for newly created forums to have them displayed.', 'FORUM_AUTO_PRUNE' => 'Enable auto-pruning', 'FORUM_AUTO_PRUNE_EXPLAIN' => 'Prunes the forum of topics, set the frequency/age parameters below.', 'FORUM_CREATED' => 'Forum created successfully.', From 3cd8c2507d4181a32484e47d6eef6601485bfb25 Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Thu, 13 Oct 2011 16:43:11 +0200 Subject: [PATCH 26/93] [ticket/10307] Return false in mysqli sql_fetchrow on empty result PHPBB3-10307 --- phpBB/includes/db/mysqli.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/phpBB/includes/db/mysqli.php b/phpBB/includes/db/mysqli.php index 46c2f9210b..456ce906d0 100644 --- a/phpBB/includes/db/mysqli.php +++ b/phpBB/includes/db/mysqli.php @@ -249,7 +249,13 @@ class dbal_mysqli extends dbal return $cache->sql_fetchrow($query_id); } - return ($query_id !== false) ? @mysqli_fetch_assoc($query_id) : false; + if ($query_id !== false) + { + $result = @mysqli_fetch_assoc($query_id); + return $result !== null ? $result : false; + } + + return false; } /** From 6d9e9d190179a33ec8873f206f75db0978992bf6 Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Thu, 13 Oct 2011 16:56:55 +0200 Subject: [PATCH 27/93] [ticket/10307] Add a test for PHPBB3-10307 PHPBB3-10307 --- tests/dbal/select_test.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/dbal/select_test.php b/tests/dbal/select_test.php index e0d08d9306..8ddd27465d 100644 --- a/tests/dbal/select_test.php +++ b/tests/dbal/select_test.php @@ -319,7 +319,7 @@ class phpbb_dbal_select_test extends phpbb_database_test_case $db->sql_freeresult($result); } - function test_nested_transactions() + public function test_nested_transactions() { $db = $this->new_dbal(); @@ -341,4 +341,20 @@ class phpbb_dbal_select_test extends phpbb_database_test_case $this->assertEquals('1', $row['user_id']); } + + /** + * fix for PHPBB3-10307 + */ + public function test_sql_fetchrow_returns_false_when_empty() + { + $db = $this->new_dbal(); + + $sql = 'SELECT * FROM (SELECT 1) AS TBL WHERE 1 = 0'; + $result = $db->sql_query($sql); + + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $this->assertSame(false, $row); + } } From ee91656968aa362aa702821de2e0c0cb0457cc0f Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Thu, 13 Oct 2011 17:09:34 +0200 Subject: [PATCH 28/93] [ticket/10275] Remove incorrect password information from FAQ FAQ contains instructions to find the password in the registration e-mail. We no longer send the password on registration. So let's just remove this incorrect piece of information from the FAQ. PHPBB3-10275 --- phpBB/language/en/help_faq.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/language/en/help_faq.php b/phpBB/language/en/help_faq.php index 3b7dc02d3f..b915a3da19 100644 --- a/phpBB/language/en/help_faq.php +++ b/phpBB/language/en/help_faq.php @@ -60,7 +60,7 @@ $help = array( ), array( 0 => 'I registered in the past but cannot login any more?!', - 1 => 'Attempt to locate the e-mail sent to you when you first registered, check your username and password and try again. It is possible an administrator has deactivated or deleted your account for some reason. Also, many boards periodically remove users who have not posted for a long time to reduce the size of the database. If this has happened, try registering again and being more involved in discussions.' + 1 => 'It is possible an administrator has deactivated or deleted your account for some reason. Also, many boards periodically remove users who have not posted for a long time to reduce the size of the database. If this has happened, try registering again and being more involved in discussions.' ), array( 0 => 'What is COPPA?', From 75ef0fde825b89a6c2fa41a723b600552921e214 Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Thu, 13 Oct 2011 17:43:59 +0200 Subject: [PATCH 29/93] [ticket/10246] Move coding guidelines VCS section to wiki The VCS section can now be found at: * http://wiki.phpbb.com/Git#Branches PHPBB3-10246 --- phpBB/docs/coding-guidelines.html | 52 +------------------------------ 1 file changed, 1 insertion(+), 51 deletions(-) diff --git a/phpBB/docs/coding-guidelines.html b/phpBB/docs/coding-guidelines.html index cd3c09f6fb..da7a3bf582 100644 --- a/phpBB/docs/coding-guidelines.html +++ b/phpBB/docs/coding-guidelines.html @@ -87,12 +87,6 @@
  • Writing Style
  • -
  • VCS Guidelines -
      -
    1. Repository structure
    2. -
    3. Commit Messages and Repository Rules
    4. -
    -
  • Copyright and disclaimer
  • @@ -2323,51 +2317,7 @@ if (utf8_case_fold_nfc($string1) == utf8_case_fold_nfc($string2))
    -

    7. VCS Guidelines

    - -
    -
    - -
    - -

    The version control system for phpBB3 is git. The repository is available at http://github.com/phpbb/phpbb3.

    - -

    7.i. Repository Structure

    - -
      -
    • develop
      The latest unstable development version with new features etc.
    • -
    • develop-*
      Development branches of stable phpBB releases. Branched off of develop at the time of feature freeze. -
        -
      • phpBB3.0develop-olympus
        Development branch of the stable 3.0 line. Bug fixes are applied here.
      • -
      • phpBB3.1develop-ascraeus
        Development branch of the stable 3.1 line. Bug fixes are applied here.
      • -
      -
    • -
    • master
      A branch containing all stable phpBB3 release points
    • -
    • tags
      Released versions. Stable ones get merged into the master branch. -
        -
      • release-3.Y-BX
        Beta release X of the 3.Y line.
      • -
      • release-3.Y-RCX
        Release candidate X of the 3.Y line.
      • -
      • release-3.Y.Z-RCX
        Release candidate X of the stable 3.Y.Z release.
      • -
      • release-3.0.X
        Stable 3.0.X release.
      • -
      • release-2.0.X
        Old stable 2.0.X release.
      • -
      -
    • -
    - -

    7.ii. Commit Messages and Repository Rules

    - -

    Information on repository rules, such as commit messages can be found at http://wiki.phpbb.com/display/DEV/Git.

    - -
    - - - -
    -
    - -
    - -

    9. Copyright and disclaimer

    +

    8. Copyright and disclaimer

    From 091119605abe794aa508c76b7e5199517fc256e3 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Thu, 13 Oct 2011 18:03:02 +0200 Subject: [PATCH 30/93] [ticket/10278] Also timeout when receiving data over a slow connection. PHPBB3-10278 --- phpBB/includes/functions_admin.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index bcd477d855..513b7a68b2 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -3140,6 +3140,7 @@ function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port @fputs($fsock, "HOST: $host\r\n"); @fputs($fsock, "Connection: close\r\n\r\n"); + $timer_stop = time() + $timeout; stream_set_timeout($fsock, $timeout); $file_info = ''; @@ -3167,7 +3168,7 @@ function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port $stream_meta_data = stream_get_meta_data($fsock); - if (!empty($stream_meta_data['timed_out'])) + if (!empty($stream_meta_data['timed_out']) || time() >= $timer_stop) { $errstr = $user->lang['FSOCK_TIMEOUT']; return false; From 1dc1583b92daa666193d766e3728ce9723f4d20f Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Thu, 13 Oct 2011 18:23:33 +0200 Subject: [PATCH 31/93] [ticket/10278] Show VERSIONCHECK_FAIL instead of FSOCK_TIMEOUT. PHPBB3-10278 --- phpBB/includes/acp/acp_update.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/acp/acp_update.php b/phpBB/includes/acp/acp_update.php index 931fa53165..7e3d1a1024 100644 --- a/phpBB/includes/acp/acp_update.php +++ b/phpBB/includes/acp/acp_update.php @@ -37,7 +37,7 @@ class acp_update $errstr = ''; $errno = 0; - $info = obtain_latest_version_info(request_var('versioncheck_force', false), true); + $info = obtain_latest_version_info(request_var('versioncheck_force', false)); if ($info === false) { From f7c1341402ea47cc33ac183421485db3efd7ea15 Mon Sep 17 00:00:00 2001 From: Alan Date: Thu, 13 Oct 2011 19:17:56 +0200 Subject: [PATCH 32/93] [ticket/8616] Direct links in pm notification emails Import the "Direct links in pm notification emails" modification, version 1.0.1. PHPBB3-8616 --- phpBB/includes/functions_privmsgs.php | 6 +++--- phpBB/includes/ucp/ucp_pm.php | 2 +- phpBB/ucp.php | 6 ++++++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index 4c34bc92ca..a857109466 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -1607,7 +1607,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']; @@ -1616,7 +1616,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; @@ -1688,7 +1688,7 @@ 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&mode=view&p=$msg_id") ); $messenger->send($addr['method']); diff --git a/phpBB/includes/ucp/ucp_pm.php b/phpBB/includes/ucp/ucp_pm.php index c675928a5b..447b6ebe87 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']; diff --git a/phpBB/ucp.php b/phpBB/ucp.php index 8fa022668b..45caeb12ea 100644 --- a/phpBB/ucp.php +++ b/phpBB/ucp.php @@ -254,6 +254,12 @@ if (!$user->data['is_registered']) redirect(append_sid("{$phpbb_root_path}index.$phpEx")); } + if ($id == 'pm' && $mode == 'view' && isset($_GET['p'])) + { + $redirect_url = append_sid("{$phpbb_root_path}ucp.$phpEx?i=pm&p=" . request_var('p', 0)); + login_box($redirect_url, $user->lang['LOGIN_EXPLAIN_UCP']); + } + login_box('', $user->lang['LOGIN_EXPLAIN_UCP']); } From 39f6d583150bcd25ff7a780686ebd9c5d933b99e Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Thu, 13 Oct 2011 19:28:46 +0200 Subject: [PATCH 33/93] [ticket/8616] Rename U_INBOX to U_VIEW_MESSAGE PHPBB3-8616 --- phpBB/includes/functions_privmsgs.php | 2 +- phpBB/language/en/email/privmsg_notify.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index a857109466..b34b742d57 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -1688,7 +1688,7 @@ function pm_notification($mode, $author, $recipients, $subject, $message, $msg_i 'AUTHOR_NAME' => htmlspecialchars_decode($author), 'USERNAME' => htmlspecialchars_decode($addr['name']), - 'U_INBOX' => generate_board_url() . "/ucp.$phpEx?i=pm&mode=view&p=$msg_id") + 'U_VIEW_MESSAGE' => generate_board_url() . "/ucp.$phpEx?i=pm&mode=view&p=$msg_id") ); $messenger->send($addr['method']); diff --git a/phpBB/language/en/email/privmsg_notify.txt b/phpBB/language/en/email/privmsg_notify.txt index d363df7973..d3a86cc73c 100644 --- a/phpBB/language/en/email/privmsg_notify.txt +++ b/phpBB/language/en/email/privmsg_notify.txt @@ -8,7 +8,7 @@ You have received a new private message from "{AUTHOR_NAME}" to your account on You can view your new message by clicking on the following link: -{U_INBOX} +{U_VIEW_MESSAGE} You have requested that you be notified on this event, remember that you can always choose not to be notified of new messages by changing the appropriate setting in your profile. From 3ad5c45097d23056d4eb21ba63cb70f595839b44 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Thu, 13 Oct 2011 21:11:58 +0200 Subject: [PATCH 34/93] [ticket/10187] XHTML fix for empty groups in UCP. PHPBB3-10187 --- phpBB/styles/prosilver/template/ucp_groups_manage.html | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/phpBB/styles/prosilver/template/ucp_groups_manage.html b/phpBB/styles/prosilver/template/ucp_groups_manage.html index bce31431cb..87b548c23b 100644 --- a/phpBB/styles/prosilver/template/ucp_groups_manage.html +++ b/phpBB/styles/prosilver/template/ucp_groups_manage.html @@ -143,8 +143,15 @@ + + - + + + + + + From 1df2148bf4d12405018fcbe93cdbff7b9bf4174e Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 13 Oct 2011 23:29:52 +0200 Subject: [PATCH 35/93] [ticket/10409] Running database_update.php multiple times breaks the update PHPBB3-10409 --- phpBB/install/database_update.php | 85 +++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 28 deletions(-) diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php index 18741191d8..4507e5c371 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -2090,42 +2090,68 @@ function change_database_data(&$no_updates, $version) // Changes from 3.1.0-dev to 3.1.0-A1 case '3.1.0-dev': - set_config('use_system_cron', 0); + if (!isset($config['use_system_cron'])) + { + set_config('use_system_cron', 0); + } - $sql = 'UPDATE ' . GROUPS_TABLE . ' - SET group_teampage = 1 - WHERE group_type = ' . GROUP_SPECIAL . " - AND group_name = 'ADMINISTRATORS'"; - _sql($sql, $errored, $error_ary); - - $sql = 'UPDATE ' . GROUPS_TABLE . ' - SET group_teampage = 2 - WHERE group_type = ' . GROUP_SPECIAL . " - AND group_name = 'GLOBAL_MODERATORS'"; - _sql($sql, $errored, $error_ary); - - set_config('legend_sort_groupname', '0'); - set_config('teampage_multiple', '1'); - set_config('teampage_forums', '1'); - - $sql = 'SELECT group_id + $sql = 'SELECT group_teampage FROM ' . GROUPS_TABLE . ' - WHERE group_legend = 1 - ORDER BY group_name ASC'; - $result = $db->sql_query($sql); + WHERE group_teampage > 0'; + $result = $db->sql_query_limit($sql, 1); + $added_groups_teampage = (bool) $db->sql_fetchfield('group_teampage'); + $db->sql_freeresult($result); - $next_legend = 1; - while ($row = $db->sql_fetchrow($result)) + if (!$added_groups_teampage) { $sql = 'UPDATE ' . GROUPS_TABLE . ' - SET group_legend = ' . $next_legend . ' - WHERE group_id = ' . (int) $row['group_id']; + SET group_teampage = 1 + WHERE group_type = ' . GROUP_SPECIAL . " + AND group_name = 'ADMINISTRATORS'"; _sql($sql, $errored, $error_ary); - $next_legend++; + $sql = 'UPDATE ' . GROUPS_TABLE . ' + SET group_teampage = 2 + WHERE group_type = ' . GROUP_SPECIAL . " + AND group_name = 'GLOBAL_MODERATORS'"; + _sql($sql, $errored, $error_ary); } + + if (!isset($config['use_system_cron'])) + { + set_config('legend_sort_groupname', '0'); + set_config('teampage_multiple', '1'); + set_config('teampage_forums', '1'); + } + + $sql = 'SELECT group_legend + FROM ' . GROUPS_TABLE . ' + WHERE group_teampage > 1'; + $result = $db->sql_query_limit($sql, 1); + $updated_group_legend = (bool) $db->sql_fetchfield('group_teampage'); $db->sql_freeresult($result); - unset($next_legend); + + if (!$updated_group_legend) + { + $sql = 'SELECT group_id + FROM ' . GROUPS_TABLE . ' + WHERE group_legend = 1 + ORDER BY group_name ASC'; + $result = $db->sql_query($sql); + + $next_legend = 1; + while ($row = $db->sql_fetchrow($result)) + { + $sql = 'UPDATE ' . GROUPS_TABLE . ' + SET group_legend = ' . $next_legend . ' + WHERE group_id = ' . (int) $row['group_id']; + _sql($sql, $errored, $error_ary); + + $next_legend++; + } + $db->sql_freeresult($result); + unset($next_legend); + } // Install modules $modules_to_install = array( @@ -2229,7 +2255,10 @@ function change_database_data(&$no_updates, $version) } // Allow custom profile fields in pm templates - set_config('load_cpf_pm', '0'); + if (!isset($config['load_cpf_pm'])) + { + set_config('load_cpf_pm', '0'); + } $no_updates = false; break; From 7f42970ba005ca27f85e4375267bd32b8ad35341 Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Fri, 14 Oct 2011 02:00:46 +0200 Subject: [PATCH 36/93] [feature/remove-imagesets] Fix create_schema_files, get rid of imagesets PHPBB3-10336 --- phpBB/develop/create_schema_files.php | 31 -------------------------- phpBB/install/schemas/mssql_schema.sql | 2 +- 2 files changed, 1 insertion(+), 32 deletions(-) diff --git a/phpBB/develop/create_schema_files.php b/phpBB/develop/create_schema_files.php index 2057d292b7..dfdb66aa73 100644 --- a/phpBB/develop/create_schema_files.php +++ b/phpBB/develop/create_schema_files.php @@ -1639,14 +1639,12 @@ function get_schema_struct() 'style_active' => array('BOOL', 1), 'template_id' => array('UINT', 0), 'theme_id' => array('UINT', 0), - 'imageset_id' => array('UINT', 0), ), 'PRIMARY_KEY' => 'style_id', 'KEYS' => array( 'style_name' => array('UNIQUE', 'style_name'), 'template_id' => array('INDEX', 'template_id'), 'theme_id' => array('INDEX', 'theme_id'), - 'imageset_id' => array('INDEX', 'imageset_id'), ), ); @@ -1679,35 +1677,6 @@ function get_schema_struct() ), ); - $schema_data['phpbb_styles_imageset'] = array( - 'COLUMNS' => array( - 'imageset_id' => array('UINT', NULL, 'auto_increment'), - 'imageset_name' => array('VCHAR_UNI:255', ''), - 'imageset_copyright' => array('VCHAR_UNI', ''), - 'imageset_path' => array('VCHAR:100', ''), - ), - 'PRIMARY_KEY' => 'imageset_id', - 'KEYS' => array( - 'imgset_nm' => array('UNIQUE', 'imageset_name'), - ), - ); - - $schema_data['phpbb_styles_imageset_data'] = array( - 'COLUMNS' => array( - 'image_id' => array('UINT', NULL, 'auto_increment'), - 'image_name' => array('VCHAR:200', ''), - 'image_filename' => array('VCHAR:200', ''), - 'image_lang' => array('VCHAR:30', ''), - 'image_height' => array('USINT', 0), - 'image_width' => array('USINT', 0), - 'imageset_id' => array('UINT', 0), - ), - 'PRIMARY_KEY' => 'image_id', - 'KEYS' => array( - 'i_d' => array('INDEX', 'imageset_id'), - ), - ); - $schema_data['phpbb_topics'] = array( 'COLUMNS' => array( 'topic_id' => array('UINT', NULL, 'auto_increment'), diff --git a/phpBB/install/schemas/mssql_schema.sql b/phpBB/install/schemas/mssql_schema.sql index fe69670ded..b78a1b7fdc 100644 --- a/phpBB/install/schemas/mssql_schema.sql +++ b/phpBB/install/schemas/mssql_schema.sql @@ -1307,7 +1307,7 @@ CREATE TABLE [phpbb_styles] ( [style_copyright] [varchar] (255) DEFAULT ('') NOT NULL , [style_active] [int] DEFAULT (1) NOT NULL , [template_id] [int] DEFAULT (0) NOT NULL , - [theme_id] [int] DEFAULT (0) NOT NULL + [theme_id] [int] DEFAULT (0) NOT NULL ) ON [PRIMARY] GO From bb616b4135fba145c961f26a4ff612d6579b6b17 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Fri, 14 Oct 2011 02:02:17 +0200 Subject: [PATCH 37/93] [ticket/10412] Replace memory_get_usage with memory_get_peak_usage PHPBB3-10412 --- phpBB/common.php | 9 --------- phpBB/includes/functions.php | 8 +++----- phpBB/includes/functions_acp.php | 8 +++----- 3 files changed, 6 insertions(+), 19 deletions(-) diff --git a/phpBB/common.php b/phpBB/common.php index 524c05ae70..061290dcea 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -59,15 +59,6 @@ if (!defined('PHPBB_INSTALLED')) exit; } -if (defined('DEBUG_EXTRA')) -{ - $base_memory_usage = 0; - if (function_exists('memory_get_usage')) - { - $base_memory_usage = memory_get_usage(); - } -} - // Load Extensions // dl() is deprecated and disabled by default as of PHP 5.3. if (!empty($load_extensions) && function_exists('dl')) diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 8f41e18db6..688c7f2000 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -4627,15 +4627,13 @@ function page_footer($run_cron = true) if ($auth->acl_get('a_') && defined('DEBUG_EXTRA')) { - if (function_exists('memory_get_usage')) + if (function_exists('memory_get_peak_usage')) { - if ($memory_usage = memory_get_usage()) + if ($memory_usage = memory_get_peak_usage()) { - global $base_memory_usage; - $memory_usage -= $base_memory_usage; $memory_usage = get_formatted_filesize($memory_usage); - $debug_output .= ' | Memory Usage: ' . $memory_usage; + $debug_output .= ' | Peak Memory Usage: ' . $memory_usage; } } diff --git a/phpBB/includes/functions_acp.php b/phpBB/includes/functions_acp.php index c3806dc786..36e22e069f 100644 --- a/phpBB/includes/functions_acp.php +++ b/phpBB/includes/functions_acp.php @@ -106,15 +106,13 @@ function adm_page_footer($copyright_html = true) if ($auth->acl_get('a_') && defined('DEBUG_EXTRA')) { - if (function_exists('memory_get_usage')) + if (function_exists('memory_get_peak_usage')) { - if ($memory_usage = memory_get_usage()) + if ($memory_usage = memory_get_peak_usage()) { - global $base_memory_usage; - $memory_usage -= $base_memory_usage; $memory_usage = get_formatted_filesize($memory_usage); - $debug_output .= ' | Memory Usage: ' . $memory_usage; + $debug_output .= ' | Peak Memory Usage: ' . $memory_usage; } } From 1f677d5de37d7d4e47edf040130424f73b7c86d4 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 14 Oct 2011 02:41:37 +0200 Subject: [PATCH 38/93] [ticket/10074] Change default value of 'Set as special rank' to No PHPBB3-10074 --- phpBB/includes/acp/acp_ranks.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/acp/acp_ranks.php b/phpBB/includes/acp/acp_ranks.php index fcfef2a61e..dfd7511427 100644 --- a/phpBB/includes/acp/acp_ranks.php +++ b/phpBB/includes/acp/acp_ranks.php @@ -199,7 +199,7 @@ class acp_ranks 'RANK_TITLE' => (isset($ranks['rank_title'])) ? $ranks['rank_title'] : '', 'S_FILENAME_LIST' => $filename_list, 'RANK_IMAGE' => ($edit_img) ? $phpbb_root_path . $config['ranks_path'] . '/' . $edit_img : $phpbb_admin_path . 'images/spacer.gif', - 'S_SPECIAL_RANK' => (!isset($ranks['rank_special']) || $ranks['rank_special']) ? true : false, + 'S_SPECIAL_RANK' => (isset($ranks['rank_special']) && $ranks['rank_special']) ? true : false, 'MIN_POSTS' => (isset($ranks['rank_min']) && !$ranks['rank_special']) ? $ranks['rank_min'] : 0) ); From 7fa14e654ad8880613897b45f5effb287d3bfd2d Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Fri, 14 Oct 2011 03:12:44 +0200 Subject: [PATCH 39/93] [ticket/10413] Make create_schema_files usable PHPBB3-10413 --- phpBB/develop/create_schema_files.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/phpBB/develop/create_schema_files.php b/phpBB/develop/create_schema_files.php index efe8837b26..9649997412 100644 --- a/phpBB/develop/create_schema_files.php +++ b/phpBB/develop/create_schema_files.php @@ -12,11 +12,7 @@ * If you overwrite the original schema files please make sure you save the file with UNIX linefeeds. */ -die("Please read the first lines of this script for instructions on how to enable it"); - -@set_time_limit(0); - -$schema_path = './../install/schemas/'; +$schema_path = dirname(__FILE__).'/../install/schemas/'; if (!is_writable($schema_path)) { @@ -242,7 +238,7 @@ $supported_dbms = array('firebird', 'mssql', 'mysql_40', 'mysql_41', 'oracle', ' foreach ($supported_dbms as $dbms) { - $fp = fopen($schema_path . '_' . $dbms . '_schema.sql', 'wt'); + $fp = fopen($schema_path . '' . $dbms . '_schema.sql', 'wt'); $line = ''; From 8cf22f552935417911306cb2830d7522791c9098 Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Fri, 14 Oct 2011 03:41:02 +0200 Subject: [PATCH 40/93] [ticket/10189] Add "automatically generated" comment into schema-files PHPBB3-10189 --- phpBB/develop/create_schema_files.php | 26 +++++++++++++++++++++++ phpBB/install/schemas/firebird_schema.sql | 5 +++++ phpBB/install/schemas/mssql_schema.sql | 8 +++++++ phpBB/install/schemas/mysql_40_schema.sql | 5 +++++ phpBB/install/schemas/mysql_41_schema.sql | 5 +++++ phpBB/install/schemas/oracle_schema.sql | 8 +++++++ phpBB/install/schemas/postgres_schema.sql | 8 +++++++ phpBB/install/schemas/sqlite_schema.sql | 5 +++++ 8 files changed, 70 insertions(+) diff --git a/phpBB/develop/create_schema_files.php b/phpBB/develop/create_schema_files.php index efe8837b26..05acf7177d 100644 --- a/phpBB/develop/create_schema_files.php +++ b/phpBB/develop/create_schema_files.php @@ -246,6 +246,32 @@ foreach ($supported_dbms as $dbms) $line = ''; + switch ($dbms) + { + case 'mysql_40': + case 'mysql_41': + case 'firebird': + case 'sqlite': + fwrite($fp, "# DO NOT EDIT THIS FILE, IT IS GENERATED\n"); + fwrite($fp, "#\n"); + fwrite($fp, "# To change the contents of this file, edit\n"); + fwrite($fp, "# phpBB/develop/create_schema_files.php and\n"); + fwrite($fp, "# run it.\n"); + break; + + case 'mssql': + case 'oracle': + case 'postgres': + fwrite($fp, "/*\n"); + fwrite($fp, " * DO NOT EDIT THIS FILE, IT IS GENERATED\n"); + fwrite($fp, " *\n"); + fwrite($fp, " * To change the contents of this file, edit\n"); + fwrite($fp, " * phpBB/develop/create_schema_files.php and\n"); + fwrite($fp, " * run it.\n"); + fwrite($fp, " */\n\n"); + break; + } + // Write Header switch ($dbms) { diff --git a/phpBB/install/schemas/firebird_schema.sql b/phpBB/install/schemas/firebird_schema.sql index 40041b13cb..852c62705e 100644 --- a/phpBB/install/schemas/firebird_schema.sql +++ b/phpBB/install/schemas/firebird_schema.sql @@ -1,3 +1,8 @@ +# DO NOT EDIT THIS FILE, IT IS GENERATED +# +# To change the contents of this file, edit +# phpBB/develop/create_schema_files.php and +# run it. # # $Id: $ # diff --git a/phpBB/install/schemas/mssql_schema.sql b/phpBB/install/schemas/mssql_schema.sql index c4fc2d4eec..bcdb0dc236 100644 --- a/phpBB/install/schemas/mssql_schema.sql +++ b/phpBB/install/schemas/mssql_schema.sql @@ -1,3 +1,11 @@ +/* + * DO NOT EDIT THIS FILE, IT IS GENERATED + * + * To change the contents of this file, edit + * phpBB/develop/create_schema_files.php and + * run it. + */ + /* $Id: $ diff --git a/phpBB/install/schemas/mysql_40_schema.sql b/phpBB/install/schemas/mysql_40_schema.sql index 06d32166f3..f0357afc23 100644 --- a/phpBB/install/schemas/mysql_40_schema.sql +++ b/phpBB/install/schemas/mysql_40_schema.sql @@ -1,3 +1,8 @@ +# DO NOT EDIT THIS FILE, IT IS GENERATED +# +# To change the contents of this file, edit +# phpBB/develop/create_schema_files.php and +# run it. # # $Id: $ # diff --git a/phpBB/install/schemas/mysql_41_schema.sql b/phpBB/install/schemas/mysql_41_schema.sql index 1db2790ec7..97fe33dbdd 100644 --- a/phpBB/install/schemas/mysql_41_schema.sql +++ b/phpBB/install/schemas/mysql_41_schema.sql @@ -1,3 +1,8 @@ +# DO NOT EDIT THIS FILE, IT IS GENERATED +# +# To change the contents of this file, edit +# phpBB/develop/create_schema_files.php and +# run it. # # $Id: $ # diff --git a/phpBB/install/schemas/oracle_schema.sql b/phpBB/install/schemas/oracle_schema.sql index 783261e365..d879da4048 100644 --- a/phpBB/install/schemas/oracle_schema.sql +++ b/phpBB/install/schemas/oracle_schema.sql @@ -1,3 +1,11 @@ +/* + * DO NOT EDIT THIS FILE, IT IS GENERATED + * + * To change the contents of this file, edit + * phpBB/develop/create_schema_files.php and + * run it. + */ + /* $Id: $ diff --git a/phpBB/install/schemas/postgres_schema.sql b/phpBB/install/schemas/postgres_schema.sql index cf655cb1c7..f532492c2c 100644 --- a/phpBB/install/schemas/postgres_schema.sql +++ b/phpBB/install/schemas/postgres_schema.sql @@ -1,3 +1,11 @@ +/* + * DO NOT EDIT THIS FILE, IT IS GENERATED + * + * To change the contents of this file, edit + * phpBB/develop/create_schema_files.php and + * run it. + */ + /* $Id: $ diff --git a/phpBB/install/schemas/sqlite_schema.sql b/phpBB/install/schemas/sqlite_schema.sql index dae1eb839c..5557e0a0b2 100644 --- a/phpBB/install/schemas/sqlite_schema.sql +++ b/phpBB/install/schemas/sqlite_schema.sql @@ -1,3 +1,8 @@ +# DO NOT EDIT THIS FILE, IT IS GENERATED +# +# To change the contents of this file, edit +# phpBB/develop/create_schema_files.php and +# run it. # # $Id: $ # From 768932a3f2c3218925d564ebfdfca902fc2922e1 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Fri, 14 Oct 2011 03:41:52 +0200 Subject: [PATCH 41/93] [ticket/10212] Return a CAPTCHA on incorrect username for ip limited users too PHPBB3-10212 --- phpBB/includes/auth/auth_db.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/phpBB/includes/auth/auth_db.php b/phpBB/includes/auth/auth_db.php index 6ca69d9174..c20196d019 100644 --- a/phpBB/includes/auth/auth_db.php +++ b/phpBB/includes/auth/auth_db.php @@ -107,6 +107,15 @@ function login_db($username, $password, $ip = '', $browser = '', $forwarded_for if (!$row) { + if ($config['ip_login_limit_max'] && $attempts >= $config['ip_login_limit_max']) + { + return array( + 'status' => LOGIN_ERROR_ATTEMPTS, + 'error_msg' => 'LOGIN_ERROR_ATTEMPTS', + 'user_row' => array('user_id' => ANONYMOUS), + ); + } + return array( 'status' => LOGIN_ERROR_USERNAME, 'error_msg' => 'LOGIN_ERROR_USERNAME', @@ -264,4 +273,4 @@ function login_db($username, $password, $ip = '', $browser = '', $forwarded_for ); } -?> \ No newline at end of file +?> From c3f3435228accc44e2fd8d358c21b81f8ec66d87 Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Fri, 14 Oct 2011 04:29:28 +0200 Subject: [PATCH 42/93] [ticket/10189] Get rid of $id$ from schema files PHPBB3-10189 --- phpBB/develop/create_schema_files.php | 17 +---------------- phpBB/install/schemas/firebird_schema.sql | 4 ---- phpBB/install/schemas/mssql_schema.sql | 6 ------ phpBB/install/schemas/mysql_40_schema.sql | 4 ---- phpBB/install/schemas/mysql_41_schema.sql | 4 ---- phpBB/install/schemas/oracle_schema.sql | 6 ------ phpBB/install/schemas/postgres_schema.sql | 6 ------ phpBB/install/schemas/sqlite_schema.sql | 4 ---- 8 files changed, 1 insertion(+), 50 deletions(-) diff --git a/phpBB/develop/create_schema_files.php b/phpBB/develop/create_schema_files.php index 05acf7177d..9ce5f72922 100644 --- a/phpBB/develop/create_schema_files.php +++ b/phpBB/develop/create_schema_files.php @@ -246,6 +246,7 @@ foreach ($supported_dbms as $dbms) $line = ''; + // Write Header switch ($dbms) { case 'mysql_40': @@ -272,37 +273,21 @@ foreach ($supported_dbms as $dbms) break; } - // Write Header switch ($dbms) { - case 'mysql_40': - case 'mysql_41': - $line = "#\n# \$I" . "d: $\n#\n\n"; - break; - case 'firebird': - $line = "#\n# \$I" . "d: $\n#\n\n"; $line .= custom_data('firebird') . "\n"; break; case 'sqlite': - $line = "#\n# \$I" . "d: $\n#\n\n"; $line .= "BEGIN TRANSACTION;\n\n"; break; - case 'mssql': - $line = "/*\n\n \$I" . "d: $\n\n*/\n\n"; - // no need to do this, no transaction support for schema changes - //$line .= "BEGIN TRANSACTION\nGO\n\n"; - break; - case 'oracle': - $line = "/*\n\n \$I" . "d: $\n\n*/\n\n"; $line .= custom_data('oracle') . "\n"; break; case 'postgres': - $line = "/*\n\n \$I" . "d: $\n\n*/\n\n"; $line .= "BEGIN;\n\n"; $line .= custom_data('postgres') . "\n"; break; diff --git a/phpBB/install/schemas/firebird_schema.sql b/phpBB/install/schemas/firebird_schema.sql index 852c62705e..73052f0a22 100644 --- a/phpBB/install/schemas/firebird_schema.sql +++ b/phpBB/install/schemas/firebird_schema.sql @@ -3,10 +3,6 @@ # To change the contents of this file, edit # phpBB/develop/create_schema_files.php and # run it. -# -# $Id: $ -# - # Table: 'phpbb_attachments' CREATE TABLE phpbb_attachments ( diff --git a/phpBB/install/schemas/mssql_schema.sql b/phpBB/install/schemas/mssql_schema.sql index bcdb0dc236..8ed3ba7e12 100644 --- a/phpBB/install/schemas/mssql_schema.sql +++ b/phpBB/install/schemas/mssql_schema.sql @@ -6,12 +6,6 @@ * run it. */ -/* - - $Id: $ - -*/ - /* Table: 'phpbb_attachments' */ diff --git a/phpBB/install/schemas/mysql_40_schema.sql b/phpBB/install/schemas/mysql_40_schema.sql index f0357afc23..42b7291d9d 100644 --- a/phpBB/install/schemas/mysql_40_schema.sql +++ b/phpBB/install/schemas/mysql_40_schema.sql @@ -3,10 +3,6 @@ # To change the contents of this file, edit # phpBB/develop/create_schema_files.php and # run it. -# -# $Id: $ -# - # Table: 'phpbb_attachments' CREATE TABLE phpbb_attachments ( attach_id mediumint(8) UNSIGNED NOT NULL auto_increment, diff --git a/phpBB/install/schemas/mysql_41_schema.sql b/phpBB/install/schemas/mysql_41_schema.sql index 97fe33dbdd..7a6d0ae188 100644 --- a/phpBB/install/schemas/mysql_41_schema.sql +++ b/phpBB/install/schemas/mysql_41_schema.sql @@ -3,10 +3,6 @@ # To change the contents of this file, edit # phpBB/develop/create_schema_files.php and # run it. -# -# $Id: $ -# - # Table: 'phpbb_attachments' CREATE TABLE phpbb_attachments ( attach_id mediumint(8) UNSIGNED NOT NULL auto_increment, diff --git a/phpBB/install/schemas/oracle_schema.sql b/phpBB/install/schemas/oracle_schema.sql index d879da4048..6e7ec31efc 100644 --- a/phpBB/install/schemas/oracle_schema.sql +++ b/phpBB/install/schemas/oracle_schema.sql @@ -6,12 +6,6 @@ * run it. */ -/* - - $Id: $ - -*/ - /* This first section is optional, however its probably the best method of running phpBB on Oracle. If you already have a tablespace and user created diff --git a/phpBB/install/schemas/postgres_schema.sql b/phpBB/install/schemas/postgres_schema.sql index f532492c2c..38f167bc7b 100644 --- a/phpBB/install/schemas/postgres_schema.sql +++ b/phpBB/install/schemas/postgres_schema.sql @@ -6,12 +6,6 @@ * run it. */ -/* - - $Id: $ - -*/ - BEGIN; /* diff --git a/phpBB/install/schemas/sqlite_schema.sql b/phpBB/install/schemas/sqlite_schema.sql index 5557e0a0b2..c0574244ca 100644 --- a/phpBB/install/schemas/sqlite_schema.sql +++ b/phpBB/install/schemas/sqlite_schema.sql @@ -3,10 +3,6 @@ # To change the contents of this file, edit # phpBB/develop/create_schema_files.php and # run it. -# -# $Id: $ -# - BEGIN TRANSACTION; # Table: 'phpbb_attachments' From d86fccf9c909602c37ec97577a19dc442e22206b Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Fri, 14 Oct 2011 04:29:53 +0200 Subject: [PATCH 43/93] [ticket/10327] Change CREATE INDEX to ALTER TABLE table ADD INDEX for MySQL. * CREATE INDEX is internally mapped to an ALTER INDEX statement. * CREATE INDEX requires the INDEX permission. * ALTER TABLE requires the (more powerful) ALTER permission. * We require the ALTER permission anyway for operation. * Changing CREATE INDEX to ALTER TABLE thus removes dependency on the INDEX permission which is good because some management software does not give out the INDEX permission by default. http://dev.mysql.com/doc/refman/5.0/en/create-index.html PHPBB3-10327 --- phpBB/includes/db/db_tools.php | 2 +- tests/dbal/db_tools_test.php | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php index 10ca6c0a1f..0d8cf7fdab 100644 --- a/phpBB/includes/db/db_tools.php +++ b/phpBB/includes/db/db_tools.php @@ -2145,7 +2145,7 @@ class phpbb_db_tools } // no break case 'mysql_41': - $statements[] = 'CREATE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; + $statements[] = 'ALTER TABLE ' . $table_name . ' ADD INDEX ' . $index_name . '(' . implode(', ', $column) . ')'; break; case 'mssql': diff --git a/tests/dbal/db_tools_test.php b/tests/dbal/db_tools_test.php index 753cc08fc5..927bce4597 100644 --- a/tests/dbal/db_tools_test.php +++ b/tests/dbal/db_tools_test.php @@ -333,4 +333,22 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case ), )); } + + public function test_index_exists() + { + $db_tools = new phpbb_db_tools($this->db); + + $this->assertTrue($db_tools->sql_index_exists('prefix_table_name', 'i_simple')); + } + + public function test_create_index_against_index_exists() + { + $db_tools = new phpbb_db_tools($this->db); + + $table_name = 'prefix_table_name'; + $index_name = 'fookey'; + + $db_tools->sql_create_index($table_name, $index_name, array('c_timestamp', 'c_decimal')); + $this->assertTrue($db_tools->sql_index_exists($table_name, $index_name)); + } } From e40abfbde9f83c3c2c24a456fc7fe4765766859f Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 14 Oct 2011 15:19:47 +0200 Subject: [PATCH 44/93] [ticket/9525] Minimum post length 0 is accepted but not working. PHPBB3-9525 --- phpBB/includes/acp/acp_board.php | 2 +- phpBB/language/en/acp/board.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index d8ab42ed2d..3ed5f40368 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -188,7 +188,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' => ' %'), diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index 5a9ca6231d..6e6d4302cd 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -174,7 +174,7 @@ $lang = array_merge($lang, array( 'MAX_POST_URLS' => 'Maximum links per post', 'MAX_POST_URLS_EXPLAIN' => 'Maximum number of URLs in a post. Set to 0 for unlimited links.', 'MIN_CHAR_LIMIT' => 'Minimum characters per post/message', - 'MIN_CHAR_LIMIT_EXPLAIN' => 'The minimum number of characters the user need to enter within a post/private message.', + 'MIN_CHAR_LIMIT_EXPLAIN' => 'The minimum number of characters the user need to enter within a post/private message. The minimum for this setting is 1.', 'POSTING' => 'Posting', 'POSTS_PER_PAGE' => 'Posts per page', 'QUOTE_DEPTH_LIMIT' => 'Maximum nesting depth for quotes', From 234edf674cd1c2ed3611f69cd925c4d5e29fdc20 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Fri, 14 Oct 2011 15:25:15 +0200 Subject: [PATCH 45/93] [ticket/8240] Add ability to get a list of tables to db_tools. PHPBB3-8240 --- phpBB/includes/db/db_tools.php | 60 ++++++++++++++++++++++++++++ phpBB/includes/functions_install.php | 57 ++++---------------------- tests/dbal/db_tools_test.php | 7 ++++ 3 files changed, 75 insertions(+), 49 deletions(-) diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php index 0d8cf7fdab..7c3d673869 100644 --- a/phpBB/includes/db/db_tools.php +++ b/phpBB/includes/db/db_tools.php @@ -347,6 +347,66 @@ class phpbb_db_tools } } + /** + * Gets a list of tables in the database. + * + * @return array Array of table names (all lower case) + */ + function sql_list_tables() + { + switch ($this->db->sql_layer) + { + case 'mysql': + case 'mysql4': + case 'mysqli': + $sql = 'SHOW TABLES'; + break; + + case 'sqlite': + $sql = 'SELECT name + FROM sqlite_master + WHERE type = "table"'; + break; + + case 'mssql': + case 'mssql_odbc': + case 'mssqlnative': + $sql = "SELECT name + FROM sysobjects + WHERE type='U'"; + break; + + case 'postgres': + $sql = 'SELECT relname + FROM pg_stat_user_tables'; + break; + + case 'firebird': + $sql = 'SELECT rdb$relation_name + FROM rdb$relations + WHERE rdb$view_source is null + AND rdb$system_flag = 0'; + break; + + case 'oracle': + $sql = 'SELECT table_name + FROM USER_TABLES'; + break; + } + + $result = $this->db->sql_query($sql); + + $tables = array(); + while ($row = $this->db->sql_fetchrow($result)) + { + $name = current($row); + $tables[$name] = $name; + } + $this->db->sql_freeresult($result); + + return $tables; + } + /** * Check if table exists * diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php index 992e8d6bb0..2c640e0999 100644 --- a/phpBB/includes/functions_install.php +++ b/phpBB/includes/functions_install.php @@ -211,61 +211,20 @@ function dbms_select($default = '', $only_20x_options = false) /** * Get tables of a database +* +* @deprecated */ -function get_tables($db) +function get_tables(&$db) { - switch ($db->sql_layer) + if (!class_exists('phpbb_db_tools')) { - case 'mysql': - case 'mysql4': - case 'mysqli': - $sql = 'SHOW TABLES'; - break; - - case 'sqlite': - $sql = 'SELECT name - FROM sqlite_master - WHERE type = "table"'; - break; - - case 'mssql': - case 'mssql_odbc': - case 'mssqlnative': - $sql = "SELECT name - FROM sysobjects - WHERE type='U'"; - break; - - case 'postgres': - $sql = 'SELECT relname - FROM pg_stat_user_tables'; - break; - - case 'firebird': - $sql = 'SELECT rdb$relation_name - FROM rdb$relations - WHERE rdb$view_source is null - AND rdb$system_flag = 0'; - break; - - case 'oracle': - $sql = 'SELECT table_name - FROM USER_TABLES'; - break; + global $phpbb_root_path, $phpEx; + require($phpbb_root_path . 'includes/db/db_tools.' . $phpEx); } - $result = $db->sql_query($sql); + $db_tools = new phpbb_db_tools($db); - $tables = array(); - - while ($row = $db->sql_fetchrow($result)) - { - $tables[] = current($row); - } - - $db->sql_freeresult($result); - - return $tables; + return $db_tools->sql_list_tables(); } /** diff --git a/tests/dbal/db_tools_test.php b/tests/dbal/db_tools_test.php index 927bce4597..130fc451f9 100644 --- a/tests/dbal/db_tools_test.php +++ b/tests/dbal/db_tools_test.php @@ -258,6 +258,13 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case $this->assertFalse($this->tools->sql_column_exists('prefix_table_name', 'c_id')); } + public function test_list_tables() + { + $tables = $this->tools->sql_list_tables(); + $this->assertTrue(isset($tables['prefix_table_name'])); + $this->assertFalse(isset($tables['prefix_does_not_exist'])); + } + public function test_table_exists() { $this->assertTrue($this->tools->sql_table_exists('prefix_table_name')); From 4effe8fb8bdf493e539b7bf883fbf1e290bf7ab2 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Fri, 14 Oct 2011 16:29:33 +0200 Subject: [PATCH 46/93] [ticket/8240] Add ability to get a list of columns of a tables to db_tools. PHPBB3-8240 --- phpBB/includes/db/db_tools.php | 111 +++++++++++---------------------- tests/dbal/db_tools_test.php | 8 +++ 2 files changed, 45 insertions(+), 74 deletions(-) diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php index 7c3d673869..317b8c6083 100644 --- a/phpBB/includes/db/db_tools.php +++ b/phpBB/includes/db/db_tools.php @@ -1071,34 +1071,21 @@ class phpbb_db_tools } /** - * Check if a specified column exist + * Gets a list of columns of a table. * - * @param string $table Table to check the column at - * @param string $column_name The column to check + * @param string $table Table name * - * @return bool True if column exists, else false + * @return array Array of column names (all lower case) */ - function sql_column_exists($table, $column_name) + function sql_list_columns($table) { + $columns = array(); + switch ($this->sql_layer) { case 'mysql_40': case 'mysql_41': - $sql = "SHOW COLUMNS FROM $table"; - $result = $this->db->sql_query($sql); - - while ($row = $this->db->sql_fetchrow($result)) - { - // lower case just in case - if (strtolower($row['Field']) == $column_name) - { - $this->db->sql_freeresult($result); - return true; - } - } - $this->db->sql_freeresult($result); - return false; break; // PostgreSQL has a way of doing this in a much simpler way but would @@ -1109,19 +1096,6 @@ class phpbb_db_tools WHERE c.relname = '{$table}' AND a.attnum > 0 AND a.attrelid = c.oid"; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - // lower case just in case - if (strtolower($row['attname']) == $column_name) - { - $this->db->sql_freeresult($result); - return true; - } - } - $this->db->sql_freeresult($result); - - return false; break; // same deal with PostgreSQL, we must perform more complex operations than @@ -1132,62 +1106,26 @@ class phpbb_db_tools FROM syscolumns c LEFT JOIN sysobjects o ON c.id = o.id WHERE o.name = '{$table}'"; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - // lower case just in case - if (strtolower($row['name']) == $column_name) - { - $this->db->sql_freeresult($result); - return true; - } - } - $this->db->sql_freeresult($result); - return false; break; case 'oracle': $sql = "SELECT column_name FROM user_tab_columns WHERE LOWER(table_name) = '" . strtolower($table) . "'"; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - // lower case just in case - if (strtolower($row['column_name']) == $column_name) - { - $this->db->sql_freeresult($result); - return true; - } - } - $this->db->sql_freeresult($result); - return false; break; case 'firebird': $sql = "SELECT RDB\$FIELD_NAME as FNAME FROM RDB\$RELATION_FIELDS WHERE RDB\$RELATION_NAME = '" . strtoupper($table) . "'"; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - // lower case just in case - if (strtolower($row['fname']) == $column_name) - { - $this->db->sql_freeresult($result); - return true; - } - } - $this->db->sql_freeresult($result); - return false; break; - // ugh, SQLite case 'sqlite': $sql = "SELECT sql FROM sqlite_master WHERE type = 'table' AND name = '{$table}'"; + $result = $this->db->sql_query($sql); if (!$result) @@ -1211,14 +1149,39 @@ class phpbb_db_tools continue; } - if (strtolower($entities[0]) == $column_name) - { - return true; - } + $column = strtolower($entities[0]); + $columns[$column] = $column; } - return false; + + return $columns; break; } + + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + $column = strtolower(current($row)); + $columns[$column] = $column; + } + $this->db->sql_freeresult($result); + + return $columns; + } + + /** + * Check whether a specified column exist in a table + * + * @param string $table Table to check + * @param string $column_name Column to check + * + * @return bool True if column exists, false otherwise + */ + function sql_column_exists($table, $column_name) + { + $columns = $this->sql_list_columns($table); + + return isset($columns[$column_name]); } /** diff --git a/tests/dbal/db_tools_test.php b/tests/dbal/db_tools_test.php index 130fc451f9..b34b471e5c 100644 --- a/tests/dbal/db_tools_test.php +++ b/tests/dbal/db_tools_test.php @@ -234,6 +234,14 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case $this->assertEquals($row2, $row_actual); } + public function test_list_columns() + { + $this->assertEquals( + array_keys($this->table_data['COLUMNS']), + array_values($this->tools->sql_list_columns('prefix_table_name')) + ); + } + public function test_column_exists() { $this->assertTrue($this->tools->sql_column_exists('prefix_table_name', 'c_id')); From 637d8eabe76907ce4a1e810d8b6bd964acb1b303 Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Sun, 21 Aug 2011 19:26:15 +0200 Subject: [PATCH 47/93] [feature/functional-tests] Implementing functional test framework with goutte PHPBB3-10414 --- phpunit.xml.dist | 1 + phpunit.xml.functional | 48 +++++++ tests/bootstrap.php | 1 + tests/functional/browse_test.php | 26 ++++ .../phpbb_functional_test_case.php | 128 ++++++++++++++++++ vendor/goutte.phar | Bin 0 -> 267414 bytes 6 files changed, 204 insertions(+) create mode 100644 phpunit.xml.functional create mode 100644 tests/functional/browse_test.php create mode 100644 tests/test_framework/phpbb_functional_test_case.php create mode 100644 vendor/goutte.phar diff --git a/phpunit.xml.dist b/phpunit.xml.dist index a2bf2288cc..27dee48aac 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -19,6 +19,7 @@ + functional slow diff --git a/phpunit.xml.functional b/phpunit.xml.functional new file mode 100644 index 0000000000..9facbcff8b --- /dev/null +++ b/phpunit.xml.functional @@ -0,0 +1,48 @@ + + + + + + ./tests/ + + + + + + functional + + + + + + ./tests/ + + + ./phpBB/includes/ + + ./phpBB/includes/db/firebird.php + ./phpBB/includes/db/mysql.php + ./phpBB/includes/db/mysqli.php + ./phpBB/includes/db/mssql.php + ./phpBB/includes/db/mssql_odbc.php + ./phpBB/includes/db/mssqlnative.php + ./phpBB/includes/db/oracle.php + ./phpBB/includes/db/postgres.php + ./phpBB/includes/db/sqlite.php + ./phpBB/includes/search/fulltext_native.php + ./phpBB/includes/search/fulltext_mysql.php + ./phpBB/includes/captcha/ + + + + diff --git a/tests/bootstrap.php b/tests/bootstrap.php index b7c3534cde..9a1c8857c0 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -39,3 +39,4 @@ require_once 'test_framework/phpbb_test_case_helpers.php'; require_once 'test_framework/phpbb_test_case.php'; require_once 'test_framework/phpbb_database_test_case.php'; require_once 'test_framework/phpbb_database_test_connection_manager.php'; +require_once 'test_framework/phpbb_functional_test_case.php'; diff --git a/tests/functional/browse_test.php b/tests/functional/browse_test.php new file mode 100644 index 0000000000..9c1d04f35d --- /dev/null +++ b/tests/functional/browse_test.php @@ -0,0 +1,26 @@ +request('GET', 'index.php'); + $this->assertGreaterThan(0, $crawler->filter('.topiclist')->count()); + } + + public function test_viewforum() + { + $crawler = $this->request('GET', 'viewforum.php?f=2'); + $this->assertGreaterThan(0, $crawler->filter('.topiclist')->count()); + } +} diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php new file mode 100644 index 0000000000..ddaa894061 --- /dev/null +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -0,0 +1,128 @@ +client = new Goutte\Client(); + $this->root_url = $_SERVER['PHPBB_FUNCTIONAL_URL']; + } + + public function request($method, $path) + { + return $this->client->request($method, $this->root_url . $path); + } + + static public function setUpBeforeClass() + { + global $phpbb_root_path, $phpEx; + + if (!isset($_SERVER['PHPBB_FUNCTIONAL_URL'])) + { + self::markTestSkipped("The 'PHPBB_FUNCTIONAL_URL' environment variable was not set."); + } + + if (!file_exists($phpbb_root_path . "config.$phpEx")) + { + self::markTestSkipped("config.php does not exist, it is required for running functional tests."); + } + + require $phpbb_root_path . "config.$phpEx"; + + $db_config = array( + 'dbhost' => $dbhost, + 'dbport' => $dbport, + 'dbname' => $dbname, + 'dbuser' => $dbuser, + 'dbpasswd' => $dbpasswd, + 'dbms' => $dbms, + 'table_prefix' => 'phpbb_', + ); + self::recreate_database($db_config); + + rename($phpbb_root_path . "config.$phpEx", $phpbb_root_path . "_config.$phpEx"); + + // begin data + $data = array(); + + $data = array_merge($data, $db_config); + + $data = array_merge($data, array( + 'default_lang' => 'en', + 'admin_name' => 'admin', + 'admin_pass1' => 'admin', + 'admin_pass2' => 'admin', + 'board_email1' => 'nobody@example.com', + 'board_email2' => 'nobody@example.com', + )); + + $parseURL = parse_url($_SERVER['PHPBB_FUNCTIONAL_URL']); + + $data = array_merge($data, array( + 'email_enable' => false, + 'smtp_delivery' => false, + 'smtp_host' => '', + 'smtp_auth' => '', + 'smtp_user' => '', + 'smtp_pass' => '', + 'cookie_secure' => false, + 'force_server_vars' => false, + 'server_protocol' => $parseURL['scheme'] . '://', + 'server_name' => 'localhost', + 'server_port' => isset($parseURL['port']) ? (int) $parseURL['port'] : 80, + 'script_path' => $parseURL['path'], + )); + // end data + + $content = self::do_request('install'); + self::assertContains('Welcome to Installation', $content); + + self::do_request('config_file', $data); + + rename($phpbb_root_path . "_config.$phpEx", $phpbb_root_path . "config.$phpEx"); + + self::do_request('create_table', $data); + self::do_request('final', $data); + } + + static public function tearDownAfterClass() + { + } + + static private function do_request($sub, $post_data = null) + { + $context = null; + + if ($post_data) + { + $context = stream_context_create(array( + 'http' => array( + 'method' => 'POST', + 'header' => 'Content-Type: application/x-www-form-urlencoded', + 'content' => http_build_query($post_data), + 'ignore_errors' => true, + ), + )); + } + + return file_get_contents($_SERVER['PHPBB_FUNCTIONAL_URL'] . 'install/index.php?mode=install&sub=' . $sub, false, $context); + } + + static private function recreate_database($config) + { + $db_conn_mgr = new phpbb_database_test_connection_manager($config); + $db_conn_mgr->recreate_db(); + } +} diff --git a/vendor/goutte.phar b/vendor/goutte.phar new file mode 100644 index 0000000000000000000000000000000000000000..20b7166a6717aa5b904859fc1ffe3b32106d55a8 GIT binary patch literal 267414 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 L-+lYd^KbrtSl@Ba literal 0 HcmV?d00001 From 0ffe494edd274647ba6694648dba070c63e55d89 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Fri, 14 Oct 2011 16:05:35 +0200 Subject: [PATCH 48/93] [feature/functional-tests] Configure functional tests through config file The functional tests now also use the test database PHPBB3-10414 --- .../phpbb_database_test_case.php | 40 ++------------ .../phpbb_functional_test_case.php | 54 ++++++++++--------- .../phpbb_test_case_helpers.php | 52 ++++++++++++++++++ 3 files changed, 86 insertions(+), 60 deletions(-) diff --git a/tests/test_framework/phpbb_database_test_case.php b/tests/test_framework/phpbb_database_test_case.php index e1b368dcea..b1484450b8 100644 --- a/tests/test_framework/phpbb_database_test_case.php +++ b/tests/test_framework/phpbb_database_test_case.php @@ -40,46 +40,14 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test public function get_database_config() { - if (isset($_SERVER['PHPBB_TEST_DBMS'])) - { - return array( - 'dbms' => isset($_SERVER['PHPBB_TEST_DBMS']) ? $_SERVER['PHPBB_TEST_DBMS'] : '', - 'dbhost' => isset($_SERVER['PHPBB_TEST_DBHOST']) ? $_SERVER['PHPBB_TEST_DBHOST'] : '', - 'dbport' => isset($_SERVER['PHPBB_TEST_DBPORT']) ? $_SERVER['PHPBB_TEST_DBPORT'] : '', - 'dbname' => isset($_SERVER['PHPBB_TEST_DBNAME']) ? $_SERVER['PHPBB_TEST_DBNAME'] : '', - 'dbuser' => isset($_SERVER['PHPBB_TEST_DBUSER']) ? $_SERVER['PHPBB_TEST_DBUSER'] : '', - 'dbpasswd' => isset($_SERVER['PHPBB_TEST_DBPASSWD']) ? $_SERVER['PHPBB_TEST_DBPASSWD'] : '', - ); - } - else if (file_exists(dirname(__FILE__) . '/../test_config.php')) - { - include(dirname(__FILE__) . '/../test_config.php'); + $config = phpbb_test_case_helpers::get_test_config(); - return array( - 'dbms' => $dbms, - 'dbhost' => $dbhost, - 'dbport' => $dbport, - 'dbname' => $dbname, - 'dbuser' => $dbuser, - 'dbpasswd' => $dbpasswd, - ); - } - else if (extension_loaded('sqlite') && version_compare(PHPUnit_Runner_Version::id(), '3.4.15', '>=')) - { - // Silently use sqlite - return array( - 'dbms' => 'sqlite', - 'dbhost' => dirname(__FILE__) . '/../phpbb_unit_tests.sqlite2', // filename - 'dbport' => '', - 'dbname' => '', - 'dbuser' => '', - 'dbpasswd' => '', - ); - } - else + if (!isset($config['dbms'])) { $this->markTestSkipped('Missing test_config.php: See first error.'); } + + return $config; } public function getConnection() diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index ddaa894061..02d51d71de 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -14,6 +14,8 @@ class phpbb_functional_test_case extends phpbb_test_case protected $client; protected $root_url; + static protected $config; + public function setUp() { $this->client = new Goutte\Client(); @@ -29,35 +31,32 @@ class phpbb_functional_test_case extends phpbb_test_case { global $phpbb_root_path, $phpEx; - if (!isset($_SERVER['PHPBB_FUNCTIONAL_URL'])) + self::$config = phpbb_test_case_helpers::get_test_config(); + + if (!isset(self::$config['phpbb_functional_url'])) { - self::markTestSkipped("The 'PHPBB_FUNCTIONAL_URL' environment variable was not set."); + self::markTestSkipped('phpbb_functional_url was not set in test_config and wasn\'t set as PHPBB_FUNCTIONAL_URL environment variable either.'); } - if (!file_exists($phpbb_root_path . "config.$phpEx")) + self::$config['table_prefix'] = 'phpbb_'; + self::recreate_database(self::$config); + + if (file_exists($phpbb_root_path . "config.$phpEx")) { - self::markTestSkipped("config.php does not exist, it is required for running functional tests."); + if (!file_exists($phpbb_root_path . "config_dev.$phpEx")) + { + rename($phpbb_root_path . "config.$phpEx", $phpbb_root_path . "config_dev.$phpEx"); + } + else + { + unlink($phpbb_root_path . "config.$phpEx"); + } } - require $phpbb_root_path . "config.$phpEx"; - - $db_config = array( - 'dbhost' => $dbhost, - 'dbport' => $dbport, - 'dbname' => $dbname, - 'dbuser' => $dbuser, - 'dbpasswd' => $dbpasswd, - 'dbms' => $dbms, - 'table_prefix' => 'phpbb_', - ); - self::recreate_database($db_config); - - rename($phpbb_root_path . "config.$phpEx", $phpbb_root_path . "_config.$phpEx"); - // begin data $data = array(); - $data = array_merge($data, $db_config); + $data = array_merge($data, self::$config); $data = array_merge($data, array( 'default_lang' => 'en', @@ -68,7 +67,7 @@ class phpbb_functional_test_case extends phpbb_test_case 'board_email2' => 'nobody@example.com', )); - $parseURL = parse_url($_SERVER['PHPBB_FUNCTIONAL_URL']); + $parseURL = parse_url(self::$config['phpbb_functional_url']); $data = array_merge($data, array( 'email_enable' => false, @@ -89,16 +88,23 @@ class phpbb_functional_test_case extends phpbb_test_case $content = self::do_request('install'); self::assertContains('Welcome to Installation', $content); + self::do_request('create_table', $data); + self::do_request('config_file', $data); - rename($phpbb_root_path . "_config.$phpEx", $phpbb_root_path . "config.$phpEx"); + if (file_exists($phpbb_root_path . "config.$phpEx")) + { + copy($phpbb_root_path . "config.$phpEx", $phpbb_root_path . "config_test.$phpEx"); + } - self::do_request('create_table', $data); self::do_request('final', $data); } static public function tearDownAfterClass() { + global $phpbb_root_path, $phpEx; + + copy($phpbb_root_path . "config_dev.$phpEx", $phpbb_root_path . "config.$phpEx"); } static private function do_request($sub, $post_data = null) @@ -117,7 +123,7 @@ class phpbb_functional_test_case extends phpbb_test_case )); } - return file_get_contents($_SERVER['PHPBB_FUNCTIONAL_URL'] . 'install/index.php?mode=install&sub=' . $sub, false, $context); + return file_get_contents(self::$config['phpbb_functional_url'] . 'install/index.php?mode=install&sub=' . $sub, false, $context); } static private function recreate_database($config) diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index 697dc93501..cbfb2540c2 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -46,4 +46,56 @@ class phpbb_test_case_helpers { mkdir($path, 0777, true); } + + static public function get_test_config() + { + if (extension_loaded('sqlite') && version_compare(PHPUnit_Runner_Version::id(), '3.4.15', '>=')) + { + $config = array( + 'dbms' => 'sqlite', + 'dbhost' => dirname(__FILE__) . '/../phpbb_unit_tests.sqlite2', // filename + 'dbport' => '', + 'dbname' => '', + 'dbuser' => '', + 'dbpasswd' => '', + 'phpbb_functional_url' => 'http://localhost/', + ); + } + + if (file_exists(dirname(__FILE__) . '/../test_config.php')) + { + include(dirname(__FILE__) . '/../test_config.php'); + + $config = array_merge($config, array( + 'dbms' => $dbms, + 'dbhost' => $dbhost, + 'dbport' => $dbport, + 'dbname' => $dbname, + 'dbuser' => $dbuser, + 'dbpasswd' => $dbpasswd, + 'phpbb_functional_url' => isset($phpbb_functional_url) ? $phpbb_functional_url : 'http://localhost/', + )); + } + + if (isset($_SERVER['PHPBB_TEST_DBMS'])) + { + $config = array_merge($config, array( + 'dbms' => isset($_SERVER['PHPBB_TEST_DBMS']) ? $_SERVER['PHPBB_TEST_DBMS'] : '', + 'dbhost' => isset($_SERVER['PHPBB_TEST_DBHOST']) ? $_SERVER['PHPBB_TEST_DBHOST'] : '', + 'dbport' => isset($_SERVER['PHPBB_TEST_DBPORT']) ? $_SERVER['PHPBB_TEST_DBPORT'] : '', + 'dbname' => isset($_SERVER['PHPBB_TEST_DBNAME']) ? $_SERVER['PHPBB_TEST_DBNAME'] : '', + 'dbuser' => isset($_SERVER['PHPBB_TEST_DBUSER']) ? $_SERVER['PHPBB_TEST_DBUSER'] : '', + 'dbpasswd' => isset($_SERVER['PHPBB_TEST_DBPASSWD']) ? $_SERVER['PHPBB_TEST_DBPASSWD'] : '' + )); + } + + if (isset($_SERVER['PHPBB_FUNCTIONAL_URL'])) + { + $config = array_merge($config, array( + 'phpbb_functional_url' => isset($_SERVER['PHPBB_FUNCTIONAL_URL']) ? $_SERVER['PHPBB_FUNCTIONAL_URL'] : '', + )); + } + + return $config; + } } From 7e18d2b861826f399805656143fbdb940f302221 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Fri, 14 Oct 2011 17:18:25 +0200 Subject: [PATCH 49/93] [ticket/10327] Also change CREATE UNIQUE INDEX to use ALTER TABLE. PHPBB3-10327 --- phpBB/includes/db/db_tools.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php index 0d8cf7fdab..392a827cb7 100644 --- a/phpBB/includes/db/db_tools.php +++ b/phpBB/includes/db/db_tools.php @@ -2092,7 +2092,7 @@ class phpbb_db_tools case 'mysql_40': case 'mysql_41': - $statements[] = 'CREATE UNIQUE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; + $statements[] = 'ALTER TABLE ' . $table_name . ' ADD UNIQUE INDEX (' . implode(', ', $column) . ')'; break; case 'mssql': From 607761e8303f456929e4755d8fabb69d9d16561a Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Fri, 14 Oct 2011 17:20:51 +0200 Subject: [PATCH 50/93] [ticket/10327] Use $this->tools instead of creating a new instance of db_tools. PHPBB3-10327 --- tests/dbal/db_tools_test.php | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/tests/dbal/db_tools_test.php b/tests/dbal/db_tools_test.php index 927bce4597..daf464d600 100644 --- a/tests/dbal/db_tools_test.php +++ b/tests/dbal/db_tools_test.php @@ -336,19 +336,12 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case public function test_index_exists() { - $db_tools = new phpbb_db_tools($this->db); - - $this->assertTrue($db_tools->sql_index_exists('prefix_table_name', 'i_simple')); + $this->assertTrue($this->tools->sql_index_exists('prefix_table_name', 'i_simple')); } public function test_create_index_against_index_exists() { - $db_tools = new phpbb_db_tools($this->db); - - $table_name = 'prefix_table_name'; - $index_name = 'fookey'; - - $db_tools->sql_create_index($table_name, $index_name, array('c_timestamp', 'c_decimal')); - $this->assertTrue($db_tools->sql_index_exists($table_name, $index_name)); + $this->tools->sql_create_index('prefix_table_name', 'fookey', array('c_timestamp', 'c_decimal')); + $this->assertTrue($this->tools->sql_index_exists('prefix_table_name', 'fookey')); } } From a3928bf82d7fd6a1da074716c08c547afc961346 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Fri, 14 Oct 2011 17:10:21 +0200 Subject: [PATCH 51/93] [feature/functional-tests] Generate config correctly and install only once PHPBB3-10414 --- phpBB/includes/functions_install.php | 44 +++++++++++- phpBB/install/install_install.php | 27 +------- .../phpbb_functional_test_case.php | 67 ++++++++++++------- .../phpbb_test_case_helpers.php | 7 +- 4 files changed, 93 insertions(+), 52 deletions(-) diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php index 4746b2f6e1..7742bb9263 100644 --- a/phpBB/includes/functions_install.php +++ b/phpBB/includes/functions_install.php @@ -104,7 +104,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'DRIVER' => 'mssqlnative', 'AVAILABLE' => true, '2.0.x' => false, - ), + ), 'oracle' => array( 'LABEL' => 'Oracle', 'SCHEMA' => 'oracle', @@ -555,3 +555,45 @@ function adjust_language_keys_callback($matches) return (!empty($lang[$matches[1]])) ? $db->sql_escape($lang[$matches[1]]) : $db->sql_escape($matches[1]); } } + +function phpbb_create_config_file_data($data, $dbms, $load_extensions, $debug = false) +{ + $load_extensions = implode(',', $load_extensions); + + $config_data = " $dbms, + 'dbhost' => $data['dbhost'], + 'dbport' => $data['dbport'], + 'dbname' => $data['dbname'], + 'dbuser' => $data['dbuser'], + 'dbpasswd' => htmlspecialchars_decode($data['dbpasswd']), + 'table_prefix' => $data['table_prefix'], + 'acm_type' => 'file', + 'load_extensions' => $load_extensions, + ); + + foreach ($config_data_array as $key => $value) + { + $config_data .= "\${$key} = '" . str_replace("'", "\\'", str_replace('\\', '\\\\', $value)) . "';\n"; + } + + $config_data .= "\n@define('PHPBB_INSTALLED', true);\n"; + + if ($debug) + { + $config_data .= "@define('DEBUG', true);\n"; + $config_data .= "@define('DEBUG_EXTRA', true);\n"; + } + else + { + $config_data .= "// @define('DEBUG', true);\n"; + $config_data .= "// @define('DEBUG_EXTRA', true);\n"; + } + + $config_data .= '?' . '>'; // Done this to prevent highlighting editors getting confused! + + return $config_data; +} diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php index f8c54678bf..439bebf27e 100644 --- a/phpBB/install/install_install.php +++ b/phpBB/install/install_install.php @@ -876,33 +876,8 @@ class install_install extends module @chmod($phpbb_root_path . 'cache/install_lock', 0777); - $load_extensions = implode(',', $load_extensions); - // Time to convert the data provided into a config file - $config_data = " $available_dbms[$data['dbms']]['DRIVER'], - 'dbhost' => $data['dbhost'], - 'dbport' => $data['dbport'], - 'dbname' => $data['dbname'], - 'dbuser' => $data['dbuser'], - 'dbpasswd' => htmlspecialchars_decode($data['dbpasswd']), - 'table_prefix' => $data['table_prefix'], - 'acm_type' => 'file', - 'load_extensions' => $load_extensions, - ); - - foreach ($config_data_array as $key => $value) - { - $config_data .= "\${$key} = '" . str_replace("'", "\\'", str_replace('\\', '\\\\', $value)) . "';\n"; - } - unset($config_data_array); - - $config_data .= "\n@define('PHPBB_INSTALLED', true);\n"; - $config_data .= "// @define('DEBUG', true);\n"; - $config_data .= "// @define('DEBUG_EXTRA', true);\n"; + $config_data = phpbb_create_config_file_data($data, $available_dbms[$data['dbms']]['DRIVER'], $load_extensions); // Attempt to write out the config file directly. If it works, this is the easiest way to do it ... if ((file_exists($phpbb_root_path . 'config.' . $phpEx) && phpbb_is_writable($phpbb_root_path . 'config.' . $phpEx)) || phpbb_is_writable($phpbb_root_path)) diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index 02d51d71de..a8601f346c 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -8,18 +8,25 @@ */ require_once __DIR__ . '/../../vendor/goutte.phar'; +require_once __DIR__ . '/../../phpBB/includes/functions_install.php'; class phpbb_functional_test_case extends phpbb_test_case { protected $client; protected $root_url; - static protected $config; + static protected $config = array(); + static protected $already_installed = false; public function setUp() { + if (!isset(self::$config['phpbb_functional_url'])) + { + $this->markTestSkipped('phpbb_functional_url was not set in test_config and wasn\'t set as PHPBB_FUNCTIONAL_URL environment variable either.'); + } + $this->client = new Goutte\Client(); - $this->root_url = $_SERVER['PHPBB_FUNCTIONAL_URL']; + $this->root_url = self::$config['phpbb_functional_url']; } public function request($method, $path) @@ -27,7 +34,29 @@ class phpbb_functional_test_case extends phpbb_test_case return $this->client->request($method, $this->root_url . $path); } - static public function setUpBeforeClass() + public function __construct($name = NULL, array $data = array(), $dataName = '') + { + parent::__construct($name, $data, $dataName); + + $this->backupStaticAttributesBlacklist += array( + 'PHP_CodeCoverage' => array('instance'), + 'PHP_CodeCoverage_Filter' => array('instance'), + 'PHP_CodeCoverage_Util' => array('ignoredLines', 'templateMethods'), + 'PHP_Timer' => array('startTimes',), + 'PHP_Token_Stream' => array('customTokens'), + 'PHP_Token_Stream_CachingFactory' => array('cache'), + + 'phpbb_functional_test_case' => array('config', 'already_installed'), + ); + + if (!self::$already_installed) + { + $this->install_board(); + self::$already_installed = true; + } + } + + protected function install_board() { global $phpbb_root_path, $phpEx; @@ -35,11 +64,11 @@ class phpbb_functional_test_case extends phpbb_test_case if (!isset(self::$config['phpbb_functional_url'])) { - self::markTestSkipped('phpbb_functional_url was not set in test_config and wasn\'t set as PHPBB_FUNCTIONAL_URL environment variable either.'); + return; } self::$config['table_prefix'] = 'phpbb_'; - self::recreate_database(self::$config); + $this->recreate_database(self::$config); if (file_exists($phpbb_root_path . "config.$phpEx")) { @@ -85,29 +114,21 @@ class phpbb_functional_test_case extends phpbb_test_case )); // end data - $content = self::do_request('install'); - self::assertContains('Welcome to Installation', $content); + $content = $this->do_request('install'); + $this->assertContains('Welcome to Installation', $content); - self::do_request('create_table', $data); + $this->do_request('create_table', $data); - self::do_request('config_file', $data); + file_put_contents($phpbb_root_path . "config.$phpEx", phpbb_create_config_file_data($data, self::$config['dbms'], array(), true)); - if (file_exists($phpbb_root_path . "config.$phpEx")) - { - copy($phpbb_root_path . "config.$phpEx", $phpbb_root_path . "config_test.$phpEx"); - } + $this->do_request('config_file', $data); - self::do_request('final', $data); + copy($phpbb_root_path . "config.$phpEx", $phpbb_root_path . "config_test.$phpEx"); + + $this->do_request('final', $data); } - static public function tearDownAfterClass() - { - global $phpbb_root_path, $phpEx; - - copy($phpbb_root_path . "config_dev.$phpEx", $phpbb_root_path . "config.$phpEx"); - } - - static private function do_request($sub, $post_data = null) + private function do_request($sub, $post_data = null) { $context = null; @@ -126,7 +147,7 @@ class phpbb_functional_test_case extends phpbb_test_case return file_get_contents(self::$config['phpbb_functional_url'] . 'install/index.php?mode=install&sub=' . $sub, false, $context); } - static private function recreate_database($config) + private function recreate_database($config) { $db_conn_mgr = new phpbb_database_test_connection_manager($config); $db_conn_mgr->recreate_db(); diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index cbfb2540c2..9177a443ab 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -58,7 +58,6 @@ class phpbb_test_case_helpers 'dbname' => '', 'dbuser' => '', 'dbpasswd' => '', - 'phpbb_functional_url' => 'http://localhost/', ); } @@ -73,8 +72,12 @@ class phpbb_test_case_helpers 'dbname' => $dbname, 'dbuser' => $dbuser, 'dbpasswd' => $dbpasswd, - 'phpbb_functional_url' => isset($phpbb_functional_url) ? $phpbb_functional_url : 'http://localhost/', )); + + if (isset($phpbb_functional_url)) + { + $config['phpbb_functional_url'] = $phpbb_functional_url; + } } if (isset($_SERVER['PHPBB_TEST_DBMS'])) From a8aa7fd6c094dcba20c45c6e81928c5a6942c48b Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Fri, 14 Oct 2011 17:18:33 +0200 Subject: [PATCH 52/93] [feature/functional-tests] Don't add elements to backup list twice PHPBB3-10414 --- tests/test_framework/phpbb_functional_test_case.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index a8601f346c..18bf2a84a8 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -39,13 +39,6 @@ class phpbb_functional_test_case extends phpbb_test_case parent::__construct($name, $data, $dataName); $this->backupStaticAttributesBlacklist += array( - 'PHP_CodeCoverage' => array('instance'), - 'PHP_CodeCoverage_Filter' => array('instance'), - 'PHP_CodeCoverage_Util' => array('ignoredLines', 'templateMethods'), - 'PHP_Timer' => array('startTimes',), - 'PHP_Token_Stream' => array('customTokens'), - 'PHP_Token_Stream_CachingFactory' => array('cache'), - 'phpbb_functional_test_case' => array('config', 'already_installed'), ); From 27279afa1ed75457e6e0d32c982bf9458f048f30 Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Fri, 14 Oct 2011 17:30:54 +0200 Subject: [PATCH 53/93] [ticket/10377] Do not allow all moderators to sticky posts In the mcp the change_topic_type does not properly check permissions, allowing moderators to make any post sticky or announced by visiting the correct URL. PHPBB3-10377 --- phpBB/includes/mcp/mcp_main.php | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index ad10a52705..ffede11d37 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( From 8d33dea2cdc68473fbcf3c45ac8bdbe8fd185054 Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Sun, 16 Oct 2011 19:30:33 +0200 Subject: [PATCH 54/93] [ticket/10413] Fix CS PHPBB3-10413 --- phpBB/develop/create_schema_files.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/develop/create_schema_files.php b/phpBB/develop/create_schema_files.php index 9649997412..1ba03707d0 100644 --- a/phpBB/develop/create_schema_files.php +++ b/phpBB/develop/create_schema_files.php @@ -12,7 +12,7 @@ * If you overwrite the original schema files please make sure you save the file with UNIX linefeeds. */ -$schema_path = dirname(__FILE__).'/../install/schemas/'; +$schema_path = dirname(__FILE__) . '/../install/schemas/'; if (!is_writable($schema_path)) { @@ -238,7 +238,7 @@ $supported_dbms = array('firebird', 'mssql', 'mysql_40', 'mysql_41', 'oracle', ' foreach ($supported_dbms as $dbms) { - $fp = fopen($schema_path . '' . $dbms . '_schema.sql', 'wt'); + $fp = fopen($schema_path . $dbms . '_schema.sql', 'wt'); $line = ''; From fa1d9a4571ac208bbc9379b9e4e3a9a5ae07f0f1 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Sun, 16 Oct 2011 20:06:08 +0200 Subject: [PATCH 55/93] [ticket/10416] Pass dbport to PDO object in ...connection_manager::connect(). PHPBB3-10416 --- .../phpbb_database_test_connection_manager.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/test_framework/phpbb_database_test_connection_manager.php b/tests/test_framework/phpbb_database_test_connection_manager.php index a7559e2183..68e09add94 100644 --- a/tests/test_framework/phpbb_database_test_connection_manager.php +++ b/tests/test_framework/phpbb_database_test_connection_manager.php @@ -69,6 +69,11 @@ class phpbb_database_test_connection_manager default: $dsn .= 'host=' . $this->config['dbhost']; + if ($this->config['dbport']) + { + $dsn .= ';port=' . $this->config['dbport']; + } + if ($use_db) { $dsn .= ';dbname=' . $this->config['dbname']; From 38e7f3fff7df947057cf5f7640d53d0bf170d4a0 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Sun, 16 Oct 2011 20:34:25 +0200 Subject: [PATCH 56/93] [ticket/10417] Fix array_merge() on undefined $config variable. PHPBB3-10417 --- tests/test_framework/phpbb_test_case_helpers.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php index 9177a443ab..649b88fdfd 100644 --- a/tests/test_framework/phpbb_test_case_helpers.php +++ b/tests/test_framework/phpbb_test_case_helpers.php @@ -49,16 +49,18 @@ class phpbb_test_case_helpers static public function get_test_config() { + $config = array(); + if (extension_loaded('sqlite') && version_compare(PHPUnit_Runner_Version::id(), '3.4.15', '>=')) { - $config = array( + $config = array_merge($config, array( 'dbms' => 'sqlite', 'dbhost' => dirname(__FILE__) . '/../phpbb_unit_tests.sqlite2', // filename 'dbport' => '', 'dbname' => '', 'dbuser' => '', 'dbpasswd' => '', - ); + )); } if (file_exists(dirname(__FILE__) . '/../test_config.php')) From 9c861a0350ae67f06a38ee6efc890412a32751f4 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Mon, 17 Oct 2011 06:52:34 +0200 Subject: [PATCH 57/93] [ticket/10414] Skip functional tests on PHP 5.2 - requires PHPUnit 3.6 on 5.2 Tests still execute correctly using PHPUnit 3.5 on PHP 5.3 and above. The php version limitation for a directory was added in PHPUnit 3.6. A separate test suite is required because the functional tests are in the whitelisted tests directory. The base test for functional testing is only included in bootstrap in versions 5.3 and above. PHPBB3-10414 --- phpunit.xml.all | 4 ++++ phpunit.xml.dist | 4 ++++ phpunit.xml.functional | 4 ++++ tests/bootstrap.php | 6 +++++- 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/phpunit.xml.all b/phpunit.xml.all index fde3bbb1a7..b835a38c20 100644 --- a/phpunit.xml.all +++ b/phpunit.xml.all @@ -14,6 +14,10 @@ ./tests/ + ./tests/functional + + + ./tests/functional diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 27dee48aac..da31dce5e3 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -14,6 +14,10 @@ ./tests/ + ./tests/functional + + + ./tests/functional diff --git a/phpunit.xml.functional b/phpunit.xml.functional index 9facbcff8b..91d569e65b 100644 --- a/phpunit.xml.functional +++ b/phpunit.xml.functional @@ -14,6 +14,10 @@ ./tests/ + ./tests/functional + + + ./tests/functional diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 9a1c8857c0..855ea1ce1f 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -39,4 +39,8 @@ require_once 'test_framework/phpbb_test_case_helpers.php'; require_once 'test_framework/phpbb_test_case.php'; require_once 'test_framework/phpbb_database_test_case.php'; require_once 'test_framework/phpbb_database_test_connection_manager.php'; -require_once 'test_framework/phpbb_functional_test_case.php'; + +if (version_compare(PHP_VERSION, '5.3.0-dev', '>=')) +{ + require_once 'test_framework/phpbb_functional_test_case.php'; +} From 8f6cfc77d21313c05cf1f7a5c94caee4bd861628 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Mon, 17 Oct 2011 19:10:41 +0200 Subject: [PATCH 58/93] [ticket/10259] Do not send notifications to user accounts joining free groups. It does not make sense to send notifications to users joining a freely open group. They already know that they were added to the group, because they triggered the actual join. PHPBB3-10259 --- phpBB/includes/ucp/ucp_groups.php | 66 +++++++++++++++---------------- 1 file changed, 31 insertions(+), 35 deletions(-) diff --git a/phpBB/includes/ucp/ucp_groups.php b/phpBB/includes/ucp/ucp_groups.php index 1c055a4823..d62dbb1866 100644 --- a/phpBB/includes/ucp/ucp_groups.php +++ b/phpBB/includes/ucp/ucp_groups.php @@ -193,48 +193,44 @@ 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(); + + $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); + + while ($row = $db->sql_fetchrow($result)) + { + $messenger->template('group_request', $row['user_lang']); + + $messenger->to($row['user_email'], $row['username']); + $messenger->im($row['user_jabber'], $row['username']); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($row['username']), + 'GROUP_NAME' => htmlspecialchars_decode($group_row[$group_id]['group_name']), + 'REQUEST_USERNAME' => $user->data['username'], + + 'U_PENDING' => generate_board_url() . "/ucp.$phpEx?i=groups&mode=manage&action=list&g=$group_id", + 'U_GROUP' => generate_board_url() . "/memberlist.$phpEx?mode=group&g=$group_id") + ); + + $messenger->send($row['user_notify_type']); + } + $db->sql_freeresult($result); + + $messenger->save_queue(); } - include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); - $messenger = new messenger(); - - $sql = 'SELECT u.username, u.username_clean, u.user_email, u.user_notify_type, u.user_jabber, u.user_lang - FROM ' . USER_GROUP_TABLE . ' ug, ' . USERS_TABLE . ' u - WHERE ug.user_id = u.user_id - AND ' . (($group_row[$group_id]['group_type'] == GROUP_FREE) ? "ug.user_id = {$user->data['user_id']}" : 'ug.group_leader = 1') . " - AND ug.group_id = $group_id"; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $messenger->template($email_template, $row['user_lang']); - - $messenger->to($row['user_email'], $row['username']); - $messenger->im($row['user_jabber'], $row['username']); - - $messenger->assign_vars(array( - 'USERNAME' => htmlspecialchars_decode($row['username']), - 'GROUP_NAME' => htmlspecialchars_decode($group_row[$group_id]['group_name']), - 'REQUEST_USERNAME' => $user->data['username'], - - 'U_PENDING' => generate_board_url() . "/ucp.$phpEx?i=groups&mode=manage&action=list&g=$group_id", - 'U_GROUP' => generate_board_url() . "/memberlist.$phpEx?mode=group&g=$group_id") - ); - - $messenger->send($row['user_notify_type']); - } - $db->sql_freeresult($result); - - $messenger->save_queue(); - add_log('user', $user->data['user_id'], 'LOG_USER_GROUP_JOIN' . (($group_row[$group_id]['group_type'] == GROUP_FREE) ? '' : '_PENDING'), $group_row[$group_id]['group_name']); meta_refresh(3, $this->u_action); From 88b31c2ab3f2fe1e88920b3d3b022ee1355321f7 Mon Sep 17 00:00:00 2001 From: rxu Date: Tue, 18 Oct 2011 01:54:17 +0800 Subject: [PATCH 59/93] [ticket/10419] Add mbstring PHP ini parameters checks to ACP PHPBB3-10419 --- phpBB/adm/style/acp_main.html | 30 ++++++++++++++++++++++++++++++ phpBB/includes/acp/acp_main.php | 11 +++++++++++ phpBB/language/en/acp/common.php | 10 ++++++++++ 3 files changed, 51 insertions(+) diff --git a/phpBB/adm/style/acp_main.html b/phpBB/adm/style/acp_main.html index 7d3b6945ac..c665c9d893 100644 --- a/phpBB/adm/style/acp_main.html +++ b/phpBB/adm/style/acp_main.html @@ -34,6 +34,36 @@ + + +
    +

    {L_ERROR_MBSTRING_FUNC_OVERLOAD}

    +

    {L_ERROR_MBSTRING_FUNC_OVERLOAD_EXPLAIN}

    +
    + + + +
    +

    {L_ERROR_MBSTRING_ENCODING_TRANSLATION}

    +

    {L_ERROR_MBSTRING_ENCODING_TRANSLATION_EXPLAIN}

    +
    + + + +
    +

    {L_ERROR_MBSTRING_HTTP_INPUT}

    +

    {L_ERROR_MBSTRING_HTTP_INPUT_EXPLAIN}

    +
    + + + +
    +

    {L_ERROR_MBSTRING_HTTP_OUTPUT}

    +

    {L_ERROR_MBSTRING_HTTP_OUTPUT_EXPLAIN}

    +
    + + +

    {L_WRITABLE_CONFIG}

    diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index 6d1c02248a..e31acfb7d1 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/language/en/acp/common.php b/phpBB/language/en/acp/common.php index 8c71e936b3..a8cfaf8aa8 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -327,6 +327,16 @@ $lang = array_merge($lang, array( 'DATABASE_SERVER_INFO' => 'Database server', 'DATABASE_SIZE' => 'Database size', + // Enviroment configuration checks, mbstring related + 'ERROR_MBSTRING_FUNC_OVERLOAD' => 'Functions overloading setting failed', + 'ERROR_MBSTRING_FUNC_OVERLOAD_EXPLAIN' => 'mbstring.func_overload must be set to either 0 or 4. You can check current value on PHP information page.', + 'ERROR_MBSTRING_ENCODING_TRANSLATION' => 'Transparent character encoding setting failed', + 'ERROR_MBSTRING_ENCODING_TRANSLATION_EXPLAIN' => 'mbstring.encoding_translation must be set to 0. You can check current value on PHP information page.', + 'ERROR_MBSTRING_HTTP_INPUT' => 'HTTP input character conversion setting failed', + 'ERROR_MBSTRING_HTTP_INPUT_EXPLAIN' => 'mbstring.http_input must be set to pass. You can check current value on PHP information page.', + 'ERROR_MBSTRING_HTTP_OUTPUT' => 'HTTP output character conversion setting failed', + 'ERROR_MBSTRING_HTTP_OUTPUT_EXPLAIN' => 'mbstring.http_output must be set to pass. You can check current value on PHP information page.', + 'FILES_PER_DAY' => 'Attachments per day', 'FORUM_STATS' => 'Board statistics', From c8399b8e30769bcc34feaee4df8f4dfddaa9576f Mon Sep 17 00:00:00 2001 From: Vjacheslav Trushkin Date: Tue, 18 Oct 2011 21:37:51 +0300 Subject: [PATCH 60/93] [ticket/10422] Invalid "if" in viewtopic_body.html Fixing incorrect "IF" in viewtopic_body.html PHPBB3-10422 --- phpBB/styles/prosilver/template/viewtopic_body.html | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/phpBB/styles/prosilver/template/viewtopic_body.html b/phpBB/styles/prosilver/template/viewtopic_body.html index 32292f89ef..57de96d853 100644 --- a/phpBB/styles/prosilver/template/viewtopic_body.html +++ b/phpBB/styles/prosilver/template/viewtopic_body.html @@ -4,13 +4,10 @@
    {FORUM_DESC}
    - -

    - - {L_MODERATOR}{L_MODERATORS}: {MODERATORS} - - -

    + +

    + {L_MODERATOR}{L_MODERATORS}: {MODERATORS} +

    From cd184e49125e70fbce40897ef3e4eec8665de12f Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Tue, 18 Oct 2011 21:16:42 +0200 Subject: [PATCH 61/93] [ticket/10420] Update includes/startup.php for PHP 5.4. PHP 5.4 dropped support for register globals and magic quotes. Calling set_magic_quotes_runtime() on PHP 5.4 actually results in an E_CORE_ERROR error. PHPBB3-10420 --- phpBB/includes/startup.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From ba1464b6e039f558b751c0631f8b5fd2c6c23a3e Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Tue, 18 Oct 2011 21:25:27 +0200 Subject: [PATCH 62/93] [ticket/10421] Correct parameter order for phpbb_check_hash() in acp_users.php PHPBB3-10421 --- phpBB/includes/acp/acp_users.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 789003e31b..abf1481000 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -818,7 +818,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)) From 8b99f04943673805a53fbea02d40faa98b0766d6 Mon Sep 17 00:00:00 2001 From: dellsystem Date: Thu, 27 Oct 2011 21:43:01 -0400 Subject: [PATCH 63/93] [ticket/10430] Fix typos/etc in coding guidelines Mainly minor changes to correct errors and improve readability. * "overcroud" --> "overcrowd" * "concentinations" --> "concatenations" * "SQL Statements", "SQL Formatting" - unnecessary capitalisation removed * "keep a very close eye to it" --> "keep a very close eye on it" * Fixed some fragmented sentences under the SQL Quotes section * Added capitalisation of "sql", "select", "select distinct" * "noticable" --> "noticeable" * "outputed" --> "outputted" * Added a missing "it" on the line about append_sid() * And some other grammatical/stylistic changes, not worth listing them all PHPBB3-10430 --- phpBB/docs/coding-guidelines.html | 42 +++++++++++++++---------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/phpBB/docs/coding-guidelines.html b/phpBB/docs/coding-guidelines.html index da7a3bf582..7d51b26dca 100644 --- a/phpBB/docs/coding-guidelines.html +++ b/phpBB/docs/coding-guidelines.html @@ -462,12 +462,12 @@ do_stuff($str); $post_url = $phpbb_root_path . 'posting.' . $phpEx . '?mode=' . $mode . '&amp;start=' . $start;
    -

    // Double quotes are sometimes needed to not overcroud the line with concentinations

    +

    // Double quotes are sometimes needed to not overcrowd the line with concatenations.

     $post_url = "{$phpbb_root_path}posting.$phpEx?mode=$mode&amp;start=$start";
     	
    -

    In SQL Statements mixing single and double quotes is partly allowed (following the guidelines listed here about SQL Formatting), else it should be tryed to only use one method - mostly single quotes.

    +

    In SQL statements mixing single and double quotes is partly allowed (following the guidelines listed here about SQL formatting), else one should try to only use one method - mostly single quotes.

    Associative array keys:

    In PHP, it's legal to use a literal string as a key to an associative array without quoting that string. We don't want to do this -- the string should always be quoted to avoid confusion. Note that this is only when we're using a literal, not when we're using a variable, examples:

    @@ -496,7 +496,7 @@ $foo = $assoc_array[$var];

    Each complex function should be preceded by a comment that tells a programmer everything they need to know to use that function. The meaning of every parameter, the expected input, and the output are required as a minimal comment. The function's behaviour in error conditions (and what those error conditions are) should also be present - but mostly included within the comment about the output.

    Especially important to document are any assumptions the code makes, or preconditions for its proper operation. Any one of the developers should be able to look at any part of the application and figure out what's going on in a reasonable amount of time.

    Avoid using /* */ comment blocks for one-line comments, // should be used for one/two-liners.

    Magic numbers:

    -

    Don't use them. Use named constants for any literal value other than obvious special cases. Basically, it's ok to check if an array has 0 elements by using the literal 0. It's not ok to assign some special meaning to a number and then use it everywhere as a literal. This hurts readability AND maintainability. The constants true and false should be used in place of the literals 1 and 0 -- even though they have the same values (but not type!), it's more obvious what the actual logic is when you use the named constants. Typecast variables where it is needed, do not rely on the correct variable type (PHP is currently very loose on typecasting which can lead to security problems if a developer does not have a very close eye to it).

    +

    Don't use them. Use named constants for any literal value other than obvious special cases. Basically, it's ok to check if an array has 0 elements by using the literal 0. It's not ok to assign some special meaning to a number and then use it everywhere as a literal. This hurts readability AND maintainability. The constants true and false should be used in place of the literals 1 and 0 -- even though they have the same values (but not type!), it's more obvious what the actual logic is when you use the named constants. Typecast variables where it is needed, do not rely on the correct variable type (PHP is currently very loose on typecasting which can lead to security problems if a developer does not keep a very close eye on it).

    Shortcut operators:

    The only shortcut operators that cause readability problems are the shortcut increment $i++ and decrement $j-- operators. These operators should not be used as part of an expression. They can, however, be used on their own line. Using them in expressions is just not worth the headaches when debugging, examples:

    @@ -665,7 +665,7 @@ $sql = 'SELECT *

    SQL Quotes:

    -

    Double quotes where applicable (The variables in these examples are typecasted to integers before) ... examples:

    +

    Use double quotes where applicable. (The variables in these examples are typecasted to integers beforehand.) Examples:

    // These are wrong.

    @@ -826,7 +826,7 @@ SELECT FROM phpbb_forums WHERE forum_id <> 1
     
     	

    sql_build_query():

    -

    The $db->sql_build_query() function is responsible for building sql statements for select and select distinct queries if you need to JOIN on more than one table or retrieving data from more than one table while doing a JOIN. This needs to be used to make sure the resulting statement is working on all supported db's. Instead of explaining every possible combination, i will give a short example:

    +

    The $db->sql_build_query() function is responsible for building sql statements for SELECT and SELECT DISTINCT queries if you need to JOIN on more than one table or retrieve data from more than one table while doing a JOIN. This needs to be used to make sure the resulting statement is working on all supported db's. Instead of explaining every possible combination, I will give a short example:

     $sql_array = array(
    @@ -911,7 +911,7 @@ for ($i = 0, $size = sizeof($post_data); $i < $size; $i++)
     	

    Use of in_array():

    -

    Try to avoid using in_array() on huge arrays, and try to not place them into loops if the array to check consist of more than 20 entries. in_array() can be very time consuming and uses a lot of cpu processing time. For little checks it is not noticable, but if checked against a huge array within a loop those checks alone can be a bunch of seconds. If you need this functionality, try using isset() on the arrays keys instead, actually shifting the values into keys and vice versa. A call to isset($array[$var]) is a lot faster than in_array($var, array_keys($array)) for example.

    +

    Try to avoid using in_array() on huge arrays, and try to not place them into loops if the array to check consist of more than 20 entries. in_array() can be very time consuming and uses a lot of cpu processing time. For little checks it is not noticeable, but if checked against a huge array within a loop those checks alone can take several seconds. If you need this functionality, try using isset() on the arrays keys instead, actually shifting the values into keys and vice versa. A call to isset($array[$var]) is a lot faster than in_array($var, array_keys($array)) for example.

    2.v. General Guidelines

    @@ -924,7 +924,7 @@ for ($i = 0, $size = sizeof($post_data); $i < $size; $i++)

    No attempt should be made to remove any copyright information (either contained within the source or displayed interactively when the source is run/compiled), neither should the copyright information be altered in any way (it may be added to).

    Variables:

    -

    Make use of the request_var() function for anything except for submit or single checking params.

    +

    Make use of the request_var() function for anything except for submit or single checking params.

    The request_var function determines the type to set from the second parameter (which determines the default value too). If you need to get a scalar variable type, you need to tell this the request_var function explicitly. Examples:

    // Old method, do not use it

    @@ -991,7 +991,7 @@ $user->setup();

    The $user->setup() call can be used to pass on additional language definition and a custom style (used in viewforum).

    Errors and messages:

    -

    All messages/errors should be outputed by calling trigger_error() using the appropriate message type and language string. Example:

    +

    All messages/errors should be outputted by calling trigger_error() using the appropriate message type and language string. Example:

     trigger_error('NO_FORUM');
    @@ -1009,7 +1009,7 @@ trigger_error('NO_MODE', E_USER_ERROR);
     
     	

    All urls pointing to internal files need to be prepended by the $phpbb_root_path variable. Within the administration control panel all urls pointing to internal files need to be prepended by the $phpbb_admin_path variable. This makes sure the path is always correct and users being able to just rename the admin folder and the acp still working as intended (though some links will fail and the code need to be slightly adjusted).

    -

    The append_sid() function from 2.0.x is available too, though does not handle url alterations automatically. Please have a look at the code documentation if you want to get more details on how to use append_sid(). A sample call to append_sid() can look like this:

    +

    The append_sid() function from 2.0.x is available too, though it does not handle url alterations automatically. Please have a look at the code documentation if you want to get more details on how to use append_sid(). A sample call to append_sid() can look like this:

     append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&amp;g=' . $row['group_id'])
    @@ -1017,7 +1017,7 @@ append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&amp;
     
     	

    General function usage:

    -

    Some of these functions are only chosen over others because of personal preference and having no other benefit than to be consistent over the code.

    +

    Some of these functions are only chosen over others because of personal preference and have no benefit other than maintaining consistency throughout the code.

    • @@ -1067,7 +1067,7 @@ append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&amp; required_imageset = prosilver

    3.2. General Styling Rules

    -

    Templates should be produced in a consistent manner. Where appropriate they should be based off an existing copy, e.g. index, viewforum or viewtopic (the combination of which implement a range of conditional and variable forms). Please also note that the intendation and coding guidelines also apply to templates where possible.

    +

    Templates should be produced in a consistent manner. Where appropriate they should be based off an existing copy, e.g. index, viewforum or viewtopic (the combination of which implement a range of conditional and variable forms). Please also note that the indentation and coding guidelines also apply to templates where possible.

    The outer table class forumline has gone and is replaced with tablebg.

    When writing <table> the order <table class="" cellspacing="" cellpadding="" border="" align=""> creates consistency and allows everyone to easily see which table produces which "look". The same applies to most other tags for which additional parameters can be set, consistency is the major aim here.

    @@ -1087,7 +1087,7 @@ append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&amp;

    Row colours/classes are now defined by the template, use an IF S_ROW_COUNT switch, see viewtopic or viewforum for an example.

    -

    Remember block level ordering is important ... while not all pages validate as XHTML 1.0 Strict compliant it is something we're trying to work too.

    +

    Remember block level ordering is important ... while not all pages validate as XHTML 1.0 Strict compliant it is something we're trying to work on.

    Use a standard cellpadding of 2 and cellspacing of 0 on outer tables. Inner tables can vary from 0 to 3 or even 4 depending on the need.

    @@ -1136,12 +1136,12 @@ append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&amp;

    4.i. General Templating

    File naming

    -

    Firstly templates now take the suffix ".html" rather than ".tpl". This was done simply to make the lifes of some people easier wrt syntax highlighting, etc.

    +

    Firstly templates now take the suffix ".html" rather than ".tpl". This was done simply to make the lives of some people easier wrt syntax highlighting, etc.

    Variables

    All template variables should be named appropriately (using underscores for spaces), language entries should be prefixed with L_, system data with S_, urls with U_, javascript urls with UA_, language to be put in javascript statements with LA_, all other variables should be presented 'as is'.

    -

    L_* template variables are automatically tried to be mapped to the corresponding language entry if the code does not set (and therefore overwrite) this variable specifically. For example {L_USERNAME} maps to $user->lang['USERNAME']. The LA_* template variables are handled within the same way, but properly escaped to be put in javascript code. This should reduce the need to assign loads of new lang vars in Modifications. +

    L_* template variables are automatically mapped to the corresponding language entry if the code does not set (and therefore overwrite) this variable specifically and if the language entry exists. For example {L_USERNAME} maps to $user->lang['USERNAME']. The LA_* template variables are handled within the same way, but properly escaped so they can be put in javascript code. This should reduce the need to assign loads of new language variables in MODifications.

    Blocks/Loops

    @@ -1424,9 +1424,9 @@ div <!-- END l_block1 -->
    -

    Here we open the loop l_block1 and doing some things if the value S_SELECTED within the current loop iteration is true, else we write the blocks link and title. Here, you see {l_block1.L_TITLE} referenced - you remember that L_* variables get automatically assigned the corresponding language entry? This is true, but not within loops. The L_TITLE variable within the loop l_block1 is assigned within the code itself.

    +

    Here we open the loop l_block1 and do some things if the value S_SELECTED within the current loop iteration is true, else we write the blocks link and title. Here, you see {l_block1.L_TITLE} referenced - you remember that L_* variables get automatically assigned the corresponding language entry? This is true, but not within loops. The L_TITLE variable within the loop l_block1 is assigned within the code itself.

    -

    Let's have a closer look to the markup:

    +

    Let's have a closer look at the markup:

     <!-- BEGIN l_block1 -->
    @@ -1520,7 +1520,7 @@ div
     </ul> <!-- written on third iteration -->
     
    -

    Just always remember that processing is taking place from up to down.

    +

    Just always remember that processing is taking place from top to bottom.

    Forms

    If a form is used for a non-trivial operation (i.e. more than a jumpbox), then it should include the {S_FORM_TOKEN} template variable.

    @@ -1536,11 +1536,9 @@ div

    4.ii. Template Inheritance

    -

    When basing a new template on an existing one, it is not necessary to provide all template files. By declaring the template to be "inheriting" in the template configuration file.

    +

    When basing a new style on an existing one, it is not necessary to provide all the template files. By declaring the base style name in the inherit_from field in the template configuration file, the style can be set to inherit template files from the base style. The limitation on this is that the base style has to be installed and complete, meaning that it is not itself inheriting.

    -

    The limitation on this is that the base style has to be installed and complete, meaning that it is not itself inheriting.

    - -

    The effect of doing so is that the template engine will use the files in the new template where they exist, but fall back to files in the base template otherwise. Declaring a style to be inheriting also causes it to use some of the configuration settings of the base style, notably database storage.

    +

    The effect of doing so is that the template engine will use the template files in the new style where they exist, but fall back to files in the base style otherwise. Declaring a style to inherit from another also causes it to use some of the configuration settings of the base style, notably database storage.

    We strongly encourage the use of inheritance for styles based on the bundled styles, as it will ease the update procedure.

    @@ -1667,7 +1665,7 @@ if (utf8_case_fold_nfc($string1) == utf8_case_fold_nfc($string2))

    Encoding:

    -

    With phpBB3, the output encoding for the forum in now UTF-8, a Universal Character Encoding by the Unicode Consortium that is by design a superset to US-ASCII and ISO-8859-1. By using one character set which simultaenously supports all scripts which previously would have required different encodings (eg: ISO-8859-1 to ISO-8859-15 (Latin, Greek, Cyrillic, Thai, Hebrew, Arabic); GB2312 (Simplified Chinese); Big5 (Traditional Chinese), EUC-JP (Japanese), EUC-KR (Korean), VISCII (Vietnamese); et cetera), this removes the need to convert between encodings and improves the accessibility of multilingual forums.

    +

    With phpBB3, the output encoding for the forum in now UTF-8, a Universal Character Encoding by the Unicode Consortium that is by design a superset to US-ASCII and ISO-8859-1. By using one character set which simultaenously supports all scripts which previously would have required different encodings (eg: ISO-8859-1 to ISO-8859-15 (Latin, Greek, Cyrillic, Thai, Hebrew, Arabic); GB2312 (Simplified Chinese); Big5 (Traditional Chinese), EUC-JP (Japanese), EUC-KR (Korean), VISCII (Vietnamese); et cetera), we remove the need to convert between encodings and improves the accessibility of multilingual forums.

    The impact is that the language files for phpBB must now also be encoded as UTF-8, with a caveat that the files must not contain a BOM for compatibility reasons with non-Unicode aware versions of PHP. For those with forums using the Latin character set (ie: most European languages), this change is transparent since UTF-8 is superset to US-ASCII and ISO-8859-1.

    From 65a34fd047f4ac1ff3638a568f44d3fe7d664d88 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 14 Oct 2011 00:54:11 +0200 Subject: [PATCH 64/93] [ticket/10410] Add option to display users in their first teampage group PHPBB3-10410 --- phpBB/adm/style/acp_groups_position.html | 7 ++++--- phpBB/includes/acp/acp_groups.php | 12 ++++++------ phpBB/install/database_update.php | 8 ++++++-- phpBB/install/schemas/schema_data.sql | 2 +- phpBB/language/en/acp/groups.php | 6 ++++-- phpBB/memberlist.php | 4 ++-- 6 files changed, 23 insertions(+), 16 deletions(-) diff --git a/phpBB/adm/style/acp_groups_position.html b/phpBB/adm/style/acp_groups_position.html index 54c1cee769..3a03573756 100644 --- a/phpBB/adm/style/acp_groups_position.html +++ b/phpBB/adm/style/acp_groups_position.html @@ -82,10 +82,11 @@
    {L_TEAMPAGE_SETTINGS}
    -

    {L_TEAMPAGE_MULTIPLE_EXPLAIN}
    +
    - - +
    +
    +
    diff --git a/phpBB/includes/acp/acp_groups.php b/phpBB/includes/acp/acp_groups.php index 221dea2345..9aa54bed89 100644 --- a/phpBB/includes/acp/acp_groups.php +++ b/phpBB/includes/acp/acp_groups.php @@ -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/install/database_update.php b/phpBB/install/database_update.php index 4507e5c371..8450cc4ab7 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -2117,10 +2117,9 @@ function change_database_data(&$no_updates, $version) _sql($sql, $errored, $error_ary); } - if (!isset($config['use_system_cron'])) + if (!isset($config['legend_sort_groupname'])) { set_config('legend_sort_groupname', '0'); - set_config('teampage_multiple', '1'); set_config('teampage_forums', '1'); } @@ -2260,6 +2259,11 @@ function change_database_data(&$no_updates, $version) set_config('load_cpf_pm', '0'); } + if (!isset($config['teampage_memberships'])) + { + set_config('teampage_memberships', '1'); + } + $no_updates = false; break; } diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index 5506922e17..4361ca45c3 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -243,7 +243,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_host', ''); INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_password', ''); INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_port', '25'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('smtp_username', ''); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('teampage_multiple', '1'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('teampage_memberships', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('teampage_forums', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('topics_per_page', '25'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('tpl_allow_php', '0'); diff --git a/phpBB/language/en/acp/groups.php b/phpBB/language/en/acp/groups.php index 11342bf4f2..28e6fb80d9 100644 --- a/phpBB/language/en/acp/groups.php +++ b/phpBB/language/en/acp/groups.php @@ -129,11 +129,13 @@ $lang = array_merge($lang, array( 'SPECIAL_GROUPS' => 'Pre-defined groups', 'SPECIAL_GROUPS_EXPLAIN' => 'Pre-defined groups are special groups, they cannot be deleted or directly modified. However you can still add users and alter basic settings.', + 'TEAMPAGE_DISP_ALL' => 'All memberships', + 'TEAMPAGE_DISP_DEFAULT' => 'User’s default group only', + 'TEAMPAGE_DISP_FIRST' => 'First membership only', 'TEAMPAGE_EXPLAIN' => 'These are the groups which are displayed on the teampage:', 'TEAMPAGE_FORUMS' => 'Display moderated forums', 'TEAMPAGE_FORUMS_EXPLAIN' => 'If set to yes, moderators will have a list with all of the forums where they have moderator permissions displayed in their row. This can be very database intensive for big boards.', - 'TEAMPAGE_MULTIPLE' => 'Display users in all groups', - 'TEAMPAGE_MULTIPLE_EXPLAIN' => 'If set to no, the users will only be displayed in their primary group (If the primary group is not listed, the users will be displayed in their first displayed group).', + 'TEAMPAGE_MEMBERSHIPS' => 'Display user memberships', 'TEAMPAGE_SETTINGS' => 'Teampage settings', 'TOTAL_MEMBERS' => 'Members', diff --git a/phpBB/memberlist.php b/phpBB/memberlist.php index 1b6cb5ef94..d9b49d7780 100644 --- a/phpBB/memberlist.php +++ b/phpBB/memberlist.php @@ -229,7 +229,7 @@ switch ($mode) if (isset($user_ary[$user_id])) { $row = $user_ary[$user_id]; - if (!$config['teampage_multiple'] && ($group_id != $groups_ary[$row['default_group']]['group_id']) && $groups_ary[$row['default_group']]['group_teampage']) + if ($config['teampage_memberships'] == 1 && ($group_id != $groups_ary[$row['default_group']]['group_id']) && $groups_ary[$row['default_group']]['group_teampage']) { // Display users in their primary group, instead of the first group, when it is displayed on the teampage. continue; @@ -259,7 +259,7 @@ switch ($mode) 'U_VIEW_PROFILE' => get_username_string('profile', $row['user_id'], $row['username'], $row['user_colour']), )); - if (!$config['teampage_multiple']) + if ($config['teampage_memberships'] != 2) { unset($user_ary[$user_id]); } From fa23def7742b66b25a8c71e68d334f999624a84d Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Sat, 29 Oct 2011 00:16:30 +0200 Subject: [PATCH 65/93] [ticket/10190] Do not show hint about permissions when editing forum settings. PHPBB3-10190 --- phpBB/includes/acp/acp_forums.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php index 27bec3f1ea..50e12a0f15 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 .= '

    ' . sprintf($user->lang['REDIRECT_ACL'], '', ''); - } - // redirect directly to permission settings screen if authed if ($action == 'add' && !$copied_permissions && $auth->acl_get('a_fauth')) { + $message .= '

    ' . sprintf($user->lang['REDIRECT_ACL'], '', ''); + meta_refresh(4, append_sid("{$phpbb_admin_path}index.$phpEx", 'i=permissions' . $acl_url)); } From 2e9e0a7d78bf5aaaac4b36960eb45cf014a5ccc6 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Sat, 29 Oct 2011 00:32:38 +0200 Subject: [PATCH 66/93] [ticket/10166] No longer refer to previous mail in admin_welcome_activated.txt It does not make much sense to say "the username you received in a previous e-mail" when the message itself contains the username. PHPBB3-10166 --- phpBB/language/en/email/admin_welcome_activated.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/language/en/email/admin_welcome_activated.txt b/phpBB/language/en/email/admin_welcome_activated.txt index 2397868323..cfdb69bdcb 100644 --- a/phpBB/language/en/email/admin_welcome_activated.txt +++ b/phpBB/language/en/email/admin_welcome_activated.txt @@ -2,7 +2,7 @@ Subject: Account activated Hello {USERNAME}, -Your account on "{SITENAME}" has now been activated, you may login using the username you received in a previous e-mail. +Your account on "{SITENAME}" has been activated by an administrator, you may login now. Your password has been securely stored in our database and cannot be retrieved. In the event that it is forgotten, you will be able to reset it using the email address associated with your account. From da8cac280c0d7067291ee173a06a92e24a906d6e Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sat, 29 Oct 2011 16:26:17 +0200 Subject: [PATCH 67/93] [ticket/9036] Add template variable 'S_AUTH_READ' to forumlist PHPBB3-9036 --- phpBB/includes/functions_display.php | 1 + 1 file changed, 1 insertion(+) diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php index 14d0c44dcf..88be332eff 100644 --- a/phpBB/includes/functions_display.php +++ b/phpBB/includes/functions_display.php @@ -465,6 +465,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, From cf49b5f46fe4035a54809d4c615cbdc1456964e1 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sat, 29 Oct 2011 23:32:47 +0200 Subject: [PATCH 68/93] [ticket/7932] Fix font size in select boxes PHPBB3-7932 --- phpBB/styles/prosilver/theme/forms.css | 1 + 1 file changed, 1 insertion(+) diff --git a/phpBB/styles/prosilver/theme/forms.css b/phpBB/styles/prosilver/theme/forms.css index 803c608bcf..ebc8059474 100644 --- a/phpBB/styles/prosilver/theme/forms.css +++ b/phpBB/styles/prosilver/theme/forms.css @@ -26,6 +26,7 @@ select { border: 1px solid #666666; padding: 1px; background-color: #FAFAFA; + font-size: 1em; } option { From 75a44a6970136122c17756522e25814d4015035b Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 10 Sep 2010 07:23:55 -0700 Subject: [PATCH 69/93] [ticket/9778] Replaced "Find a member" with "Enter username" When clicking on the "Users and groups" tab in the ACP, the user is able to either enter the username of the member he wants to manage or click on "Find a member" below the input field. Unfortunately, the label for the input field is also "Find a member", which leads some users to the idea that they can search for users using that input field. By changing the label to "Enter username" this should be clear to the user. PHPBB3-9778 --- phpBB/adm/style/acp_users.html | 2 +- phpBB/language/en/common.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/phpBB/adm/style/acp_users.html b/phpBB/adm/style/acp_users.html index e266654649..d5a29a21cc 100644 --- a/phpBB/adm/style/acp_users.html +++ b/phpBB/adm/style/acp_users.html @@ -13,7 +13,7 @@
    {L_SELECT_USER}
    -
    +
    [ {L_FIND_USERNAME} ]
    diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php index bc38c1563d..d686d51c89 100644 --- a/phpBB/language/en/common.php +++ b/phpBB/language/en/common.php @@ -165,6 +165,7 @@ $lang = array_merge($lang, array( 'EMPTY_MESSAGE_SUBJECT' => 'You must specify a subject when composing a new message.', 'ENABLED' => 'Enabled', 'ENCLOSURE' => 'Enclosure', + 'ENTER_USERNAME' => 'Enter username', 'ERR_CHANGING_DIRECTORY' => 'Unable to change directory.', 'ERR_CONNECTING_SERVER' => 'Error connecting to the server.', 'ERR_JAB_AUTH' => 'Could not authorise on Jabber server.', From d6c3e7785d98190436acdd8468a1d343b673c55b Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Sun, 30 Oct 2011 18:45:41 +0100 Subject: [PATCH 70/93] [ticket/10365] Make sure moderators only get mcp_reports link when allowed The m_report permission is not not being checked when displaying the link to mcp_reports. PHPBB3-10365 --- phpBB/includes/mcp/mcp_topic.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php index 76cd9beb92..9cdb69ed99 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' => ($auth->acl_get('m_report', $topic_info['forum_id']) && $row['post_reported']) ? true : false, + 'S_POST_UNAPPROVED' => ($auth->acl_get('m_approve', $topic_info['forum_id']) && $row['post_approved']) ? false : true, 'S_CHECKED' => (($submitted_id_list && !in_array(intval($row['post_id']), $submitted_id_list)) || in_array(intval($row['post_id']), $checked_ids)) ? true : false, 'S_HAS_ATTACHMENTS' => (!empty($attachments[$row['post_id']])) ? true : false, From 18ca3a32bc9f5ec84b6abba3c79920d23df8c778 Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Sun, 30 Oct 2011 19:06:34 +0100 Subject: [PATCH 71/93] [ticket/10365] Require m_report permission to see reports in mcp_post This was exposed to anyone with m_ perms in mcp_post_details. PHPBB3-10365 --- phpBB/includes/mcp/mcp_post.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/mcp/mcp_post.php b/phpBB/includes/mcp/mcp_post.php index de7f3e63ee..ba45037a18 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 From 2918fbc9709fd1cd698eb3ba5b9459f1301ae898 Mon Sep 17 00:00:00 2001 From: rxu Date: Sat, 5 Nov 2011 01:02:40 +0800 Subject: [PATCH 72/93] [ticket/10419] Reword some language strings, minor code changes PHPBB3-10419 --- phpBB/includes/acp/acp_main.php | 8 ++++---- phpBB/language/en/acp/common.php | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index e31acfb7d1..c8df21f5a9 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -600,15 +600,15 @@ class acp_main $template->assign_var('S_WRITABLE_CONFIG', (bool) (@fileperms($phpbb_root_path . 'config.' . $phpEx) & 0x0002)); } - if (@extension_loaded('mbstring')) + 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_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')) - ); + 'S_MBSTRING_HTTP_OUTPUT_FAIL' => (@ini_get('mbstring.http_output') != 'pass'), + )); } // Fill dbms version if not yet filled diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php index a8cfaf8aa8..85da6fbd79 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -328,13 +328,13 @@ $lang = array_merge($lang, array( 'DATABASE_SIZE' => 'Database size', // Enviroment configuration checks, mbstring related - 'ERROR_MBSTRING_FUNC_OVERLOAD' => 'Functions overloading setting failed', + 'ERROR_MBSTRING_FUNC_OVERLOAD' => 'Function overloading setting is invalid', 'ERROR_MBSTRING_FUNC_OVERLOAD_EXPLAIN' => 'mbstring.func_overload must be set to either 0 or 4. You can check current value on PHP information page.', - 'ERROR_MBSTRING_ENCODING_TRANSLATION' => 'Transparent character encoding setting failed', + 'ERROR_MBSTRING_ENCODING_TRANSLATION' => 'Transparent character encoding setting is invalid', 'ERROR_MBSTRING_ENCODING_TRANSLATION_EXPLAIN' => 'mbstring.encoding_translation must be set to 0. You can check current value on PHP information page.', - 'ERROR_MBSTRING_HTTP_INPUT' => 'HTTP input character conversion setting failed', + 'ERROR_MBSTRING_HTTP_INPUT' => 'HTTP input character conversion setting is invalid', 'ERROR_MBSTRING_HTTP_INPUT_EXPLAIN' => 'mbstring.http_input must be set to pass. You can check current value on PHP information page.', - 'ERROR_MBSTRING_HTTP_OUTPUT' => 'HTTP output character conversion setting failed', + 'ERROR_MBSTRING_HTTP_OUTPUT' => 'HTTP output character conversion setting is invalid', 'ERROR_MBSTRING_HTTP_OUTPUT_EXPLAIN' => 'mbstring.http_output must be set to pass. You can check current value on PHP information page.', 'FILES_PER_DAY' => 'Attachments per day', From 1a19388aa38113262db648caedd4a745f5691ed1 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Wed, 20 Jul 2011 00:55:49 +0200 Subject: [PATCH 73/93] [ticket/10237] Display login-box for guests, when (un)subscribing Also initialise $is_watching for PHP Notice: Undefined variable is_watching PHPBB3-10237 --- phpBB/includes/functions_display.php | 21 +++++++++++++++------ phpBB/viewforum.php | 2 +- phpBB/viewtopic.php | 5 +++-- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php index 7982b9908d..ffc9fecb5e 100644 --- a/phpBB/includes/functions_display.php +++ b/phpBB/includes/functions_display.php @@ -1067,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) @@ -1093,9 +1094,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) || ($_GET['unwatch'] != $mode)) + if ($uid != $user_id || $_GET['unwatch'] != $mode) { $redirect_url = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&start=$start"); $message = $user->lang['ERR_UNWATCHING'] . '

    ' . sprintf($user->lang['RETURN_' . strtoupper($mode)], '', ''); @@ -1108,7 +1109,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)] . '

    ' . sprintf($user->lang['RETURN_' . strtoupper($mode)], '', ''); + $message = $user->lang['NOT_WATCHING_' . strtoupper($mode)] . '

    '; + $message .= sprintf($user->lang['RETURN_' . strtoupper($mode)], '', ''); meta_refresh(3, $redirect_url); trigger_error($message); } @@ -1125,7 +1127,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)); } } @@ -1150,9 +1159,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) || ($_GET['watch'] != $mode)) + if ($uid != $user_id || $_GET['watch'] != $mode) { $redirect_url = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&start=$start"); $message = $user->lang['ERR_WATCHING'] . '

    ' . sprintf($user->lang['RETURN_' . strtoupper($mode)], '', ''); diff --git a/phpBB/viewforum.php b/phpBB/viewforum.php index e0b51bf782..2eacbb500a 100644 --- a/phpBB/viewforum.php +++ b/phpBB/viewforum.php @@ -205,7 +205,7 @@ $s_watching_forum = array( 'is_watching' => false, ); -if (($config['email_enable'] || $config['jab_enable']) && $config['allow_forum_notify'] && $forum_data['forum_type'] == FORUM_POST && $auth->acl_get('f_subscribe', $forum_id)) +if (($config['email_enable'] || $config['jab_enable']) && $config['allow_forum_notify'] && $forum_data['forum_type'] == FORUM_POST && ($auth->acl_get('f_subscribe', $forum_id) || $user->data['user_id'] == ANONYMOUS)) { $notify_status = (isset($forum_data['notify_status'])) ? $forum_data['notify_status'] : NULL; watch_topic_forum('forum', $s_watching_forum, $user->data['user_id'], $forum_id, 0, $notify_status, $start, $forum_data['forum_name']); diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php index 8b081b4aec..bb88241481 100644 --- a/phpBB/viewtopic.php +++ b/phpBB/viewtopic.php @@ -486,9 +486,10 @@ $s_watching_topic = array( 'is_watching' => false, ); -if (($config['email_enable'] || $config['jab_enable']) && $config['allow_topic_notify'] && $user->data['is_registered']) +if (($config['email_enable'] || $config['jab_enable']) && $config['allow_topic_notify']) { - watch_topic_forum('topic', $s_watching_topic, $user->data['user_id'], $forum_id, $topic_id, $topic_data['notify_status'], $start, $topic_data['topic_title']); + $notify_status = (isset($topic_data['notify_status'])) ? $topic_data['notify_status'] : null; + watch_topic_forum('topic', $s_watching_topic, $user->data['user_id'], $forum_id, $topic_id, $notify_status, $start, $topic_data['topic_title']); // Reset forum notification if forum notify is set if ($config['allow_forum_notify'] && $auth->acl_get('f_subscribe', $forum_id)) From 0d3e9bf446f93afcb4537d561de665c678a44c2a Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 11 Nov 2011 14:06:02 +0100 Subject: [PATCH 74/93] [ticket/10435] Readd local announcements to total topic count in viewforum We need to readd the local announcements to the forums total topic count, otherwise the number is different from the one in the forum list. PHPBB3-10435 --- phpBB/viewforum.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/phpBB/viewforum.php b/phpBB/viewforum.php index e0b51bf782..31096d42f5 100644 --- a/phpBB/viewforum.php +++ b/phpBB/viewforum.php @@ -533,10 +533,13 @@ if ($s_display_active) $topics_count = 1; } +// We need to readd the local announcements to the forums total topic count, otherwise the number is different from the one on the forum list +$total_topic_count = $topics_count + sizeof($announcement_list) - sizeof($global_announce_list); + $template->assign_vars(array( 'PAGINATION' => generate_pagination(append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id" . ((strlen($u_sort_param)) ? "&$u_sort_param" : '')), $topics_count, $config['topics_per_page'], $start), 'PAGE_NUMBER' => on_page($topics_count, $config['topics_per_page'], $start), - 'TOTAL_TOPICS' => ($s_display_active) ? false : (($topics_count == 1) ? $user->lang['VIEW_FORUM_TOPIC'] : sprintf($user->lang['VIEW_FORUM_TOPICS'], $topics_count))) + 'TOTAL_TOPICS' => ($s_display_active) ? false : (($total_topic_count == 1) ? $user->lang['VIEW_FORUM_TOPIC'] : sprintf($user->lang['VIEW_FORUM_TOPICS'], $total_topic_count))) ); $topic_list = ($store_reverse) ? array_merge($announcement_list, array_reverse($topic_list)) : array_merge($announcement_list, $topic_list); From 6a379f1a55eaaf4a32ab357bd9a69bfee2e6d069 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 11 Nov 2011 14:11:00 +0100 Subject: [PATCH 75/93] [ticket/10435] Remove global announcement from forums total topic count We need to remove the global announcements from the forums total topic count, otherwise the number is different from the one on the forum list. PHPBB3-10435 --- phpBB/viewforum.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/phpBB/viewforum.php b/phpBB/viewforum.php index 62cf939545..0f17fb340f 100644 --- a/phpBB/viewforum.php +++ b/phpBB/viewforum.php @@ -561,6 +561,9 @@ if (sizeof($shadow_topic_list)) } unset($shadow_topic_list); +// We need to remove the global announcements from the forums total topic count, otherwise the number is different from the one on the forum list +$total_topics_count = $topics_count - sizeof($global_announce_forums); + // Ok, adjust topics count for active topics list if ($s_display_active) { @@ -570,7 +573,7 @@ if ($s_display_active) $template->assign_vars(array( 'PAGINATION' => generate_pagination(append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id" . ((strlen($u_sort_param)) ? "&$u_sort_param" : '')), $topics_count, $config['topics_per_page'], $start), 'PAGE_NUMBER' => on_page($topics_count, $config['topics_per_page'], $start), - 'TOTAL_TOPICS' => ($s_display_active) ? false : (($topics_count == 1) ? $user->lang['VIEW_FORUM_TOPIC'] : sprintf($user->lang['VIEW_FORUM_TOPICS'], $topics_count))) + 'TOTAL_TOPICS' => ($s_display_active) ? false : (($total_topics_count == 1) ? $user->lang['VIEW_FORUM_TOPIC'] : sprintf($user->lang['VIEW_FORUM_TOPICS'], $total_topics_count))) ); $topic_list = ($store_reverse) ? array_merge($announcement_list, array_reverse($topic_list)) : array_merge($announcement_list, $topic_list); From 2b3effb13c0f1d8322653147e5dcbc20ae36b418 Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Fri, 11 Nov 2011 22:32:59 +0100 Subject: [PATCH 76/93] [ticket/8616] Include old U_INBOX var for BC PHPBB3-8616 --- phpBB/includes/functions_privmsgs.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index b34b742d57..c40ceb088f 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -1688,8 +1688,9 @@ function pm_notification($mode, $author, $recipients, $subject, $message, $msg_i 'AUTHOR_NAME' => htmlspecialchars_decode($author), 'USERNAME' => htmlspecialchars_decode($addr['name']), - 'U_VIEW_MESSAGE' => generate_board_url() . "/ucp.$phpEx?i=pm&mode=view&p=$msg_id") - ); + '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']); } From edd5866a6ed4325a6d1df728842c310d7da407fd Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Fri, 11 Nov 2011 23:05:57 +0100 Subject: [PATCH 77/93] [ticket/10087] Organize bans in acp_baninto optgroups PHPBB3-10087 --- phpBB/includes/acp/acp_ban.php | 34 +++++++++++++++++++++++++++++----- phpBB/language/en/acp/ban.php | 3 +++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/phpBB/includes/acp/acp_ban.php b/phpBB/includes/acp/acp_ban.php index a7ea57b753..f8af1b86e1 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 .= '' . $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,11 +250,26 @@ class acp_ban } } + $options = ''; + if ($excluded_options) + { + $options .= ''; + $options .= implode('', $excluded_options); + $options .= ''; + } + + if ($banned_options) + { + $options .= ''; + $options .= implode('', $banned_options); + $options .= ''; + } + $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/language/en/acp/ban.php b/phpBB/language/en/acp/ban.php index 099834d1e4..7b2ef59a7a 100644 --- a/phpBB/language/en/acp/ban.php +++ b/phpBB/language/en/acp/ban.php @@ -68,6 +68,9 @@ $lang = array_merge($lang, array( 'LENGTH_BAN_INVALID' => 'The date has to be formatted YYYY-MM-DD.', + 'OPTIONS_BANNED' => 'Banned', + 'OPTIONS_EXCLUDED' => 'Excluded', + 'PERMANENT' => 'Permanent', 'UNTIL' => 'Until', From 91155d1330f04b9be1a7722ef0335ba87fd11cbc Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 1 Nov 2011 18:43:24 +0100 Subject: [PATCH 78/93] [ticket/10437] Do not display announcements that are waiting for approval PHPBB3-10437 --- phpBB/viewforum.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/phpBB/viewforum.php b/phpBB/viewforum.php index e0b51bf782..215911c8cb 100644 --- a/phpBB/viewforum.php +++ b/phpBB/viewforum.php @@ -376,6 +376,12 @@ if ($forum_data['forum_type'] == FORUM_POST) while ($row = $db->sql_fetchrow($result)) { + if (!$row['topic_approved'] && !$auth->acl_get('m_approve', $row['forum_id'])) + { + // Do not display announcements that are waiting for approval. + continue; + } + $rowset[$row['topic_id']] = $row; $announcement_list[] = $row['topic_id']; From 52bd8c307f388ac95d4bdd1bcdc52fdaa83ef4df Mon Sep 17 00:00:00 2001 From: Igor Wiedler Date: Sun, 13 Nov 2011 15:37:26 +0100 Subject: [PATCH 79/93] [ticket/10365] Fix up S_POST_UNAPPROVED check, make it easier to read PHPBB3-10365 --- phpBB/includes/mcp/mcp_topic.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php index 9cdb69ed99..d7cc1e795a 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' => ($auth->acl_get('m_report', $topic_info['forum_id']) && $row['post_reported']) ? true : false, - 'S_POST_UNAPPROVED' => ($auth->acl_get('m_approve', $topic_info['forum_id']) && $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, From 6370ef27057643ee7fe0a6fbf2341c2ebdb57d4c Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Mon, 17 Oct 2011 23:22:36 +0200 Subject: [PATCH 80/93] [ticket/9066] Disallow some database prefix to prevent same errors and problems With this patch database prefixes must not be empty and only contain alphanumeric characters, numbers and underscores. PHPBB3-9066 --- phpBB/install/install_install.php | 7 ++++++- phpBB/language/en/install.php | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php index 9fe0c8aed5..bb1d858cfc 100644 --- a/phpBB/install/install_install.php +++ b/phpBB/install/install_install.php @@ -546,6 +546,11 @@ class install_install extends module $error[] = $lang['INST_ERR_NO_DB']; $connect_test = false; } + else if (!preg_match('#^[a-zA-Z][a-zA-Z0-9_]*$#', $data['table_prefix'], $result)) + { + $error[] = $lang['INST_ERR_DB_INVALID_PREFIX']; + $connect_test = false; + } else { $connect_test = connect_check_db(true, $error, $available_dbms[$data['dbms']], $data['table_prefix'], $data['dbhost'], $data['dbuser'], htmlspecialchars_decode($data['dbpasswd']), $data['dbname'], $data['dbport']); @@ -2032,7 +2037,7 @@ class install_install extends module 'dbname' => array('lang' => 'DB_NAME', 'type' => 'text:25:100', 'explain' => false), 'dbuser' => array('lang' => 'DB_USERNAME', 'type' => 'text:25:100', 'explain' => false), 'dbpasswd' => array('lang' => 'DB_PASSWORD', 'type' => 'password:25:100', 'explain' => false), - 'table_prefix' => array('lang' => 'TABLE_PREFIX', 'type' => 'text:25:100', 'explain' => false), + 'table_prefix' => array('lang' => 'TABLE_PREFIX', 'type' => 'text:25:100', 'explain' => true), ); var $admin_config_options = array( 'legend1' => 'ADMIN_CONFIG', diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php index befa7c6f40..f038177df4 100644 --- a/phpBB/language/en/install.php +++ b/phpBB/language/en/install.php @@ -232,6 +232,7 @@ $lang = array_merge($lang, array( 'INST_ERR' => 'Installation error', 'INST_ERR_DB_CONNECT' => 'Could not connect to the database, see error message below.', 'INST_ERR_DB_FORUM_PATH' => 'The database file specified is within your board directory tree. You should put this file in a non web-accessible location.', + 'INST_ERR_DB_INVALID_PREFIX'=> 'The prefix you entered is invalid. It must start with an alphanumeric character and must only contain alphanumeric characters, numbers and underscores.', 'INST_ERR_DB_NO_ERROR' => 'No error message given.', 'INST_ERR_DB_NO_MYSQLI' => 'The version of MySQL installed on this machine is incompatible with the “MySQL with MySQLi Extension” option you have selected. Please try the “MySQL” option instead.', 'INST_ERR_DB_NO_SQLITE' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 2.8.2.', @@ -352,6 +353,7 @@ $lang = array_merge($lang, array( 'TABLES_MISSING' => 'Could not find these tables
    » %s.', 'TABLE_PREFIX' => 'Prefix for tables in database', + 'TABLE_PREFIX_EXPLAIN' => 'The prefix must start with an alphanumeric character and must only contain alphanumeric characters, numbers and underscores.', 'TABLE_PREFIX_SAME' => 'The table prefix needs to be the one used by the software you are converting from.
    » Specified table prefix was %s.', 'TESTS_PASSED' => 'Tests passed', 'TESTS_FAILED' => 'Tests failed', From b371d62dd3e8f7a207b7398fb0fe3150799d350b Mon Sep 17 00:00:00 2001 From: David King Date: Sun, 13 Nov 2011 16:30:11 +0100 Subject: [PATCH 81/93] [ticket/7138] Allow simple header and footer for trigger_error() messages Adds a template condition using S_SIMPLE_MESSAGE that must be set to true before calling trigger_error() which will automatically use the simple header and footer files in the template directory instead of the overall header and footer files. PHPBB3-7138 --- phpBB/styles/prosilver/template/message_body.html | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/phpBB/styles/prosilver/template/message_body.html b/phpBB/styles/prosilver/template/message_body.html index 896f0b826e..3a970769b7 100644 --- a/phpBB/styles/prosilver/template/message_body.html +++ b/phpBB/styles/prosilver/template/message_body.html @@ -1,4 +1,8 @@ - + + + + +
    @@ -8,4 +12,8 @@
    - \ No newline at end of file + + + + + From dee836315ca0d449d252929313e30fb64e452fe4 Mon Sep 17 00:00:00 2001 From: maelsoucaze Date: Sat, 29 Oct 2011 17:20:36 +0200 Subject: [PATCH 82/93] [ticket/10254] Remove style names from themes and fix some informations on it. PHPBB3-10254 --- phpBB/styles/prosilver/theme/bidi.css | 4 ++-- phpBB/styles/prosilver/theme/buttons.css | 2 +- phpBB/styles/prosilver/theme/common.css | 2 +- phpBB/styles/prosilver/theme/content.css | 2 +- phpBB/styles/prosilver/theme/cp.css | 2 +- phpBB/styles/prosilver/theme/forms.css | 2 +- phpBB/styles/prosilver/theme/links.css | 2 +- phpBB/styles/prosilver/theme/print.css | 9 ++------- phpBB/styles/prosilver/theme/stylesheet.css | 12 +++++++----- phpBB/styles/prosilver/theme/tweaks.css | 2 +- phpBB/styles/subsilver2/theme/stylesheet.css | 17 ++++++++--------- 11 files changed, 26 insertions(+), 30 deletions(-) diff --git a/phpBB/styles/prosilver/theme/bidi.css b/phpBB/styles/prosilver/theme/bidi.css index f441784d85..d1cff9c8be 100644 --- a/phpBB/styles/prosilver/theme/bidi.css +++ b/phpBB/styles/prosilver/theme/bidi.css @@ -1,4 +1,4 @@ -/* proSilver RTL definitions +/* RTL definitions ---------------------------------------- */ /** @@ -519,7 +519,7 @@ /** * cp.css */ -/* proSilver Control Panel Styles +/* Control Panel Styles ---------------------------------------- */ diff --git a/phpBB/styles/prosilver/theme/buttons.css b/phpBB/styles/prosilver/theme/buttons.css index 6cffdc5930..a9ded9cf98 100644 --- a/phpBB/styles/prosilver/theme/buttons.css +++ b/phpBB/styles/prosilver/theme/buttons.css @@ -1,4 +1,4 @@ -/* proSilver Button Styles +/* Button Styles ---------------------------------------- */ /* Rollover buttons diff --git a/phpBB/styles/prosilver/theme/common.css b/phpBB/styles/prosilver/theme/common.css index a86f723f81..8b5e09297e 100644 --- a/phpBB/styles/prosilver/theme/common.css +++ b/phpBB/styles/prosilver/theme/common.css @@ -1,4 +1,4 @@ -/* General proSilver Markup Styles +/* General Markup Styles ---------------------------------------- */ * { diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css index 58247883e5..c278a16dc5 100644 --- a/phpBB/styles/prosilver/theme/content.css +++ b/phpBB/styles/prosilver/theme/content.css @@ -1,4 +1,4 @@ -/* proSilver Content Styles +/* Content Styles ---------------------------------------- */ ul.topiclist { diff --git a/phpBB/styles/prosilver/theme/cp.css b/phpBB/styles/prosilver/theme/cp.css index b574b0ae1f..708bfbaf83 100644 --- a/phpBB/styles/prosilver/theme/cp.css +++ b/phpBB/styles/prosilver/theme/cp.css @@ -1,4 +1,4 @@ -/* proSilver Control Panel Styles +/* Control Panel Styles ---------------------------------------- */ diff --git a/phpBB/styles/prosilver/theme/forms.css b/phpBB/styles/prosilver/theme/forms.css index 803c608bcf..2b54e17290 100644 --- a/phpBB/styles/prosilver/theme/forms.css +++ b/phpBB/styles/prosilver/theme/forms.css @@ -1,4 +1,4 @@ -/* proSilver Form Styles +/* Form Styles ---------------------------------------- */ /* General form styles diff --git a/phpBB/styles/prosilver/theme/links.css b/phpBB/styles/prosilver/theme/links.css index 1f6c2af550..05662b9b44 100644 --- a/phpBB/styles/prosilver/theme/links.css +++ b/phpBB/styles/prosilver/theme/links.css @@ -1,4 +1,4 @@ -/* proSilver Link Styles +/* Link Styles ---------------------------------------- */ /* Links adjustment to correctly display an order of rtl/ltr mixed content */ diff --git a/phpBB/styles/prosilver/theme/print.css b/phpBB/styles/prosilver/theme/print.css index 2cfcd4da20..bc3ca80fdc 100644 --- a/phpBB/styles/prosilver/theme/print.css +++ b/phpBB/styles/prosilver/theme/print.css @@ -1,10 +1,5 @@ -/* proSilver Print Style Sheet -------------------------------------------------- - Author: subBlue ( http://www.subBlue.com/ ) - Version: 25 August 2004 - - Copyright 2004 phpBB Group --------------------------------------------------*/ +/* Print Style Sheet +---------------------------------------- */ /* Lots still TODO here! */ diff --git a/phpBB/styles/prosilver/theme/stylesheet.css b/phpBB/styles/prosilver/theme/stylesheet.css index c7db605bbb..d771a321ca 100644 --- a/phpBB/styles/prosilver/theme/stylesheet.css +++ b/phpBB/styles/prosilver/theme/stylesheet.css @@ -1,11 +1,13 @@ -/* phpBB 3.0 Style Sheet +/* phpBB3 Style Sheet -------------------------------------------------------------- - Style name: proSilver - Based on style: proSilver (this is the default phpBB 3 style) - Original author: subBlue ( http://www.subBlue.com/ ) + Style name: prosilver (the default phpBB 3.0.x style) + Based on style: + Original author: Tom Beddard ( http://www.subblue.com/ ) Modified by: - Copyright 2006 phpBB Group ( http://www.phpbb.com/ ) + NOTE: This page was generated by phpBB, the free open-source bulletin board package. + The phpBB Group is not responsible for the content of this page and forum. + For more information about phpBB please visit http://www.phpbb.com/ -------------------------------------------------------------- */ diff --git a/phpBB/styles/prosilver/theme/tweaks.css b/phpBB/styles/prosilver/theme/tweaks.css index 30fe5fb986..f7322c2cce 100644 --- a/phpBB/styles/prosilver/theme/tweaks.css +++ b/phpBB/styles/prosilver/theme/tweaks.css @@ -1,4 +1,4 @@ -/* proSilver Style Sheet Tweaks +/* Style Sheet Tweaks These style definitions are mainly IE specific tweaks required due to its poor CSS support. diff --git a/phpBB/styles/subsilver2/theme/stylesheet.css b/phpBB/styles/subsilver2/theme/stylesheet.css index c2b6718d87..b497620573 100644 --- a/phpBB/styles/subsilver2/theme/stylesheet.css +++ b/phpBB/styles/subsilver2/theme/stylesheet.css @@ -1,14 +1,13 @@ -/* phpBB 3.0 Style Sheet +/* phpBB3 Style Sheet -------------------------------------------------------------- - Style name: subsilver2 - Based on style: subSilver (the default phpBB 2 style) - Original author: subBlue ( http://www.subBlue.com/ ) - Modified by: psoTFX and the phpBB team ( http://www.phpbb.com ) + Style name: subsilver2 (the default phpBB 3.0.x style) + Based on style: subSilver (the default phpBB 2.0.x style) + Original author: Tom Beddard ( http://www.subblue.com/ ) + Modified by: phpBB Group ( http://www.phpbb.com/ ) - This is an alternative style for phpBB3 for those wishing to stay with - the familiar subSilver style of phpBB version 2.x - - Copyright 2006 phpBB Group ( http://www.phpbb.com/ ) + NOTE: This page was generated by phpBB, the free open-source bulletin board package. + The phpBB Group is not responsible for the content of this page and forum. + For more information about phpBB please visit http://www.phpbb.com/ -------------------------------------------------------------- */ From c79992d1cc06a6133b67117262685d8b4b7ae51b Mon Sep 17 00:00:00 2001 From: maelsoucaze Date: Sat, 29 Oct 2011 19:09:54 +0200 Subject: [PATCH 83/93] [ticket/10254] Remove subsilver2 as default style on theme. PHPBB3-10254 --- phpBB/styles/subsilver2/theme/stylesheet.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/styles/subsilver2/theme/stylesheet.css b/phpBB/styles/subsilver2/theme/stylesheet.css index b497620573..e658994de4 100644 --- a/phpBB/styles/subsilver2/theme/stylesheet.css +++ b/phpBB/styles/subsilver2/theme/stylesheet.css @@ -1,6 +1,6 @@ /* phpBB3 Style Sheet -------------------------------------------------------------- - Style name: subsilver2 (the default phpBB 3.0.x style) + Style name: subsilver2 Based on style: subSilver (the default phpBB 2.0.x style) Original author: Tom Beddard ( http://www.subblue.com/ ) Modified by: phpBB Group ( http://www.phpbb.com/ ) From 4d760630c362b69150e7a5089593f9a610b97ff1 Mon Sep 17 00:00:00 2001 From: maelsoucaze Date: Thu, 10 Nov 2011 00:19:30 +0100 Subject: [PATCH 84/93] [ticket/10254] Removing the NOTE as it is incompatible with phpBB.com. PHPBB3-10254 --- phpBB/styles/prosilver/theme/stylesheet.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/phpBB/styles/prosilver/theme/stylesheet.css b/phpBB/styles/prosilver/theme/stylesheet.css index d771a321ca..312e8497b8 100644 --- a/phpBB/styles/prosilver/theme/stylesheet.css +++ b/phpBB/styles/prosilver/theme/stylesheet.css @@ -4,10 +4,6 @@ Based on style: Original author: Tom Beddard ( http://www.subblue.com/ ) Modified by: - - NOTE: This page was generated by phpBB, the free open-source bulletin board package. - The phpBB Group is not responsible for the content of this page and forum. - For more information about phpBB please visit http://www.phpbb.com/ -------------------------------------------------------------- */ From cf044c363b788ab77cf1539af13c4c035ba0b970 Mon Sep 17 00:00:00 2001 From: maelsoucaze Date: Thu, 10 Nov 2011 16:31:47 +0100 Subject: [PATCH 85/93] [ticket/10254] Removing the subsilver2 NOTE, incompatible with phpBB.com. PHPBB3-10254 --- phpBB/styles/subsilver2/theme/stylesheet.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/phpBB/styles/subsilver2/theme/stylesheet.css b/phpBB/styles/subsilver2/theme/stylesheet.css index e658994de4..444104ae3c 100644 --- a/phpBB/styles/subsilver2/theme/stylesheet.css +++ b/phpBB/styles/subsilver2/theme/stylesheet.css @@ -4,10 +4,6 @@ Based on style: subSilver (the default phpBB 2.0.x style) Original author: Tom Beddard ( http://www.subblue.com/ ) Modified by: phpBB Group ( http://www.phpbb.com/ ) - - NOTE: This page was generated by phpBB, the free open-source bulletin board package. - The phpBB Group is not responsible for the content of this page and forum. - For more information about phpBB please visit http://www.phpbb.com/ -------------------------------------------------------------- */ From e543effc64d6a1b615166826a5a65dd8c7e34316 Mon Sep 17 00:00:00 2001 From: Andreas Fischer Date: Mon, 14 Nov 2011 13:32:54 +0100 Subject: [PATCH 86/93] [ticket/10254] Add "phpBB Group" to "Modified by" in prosilver stylesheet.css PHPBB3-10254 --- phpBB/styles/prosilver/theme/stylesheet.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/styles/prosilver/theme/stylesheet.css b/phpBB/styles/prosilver/theme/stylesheet.css index 312e8497b8..4a7356fbaa 100644 --- a/phpBB/styles/prosilver/theme/stylesheet.css +++ b/phpBB/styles/prosilver/theme/stylesheet.css @@ -3,7 +3,7 @@ Style name: prosilver (the default phpBB 3.0.x style) Based on style: Original author: Tom Beddard ( http://www.subblue.com/ ) - Modified by: + Modified by: phpBB Group ( http://www.phpbb.com/ ) -------------------------------------------------------------- */ From 3302305cd4a499603784aa87a40f5170d62a4f26 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sun, 13 Nov 2011 16:11:32 +0100 Subject: [PATCH 87/93] [ticket/9066] Move regex into get_preg_expression function and add tests PHPBB3-9066 --- phpBB/includes/functions.php | 4 ++++ phpBB/install/install_install.php | 2 +- tests/regex/table_prefix_test.php | 35 +++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 tests/regex/table_prefix_test.php diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index c2b099d48a..e477b0454e 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -3486,6 +3486,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 ''; diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php index bb1d858cfc..ccdcf211f1 100644 --- a/phpBB/install/install_install.php +++ b/phpBB/install/install_install.php @@ -546,7 +546,7 @@ class install_install extends module $error[] = $lang['INST_ERR_NO_DB']; $connect_test = false; } - else if (!preg_match('#^[a-zA-Z][a-zA-Z0-9_]*$#', $data['table_prefix'], $result)) + else if (!preg_match(get_preg_expression('table_prefix'), $data['table_prefix'])) { $error[] = $lang['INST_ERR_DB_INVALID_PREFIX']; $connect_test = false; diff --git a/tests/regex/table_prefix_test.php b/tests/regex/table_prefix_test.php new file mode 100644 index 0000000000..67a18b4fbc --- /dev/null +++ b/tests/regex/table_prefix_test.php @@ -0,0 +1,35 @@ +assertEquals($expected, preg_match(get_preg_expression('table_prefix'), $prefix)); + } +} From 983045348743d0205dd3a053df95e3ea993f9830 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Mon, 14 Nov 2011 18:41:19 +0100 Subject: [PATCH 88/93] [ticket/10452] Fix xHTML errors when print-viewing PMs Also changed the layout of prosilvers PM print-view, so it looks like the post print-view and not like the subsilver2 print-view. PHPBB3-10452 --- .../template/ucp_pm_viewmessage_print.html | 145 +++++------------- .../template/ucp_pm_viewmessage_print.html | 2 +- 2 files changed, 42 insertions(+), 105 deletions(-) diff --git a/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html b/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html index b1a93296bd..ce2a376768 100644 --- a/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html +++ b/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html @@ -1,120 +1,57 @@ + -{SITENAME} :: {PAGE_TITLE} - - + + + + + + +{META} +{SITENAME} • {PAGE_TITLE} + - -
    {L_GROUPS_NO_MEMBERS}{L_MEMBERS}
    {L_GROUPS_NO_MEMBERS}
    - - - - - - - - - - -
    {SITENAME}
    {L_PRIVATE_MESSAGING}

    {SUBJECT}
    {PAGE_NUMBER}
    + +
    + -
    + \ No newline at end of file diff --git a/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html b/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html index 6753a5bc33..24194e4c26 100644 --- a/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html +++ b/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html @@ -61,7 +61,7 @@ hr.sep { - + From 160e89aa06cf75e28b01311489e5b9b16bb2651b Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Mon, 14 Nov 2011 18:49:07 +0100 Subject: [PATCH 89/93] [ticket/10457] Undefined variable $request, when print-viewing PMs PHPBB3-10457 --- phpBB/includes/ucp/ucp_pm_viewmessage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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')); From 14af18cb1b81e5dcee70c9eccb35d19f17af6948 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 14 Oct 2011 16:23:16 +0200 Subject: [PATCH 90/93] [ticket/9361] View correct error messages when editing account information Currently the "current password" is only checked, when you change something. This means you get "Your profile has been updated." although you enter a wrong password. I also added proper error messages, when you leave the confirm fields empty, and sorted them in the order of the field appearances on the html page. PHPBB3-9361 --- phpBB/includes/ucp/ucp_profile.php | 12 ++++++------ phpBB/language/en/ucp.php | 3 +++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index c099e3b3fa..65b32bd0c4 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -78,14 +78,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 @@ -94,9 +94,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')) diff --git a/phpBB/language/en/ucp.php b/phpBB/language/en/ucp.php index c1e3c06c43..3ebc863447 100644 --- a/phpBB/language/en/ucp.php +++ b/phpBB/language/en/ucp.php @@ -138,6 +138,7 @@ $lang = array_merge($lang, array( 'CURRENT_IMAGE' => 'Current image', 'CURRENT_PASSWORD' => 'Current password', 'CURRENT_PASSWORD_EXPLAIN' => 'You must confirm your current password if you wish to change it, alter your e-mail address or username.', + 'CUR_PASSWORD_EMPTY' => 'You did not enter your current password.', 'CUR_PASSWORD_ERROR' => 'The current password you entered is incorrect.', 'CUSTOM_DATEFORMAT' => 'Custom…', @@ -268,9 +269,11 @@ $lang = array_merge($lang, array( 'MOVE_TO_FOLDER' => 'Move to folder', 'MOVE_UP' => 'Move up', + 'NEW_EMAIL_CONFIRM_EMPTY' => 'You did not enter a confirm e-mail address.', 'NEW_EMAIL_ERROR' => 'The e-mail addresses you entered do not match.', 'NEW_FOLDER_NAME' => 'New folder name', 'NEW_PASSWORD' => 'New password', + 'NEW_PASSWORD_CONFIRM_EMPTY' => 'You did not enter a confirm password.', 'NEW_PASSWORD_ERROR' => 'The passwords you entered do not match.', 'NOTIFY_METHOD' => 'Notification method', 'NOTIFY_METHOD_BOTH' => 'Both', From f1a53659bdacdc045943b8a09240e6ecadcc5360 Mon Sep 17 00:00:00 2001 From: rxu Date: Tue, 15 Nov 2011 22:33:11 +0800 Subject: [PATCH 91/93] [ticket/10419] Reword the language strings PHPBB3-10419 --- phpBB/language/en/acp/common.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php index 85da6fbd79..ef8d6f1cb3 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -328,14 +328,14 @@ $lang = array_merge($lang, array( 'DATABASE_SIZE' => 'Database size', // Enviroment configuration checks, mbstring related - 'ERROR_MBSTRING_FUNC_OVERLOAD' => 'Function overloading setting is invalid', - 'ERROR_MBSTRING_FUNC_OVERLOAD_EXPLAIN' => 'mbstring.func_overload must be set to either 0 or 4. You can check current value on PHP information page.', - 'ERROR_MBSTRING_ENCODING_TRANSLATION' => 'Transparent character encoding setting is invalid', - 'ERROR_MBSTRING_ENCODING_TRANSLATION_EXPLAIN' => 'mbstring.encoding_translation must be set to 0. You can check current value on PHP information page.', - 'ERROR_MBSTRING_HTTP_INPUT' => 'HTTP input character conversion setting is invalid', - 'ERROR_MBSTRING_HTTP_INPUT_EXPLAIN' => 'mbstring.http_input must be set to pass. You can check current value on PHP information page.', - 'ERROR_MBSTRING_HTTP_OUTPUT' => 'HTTP output character conversion setting is invalid', - 'ERROR_MBSTRING_HTTP_OUTPUT_EXPLAIN' => 'mbstring.http_output must be set to pass. You can check current value on PHP information page.', + 'ERROR_MBSTRING_FUNC_OVERLOAD' => 'Function overloading is improperly configured', + 'ERROR_MBSTRING_FUNC_OVERLOAD_EXPLAIN' => 'mbstring.func_overload must be set to either 0 or 4. You can check the current value on the PHP information page.', + 'ERROR_MBSTRING_ENCODING_TRANSLATION' => 'Transparent character encoding is improperly configured', + 'ERROR_MBSTRING_ENCODING_TRANSLATION_EXPLAIN' => 'mbstring.encoding_translation must be set to 0. You can check the current value on the PHP information page.', + 'ERROR_MBSTRING_HTTP_INPUT' => 'HTTP input character conversion is improperly configured', + 'ERROR_MBSTRING_HTTP_INPUT_EXPLAIN' => 'mbstring.http_input must be set to pass. You can check the current value on the PHP information page.', + 'ERROR_MBSTRING_HTTP_OUTPUT' => 'HTTP output character conversion is improperly configured', + 'ERROR_MBSTRING_HTTP_OUTPUT_EXPLAIN' => 'mbstring.http_output must be set to pass. You can check the current value on the PHP information page.', 'FILES_PER_DAY' => 'Attachments per day', 'FORUM_STATS' => 'Board statistics', From 815dd3591b2618f072791aeb7bf6d87492e690b0 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Tue, 15 Nov 2011 17:23:55 +0100 Subject: [PATCH 92/93] [ticket/10185] Always set board startdate on conversion The board startdate should always be set to first user registration date. The current code did not do anything at all, as the board_startdate was always set on installation before running the convertor. PHPBB3-10185 --- phpBB/install/install_convert.php | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/phpBB/install/install_convert.php b/phpBB/install/install_convert.php index 814b50cf68..62efc3e46b 100644 --- a/phpBB/install/install_convert.php +++ b/phpBB/install/install_convert.php @@ -1716,19 +1716,16 @@ class install_convert extends module fix_empty_primary_groups(); - if (!isset($config['board_startdate'])) - { - $sql = 'SELECT MIN(user_regdate) AS board_startdate - FROM ' . USERS_TABLE; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); + $sql = 'SELECT MIN(user_regdate) AS board_startdate + FROM ' . USERS_TABLE; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); - if (($row['board_startdate'] < $config['board_startdate'] && $row['board_startdate'] > 0) || !isset($config['board_startdate'])) - { - set_config('board_startdate', $row['board_startdate']); - $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_regdate = ' . $row['board_startdate'] . ' WHERE user_id = ' . ANONYMOUS); - } + if (!isset($config['board_startdate']) || ($row['board_startdate'] < $config['board_startdate'] && $row['board_startdate'] > 0)) + { + set_config('board_startdate', $row['board_startdate']); + $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_regdate = ' . $row['board_startdate'] . ' WHERE user_id = ' . ANONYMOUS); } update_dynamic_config(); From b2b057910e57961b3d31432267fadb4ddc922783 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Sat, 29 Oct 2011 23:04:18 +0200 Subject: [PATCH 93/93] [ticket/10157] Add notification to update cpfs when installing a language. We currently just copy the language-strings from the default language. But the admin should be reminded to change them. PHPBB3-10157 --- phpBB/includes/acp/acp_language.php | 9 ++++++++- phpBB/language/en/acp/language.php | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/phpBB/includes/acp/acp_language.php b/phpBB/includes/acp/acp_language.php index 598b390302..d560cdd0c5 100644 --- a/phpBB/includes/acp/acp_language.php +++ b/phpBB/includes/acp/acp_language.php @@ -919,6 +919,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" @@ -932,6 +935,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); @@ -944,12 +948,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) ? '

    ' . $user->lang['LANGUAGE_PACK_CPF_UPDATE'] : ''; + trigger_error($message . adm_back_link($this->u_action)); break; diff --git a/phpBB/language/en/acp/language.php b/phpBB/language/en/acp/language.php index 4d11309ebb..dde4e3d722 100644 --- a/phpBB/language/en/acp/language.php +++ b/phpBB/language/en/acp/language.php @@ -59,6 +59,7 @@ $lang = array_merge($lang, array( 'LANGUAGE_PACK_DELETED' => 'The language pack %s has been removed successfully. All users using this language have been reset to the boards default language.', 'LANGUAGE_PACK_DETAILS' => 'Language pack details', 'LANGUAGE_PACK_INSTALLED' => 'The language pack %s has been successfully installed.', + 'LANGUAGE_PACK_CPF_UPDATE' => 'The custom profile fields’ language strings were copied from the default language. Please change them if necessary.', 'LANGUAGE_PACK_ISO' => 'ISO', 'LANGUAGE_PACK_LOCALNAME' => 'Local name', 'LANGUAGE_PACK_NAME' => 'Name',
    {SITENAME}
    {L_PRIVATE_MESSAGING}
    {SITENAME}
    {L_PRIVATE_MESSAGING}