diff options
16 files changed, 374 insertions, 59 deletions
diff --git a/git-tools/hooks/pre-commit b/git-tools/hooks/pre-commit index 03babe47cd..06ba15c7fa 100755 --- a/git-tools/hooks/pre-commit +++ b/git-tools/hooks/pre-commit @@ -33,9 +33,7 @@ else against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 fi -error=0 errors="" - if ! which "$PHP_BIN" >/dev/null 2>&1 then echo "PHP Syntax check failed:" @@ -73,63 +71,18 @@ do # check the staged file content for syntax errors # using php -l (lint) - # note: if display_errors=stderr in php.ini, - # parse errors are printed on stderr; otherwise - # they are printed on stdout. - # we filter everything other than parse errors - # with a grep below, therefore it should be safe - # to combine stdout and stderr in all circumstances - result=$(git cat-file -p $sha | "$PHP_BIN" -l 2>&1) + result=$(git cat-file -p $sha | "$PHP_BIN" -n -l -ddisplay_errors\=1 -derror_reporting\=E_ALL -dlog_errrors\=0 2>&1) if [ $? -ne 0 ] then - error=1 # Swap back in correct filenames - errors=$(echo "$errors"; echo "$result" |sed -e "s@in - on@in $filename on@g") + errors=$(echo "$errors"; echo "$result" | grep ':' | sed -e "s@in - on@in $filename on@g") fi done unset IFS -if [ $error -eq 1 ] +if [ -n "$errors" ] then - echo "PHP Syntax check failed:" - # php "display errors" (display_errors php.ini value) - # and "log errors" (log_errors php.ini value). - # these are independent settings - see main/main.c in php source. - # the "log errors" setting produces output which - # starts with "PHP Parse error:"; the "display errors" - # setting produces output starting with "Parse error:". - # if both are turned on php dumps the parse error twice. - # therefore here we try to grep for one version and - # if that yields no results grep for the other version. - # - # other fun php facts: - # - # 1. in cli, display_errors and log_errors have different - # destinations by default. display_errors prints to - # standard output and log_errors prints to standard error. - # whether these destinations make sense is left - # as an exercise for the reader. - # 2. as mentioned above, with all output turned on - # php will print parse errors twice, one time on stdout - # and one time on stderr. - # 3. it is possible to set both display_errors and log_errors - # to off. if this is done php will print the text - # "Errors parsing <file>" but will not say what - # the errors are. useful behavior, this. - # 4. on my system display_errors defaults to on and - # log_errors defaults to off, therefore providing - # by default one copy of messages. your mileage may vary. - # 5. by setting display_errors=stderr and log_errors=on, - # both sets of messages will be printed on stderr. - # 6. php-cgi binary, given display_errors=stderr and - # log_errors=on, still prints both sets of messages - # on stderr, but formats one set as an html fragment. - # 7. your entry here? ;) - $echo_e "$errors" | grep "^Parse error:" - if [ $? -ne 0 ] - then - # match failed - $echo_e "$errors" | grep "^PHP Parse error:" - fi + echo "PHP Syntax check failed: " + $echo_e "$errors" exit 1 fi diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php index e537d7a8b9..9c430b5a0b 100644 --- a/phpBB/includes/acp/acp_bbcodes.php +++ b/phpBB/includes/acp/acp_bbcodes.php @@ -112,8 +112,8 @@ class acp_bbcodes { $template->assign_block_vars('token', array( 'TOKEN' => '{' . $token . '}', - 'EXPLAIN' => $token_explain) - ); + 'EXPLAIN' => ($token === 'LOCAL_URL') ? sprintf($token_explain, generate_board_url() . '/') : $token_explain, + )); } return; @@ -347,6 +347,9 @@ class acp_bbcodes 'LOCAL_URL' => array( '!(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('relative_url')) . ')!e' => "\$this->bbcode_specialchars('$1')" ), + 'RELATIVE_URL' => array( + '!(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('relative_url')) . ')!e' => "\$this->bbcode_specialchars('$1')" + ), 'EMAIL' => array( '!(' . get_preg_expression('email') . ')!ie' => "\$this->bbcode_specialchars('$1')" ), @@ -373,6 +376,7 @@ class acp_bbcodes $sp_tokens = array( 'URL' => '(?i)((?:' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('url')) . ')|(?:' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('www_url')) . '))(?-i)', 'LOCAL_URL' => '(?i)(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('relative_url')) . ')(?-i)', + 'RELATIVE_URL' => '(?i)(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('relative_url')) . ')(?-i)', 'EMAIL' => '(' . get_preg_expression('email') . ')', 'TEXT' => '(.*?)', 'SIMPLETEXT' => '([a-zA-Z0-9-+.,_ ]+)', @@ -429,7 +433,11 @@ class acp_bbcodes $fp_replace = str_replace($token, $replace, $fp_replace); $sp_match = str_replace(preg_quote($token, '!'), $sp_tokens[$token_type], $sp_match); - $sp_replace = str_replace($token, '${' . ($n + 1) . '}', $sp_replace); + + // Prepend the board url to local relative links + $replace_prepend = ($token_type === 'LOCAL_URL') ? generate_board_url() . '/' : ''; + + $sp_replace = str_replace($token, $replace_prepend . '${' . ($n + 1) . '}', $sp_replace); } $fp_match = '!' . $fp_match . '!' . $modifiers; diff --git a/phpBB/includes/auth/provider_apache.php b/phpBB/includes/auth/provider/apache.php index 5f6f2862b6..5f6f2862b6 100644 --- a/phpBB/includes/auth/provider_apache.php +++ b/phpBB/includes/auth/provider/apache.php diff --git a/phpBB/includes/auth/provider_db.php b/phpBB/includes/auth/provider/db.php index 894041c9cf..894041c9cf 100644 --- a/phpBB/includes/auth/provider_db.php +++ b/phpBB/includes/auth/provider/db.php diff --git a/phpBB/includes/auth/provider/index.htm b/phpBB/includes/auth/provider/index.htm new file mode 100644 index 0000000000..ee1f723a7d --- /dev/null +++ b/phpBB/includes/auth/provider/index.htm @@ -0,0 +1,10 @@ +<html> +<head> +<title></title> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> +</head> + +<body bgcolor="#FFFFFF" text="#000000"> + +</body> +</html> diff --git a/phpBB/includes/auth/provider_interface.php b/phpBB/includes/auth/provider/interface.php index 2d1935f8f0..2d1935f8f0 100644 --- a/phpBB/includes/auth/provider_interface.php +++ b/phpBB/includes/auth/provider/interface.php diff --git a/phpBB/includes/auth/provider_ldap.php b/phpBB/includes/auth/provider/ldap.php index f67c1e9247..f67c1e9247 100644 --- a/phpBB/includes/auth/provider_ldap.php +++ b/phpBB/includes/auth/provider/ldap.php diff --git a/phpBB/includes/db/migration/data/30x/local_url_bbcode.php b/phpBB/includes/db/migration/data/30x/local_url_bbcode.php new file mode 100644 index 0000000000..f324b8880d --- /dev/null +++ b/phpBB/includes/db/migration/data/30x/local_url_bbcode.php @@ -0,0 +1,57 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +class phpbb_db_migration_data_30x_local_url_bbcode extends phpbb_db_migration +{ + static public function depends_on() + { + return array('phpbb_db_migration_data_30x_3_0_12_rc1'); + } + + public function update_data() + { + return array( + array('custom', array(array($this, 'update_local_url_bbcode'))), + ); + } + + /** + * Update BBCodes that currently use the LOCAL_URL tag + * + * To fix http://tracker.phpbb.com/browse/PHPBB3-8319 we changed + * the second_pass_replace value, so that needs updating for existing ones + */ + public function update_local_url_bbcode() + { + $sql = 'SELECT * + FROM ' . BBCODES_TABLE . ' + WHERE bbcode_match ' . $this->db->sql_like_expression($this->db->any_char . 'LOCAL_URL' . $this->db->any_char); + $result = $this->db->sql_query($sql); + + while ($row = $this->db->sql_fetchrow($result)) + { + if (!class_exists('acp_bbcodes')) + { + global $phpEx; + phpbb_require_updated('includes/acp/acp_bbcodes.' . $phpEx); + } + $bbcode_match = $row['bbcode_match']; + $bbcode_tpl = $row['bbcode_tpl']; + + $acp_bbcodes = new acp_bbcodes(); + $sql_ary = $acp_bbcodes->build_regexp($bbcode_match, $bbcode_tpl); + + $sql = 'UPDATE ' . BBCODES_TABLE . ' + SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE bbcode_id = ' . (int) $row['bbcode_id']; + $this->sql_query($sql); + } + $this->db->sql_freeresult($result); + } +} diff --git a/phpBB/includes/db/migration/data/310/signature_module_auth.php b/phpBB/includes/db/migration/data/310/signature_module_auth.php new file mode 100644 index 0000000000..e4fbb27bcb --- /dev/null +++ b/phpBB/includes/db/migration/data/310/signature_module_auth.php @@ -0,0 +1,51 @@ +<?php +/** +* +* @package migration +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License v2 +* +*/ + +class phpbb_db_migration_data_310_signature_module_auth extends phpbb_db_migration +{ + public function effectively_installed() + { + $sql = 'SELECT module_auth + FROM ' . MODULES_TABLE . " + WHERE module_class = 'ucp' + AND module_basename = 'ucp_profile' + AND module_mode = 'signature'"; + $result = $this->db->sql_query($sql); + $module_auth = $this->db_sql_fetchfield('module_auth'); + $this->db->sql_freeresult($result); + + return $module_auth === 'acl_u_sig' || $module_auth === false; + } + + static public function depends_on() + { + return array('phpbb_db_migration_data_31x_dev'); + } + + public function update_data() + { + return array( + array('custom', array( + array($this, 'update_signature_module_auth'), + ), + ), + ); + } + + public function update_signature_module_auth() + { + $sql = 'UPDATE ' . MODULES_TABLE . " + SET module_auth = 'acl_u_sig' + WHERE module_class = 'ucp' + AND module_basename = 'ucp_profile' + AND module_mode = 'signature' + AND module_auth = ''"; + $this->db->sql_query($sql); + } +} diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 72855af5f8..21662eb493 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -2899,7 +2899,7 @@ function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port if ($fsock = @fsockopen($host, $port, $errno, $errstr, $timeout)) { - @fputs($fsock, "GET $directory/$filename HTTP/1.1\r\n"); + @fputs($fsock, "GET $directory/$filename HTTP/1.0\r\n"); @fputs($fsock, "HOST: $host\r\n"); @fputs($fsock, "Connection: close\r\n\r\n"); diff --git a/phpBB/language/en/acp/posting.php b/phpBB/language/en/acp/posting.php index 89e171744f..ea3eadb0dd 100644 --- a/phpBB/language/en/acp/posting.php +++ b/phpBB/language/en/acp/posting.php @@ -83,7 +83,8 @@ $lang = array_merge($lang, array( 'NUMBER' => 'Any series of digits', 'EMAIL' => 'A valid email address', 'URL' => 'A valid URL using any protocol (http, ftp, etc… cannot be used for javascript exploits). If none is given, “http://” is prefixed to the string.', - 'LOCAL_URL' => 'A local URL. The URL must be relative to the topic page and cannot contain a server name or protocol.', + 'LOCAL_URL' => 'A local URL. The URL must be relative to the topic page and cannot contain a server name or protocol, as links are prefixed with “%s”', + 'RELATIVE_URL' => 'A relative URL. You can use this to match parts of a URL, but be careful: a full URL is a valid relative URL. When you want to use relative URLs of your board, use the LOCAL_URL token.', 'COLOR' => 'A HTML colour, can be either in the numeric form <samp>#FF1234</samp> or a <a href="http://www.w3.org/TR/CSS21/syndata.html#value-def-color">CSS colour keyword</a> such as <samp>fuchsia</samp> or <samp>InactiveBorder</samp>' ) )); diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php index 59ef7bbc80..4dd03202f1 100644 --- a/phpBB/viewtopic.php +++ b/phpBB/viewtopic.php @@ -145,7 +145,14 @@ if ($view && !$post_id) if (!$row) { - $user->setup('viewtopic'); + $sql = 'SELECT forum_style + FROM ' . FORUMS_TABLE . " + WHERE forum_id = $forum_id"; + $result = $db->sql_query($sql); + $forum_style = (int) $db->sql_fetchfield('forum_style'); + $db->sql_freeresult($result); + + $user->setup('viewtopic', $forum_style); trigger_error(($view == 'next') ? 'NO_NEWER_TOPICS' : 'NO_OLDER_TOPICS'); } else diff --git a/tests/dbal/order_lower_test.php b/tests/dbal/order_lower_test.php index 84d454742f..d826765681 100644 --- a/tests/dbal/order_lower_test.php +++ b/tests/dbal/order_lower_test.php @@ -18,6 +18,11 @@ class phpbb_dbal_order_lower_test extends phpbb_database_test_case { $db = $this->new_dbal(); + if (strpos($db->sql_layer, 'mysql') === 0 && version_compare($db->sql_server_info(true, false), '5.6', '>=')) + { + $this->markTestSkipped('MySQL 5.6 fails to order things correctly. See also: http://tracker.phpbb.com/browse/PHPBB3-11571 http://bugs.mysql.com/bug.php?id=69005'); + } + // http://tracker.phpbb.com/browse/PHPBB3-10507 // Test ORDER BY LOWER(style_name) $db->sql_return_on_error(true); @@ -58,7 +63,7 @@ class phpbb_dbal_order_lower_test extends phpbb_database_test_case 'style_parent_id' => 0, 'style_parent_tree' => '', ) - ), + ), $db->sql_fetchrowset($result) ); } diff --git a/tests/functional/forum_style_test.php b/tests/functional/forum_style_test.php new file mode 100644 index 0000000000..59f7341eb6 --- /dev/null +++ b/tests/functional/forum_style_test.php @@ -0,0 +1,45 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @group functional +*/ +class phpbb_functional_forum_style_test extends phpbb_functional_test_case +{ + public function test_default_forum_style() + { + $crawler = self::request('GET', 'viewtopic.php?t=1&f=2'); + $this->assertContains('styles/prosilver/', $crawler->filter('head > link[rel=stylesheet]')->attr('href')); + + $crawler = self::request('GET', 'viewtopic.php?t=1'); + $this->assertContains('styles/prosilver/', $crawler->filter('head > link[rel=stylesheet]')->attr('href')); + + $crawler = self::request('GET', 'viewtopic.php?t=1&view=next'); + $this->assertContains('styles/prosilver/', $crawler->filter('head > link[rel=stylesheet]')->attr('href')); + } + + public function test_custom_forum_style() + { + $db = $this->get_db(); + $this->add_style(2, 'test_style'); + $db->sql_query('UPDATE ' . FORUMS_TABLE . ' SET forum_style = 2 WHERE forum_id = 2'); + + $crawler = self::request('GET', 'viewtopic.php?t=1&f=2'); + $this->assertContains('styles/test_style/', $crawler->filter('head > link[rel=stylesheet]')->attr('href')); + + $crawler = self::request('GET', 'viewtopic.php?t=1'); + $this->assertContains('styles/test_style/', $crawler->filter('head > link[rel=stylesheet]')->attr('href')); + + $crawler = self::request('GET', 'viewtopic.php?t=1&view=next'); + $this->assertContains('styles/test_style/', $crawler->filter('head > link[rel=stylesheet]')->attr('href')); + + $db->sql_query('UPDATE ' . FORUMS_TABLE . ' SET forum_style = 0 WHERE forum_id = 2'); + $this->delete_style(2, 'test_style'); + } +} diff --git a/tests/functions/get_remote_file_test.php b/tests/functions/get_remote_file_test.php new file mode 100644 index 0000000000..4032ca5b58 --- /dev/null +++ b/tests/functions/get_remote_file_test.php @@ -0,0 +1,75 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions_admin.php'; + +/** +* @group slow +*/ +class phpbb_functions_get_remote_file extends phpbb_test_case +{ + public function test_version_phpbb_com() + { + $hostname = 'version.phpbb.com'; + + if (!phpbb_checkdnsrr($hostname, 'A')) + { + $this->markTestSkipped(sprintf( + 'Could not find a DNS record for hostname %s. ' . + 'Assuming network is down.', + $hostname + )); + } + + $errstr = $errno = null; + $file = get_remote_file($hostname, '/phpbb', '30x.txt', $errstr, $errno); + + $this->assertNotEquals( + 0, + strlen($file), + 'Failed asserting that the response is not empty.' + ); + + $this->assertSame( + '', + $errstr, + 'Failed asserting that the error string is empty.' + ); + + $this->assertSame( + 0, + $errno, + 'Failed asserting that the error number is 0 (i.e. no error occurred).' + ); + + $lines = explode("\n", $file); + + $this->assertGreaterThanOrEqual( + 2, + sizeof($lines), + 'Failed asserting that the version file has at least two lines.' + ); + + $this->assertStringStartsWith( + '3.', + $lines[0], + "Failed asserting that the first line of the version file starts with '3.'" + ); + + $this->assertNotSame( + false, + filter_var($lines[1], FILTER_VALIDATE_URL), + 'Failed asserting that the second line of the version file is a valid URL.' + ); + + $this->assertContains('http', $lines[1]); + $this->assertContains('phpbb.com', $lines[1], '', true); + } +} diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index 7e2e750e30..f27e339bb7 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -358,6 +358,109 @@ class phpbb_functional_test_case extends phpbb_test_case } /** + * Creates a new style + * + * @param string $style_id Style ID + * @param string $style_path Style directory + * @param string $parent_style_id Parent style id. Default = 1 + * @param string $parent_style_path Parent style directory. Default = 'prosilver' + */ + protected function add_style($style_id, $style_path, $parent_style_id = 1, $parent_style_path = 'prosilver') + { + global $phpbb_root_path; + + $db = $this->get_db(); + if (version_compare(PHPBB_VERSION, '3.1.0-dev', '<')) + { + $sql = 'INSERT INTO ' . STYLES_TABLE . ' ' . $db->sql_build_array('INSERT', array( + 'style_id' => $style_id, + 'style_name' => $style_path, + 'style_copyright' => '', + 'style_active' => 1, + 'template_id' => $style_id, + 'theme_id' => $style_id, + 'imageset_id' => $style_id, + )); + $db->sql_query($sql); + + $sql = 'INSERT INTO ' . STYLES_IMAGESET_TABLE . ' ' . $db->sql_build_array('INSERT', array( + 'imageset_id' => $style_id, + 'imageset_name' => $style_path, + 'imageset_copyright' => '', + 'imageset_path' => $style_path, + )); + $db->sql_query($sql); + + $sql = 'INSERT INTO ' . STYLES_TEMPLATE_TABLE . ' ' . $db->sql_build_array('INSERT', array( + 'template_id' => $style_id, + 'template_name' => $style_path, + 'template_copyright' => '', + 'template_path' => $style_path, + 'bbcode_bitfield' => 'kNg=', + 'template_inherits_id' => $parent_style_id, + 'template_inherit_path' => $parent_style_path, + )); + $db->sql_query($sql); + + $sql = 'INSERT INTO ' . STYLES_THEME_TABLE . ' ' . $db->sql_build_array('INSERT', array( + 'theme_id' => $style_id, + 'theme_name' => $style_path, + 'theme_copyright' => '', + 'theme_path' => $style_path, + 'theme_storedb' => 0, + 'theme_mtime' => 0, + 'theme_data' => '', + )); + $db->sql_query($sql); + + if ($style_path != 'prosilver' && $style_path != 'subsilver2') + { + @mkdir($phpbb_root_path . 'styles/' . $style_path, 0777); + @mkdir($phpbb_root_path . 'styles/' . $style_path . '/template', 0777); + } + } + else + { + $db->sql_multi_insert(STYLES_TABLE, array( + 'style_id' => $style_id, + 'style_name' => $style_path, + 'style_copyright' => '', + 'style_active' => 1, + 'style_path' => $style_path, + 'bbcode_bitfield' => 'kNg=', + 'style_parent_id' => $parent_style_id, + 'style_parent_tree' => $parent_style_path, + )); + } + } + + /** + * Remove temporary style created by add_style() + * + * @param string $style_id Style ID + * @param string $style_path Style directory + */ + protected function delete_style($style_id, $style_path) + { + global $phpbb_root_path; + + $db = $this->get_db(); + $db->sql_query('DELETE FROM ' . STYLES_TABLE . ' WHERE style_id = ' . $style_id); + if (version_compare(PHPBB_VERSION, '3.1.0-dev', '<')) + { + $db->sql_query('DELETE FROM ' . STYLES_IMAGESET_TABLE . ' WHERE imageset_id = ' . $style_id); + $db->sql_query('DELETE FROM ' . STYLES_TEMPLATE_TABLE . ' WHERE template_id = ' . $style_id); + $db->sql_query('DELETE FROM ' . STYLES_THEME_TABLE . ' WHERE theme_id = ' . $style_id); + + if ($style_path != 'prosilver' && $style_path != 'subsilver2') + { + @rmdir($phpbb_root_path . 'styles/' . $style_path . '/template'); + @rmdir($phpbb_root_path . 'styles/' . $style_path); + } + } + } + + /** * Creates a new user with limited permissions * * @param string $username Also doubles up as the user's password |