diff options
34 files changed, 627 insertions, 144 deletions
diff --git a/.gitignore b/.gitignore index 65058b2eaf..7d789c59a1 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,4 @@ /phpBB/store/* /tests/phpbb_unit_tests.sqlite2 /tests/test_config.php -/tests/utf/data/*.txt +/tests/tmp/* diff --git a/build/build.xml b/build/build.xml index 7cfb5d0bf8..eb63bde034 100644 --- a/build/build.xml +++ b/build/build.xml @@ -119,6 +119,15 @@ <target name="create-package" depends="prepare-new-version,old-version-diffs"> <exec dir="build" command="php -f package.php '${versions}' > logs/package.log" escape="false" /> <exec dir="build" command="php -f build_diff.php '${prevversion}' '${newversion}' > logs/build_diff.log" escape="false" /> + <exec dir="build" escape="false" + command="diff -crNEBwd old_versions/release-${prevversion}/language new_version/phpBB3/language > + save/save_${prevversion}_to_${newversion}/language/phpbb-${prevversion}_to_${newversion}_language.patch" /> + <exec dir="build" escape="false" + command="diff -crNEBwd old_versions/release-${prevversion}/styles/prosilver new_version/phpBB3/styles/prosilver > + save/save_${prevversion}_to_${newversion}/prosilver/phpbb-${prevversion}_to_${newversion}_prosilver.patch" /> + <exec dir="build" escape="false" + command="diff -crNEBwd old_versions/release-${prevversion}/styles/subsilver2 new_version/phpBB3/styles/subsilver2 > + save/save_${prevversion}_to_${newversion}/subsilver2/phpbb-${prevversion}_to_${newversion}_subsilver2.patch" /> </target> <!-- diff --git a/phpBB/feed.php b/phpBB/feed.php index d737b8e10c..9816f0f303 100644 --- a/phpBB/feed.php +++ b/phpBB/feed.php @@ -173,6 +173,12 @@ if (defined('DEBUG_EXTRA') && request_var('explain', 0) && $auth->acl_get('a_')) header("Content-Type: application/atom+xml; charset=UTF-8"); header("Last-Modified: " . gmdate('D, d M Y H:i:s', $feed_updated_time) . ' GMT'); +if (!empty($user->data['is_bot'])) +{ + // Let reverse proxies know we detected a bot. + header('X-PHPBB-IS-BOT: yes'); +} + echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n"; echo '<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="' . $global_vars['FEED_LANG'] . '">' . "\n"; echo '<link rel="self" type="application/atom+xml" href="' . $global_vars['SELF_LINK'] . '" />' . "\n\n"; @@ -604,30 +610,9 @@ class phpbb_feed_base function get_passworded_forums() { - global $db, $user; - - // Exclude passworded forums - $sql = 'SELECT f.forum_id, fa.user_id - FROM ' . FORUMS_TABLE . ' f - LEFT JOIN ' . FORUMS_ACCESS_TABLE . " fa - ON (fa.forum_id = f.forum_id - AND fa.session_id = '" . $db->sql_escape($user->session_id) . "') - WHERE f.forum_password <> ''"; - $result = $db->sql_query($sql); - - $forum_ids = array(); - while ($row = $db->sql_fetchrow($result)) - { - $forum_id = (int) $row['forum_id']; - - if ($row['user_id'] != $user->data['user_id']) - { - $forum_ids[$forum_id] = $forum_id; - } - } - $db->sql_freeresult($result); + global $user; - return $forum_ids; + return $user->get_passworded_forums(); } function get_item() diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php index d23323a5b1..10ca6c0a1f 100644 --- a/phpBB/includes/db/db_tools.php +++ b/phpBB/includes/db/db_tools.php @@ -649,6 +649,23 @@ class phpbb_db_tools $sqlite = true; } + // Drop tables? + if (!empty($schema_changes['drop_tables'])) + { + foreach ($schema_changes['drop_tables'] as $table) + { + // only drop table if it exists + if ($this->sql_table_exists($table)) + { + $result = $this->sql_table_drop($table); + if ($this->return_statements) + { + $statements = array_merge($statements, $result); + } + } + } + } + // Add tables? if (!empty($schema_changes['add_tables'])) { @@ -1788,7 +1805,7 @@ class phpbb_db_tools break; case 'oracle': - $statements[] = 'ALTER TABLE ' . $table_name . ' DROP ' . $column_name; + $statements[] = 'ALTER TABLE ' . $table_name . ' DROP COLUMN ' . $column_name; break; case 'postgres': @@ -1939,6 +1956,7 @@ class phpbb_db_tools $statements[] = "DROP SEQUENCE {$row['referenced_name']}"; } $this->db->sql_freeresult($result); + break; case 'postgres': // PGSQL does not "tightly" bind sequences and tables, we must guess... diff --git a/phpBB/includes/db/mssqlnative.php b/phpBB/includes/db/mssqlnative.php index 6810562d17..7fbc374e77 100644 --- a/phpBB/includes/db/mssqlnative.php +++ b/phpBB/includes/db/mssqlnative.php @@ -396,7 +396,7 @@ class dbal_mssqlnative extends dbal */ function sql_affectedrows() { - return ($this->db_connect_id) ? @sqlsrv_rows_affected($this->db_connect_id) : false; + return (!empty($this->query_result)) ? @sqlsrv_rows_affected($this->query_result) : false; } /** diff --git a/phpBB/includes/error_collector.php b/phpBB/includes/error_collector.php index 55834f354c..3c0a89a1f3 100644 --- a/phpBB/includes/error_collector.php +++ b/phpBB/includes/error_collector.php @@ -49,13 +49,15 @@ class phpbb_error_collector { $text .= "<br />\n"; } + list($errno, $msg_text, $errfile, $errline) = $error; - $text .= "Errno $errno: $msg_text"; - if (defined('DEBUG_EXTRA') || defined('IN_INSTALL')) - { - $text .= " at $errfile line $errline"; - } + + // Prevent leakage of local path to phpBB install + $errfile = phpbb_filter_root_path($errfile); + + $text .= "Errno $errno: $msg_text at $errfile line $errline"; } + return $text; } } diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 6b6679bde5..c2b099d48a 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -2225,6 +2225,12 @@ function append_sid($url, $params = false, $is_amp = true, $session_id = false) { global $_SID, $_EXTRA_URL, $phpbb_hook; + if ($params === '' || (is_array($params) && empty($params))) + { + // Do not append the ? if the param-list is empty anyway. + $params = false; + } + // Developers using the hook function need to globalise the $_SID and $_EXTRA_URL on their own and also handle it appropriately. // They could mimic most of what is within this function if (!empty($phpbb_hook) && $phpbb_hook->call_hook(__FUNCTION__, $url, $params, $is_amp, $session_id)) @@ -3381,61 +3387,44 @@ function add_log() } /** -* Return a nicely formatted backtrace (parts from the php manual by diz at ysagoon dot com) +* Return a nicely formatted backtrace. +* +* Turns the array returned by debug_backtrace() into HTML markup. +* Also filters out absolute paths to phpBB root. +* +* @return string HTML markup */ function get_backtrace() { - global $phpbb_root_path; - $output = '<div style="font-family: monospace;">'; $backtrace = debug_backtrace(); - $path = phpbb_realpath($phpbb_root_path); - foreach ($backtrace as $number => $trace) - { - // We skip the first one, because it only shows this file/function - if ($number == 0) - { - continue; - } + // We skip the first one, because it only shows this file/function + unset($backtrace[0]); + foreach ($backtrace as $trace) + { // Strip the current directory from path - if (empty($trace['file'])) - { - $trace['file'] = ''; - } - else - { - $trace['file'] = str_replace(array($path, '\\'), array('', '/'), $trace['file']); - $trace['file'] = substr($trace['file'], 1); - } - $args = array(); + $trace['file'] = (empty($trace['file'])) ? '(not given by php)' : htmlspecialchars(phpbb_filter_root_path($trace['file'])); + $trace['line'] = (empty($trace['line'])) ? '(not given by php)' : $trace['line']; - // If include/require/include_once is not called, do not show arguments - they may contain sensible information - if (!in_array($trace['function'], array('include', 'require', 'include_once'))) - { - unset($trace['args']); - } - else + // Only show function arguments for include etc. + // Other parameters may contain sensible information + $argument = ''; + if (!empty($trace['args'][0]) && in_array($trace['function'], array('include', 'require', 'include_once', 'require_once'))) { - // Path... - if (!empty($trace['args'][0])) - { - $argument = htmlspecialchars($trace['args'][0]); - $argument = str_replace(array($path, '\\'), array('', '/'), $argument); - $argument = substr($argument, 1); - $args[] = "'{$argument}'"; - } + $argument = htmlspecialchars(phpbb_filter_root_path($trace['args'][0])); } $trace['class'] = (!isset($trace['class'])) ? '' : $trace['class']; $trace['type'] = (!isset($trace['type'])) ? '' : $trace['type']; $output .= '<br />'; - $output .= '<b>FILE:</b> ' . htmlspecialchars($trace['file']) . '<br />'; + $output .= '<b>FILE:</b> ' . $trace['file'] . '<br />'; $output .= '<b>LINE:</b> ' . ((!empty($trace['line'])) ? $trace['line'] : '') . '<br />'; - $output .= '<b>CALL:</b> ' . htmlspecialchars($trace['class'] . $trace['type'] . $trace['function']) . '(' . ((sizeof($args)) ? implode(', ', $args) : '') . ')<br />'; + $output .= '<b>CALL:</b> ' . htmlspecialchars($trace['class'] . $trace['type'] . $trace['function']); + $output .= '(' . (($argument !== '') ? "'$argument'" : '') . ')<br />'; } $output .= '</div>'; return $output; @@ -3810,9 +3799,8 @@ function msg_handler($errno, $msg_text, $errfile, $errline) if (strpos($errfile, 'cache') === false && strpos($errfile, 'template.') === false) { - // remove complete path to installation, with the risk of changing backslashes meant to be there - $errfile = str_replace(array(phpbb_realpath($phpbb_root_path), '\\'), array('', '/'), $errfile); - $msg_text = str_replace(array(phpbb_realpath($phpbb_root_path), '\\'), array('', '/'), $msg_text); + $errfile = phpbb_filter_root_path($errfile); + $msg_text = phpbb_filter_root_path($msg_text); $error_name = ($errno === E_WARNING) ? 'PHP Warning' : 'PHP Notice'; echo '<b>[phpBB Debug] ' . $error_name . '</b>: in file <b>' . $errfile . '</b> on line <b>' . $errline . '</b>: <b>' . $msg_text . '</b><br />' . "\n"; @@ -3991,6 +3979,29 @@ function msg_handler($errno, $msg_text, $errfile, $errline) } /** +* Removes absolute path to phpBB root directory from error messages +* and converts backslashes to forward slashes. +* +* @param string $errfile Absolute file path +* (e.g. /var/www/phpbb3/phpBB/includes/functions.php) +* Please note that if $errfile is outside of the phpBB root, +* the root path will not be found and can not be filtered. +* @return string Relative file path +* (e.g. /includes/functions.php) +*/ +function phpbb_filter_root_path($errfile) +{ + static $root_path; + + if (empty($root_path)) + { + $root_path = phpbb_realpath(dirname(__FILE__) . '/../'); + } + + return str_replace(array($root_path, '\\'), array('[ROOT]', '/'), $errfile); +} + +/** * Queries the session table to get information about online guests * @param int $item_id Limits the search to the item with this id * @param string $item The name of the item which is stored in the session table as session_{$item}_id @@ -4641,6 +4652,12 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 header('Expires: 0'); header('Pragma: no-cache'); + if (!empty($user->data['is_bot'])) + { + // Let reverse proxies know we detected a bot. + header('X-PHPBB-IS-BOT: yes'); + } + return; } diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php index b34976db2a..b7650ecd6a 100644 --- a/phpBB/includes/functions_content.php +++ b/phpBB/includes/functions_content.php @@ -691,9 +691,6 @@ function censor_text($text) return ''; } - // Strip control characters - $text = preg_replace('/[\x00-\x0f]/', '', $text); - // We moved the word censor checks in here because we call this function quite often - and then only need to do the check once if (!isset($censors) || !is_array($censors)) { diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php index 7982b9908d..14d0c44dcf 100644 --- a/phpBB/includes/functions_display.php +++ b/phpBB/includes/functions_display.php @@ -51,6 +51,27 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod $sql_where = 'left_id > ' . $root_data['left_id'] . ' AND left_id < ' . $root_data['right_id']; } + // Handle marking everything read + if ($mark_read == 'all') + { + $redirect = build_url(array('mark', 'hash')); + meta_refresh(3, $redirect); + + if (check_link_hash(request_var('hash', ''), 'global')) + { + markread('all'); + + trigger_error( + $user->lang['FORUMS_MARKED'] . '<br /><br />' . + sprintf($user->lang['RETURN_INDEX'], '<a href="' . $redirect . '">', '</a>') + ); + } + else + { + trigger_error(sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>')); + } + } + // Display list of active topics for this category? $show_active = (isset($root_data['forum_flags']) && ($root_data['forum_flags'] & FORUM_FLAG_ACTIVE_TOPICS)) ? true : false; @@ -120,13 +141,14 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod $forum_id = $row['forum_id']; // Mark forums read? - if ($mark_read == 'forums' || $mark_read == 'all') + if ($mark_read == 'forums') { if ($auth->acl_get('f_list', $forum_id)) { $forum_ids[] = $forum_id; - continue; } + + continue; } // Category with no members @@ -152,8 +174,6 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod continue; } - $forum_ids[] = $forum_id; - if ($config['load_db_lastread'] && $user->data['is_registered']) { $forum_tracking_info[$forum_id] = (!empty($row['mark_time'])) ? $row['mark_time'] : $user->data['user_lastmark']; @@ -255,24 +275,16 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod $db->sql_freeresult($result); // Handle marking posts - if ($mark_read == 'forums' || $mark_read == 'all') + if ($mark_read == 'forums') { $redirect = build_url(array('mark', 'hash')); $token = request_var('hash', ''); if (check_link_hash($token, 'global')) { - if ($mark_read == 'all') - { - markread('all'); - $message = sprintf($user->lang['RETURN_INDEX'], '<a href="' . $redirect . '">', '</a>'); - } - else - { - // Add 0 to forums array to mark global announcements correctly - $forum_ids[] = 0; - markread('topics', $forum_ids); - $message = sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect . '">', '</a>'); - } + // Add 0 to forums array to mark global announcements correctly + $forum_ids[] = 0; + markread('topics', $forum_ids); + $message = sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect . '">', '</a>'); meta_refresh(3, $redirect); trigger_error($user->lang['FORUMS_MARKED'] . '<br /><br />' . $message); } @@ -996,13 +1008,17 @@ function display_user_activity(&$userdata) } // Obtain active topic + // We need to exclude passworded forums here so we do not leak the topic title + $forum_ary_topic = array_unique(array_merge($forum_ary, $user->get_passworded_forums())); + $forum_sql_topic = (!empty($forum_ary_topic)) ? 'AND ' . $db->sql_in_set('forum_id', $forum_ary_topic, true) : ''; + $sql = 'SELECT topic_id, COUNT(post_id) AS num_posts FROM ' . POSTS_TABLE . ' WHERE poster_id = ' . $userdata['user_id'] . " AND post_postcount = 1 AND (post_approved = 1 $sql_m_approve) - $forum_sql + $forum_sql_topic GROUP BY topic_id ORDER BY num_posts DESC"; $result = $db->sql_query_limit($sql, 1); diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index b5c87094c0..08c686d9e3 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -975,9 +975,16 @@ function smtpmail($addresses, $subject, $message, &$err_msg, $headers = false) $smtp->add_backtrace('Connecting to ' . $config['smtp_host'] . ':' . $config['smtp_port']); // Ok we have error checked as much as we can to this point let's get on it already. - ob_start(); + if (!class_exists('phpbb_error_collector')) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/error_collector.' . $phpEx); + } + $collector = new phpbb_error_collector; + $collector->install(); $smtp->socket = fsockopen($config['smtp_host'], $config['smtp_port'], $errno, $errstr, 20); - $error_contents = ob_get_clean(); + $collector->uninstall(); + $error_contents = $collector->format_errors(); if (!$smtp->socket) { @@ -1608,18 +1615,27 @@ function mail_encode($str, $eol = "\r\n") */ function phpbb_mail($to, $subject, $msg, $headers, $eol, &$err_msg) { - global $config; + global $config, $phpbb_root_path, $phpEx; // We use the EOL character for the OS here because the PHP mail function does not correctly transform line endings. On Windows SMTP is used (SMTP is \r\n), on UNIX a command is used... // Reference: http://bugs.php.net/bug.php?id=15841 $headers = implode($eol, $headers); - ob_start(); + if (!class_exists('phpbb_error_collector')) + { + include($phpbb_root_path . 'includes/error_collector.' . $phpEx); + } + + $collector = new phpbb_error_collector; + $collector->install(); + // On some PHP Versions mail() *may* fail if there are newlines within the subject. // Newlines are used as a delimiter for lines in mail_encode() according to RFC 2045 section 6.8. // Because PHP can't decide what is wanted we revert back to the non-RFC-compliant way of separating by one space (Use '' as parameter to mail_encode() results in SPACE used) $result = $config['email_function_name']($to, mail_encode($subject, ''), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $headers); - $err_msg = ob_get_clean(); + + $collector->uninstall(); + $err_msg = $collector->format_errors(); return $result; } diff --git a/phpBB/includes/functions_transfer.php b/phpBB/includes/functions_transfer.php index 046abede8e..5ab7a87efd 100644 --- a/phpBB/includes/functions_transfer.php +++ b/phpBB/includes/functions_transfer.php @@ -808,23 +808,56 @@ class ftp_fsock extends transfer */ function _open_data_connection() { - $this->_send_command('PASV', '', false); - - if (!$ip_port = $this->_check_command(true)) + // Try to find out whether we have a IPv4 or IPv6 (control) connection + if (function_exists('stream_socket_get_name')) { - return false; + $socket_name = stream_socket_get_name($this->connection, true); + $server_ip = substr($socket_name, 0, strrpos($socket_name, ':')); } - // open the connection to start sending the file - if (!preg_match('#[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+#', $ip_port, $temp)) + if (!isset($server_ip) || preg_match(get_preg_expression('ipv4'), $server_ip)) { - // bad ip and port - return false; + // Passive mode + $this->_send_command('PASV', '', false); + + if (!$ip_port = $this->_check_command(true)) + { + return false; + } + + // open the connection to start sending the file + if (!preg_match('#[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+#', $ip_port, $temp)) + { + // bad ip and port + return false; + } + + $temp = explode(',', $temp[0]); + $server_ip = $temp[0] . '.' . $temp[1] . '.' . $temp[2] . '.' . $temp[3]; + $server_port = $temp[4] * 256 + $temp[5]; + } + else + { + // Extended Passive Mode - RFC2428 + $this->_send_command('EPSV', '', false); + + if (!$epsv_response = $this->_check_command(true)) + { + return false; + } + + // Response looks like "229 Entering Extended Passive Mode (|||12345|)" + // where 12345 is the tcp port for the data connection + if (!preg_match('#\(\|\|\|([0-9]+)\|\)#', $epsv_response, $match)) + { + return false; + } + $server_port = (int) $match[1]; + + // fsockopen expects IPv6 address in square brackets + $server_ip = "[$server_ip]"; } - $temp = explode(',', $temp[0]); - $server_ip = $temp[0] . '.' . $temp[1] . '.' . $temp[2] . '.' . $temp[3]; - $server_port = $temp[4] * 256 + $temp[5]; $errno = 0; $errstr = ''; diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php index e9e706e2b8..caadcbafaa 100644 --- a/phpBB/includes/session.php +++ b/phpBB/includes/session.php @@ -2410,6 +2410,39 @@ class user extends session return true; } + + /** + * Returns all password protected forum ids the user is currently NOT authenticated for. + * + * @return array Array of forum ids + * @access public + */ + function get_passworded_forums() + { + global $db; + + $sql = 'SELECT f.forum_id, fa.user_id + FROM ' . FORUMS_TABLE . ' f + LEFT JOIN ' . FORUMS_ACCESS_TABLE . " fa + ON (fa.forum_id = f.forum_id + AND fa.session_id = '" . $db->sql_escape($this->session_id) . "') + WHERE f.forum_password <> ''"; + $result = $db->sql_query($sql); + + $forum_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $forum_id = (int) $row['forum_id']; + + if ($row['user_id'] != $this->data['user_id']) + { + $forum_ids[$forum_id] = $forum_id; + } + } + $db->sql_freeresult($result); + + return $forum_ids; + } } ?>
\ No newline at end of file diff --git a/phpBB/index.php b/phpBB/index.php index 3b58646af0..0105a0a1bd 100644 --- a/phpBB/index.php +++ b/phpBB/index.php @@ -81,15 +81,23 @@ $legend = implode(', ', $legend); // Generate birthday list if required ... $birthday_list = ''; -if ($config['load_birthdays'] && $config['allow_birthdays']) +if ($config['load_birthdays'] && $config['allow_birthdays'] && $auth->acl_gets('u_viewprofile', 'a_user', 'a_useradd', 'a_userdel')) { $now = phpbb_gmgetdate(time() + $user->timezone + $user->dst); + + // Display birthdays of 29th february on 28th february in non-leap-years + $leap_year_birthdays = ''; + if ($now['mday'] == 28 && $now['mon'] == 2 && !$user->format_date(time(), 'L')) + { + $leap_year_birthdays = " OR user_birthday LIKE '" . $db->sql_escape(sprintf('%2d-%2d-', 29, 2)) . "%'"; + } + $sql = 'SELECT u.user_id, u.username, u.user_colour, u.user_birthday FROM ' . USERS_TABLE . ' u LEFT JOIN ' . BANLIST_TABLE . " b ON (u.user_id = b.ban_userid) WHERE (b.ban_id IS NULL OR b.ban_exclude = 1) - AND u.user_birthday LIKE '" . $db->sql_escape(sprintf('%2d-%2d-', $now['mday'], $now['mon'])) . "%' + AND (u.user_birthday LIKE '" . $db->sql_escape(sprintf('%2d-%2d-', $now['mday'], $now['mon'])) . "%' $leap_year_birthdays) AND u.user_type IN (" . USER_NORMAL . ', ' . USER_FOUNDER . ')'; $result = $db->sql_query($sql); @@ -99,7 +107,7 @@ if ($config['load_birthdays'] && $config['allow_birthdays']) if ($age = (int) substr($row['user_birthday'], -4)) { - $birthday_list .= ' (' . ($now['year'] - $age) . ')'; + $birthday_list .= ' (' . max(0, $now['year'] - $age) . ')'; } } $db->sql_freeresult($result); diff --git a/phpBB/memberlist.php b/phpBB/memberlist.php index 351759fcbd..8169ee7a3e 100644 --- a/phpBB/memberlist.php +++ b/phpBB/memberlist.php @@ -1697,7 +1697,7 @@ function show_profile($data, $user_notes_enabled = false, $warn_user_enabled = f $diff = ($diff < 0) ? 1 : 0; } - $age = (int) ($now['year'] - $bday_year - $diff); + $age = max(0, (int) ($now['year'] - $bday_year - $diff)); } } diff --git a/phpBB/styles/prosilver/template/editor.js b/phpBB/styles/prosilver/template/editor.js index ddc862bb8c..cfdb54f54b 100644 --- a/phpBB/styles/prosilver/template/editor.js +++ b/phpBB/styles/prosilver/template/editor.js @@ -151,8 +151,10 @@ function insert_text(text, spaces, popup) { text = ' ' + text + ' '; } - - if (!isNaN(textarea.selectionStart)) + + // Since IE9, IE also has textarea.selectionStart, but it still needs to be treated the old way. + // Therefore we simply add a !is_ie here until IE fixes the text-selection completely. + if (!isNaN(textarea.selectionStart) && !is_ie) { var sel_start = textarea.selectionStart; var sel_end = textarea.selectionEnd; @@ -216,11 +218,12 @@ function addquote(post_id, username, l_wrote) } // Get text selection - not only the post content :( - if (window.getSelection) + // IE9 must use the document.selection method but has the *.getSelection so we just force no IE + if (window.getSelection && !is_ie) { theSelection = window.getSelection().toString(); } - else if (document.getSelection) + else if (document.getSelection && !is_ie) { theSelection = document.getSelection(); } diff --git a/phpBB/styles/prosilver/template/forum_fn.js b/phpBB/styles/prosilver/template/forum_fn.js index 4a85858df5..240fe7e51d 100644 --- a/phpBB/styles/prosilver/template/forum_fn.js +++ b/phpBB/styles/prosilver/template/forum_fn.js @@ -200,7 +200,7 @@ function selectCode(a) // Get ID of code block var e = a.parentNode.parentNode.getElementsByTagName('CODE')[0]; - // Not IE + // Not IE and IE9+ if (window.getSelection) { var s = window.getSelection(); diff --git a/phpBB/styles/prosilver/template/mcp_front.html b/phpBB/styles/prosilver/template/mcp_front.html index 0891948fb6..b71d120ed6 100644 --- a/phpBB/styles/prosilver/template/mcp_front.html +++ b/phpBB/styles/prosilver/template/mcp_front.html @@ -28,7 +28,6 @@ <dl> <dt> <a href="{unapproved.U_POST_DETAILS}" class="topictitle">{unapproved.SUBJECT}</a> {unapproved.ATTACH_ICON_IMG}<br /> - <!-- IF report.PAGINATION --><strong class="pagination"><span>{report.PAGINATION}</span></strong><!-- ENDIF --> {L_POSTED} {L_POST_BY_AUTHOR} {unapproved.AUTHOR_FULL} » {unapproved.POST_TIME} </dt> <dd class="moderation"><span> diff --git a/phpBB/styles/prosilver/template/mcp_notes_user.html b/phpBB/styles/prosilver/template/mcp_notes_user.html index c7c089ecad..7e92445476 100644 --- a/phpBB/styles/prosilver/template/mcp_notes_user.html +++ b/phpBB/styles/prosilver/template/mcp_notes_user.html @@ -78,7 +78,7 @@ <td style="text-align: center">{usernotes.REPORT_AT}</td> <td>{usernotes.ACTION}</td> - <!-- IF S_CLEAR_ALLOWED --><td width="5%" align="center"><input type="checkbox" name="marknote[]" id="note-{usernotes.ID}" value="{usernotes.ID}" /></td><!-- ENDIF --> + <!-- IF S_CLEAR_ALLOWED --><td style="width: 5%; text-align: center;"><input type="checkbox" name="marknote[]" id="note-{usernotes.ID}" value="{usernotes.ID}" /></td><!-- ENDIF --> </tr> <!-- BEGINELSE --> <tr> diff --git a/phpBB/styles/prosilver/template/memberlist_view.html b/phpBB/styles/prosilver/template/memberlist_view.html index 031bfec6ff..cfec07cff0 100644 --- a/phpBB/styles/prosilver/template/memberlist_view.html +++ b/phpBB/styles/prosilver/template/memberlist_view.html @@ -28,7 +28,7 @@ <!-- ENDIF --> <!-- IF S_USER_INACTIVE --><dt>{L_USER_IS_INACTIVE}:</dt> <dd>{USER_INACTIVE_REASON}</dd><!-- ENDIF --> <!-- IF LOCATION --><dt>{L_LOCATION}:</dt> <dd>{LOCATION}</dd><!-- ENDIF --> - <!-- IF AGE --><dt>{L_AGE}:</dt> <dd>{AGE}</dd><!-- ENDIF --> + <!-- IF AGE !== '' --><dt>{L_AGE}:</dt> <dd>{AGE}</dd><!-- ENDIF --> <!-- IF OCCUPATION --><dt>{L_OCCUPATION}:</dt> <dd>{OCCUPATION}</dd><!-- ENDIF --> <!-- IF INTERESTS --><dt>{L_INTERESTS}:</dt> <dd>{INTERESTS}</dd><!-- ENDIF --> <!-- IF S_GROUP_OPTIONS --><dt>{L_USERGROUPS}:</dt> <dd><select name="g">{S_GROUP_OPTIONS}</select> <input type="submit" name="submit" value="{L_GO}" class="button2" /></dd><!-- ENDIF --> @@ -89,8 +89,8 @@ <!-- IF POSTS_IN_QUEUE and U_MCP_QUEUE --><br />(<a href="{U_MCP_QUEUE}">{L_POSTS_IN_QUEUE}</a>)<!-- ELSEIF POSTS_IN_QUEUE --><br />({L_POSTS_IN_QUEUE})<!-- ENDIF --> </dd> <!-- IF S_SHOW_ACTIVITY and POSTS --> - <dt>{L_ACTIVE_IN_FORUM}:</dt> <dd><!-- IF ACTIVE_FORUM --><strong><a href="{U_ACTIVE_FORUM}">{ACTIVE_FORUM}</a></strong><br />({ACTIVE_FORUM_POSTS} / {ACTIVE_FORUM_PCT})<!-- ELSE --> - <!-- ENDIF --></dd> - <dt>{L_ACTIVE_IN_TOPIC}:</dt> <dd><!-- IF ACTIVE_TOPIC --><strong><a href="{U_ACTIVE_TOPIC}">{ACTIVE_TOPIC}</a></strong><br />({ACTIVE_TOPIC_POSTS} / {ACTIVE_TOPIC_PCT})<!-- ELSE --> - <!-- ENDIF --></dd> + <dt>{L_ACTIVE_IN_FORUM}:</dt> <dd><!-- IF ACTIVE_FORUM != '' --><strong><a href="{U_ACTIVE_FORUM}">{ACTIVE_FORUM}</a></strong><br />({ACTIVE_FORUM_POSTS} / {ACTIVE_FORUM_PCT})<!-- ELSE --> - <!-- ENDIF --></dd> + <dt>{L_ACTIVE_IN_TOPIC}:</dt> <dd><!-- IF ACTIVE_TOPIC != '' --><strong><a href="{U_ACTIVE_TOPIC}">{ACTIVE_TOPIC}</a></strong><br />({ACTIVE_TOPIC_POSTS} / {ACTIVE_TOPIC_PCT})<!-- ELSE --> - <!-- ENDIF --></dd> <!-- ENDIF --> </dl> </div> diff --git a/phpBB/styles/prosilver/template/overall_header.html b/phpBB/styles/prosilver/template/overall_header.html index e13c49b59a..a46c161542 100644 --- a/phpBB/styles/prosilver/template/overall_header.html +++ b/phpBB/styles/prosilver/template/overall_header.html @@ -68,7 +68,7 @@ { eval(onload_functions[i]); } - } + }; window.onunload = function() { @@ -76,7 +76,7 @@ { eval(onunload_functions[i]); } - } + }; // ]]> </script> diff --git a/phpBB/styles/subsilver2/template/editor.js b/phpBB/styles/subsilver2/template/editor.js index cd22812bab..7cc5de9034 100644 --- a/phpBB/styles/subsilver2/template/editor.js +++ b/phpBB/styles/subsilver2/template/editor.js @@ -151,8 +151,10 @@ function insert_text(text, spaces, popup) { text = ' ' + text + ' '; } - - if (!isNaN(textarea.selectionStart)) + + // Since IE9, IE also has textarea.selectionStart, but it still needs to be treated the old way. + // Therefore we simply add a !is_ie here until IE fixes the text-selection completely. + if (!isNaN(textarea.selectionStart) && !is_ie) { var sel_start = textarea.selectionStart; var sel_end = textarea.selectionEnd; @@ -218,11 +220,12 @@ function addquote(post_id, username, l_wrote) } // Get text selection - not only the post content :( - if (window.getSelection) + // IE9 must use the document.selection method but has the *.getSelection so we just force no IE + if (window.getSelection && !is_ie) { theSelection = window.getSelection().toString(); } - else if (document.getSelection) + else if (document.getSelection && !is_ie) { theSelection = document.getSelection(); } diff --git a/phpBB/styles/subsilver2/template/memberlist_view.html b/phpBB/styles/subsilver2/template/memberlist_view.html index 9ef2b85878..434d795895 100644 --- a/phpBB/styles/subsilver2/template/memberlist_view.html +++ b/phpBB/styles/subsilver2/template/memberlist_view.html @@ -89,11 +89,11 @@ <!-- IF S_SHOW_ACTIVITY --> <tr> <td class="gen" align="{S_CONTENT_FLOW_END}" valign="top" nowrap="nowrap">{L_ACTIVE_IN_FORUM}: </td> - <td><!-- IF ACTIVE_FORUM --><b><a class="gen" href="{U_ACTIVE_FORUM}">{ACTIVE_FORUM}</a></b><br /><span class="genmed">[ {ACTIVE_FORUM_POSTS} / {ACTIVE_FORUM_PCT} ]</span><!-- ELSE --><span class="gen">-</span><!-- ENDIF --></td> + <td><!-- IF ACTIVE_FORUM != '' --><b><a class="gen" href="{U_ACTIVE_FORUM}">{ACTIVE_FORUM}</a></b><br /><span class="genmed">[ {ACTIVE_FORUM_POSTS} / {ACTIVE_FORUM_PCT} ]</span><!-- ELSE --><span class="gen">-</span><!-- ENDIF --></td> </tr> <tr> <td class="gen" align="{S_CONTENT_FLOW_END}" valign="top" nowrap="nowrap">{L_ACTIVE_IN_TOPIC}: </td> - <td><!-- IF ACTIVE_TOPIC --><b><a class="gen" href="{U_ACTIVE_TOPIC}">{ACTIVE_TOPIC}</a></b><br /><span class="genmed">[ {ACTIVE_TOPIC_POSTS} / {ACTIVE_TOPIC_PCT} ]</span><!-- ELSE --><span class="gen">-</span><!-- ENDIF --></td> + <td><!-- IF ACTIVE_TOPIC != '' --><b><a class="gen" href="{U_ACTIVE_TOPIC}">{ACTIVE_TOPIC}</a></b><br /><span class="genmed">[ {ACTIVE_TOPIC_POSTS} / {ACTIVE_TOPIC_PCT} ]</span><!-- ELSE --><span class="gen">-</span><!-- ENDIF --></td> </tr> <!-- ENDIF --> </table> @@ -148,10 +148,10 @@ <td class="gen" align="{S_CONTENT_FLOW_END}" nowrap="nowrap">{L_LOCATION}: </td> <td><!-- IF LOCATION --><b class="genmed">{LOCATION}</b><!-- ENDIF --></td> </tr> - <!-- IF AGE --> + <!-- IF AGE !== '' --> <tr> <td class="gen" align="{S_CONTENT_FLOW_END}" nowrap="nowrap">{L_AGE}: </td> - <td><b class="genmed"><!-- IF AGE -->{AGE}<!-- ELSE --> - <!-- ENDIF --></b></td> + <td><b class="genmed">{AGE}</b></td> </tr> <!-- ENDIF --> <tr> diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php index f1ab30aad3..203b8586ce 100644 --- a/phpBB/viewtopic.php +++ b/phpBB/viewtopic.php @@ -196,7 +196,7 @@ if ($db->sql_layer === 'firebird') // The FROM-Order is quite important here, else t.* columns can not be correctly bound. if ($post_id) { - $sql_array['SELECT'] .= ', p.post_approved, p.post_time'; + $sql_array['SELECT'] .= ', p.post_approved, p.post_time, p.post_id'; $sql_array['FROM'][POSTS_TABLE] = 'p'; } @@ -317,8 +317,16 @@ if ($post_id) $sql = 'SELECT COUNT(p.post_id) AS prev_posts FROM ' . POSTS_TABLE . " p WHERE p.topic_id = {$topic_data['topic_id']} - " . ((!$auth->acl_get('m_approve', $forum_id)) ? 'AND p.post_approved = 1' : '') . ' - AND ' . (($sort_dir == 'd') ? "p.post_time >= {$topic_data['post_time']}" : "p.post_time <= {$topic_data['post_time']}"); + " . ((!$auth->acl_get('m_approve', $forum_id)) ? 'AND p.post_approved = 1' : ''); + + if ($sort_dir == 'd') + { + $sql .= " AND (p.post_time > {$topic_data['post_time']} OR (p.post_time = {$topic_data['post_time']} AND p.post_id >= {$topic_data['post_id']}))"; + } + else + { + $sql .= " AND (p.post_time < {$topic_data['post_time']} OR (p.post_time = {$topic_data['post_time']} AND p.post_id <= {$topic_data['post_id']}))"; + } $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); diff --git a/tests/dbal/db_tools_test.php b/tests/dbal/db_tools_test.php index ddea500f83..753cc08fc5 100644 --- a/tests/dbal/db_tools_test.php +++ b/tests/dbal/db_tools_test.php @@ -271,6 +271,66 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case 'foo' => array('UINT', 42))) ); + $this->assertTrue($this->tools->sql_table_exists('prefix_test_table')); + $this->tools->sql_table_drop('prefix_test_table'); + + $this->assertFalse($this->tools->sql_table_exists('prefix_test_table')); + } + + public function test_peform_schema_changes_drop_tables() + { + $db_tools = $this->getMock('phpbb_db_tools', array( + 'sql_table_exists', + 'sql_table_drop', + ), array(&$this->db)); + + // pretend all tables exist + $db_tools->expects($this->any())->method('sql_table_exists') + ->will($this->returnValue(true)); + + // drop tables + $db_tools->expects($this->exactly(2))->method('sql_table_drop'); + $db_tools->expects($this->at(1))->method('sql_table_drop') + ->with($this->equalTo('dropped_table_1')); + $db_tools->expects($this->at(3))->method('sql_table_drop') + ->with($this->equalTo('dropped_table_2')); + + $db_tools->perform_schema_changes(array( + 'drop_tables' => array( + 'dropped_table_1', + 'dropped_table_2', + ), + )); + } + + public function test_peform_schema_changes_drop_columns() + { + $db_tools = $this->getMock('phpbb_db_tools', array( + 'sql_column_exists', + 'sql_column_remove', + ), array(&$this->db)); + + // pretend all columns exist + $db_tools->expects($this->any())->method('sql_column_exists') + ->will($this->returnValue(true)); + $db_tools->expects($this->any())->method('sql_column_exists') + ->will($this->returnValue(true)); + + // drop columns + $db_tools->expects($this->exactly(2))->method('sql_column_remove'); + $db_tools->expects($this->at(1))->method('sql_column_remove') + ->with($this->equalTo('existing_table'), $this->equalTo('dropped_column_1')); + $db_tools->expects($this->at(3))->method('sql_column_remove') + ->with($this->equalTo('existing_table'), $this->equalTo('dropped_column_2')); + + $db_tools->perform_schema_changes(array( + 'drop_columns' => array( + 'existing_table' => array( + 'dropped_column_1', + 'dropped_column_2', + ), + ), + )); } } diff --git a/tests/error_collector_test.php b/tests/error_collector_test.php new file mode 100644 index 0000000000..e1ac32f5ac --- /dev/null +++ b/tests/error_collector_test.php @@ -0,0 +1,35 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +require_once dirname(__FILE__) . '/../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../phpBB/includes/error_collector.php'; + +class phpbb_error_collector_test extends phpbb_test_case +{ + public function test_collection() + { + $collector = new phpbb_error_collector; + $collector->install(); + + // Cause a warning + 1/0; $line = __LINE__; + + $collector->uninstall(); + + list($errno, $msg_text, $errfile, $errline) = $collector->errors[0]; + $error_contents = $collector->format_errors(); + + $this->assertEquals($errno, 2); + + // Unfortunately $error_contents will contain the full path here, + // because the tests directory is outside of phpbb root path. + $this->assertStringStartsWith('Errno 2: Division by zero at ', $error_contents); + $this->assertStringEndsWith(" line $line", $error_contents); + } +} diff --git a/tests/mock/cache.php b/tests/mock/cache.php index 11e525ff79..020574b0bb 100644 --- a/tests/mock/cache.php +++ b/tests/mock/cache.php @@ -41,6 +41,28 @@ class phpbb_mock_cache { return $this->data['_bots']; } + + /** + * Obtain list of word censors. We don't need to parse them here, + * that is tested elsewhere. + */ + public function obtain_word_list() + { + return array( + 'match' => array( + '#(?<![\\p{Nd}\\p{L}_-])([\\p{Nd}\\p{L}_-]*?badword1[\\p{Nd}\\p{L}_-]*?)(?![\\p{Nd}\\p{L}_-])#iu', + '#(?<![\\p{Nd}\\p{L}_-])([\\p{Nd}\\p{L}_-]*?badword2)(?![\\p{Nd}\\p{L}_-])#iu', + '#(?<![\\p{Nd}\\p{L}_-])(badword3[\\p{Nd}\\p{L}_-]*?)(?![\\p{Nd}\\p{L}_-])#iu', + '#(?<![\\p{Nd}\\p{L}_-])(badword4)(?![\\p{Nd}\\p{L}_-])#iu', + ), + 'replace' => array( + 'replacement1', + 'replacement2', + 'replacement3', + 'replacement4', + ), + ); + } public function set_bots($bots) { diff --git a/tests/mock_user.php b/tests/mock_user.php index 74d31c4c4a..5b89ea3e19 100644 --- a/tests/mock_user.php +++ b/tests/mock_user.php @@ -17,4 +17,20 @@ class phpbb_mock_user { public $host = "testhost"; public $page = array('root_script_path' => '/'); + + private $options = array(); + public function optionget($item) + { + if (!isset($this->options[$item])) + { + throw new Exception(sprintf("You didn't set the option '%s' on the mock user using optionset.", $item)); + } + + return $this->options[$item]; + } + + public function optionset($item, $value) + { + $this->options[$item] = $value; + } } diff --git a/tests/network/ftp_fsock_pasv_epsv_test.php b/tests/network/ftp_fsock_pasv_epsv_test.php new file mode 100644 index 0000000000..6ad811e3ca --- /dev/null +++ b/tests/network/ftp_fsock_pasv_epsv_test.php @@ -0,0 +1,63 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions_transfer.php'; + +/** +* @group slow +*/ +class phpbb_network_ftp_fsock_pasv_epsv_test extends phpbb_test_case +{ + static protected $ipv4; + + static public function setUpBeforeClass() + { + $hostname = 'ftp.debian.org.'; + self::$ipv4 = gethostbyname($hostname); + + if (self::$ipv4 == $hostname) + { + self::markTestSkipped("Got no A record back from DNS query for $hostname"); + } + } + + public function test_pasv() + { + // PASV + $this->assert_ls_contains_debian(self::$ipv4); + } + + public function test_epsv() + { + $ipv4 = self::$ipv4; + // EPSV + $this->assert_ls_contains_debian("[::ffff:$ipv4]"); + } + + protected function assert_ls_contains_debian($hostname) + { + $o = $this->get_object($hostname); + $result = $o->_init(); + // This test may fail on IPv6 addresses if IPv6 support is + // not available. PHP must be compiled with IPv6 support enabled, + // and your operating system must be configured for IPv6 as well. + if ($result !== true) + { + $this->markTestSkipped("Failed to connect to $hostname: $result"); + } + $this->assertContains('debian', $o->_ls()); + $o->_close(); + } + + protected function get_object($hostname) + { + return new ftp_fsock($hostname, 'anonymous', 'anonymous@localhost.tld', '/'); + } +} diff --git a/tests/profile/custom_test.php b/tests/profile/custom_test.php index 0e0a851243..585182e583 100644 --- a/tests/profile/custom_test.php +++ b/tests/profile/custom_test.php @@ -48,7 +48,7 @@ class phpbb_profile_custom_test extends phpbb_database_test_case ); $cp = new custom_profile; - $result = $cp->validate_profile_field(FIELD_DROPDOWN, &$field_value, $field_data); + $result = $cp->validate_profile_field(FIELD_DROPDOWN, $field_value, $field_data); $this->assertEquals($expected, $result, $description); } diff --git a/tests/session/append_sid_test.php b/tests/session/append_sid_test.php new file mode 100644 index 0000000000..1a3ad633e3 --- /dev/null +++ b/tests/session/append_sid_test.php @@ -0,0 +1,51 @@ +<?php
+/**
+*
+* @package testing
+* @copyright (c) 2011 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
+
+class phpbb_session_append_sid_test extends phpbb_test_case
+{
+
+ public function append_sid_data()
+ {
+ return array(
+ array('viewtopic.php?t=1&f=2', false, true, false, 'viewtopic.php?t=1&f=2', 'parameters in url-argument'),
+ array('viewtopic.php', 't=1&f=2', true, false, 'viewtopic.php?t=1&f=2', 'parameters in params-argument using amp'),
+ array('viewtopic.php', 't=1&f=2', false, false, 'viewtopic.php?t=1&f=2', 'parameters in params-argument using &'),
+ array('viewtopic.php', array('t' => 1, 'f' => 2), true, false, 'viewtopic.php?t=1&f=2', 'parameters in params-argument as array'),
+
+ // Custom sid parameter
+ array('viewtopic.php', 't=1&f=2', true, 'custom-sid', 'viewtopic.php?t=1&f=2&sid=custom-sid', 'using session_id'),
+
+ // Testing anchors
+ array('viewtopic.php?t=1&f=2#anchor', false, true, false, 'viewtopic.php?t=1&f=2#anchor', 'anchor in url-argument'),
+ array('viewtopic.php', 't=1&f=2#anchor', true, false, 'viewtopic.php?t=1&f=2#anchor', 'anchor in params-argument'),
+ array('viewtopic.php', array('t' => 1, 'f' => 2, '#' => 'anchor'), true, false, 'viewtopic.php?t=1&f=2#anchor', 'anchor in params-argument (array)'),
+
+ // Anchors and custom sid
+ array('viewtopic.php?t=1&f=2#anchor', false, true, 'custom-sid', 'viewtopic.php?t=1&f=2&sid=custom-sid#anchor', 'anchor in url-argument using session_id'),
+ array('viewtopic.php', 't=1&f=2#anchor', true, 'custom-sid', 'viewtopic.php?t=1&f=2&sid=custom-sid#anchor', 'anchor in params-argument using session_id'),
+ array('viewtopic.php', array('t' => 1, 'f' => 2, '#' => 'anchor'), true, 'custom-sid', 'viewtopic.php?t=1&f=2&sid=custom-sid#anchor', 'anchor in params-argument (array) using session_id'),
+
+ // Empty parameters should not append the ?
+ array('viewtopic.php', false, true, false, 'viewtopic.php', 'no params using bool false'),
+ array('viewtopic.php', '', true, false, 'viewtopic.php', 'no params using empty string'),
+ array('viewtopic.php', array(), true, false, 'viewtopic.php', 'no params using empty array'),
+ );
+ }
+
+ /**
+ * @dataProvider append_sid_data
+ */
+ public function test_append_sid($url, $params, $is_amp, $session_id, $expected, $description)
+ {
+ $this->assertEquals($expected, append_sid($url, $params, $is_amp, $session_id));
+ }
+}
+
diff --git a/tests/template/template_test.php b/tests/template/template_test.php index 33c82d53ad..5005710220 100644 --- a/tests/template/template_test.php +++ b/tests/template/template_test.php @@ -63,9 +63,10 @@ class phpbb_template_template_test extends phpbb_test_case // Test the engine can be used $this->setup_engine(); - if (!is_writable(dirname($this->template->cachepath))) + $template_cache_dir = dirname($this->template->cachepath); + if (!is_writable($template_cache_dir)) { - $this->markTestSkipped("Template cache directory is not writable."); + $this->markTestSkipped("Template cache directory ({$template_cache_dir}) is not writable."); } foreach (glob($this->template->cachepath . '*') as $file) diff --git a/tests/text_processing/censor_text_test.php b/tests/text_processing/censor_text_test.php new file mode 100644 index 0000000000..2843f0b20b --- /dev/null +++ b/tests/text_processing/censor_text_test.php @@ -0,0 +1,85 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; +require_once dirname(__FILE__) . '/../mock_user.php'; +require_once dirname(__FILE__) . '/../mock/cache.php'; + +class phpbb_text_processing_censor_text_test extends phpbb_test_case +{ + public function censor_text_data() + { + global $cache, $user; + $cache = new phpbb_mock_cache; + $user = new phpbb_mock_user; + + $user->optionset('viewcensors', false); + + return array( + array('', ''), + + array('badword1', 'replacement1'), + array(' badword1', ' replacement1'), + array('badword1 ', 'replacement1 '), + array(' badword1 ', ' replacement1 '), + array('abadword1', 'replacement1'), + array('badword1w', 'replacement1'), + array('abadword1w', 'replacement1'), + array('anotherbadword1test', 'replacement1'), + array('this badword1', 'this replacement1'), + array('this badword1 word', 'this replacement1 word'), + + array('badword2', 'replacement2'), + array('bbadword2', 'replacement2'), + array('bbbadword2', 'replacement2'), + array('badword2d', 'badword2d'), + array('bbadword2d', 'bbadword2d'), + array('test badword2', 'test replacement2'), + array('test badword2 word', 'test replacement2 word'), + + array('badword3', 'replacement3'), + array('bbadword3', 'bbadword3'), + array('badword3d', 'replacement3'), + array('badword3ddd', 'replacement3'), + array('bbadword3d', 'bbadword3d'), + array(' badword3 ', ' replacement3 '), + array(' badword3', ' replacement3'), + + array('badword4', 'replacement4'), + array('this badword4 word', 'this replacement4 word'), + array('abadword4', 'abadword4'), + array('badword4d', 'badword4d'), + array('abadword4d', 'abadword4d'), + + array('badword1 badword2 badword3 badword4', 'replacement1 replacement2 replacement3 replacement4'), + array('badword1 badword2 badword3 badword4d', 'replacement1 replacement2 replacement3 badword4d'), + array('abadword1 badword2 badword3 badword4', 'replacement1 replacement2 replacement3 replacement4'), + + array("new\nline\ntest", "new\nline\ntest"), + array("tab\ttest\t", "tab\ttest\t"), + array('öäü', 'öäü'), + array('badw' . chr(1) . 'ord1', 'badw' . chr(1) . 'ord1'), + array('badw' . chr(2) . 'ord1', 'badw' . chr(2) . 'ord1'), + array('badw' . chr(3) . 'ord1', 'badw' . chr(3) . 'ord1'), + array('badw' . chr(4) . 'ord1', 'badw' . chr(4) . 'ord1'), + array('badw' . chr(5) . 'ord1', 'badw' . chr(5) . 'ord1'), + array('badw' . chr(6) . 'ord1', 'badw' . chr(6) . 'ord1'), + ); + } + + /** + * @dataProvider censor_text_data + */ + public function test_censor_text($input, $expected) + { + $label = 'Testing word censor: ' . $input; + $this->assertEquals($expected, censor_text($input), $label); + } +} diff --git a/tests/utf/data/.gitkeep b/tests/tmp/.gitkeep index e69de29bb2..e69de29bb2 100644 --- a/tests/utf/data/.gitkeep +++ b/tests/tmp/.gitkeep diff --git a/tests/utf/normalizer_test.php b/tests/utf/normalizer_test.php index f78dba8004..f8f2467082 100644 --- a/tests/utf/normalizer_test.php +++ b/tests/utf/normalizer_test.php @@ -14,10 +14,13 @@ require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_normalizer.php'; */ class phpbb_utf_normalizer_test extends phpbb_test_case { + static private $data_dir; + static public function setUpBeforeClass() { - self::download('http://www.unicode.org/Public/UNIDATA/NormalizationTest.txt', dirname(__FILE__).'/data'); - self::download('http://www.unicode.org/Public/UNIDATA/UnicodeData.txt', dirname(__FILE__).'/data'); + self::$data_dir = dirname(__file__) . '/../tmp'; + self::download('http://www.unicode.org/Public/UNIDATA/NormalizationTest.txt', self::$data_dir); + self::download('http://www.unicode.org/Public/UNIDATA/UnicodeData.txt', self::$data_dir); } public function test_normalizer() @@ -62,7 +65,7 @@ class phpbb_utf_normalizer_test extends phpbb_test_case $tested_chars = array(); - $fp = fopen(dirname(__FILE__).'/data/NormalizationTest.txt', 'rb'); + $fp = fopen(self::$data_dir . '/NormalizationTest.txt', 'rb'); while (!feof($fp)) { $line = fgets($fp); @@ -99,7 +102,7 @@ class phpbb_utf_normalizer_test extends phpbb_test_case foreach ($tests as $test) { $utf_result = $utf_expected; - call_user_func(array('utf_normalizer', $form), &$utf_result); + call_user_func(array('utf_normalizer', $form), $utf_result); $hex_result = $this->utf_to_hexseq($utf_result); $this->assertEquals($utf_expected, $utf_result, "$expected == $form($test) ($hex_expected != $hex_result)"); @@ -117,7 +120,7 @@ class phpbb_utf_normalizer_test extends phpbb_test_case */ public function test_invariants(array $tested_chars) { - $fp = fopen(dirname(__FILE__).'/data/UnicodeData.txt', 'rb'); + $fp = fopen(self::$data_dir . '/UnicodeData.txt', 'rb'); while (!feof($fp)) { @@ -151,7 +154,7 @@ class phpbb_utf_normalizer_test extends phpbb_test_case foreach (array('nfc', 'nfkc', 'nfd', 'nfkd') as $form) { $utf_result = $utf_expected; - call_user_func(array('utf_normalizer', $form), &$utf_result); + call_user_func(array('utf_normalizer', $form), $utf_result); $hex_result = $this->utf_to_hexseq($utf_result); $this->assertEquals($utf_expected, $utf_result, "$hex_expected == $form($hex_tested) ($hex_expected != $hex_result)"); |