Merge branch 'develop' of git://github.com/phpbb/phpbb3 into feature/new-tz-handling

This commit is contained in:
Joas Schilling 2012-07-18 11:07:32 +02:00
commit f4136eacdc
124 changed files with 2739 additions and 300 deletions

View file

@ -9,8 +9,8 @@ env:
- DB=postgres
before_script:
- sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'DROP DATABASE IF EXISTS phpbb_tests;' -U postgres; fi"
- sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'create database phpbb_tests;' -U postgres; fi"
- sh -c "if [ '$DB' = 'postgres' ]; then psql -c 'DROP DATABASE IF EXISTS phpbb_tests;' -U postgres; fi"
- sh -c "if [ '$DB' = 'postgres' ]; then psql -c 'create database phpbb_tests;' -U postgres; fi"
- sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'create database IF NOT EXISTS phpbb_tests;'; fi"
- pyrus install --force phpunit/DbUnit
- phpenv rehash

View file

@ -45,13 +45,7 @@
<target name="composer" depends="clean,prepare">
<exec dir="./phpBB/"
command="curl -s http://getcomposer.org/installer | php"
passthru="true" />
<exec dir="./phpBB/"
command="php composer.phar install"
passthru="true" />
<exec dir="./phpBB/"
command="rm composer.phar"
command="php ../composer.phar install"
passthru="true" />
</target>
@ -169,13 +163,7 @@
checkreturn="true" />
<exec dir="${dir}"
command="curl -s http://getcomposer.org/installer | php"
passthru="true" />
<exec dir="${dir}"
command="php composer.phar install"
passthru="true" />
<exec dir="${dir}"
command="rm composer.phar"
command="php ../composer.phar install"
passthru="true" />
<delete file="${dir}/config.php" />

BIN
composer.phar Executable file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

View file

@ -146,15 +146,15 @@ li {
#page-header {
clear: both;
text-align: right;
background: url("../images/phpbb_logo.gif") top left no-repeat;
height: 49px;
background: url("../images/phpbb_logo.png") top left no-repeat;
height: 54px;
font-size: 0.85em;
margin-bottom: 10px;
}
.rtl #page-header {
text-align: left;
background: url("../images/phpbb_logo.gif") top right no-repeat;
background: url("../images/phpbb_logo.png") top right no-repeat;
}
#page-header h1 {

View file

@ -521,14 +521,47 @@ phpbb.add_ajax_callback = function(id, callback)
* the alt-text data attribute, and replaces the text in the attribute with the
* current text so that the process can be repeated.
*/
phpbb.add_ajax_callback('alt_text', function(data) {
phpbb.add_ajax_callback('alt_text', function() {
var el = $(this),
alt_text;
alt_text = el.attr('data-alt-text');
el.attr('data-alt-text', el.text());
el.attr('title', alt_text);
el.text(alt_text);
});
/**
* This callback is based on the alt_text callback.
*
* It replaces the current text with the text in the alt-text data attribute,
* and replaces the text in the attribute with the current text so that the
* process can be repeated.
* Additionally it replaces the class of the link's parent
* and changes the link itself.
*/
phpbb.add_ajax_callback('toggle_link', function() {
var el = $(this),
toggle_text,
toggle_url,
toggle_class;
// Toggle link text
toggle_text = el.attr('data-toggle-text');
el.attr('data-toggle-text', el.text());
el.attr('title', toggle_text);
el.text(toggle_text);
// Toggle link url
toggle_url = el.attr('data-toggle-url');
el.attr('data-toggle-url', el.attr('href'));
el.attr('href', toggle_url);
// Toggle class of link parent
toggle_class = el.attr('data-toggle-class');
el.attr('data-toggle-class', el.parent().attr('class'));
el.parent().attr('class', toggle_class);
});
})(jQuery); // Avoid conflicts with other libraries

View file

@ -237,7 +237,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', 'wb');
$line = '';

View file

@ -132,7 +132,7 @@
<ul>
<li>MySQL 3.23 or above (MySQLi supported)</li>
<li>PostgreSQL 7.3+</li>
<li>SQLite 2.8.2+</li>
<li>SQLite 2.8.2+ (SQLite 3 is not supported)</li>
<li>Firebird 2.1+</li>
<li>MS SQL Server 2000 or above (directly or via ODBC or the native adapter)</li>
<li>Oracle</li>

View file

@ -295,11 +295,17 @@ PHPBB_QA (Set board to QA-Mode, which means the updater also c
<p>We will not be using any form of hungarian notation in our naming conventions. Many of us believe that hungarian naming is one of the primary code obfuscation techniques currently in use.</p>
<h4>Variable Names:</h4>
<p>Variable names should be in all lowercase, with words separated by an underscore, example:</p>
<p>In PHP, variable names should be in all lowercase, with words separated by an underscore, example:</p>
<div class="indent">
<p><code>$current_user</code> is right, but <code>$currentuser</code> and <code> $currentUser</code> are not.</p>
</div>
<p>In JavaScript, variable names should use camel case:</p>
<div class="indent">
<p><code>currentUser</code> is right, but <code>currentuser</code> and <code>current_user</code> are not.</p>
</div>
<p>Names should be descriptive, but concise. We don't want huge sentences as our variable names, but typing an extra couple of characters is always better than wondering what exactly a certain variable is for. </p>
@ -317,7 +323,7 @@ for ($i = 0; $i &lt; $outer_size; $i++)
</pre></div>
<h4>Function Names:</h4>
<p>Functions should also be named descriptively. We're not programming in C here, we don't want to write functions called things like "stristr()". Again, all lower-case names with words separated by a single underscore character. Function names should preferably have a verb in them somewhere. Good function names are <code>print_login_status()</code>, <code>get_user_data()</code>, etc. </p>
<p>Functions should also be named descriptively. We're not programming in C here, we don't want to write functions called things like "stristr()". Again, all lower-case names with words separated by a single underscore character in PHP, and camel caps in JavaScript. Function names should preferably have a verb in them somewhere. Good function names are <code>print_login_status()</code>, <code>get_user_data()</code>, etc. Constructor functions in JavaScript should begin with a capital letter.</p>
<h4>Function Arguments:</h4>
<p>Arguments are subject to the same guidelines as variable names. We don't want a bunch of functions like: <code>do_stuff($a, $b, $c)</code>. In most cases, we'd like to be able to tell how to use a function by just looking at its declaration. </p>
@ -397,7 +403,7 @@ for ($i = 0; $i &lt; size; $i++)
</pre></div>
<h4>Where to put the braces:</h4>
<p>This one is a bit of a holy war, but we're going to use a style that can be summed up in one sentence: Braces always go on their own line. The closing brace should also always be at the same column as the corresponding opening brace, examples:</p>
<p>In PHP code, braces always go on their own line. The closing brace should also always be at the same column as the corresponding opening brace, examples:</p>
<div class="codebox"><pre>
if (condition)
@ -427,6 +433,30 @@ function do_stuff()
...
}
</pre></div>
<p>In JavaScript code, braces always go on the same line:</p>
<div class="codebox"><pre>
if (condition) {
while (condition2) {
...
}
} else {
...
}
for (var i = 0; i &lt; size; i++) {
...
}
while (condition) {
...
}
function do_stuff() {
...
}
</pre></div>
<h4>Use spaces between tokens:</h4>
<p>This is another simple, easy step that helps keep code readable without much effort. Whenever you write an assignment, expression, etc.. Always leave <em>one</em> space between the tokens. Basically, write code as if it was English. Put spaces between variable names and operators. Don't put spaces just after an opening bracket or before a closing bracket. Don't put spaces just before a comma or a semicolon. This is best shown with a few examples, examples:</p>
@ -502,7 +532,7 @@ $post_url = "{$phpbb_root_path}posting.$phpEx?mode=$mode&amp;amp;start=$start";
<p>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.</p>
<h4>Commas after every array element:</h4>
<p>If an array is defined with each element on its own line, you still have to modify the previous line to add a comma when appending a new element. PHP allows for trailing (useless) commas in array definitions. These should always be used so each element including the comma can be appended with a single line</p>
<p>If an array is defined with each element on its own line, you still have to modify the previous line to add a comma when appending a new element. PHP allows for trailing (useless) commas in array definitions. These should always be used so each element including the comma can be appended with a single line. In JavaScript, do not use the trailing comma, as it causes browsers to throw errors.</p>
<p class="bad">// wrong</p>
<div class="codebox"><pre>

View file

@ -136,6 +136,8 @@ class acp_inactive
add_log('admin', 'LOG_USER_ACTIVE', $row['username']);
add_log('user', $row['user_id'], 'LOG_USER_ACTIVE_USER');
}
trigger_error(sprintf($user->lang['LOG_INACTIVE_ACTIVATE'], implode($user->lang['COMMA_SEPARATOR'], $user_affected) . ' ' . adm_back_link($this->u_action)));
}
// For activate we really need to redirect, else a refresh can result in users being deactivated again
@ -159,6 +161,8 @@ class acp_inactive
}
add_log('admin', 'LOG_INACTIVE_' . strtoupper($action), implode(', ', $user_affected));
trigger_error(sprintf($user->lang['LOG_INACTIVE_DELETE'], implode($user->lang['COMMA_SEPARATOR'], $user_affected) . ' ' . adm_back_link($this->u_action)));
}
else
{
@ -230,7 +234,8 @@ class acp_inactive
$db->sql_query($sql);
add_log('admin', 'LOG_INACTIVE_REMIND', implode(', ', $usernames));
unset($usernames);
trigger_error(sprintf($user->lang['LOG_INACTIVE_REMIND'], implode($user->lang['COMMA_SEPARATOR'], $usernames) . ' ' . adm_back_link($this->u_action)));
}
$db->sql_freeresult($result);

View file

@ -130,7 +130,7 @@ class bbcode
if (empty($this->template_filename))
{
$this->template_bitfield = new bitfield($user->theme['bbcode_bitfield']);
$this->template_bitfield = new bitfield($user->style['bbcode_bitfield']);
$style_resource_locator = new phpbb_style_resource_locator();
$style_path_provider = new phpbb_style_extension_path_provider($phpbb_extension_manager, new phpbb_style_path_provider());

View file

@ -321,50 +321,39 @@ class phpbb_cache_service
/**
* Obtain cfg file data
*/
function obtain_cfg_items($theme)
function obtain_cfg_items($style)
{
global $config, $phpbb_root_path;
$parsed_items = array(
'theme' => array(),
'template' => array(),
'imageset' => array()
);
$parsed_array = $this->driver->get('_cfg_' . $style['style_path']);
foreach ($parsed_items as $key => $parsed_array)
if ($parsed_array === false)
{
$parsed_array = $this->driver->get('_cfg_' . $key . '_' . $theme[$key . '_path']);
if ($parsed_array === false)
{
$parsed_array = array();
}
$reparse = false;
$filename = $phpbb_root_path . 'styles/' . $theme[$key . '_path'] . '/' . $key . '/' . $key . '.cfg';
if (!file_exists($filename))
{
continue;
}
if (!isset($parsed_array['filetime']) || (($config['load_tplcompile'] && @filemtime($filename) > $parsed_array['filetime'])))
{
$reparse = true;
}
// Re-parse cfg file
if ($reparse)
{
$parsed_array = parse_cfg_file($filename);
$parsed_array['filetime'] = @filemtime($filename);
$this->driver->put('_cfg_' . $key . '_' . $theme[$key . '_path'], $parsed_array);
}
$parsed_items[$key] = $parsed_array;
$parsed_array = array();
}
return $parsed_items;
$reparse = false;
$filename = $phpbb_root_path . 'styles/' . $style['style_path'] . '/style.cfg';
if (!file_exists($filename))
{
continue;
}
if (!isset($parsed_array['filetime']) || (($config['load_tplcompile'] && @filemtime($filename) > $parsed_array['filetime'])))
{
$reparse = true;
}
// Re-parse cfg file
if ($reparse)
{
$parsed_array = parse_cfg_file($filename);
$parsed_array['filetime'] = @filemtime($filename);
$this->driver->put('_cfg_' . $style['style_path'], $parsed_array);
}
return $parsed_array;
}
/**

View file

@ -283,6 +283,37 @@ class dbal
return $this->_sql_like_expression('LIKE \'' . $this->sql_escape($expression) . '\'');
}
/**
* Build a case expression
*
* Note: The two statements action_true and action_false must have the same data type (int, vchar, ...) in the database!
*
* @param string $condition The condition which must be true, to use action_true rather then action_else
* @param string $action_true SQL expression that is used, if the condition is true
* @param string $action_else SQL expression that is used, if the condition is false, optional
* @return string CASE expression including the condition and statements
*/
public function sql_case($condition, $action_true, $action_false = false)
{
$sql_case = 'CASE WHEN ' . $condition;
$sql_case .= ' THEN ' . $action_true;
$sql_case .= ($action_false !== false) ? ' ELSE ' . $action_false : '';
$sql_case .= ' END';
return $sql_case;
}
/**
* Build a concatenated expression
*
* @param string $expr1 Base SQL expression where we append the second one
* @param string $expr2 SQL expression that is appended to the first expression
* @return string Concatenated string
*/
public function sql_concatenate($expr1, $expr2)
{
return $expr1 . ' || ' . $expr2;
}
/**
* Returns whether results of a query need to be buffered to run a transaction while iterating over them.
*

View file

@ -91,6 +91,14 @@ class dbal_mssql extends dbal
return ($this->sql_server_version) ? 'MSSQL<br />' . $this->sql_server_version : 'MSSQL';
}
/**
* {@inheritDoc}
*/
public function sql_concatenate($expr1, $expr2)
{
return $expr1 . ' + ' . $expr2;
}
/**
* SQL Transaction
* @access private

View file

@ -109,6 +109,14 @@ class dbal_mssql_odbc extends dbal
return ($this->sql_server_version) ? 'MSSQL (ODBC)<br />' . $this->sql_server_version : 'MSSQL (ODBC)';
}
/**
* {@inheritDoc}
*/
public function sql_concatenate($expr1, $expr2)
{
return $expr1 . ' + ' . $expr2;
}
/**
* SQL Transaction
* @access private

View file

@ -257,6 +257,14 @@ class dbal_mssqlnative extends dbal
return ($this->sql_server_version) ? 'MSSQL<br />' . $this->sql_server_version : 'MSSQL';
}
/**
* {@inheritDoc}
*/
public function sql_concatenate($expr1, $expr2)
{
return $expr1 . ' + ' . $expr2;
}
/**
* {@inheritDoc}
*/
@ -435,7 +443,7 @@ class dbal_mssqlnative extends dbal
unset($row['line2'], $row['line3']);
}
}
return $row;
return (sizeof($row)) ? $row : false;
}
/**

View file

@ -119,6 +119,14 @@ class dbal_mysql extends dbal
return ($raw) ? $this->sql_server_version : 'MySQL ' . $this->sql_server_version;
}
/**
* {@inheritDoc}
*/
public function sql_concatenate($expr1, $expr2)
{
return 'CONCAT(' . $expr1 . ', ' . $expr2 . ')';
}
/**
* SQL Transaction
* @access private

View file

@ -122,6 +122,14 @@ class dbal_mysqli extends dbal
return ($raw) ? $this->sql_server_version : 'MySQL(i) ' . $this->sql_server_version;
}
/**
* {@inheritDoc}
*/
public function sql_concatenate($expr1, $expr2)
{
return 'CONCAT(' . $expr1 . ', ' . $expr2 . ')';
}
/**
* SQL Transaction
* @access private

View file

@ -4922,9 +4922,9 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
'T_ASSETS_VERSION' => $config['assets_version'],
'T_ASSETS_PATH' => "{$web_path}assets",
'T_THEME_PATH' => "{$web_path}styles/" . rawurlencode($user->theme['style_path']) . '/theme',
'T_TEMPLATE_PATH' => "{$web_path}styles/" . rawurlencode($user->theme['style_path']) . '/template',
'T_SUPER_TEMPLATE_PATH' => "{$web_path}styles/" . rawurlencode($user->theme['style_path']) . '/template',
'T_THEME_PATH' => "{$web_path}styles/" . rawurlencode($user->style['style_path']) . '/theme',
'T_TEMPLATE_PATH' => "{$web_path}styles/" . rawurlencode($user->style['style_path']) . '/template',
'T_SUPER_TEMPLATE_PATH' => "{$web_path}styles/" . rawurlencode($user->style['style_path']) . '/template',
'T_IMAGES_PATH' => "{$web_path}images/",
'T_SMILIES_PATH' => "{$web_path}{$config['smilies_path']}/",
'T_AVATAR_PATH' => "{$web_path}{$config['avatar_path']}/",
@ -4932,16 +4932,15 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
'T_ICONS_PATH' => "{$web_path}{$config['icons_path']}/",
'T_RANKS_PATH' => "{$web_path}{$config['ranks_path']}/",
'T_UPLOAD_PATH' => "{$web_path}{$config['upload_path']}/",
'T_STYLESHEET_LINK' => "{$web_path}styles/" . rawurlencode($user->theme['style_path']) . '/theme/stylesheet.css?assets_version=' . $config['assets_version'],
'T_STYLESHEET_LANG_LINK' => "{$web_path}styles/" . rawurlencode($user->theme['style_path']) . '/theme/' . $user->lang_name . '/stylesheet.css?assets_version=' . $config['assets_version'],
'T_STYLESHEET_NAME' => $user->theme['style_name'],
'T_STYLESHEET_LINK' => "{$web_path}styles/" . rawurlencode($user->style['style_path']) . '/theme/stylesheet.css?assets_version=' . $config['assets_version'],
'T_STYLESHEET_LANG_LINK' => "{$web_path}styles/" . rawurlencode($user->style['style_path']) . '/theme/' . $user->lang_name . '/stylesheet.css?assets_version=' . $config['assets_version'],
'T_JQUERY_LINK' => ($config['load_jquery_cdn'] && !empty($config['load_jquery_url'])) ? $config['load_jquery_url'] : "{$web_path}assets/javascript/jquery.js?assets_version=" . $config['assets_version'],
'S_JQUERY_FALLBACK' => ($config['load_jquery_cdn']) ? true : false,
'T_THEME_NAME' => rawurlencode($user->theme['style_path']),
'T_THEME_NAME' => rawurlencode($user->style['style_path']),
'T_THEME_LANG_NAME' => $user->data['user_lang'],
'T_TEMPLATE_NAME' => $user->theme['style_path'],
'T_SUPER_TEMPLATE_NAME' => rawurlencode((isset($user->theme['style_parent_tree']) && $user->theme['style_parent_tree']) ? $user->theme['style_parent_tree'] : $user->theme['style_path']),
'T_TEMPLATE_NAME' => $user->style['style_path'],
'T_SUPER_TEMPLATE_NAME' => rawurlencode((isset($user->style['style_parent_tree']) && $user->style['style_parent_tree']) ? $user->style['style_parent_tree'] : $user->style['style_path']),
'T_IMAGES' => 'images',
'T_SMILIES' => $config['smilies_path'],
'T_AVATAR' => $config['avatar_path'],
@ -5137,3 +5136,16 @@ function phpbb_pcre_utf8_support()
}
return $utf8_pcre_properties;
}
/**
* Casts a numeric string $input to an appropriate numeric type (i.e. integer or float)
*
* @param string $input A numeric string.
*
* @return int|float Integer $input if $input fits integer,
* float $input otherwise.
*/
function phpbb_to_numeric($input)
{
return ($input > PHP_INT_MAX) ? (float) $input : (int) $input;
}

View file

@ -1221,7 +1221,9 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id,
if ($can_watch)
{
$s_watching['link'] = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&amp;" . (($is_watching) ? 'unwatch' : 'watch') . "=$mode&amp;start=$start&amp;hash=" . generate_link_hash("{$mode}_$match_id"));
$s_watching['link_toggle'] = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&amp;" . ((!$is_watching) ? 'unwatch' : 'watch') . "=$mode&amp;start=$start&amp;hash=" . generate_link_hash("{$mode}_$match_id"));
$s_watching['title'] = $user->lang[(($is_watching) ? 'STOP' : 'START') . '_WATCHING_' . strtoupper($mode)];
$s_watching['title_toggle'] = $user->lang[((!$is_watching) ? 'STOP' : 'START') . '_WATCHING_' . strtoupper($mode)];
$s_watching['is_watching'] = $is_watching;
}

View file

@ -463,17 +463,21 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix,
}
/**
* Removes comments from schema files
* Removes "/* style" as well as "# style" comments from $input.
*
* @param string $input Input string
*
* @return string Input string with comments removed
*/
function remove_comments($sql)
function phpbb_remove_comments($input)
{
// Remove /* */ comments (http://ostermiller.org/findcomment.html)
$sql = preg_replace('#/\*(.|[\r\n])*?\*/#', "\n", $sql);
$input = preg_replace('#/\*(.|[\r\n])*?\*/#', "\n", $input);
// Remove # style comments
$sql = preg_replace('/\n{2,}/', "\n", preg_replace('/^#.*$/m', "\n", $sql));
$input = preg_replace('/\n{2,}/', "\n", preg_replace('/^#.*$/m', "\n", $input));
return $sql;
return $input;
}
/**

View file

@ -1657,8 +1657,8 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
// First of all make sure the subject and topic title are having the correct length.
// To achieve this without cutting off between special chars we convert to an array and then count the elements.
$subject = truncate_string($subject);
$data['topic_title'] = truncate_string($data['topic_title']);
$subject = truncate_string($subject, 120);
$data['topic_title'] = truncate_string($data['topic_title'], 120);
// Collect some basic information about which tables and which rows to update/insert
$sql_data = $topic_row = array();

View file

@ -151,7 +151,8 @@ class filespec
*/
function is_image()
{
return (strpos($this->mimetype, 'image/') !== false) ? true : false;
$mimetype = $this->get_mimetype($this->filename);
return (strpos($mimetype, 'image/') === 0);
}
/**
@ -200,17 +201,12 @@ class filespec
}
/**
* Get mimetype. Utilize mime_content_type if the function exist.
* Not used at the moment...
* Get mimetype. Utilises the finfo class.
*/
function get_mimetype($filename)
{
$mimetype = '';
if (function_exists('mime_content_type'))
{
$mimetype = mime_content_type($filename);
}
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mimetype = $finfo->file($filename);
// Some browsers choke on a mimetype of application/octet-stream
if (!$mimetype || $mimetype == 'application/octet-stream')
@ -342,6 +338,7 @@ class filespec
// Remove temporary filename
@unlink($this->filename);
$this->filename = $this->destination_file;
if (sizeof($this->error))
{

175
phpBB/includes/php/ini.php Normal file
View file

@ -0,0 +1,175 @@
<?php
/**
*
* @package phpBB
* @copyright (c) 2011 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Wrapper class for ini_get function.
*
* Provides easier handling of the different interpretations of ini values.
*
* @package phpBB
*/
class phpbb_php_ini
{
/**
* Simple wrapper for ini_get()
* See http://php.net/manual/en/function.ini-get.php
*
* @param string $varname The configuration option name.
* @return bool|string False if configuration option does not exist,
* the configuration option value (string) otherwise.
*/
public function get($varname)
{
return ini_get($varname);
}
/**
* Gets the configuration option value as a trimmed string.
*
* @param string $varname The configuration option name.
* @return bool|string False if configuration option does not exist,
* the configuration option value (string) otherwise.
*/
public function get_string($varname)
{
$value = $this->get($varname);
if ($value === false)
{
return false;
}
return trim($value);
}
/**
* Gets configuration option value as a boolean.
* Interprets the string value 'off' as false.
*
* @param string $varname The configuration option name.
* @return bool False if configuration option does not exist.
* False if configuration option is disabled.
* True otherwise.
*/
public function get_bool($varname)
{
$value = $this->get_string($varname);
if (empty($value) || strtolower($value) == 'off')
{
return false;
}
return true;
}
/**
* Gets configuration option value as an integer.
*
* @param string $varname The configuration option name.
* @return bool|int False if configuration option does not exist,
* false if configuration option value is not numeric,
* the configuration option value (integer) otherwise.
*/
public function get_int($varname)
{
$value = $this->get_string($varname);
if (!is_numeric($value))
{
return false;
}
return (int) $value;
}
/**
* Gets configuration option value as a float.
*
* @param string $varname The configuration option name.
* @return bool|float False if configuration option does not exist,
* false if configuration option value is not numeric,
* the configuration option value (float) otherwise.
*/
public function get_float($varname)
{
$value = $this->get_string($varname);
if (!is_numeric($value))
{
return false;
}
return (float) $value;
}
/**
* Gets configuration option value in bytes.
* Converts strings like '128M' to bytes (integer or float).
*
* @param string $varname The configuration option name.
* @return bool|int|float False if configuration option does not exist,
* false if configuration option value is not well-formed,
* the configuration option value otherwise.
*/
public function get_bytes($varname)
{
$value = $this->get_string($varname);
if ($value === false)
{
return false;
}
if (is_numeric($value))
{
// Already in bytes.
return phpbb_to_numeric($value);
}
else if (strlen($value) < 2)
{
// Single character.
return false;
}
else if (strlen($value) < 3 && $value[0] === '-')
{
// Two characters but the first one is a minus.
return false;
}
$value_lower = strtolower($value);
$value_numeric = phpbb_to_numeric($value);
switch ($value_lower[strlen($value_lower) - 1])
{
case 'g':
$value_numeric *= 1024;
case 'm':
$value_numeric *= 1024;
case 'k':
$value_numeric *= 1024;
break;
default:
// It's not already in bytes (and thus numeric)
// and does not carry a unit.
return false;
}
return $value_numeric;
}
}

View file

@ -27,8 +27,6 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
var $split_words = array();
var $search_query;
var $common_words = array();
var $pcre_properties = false;
var $mbstring_regex = false;
public function __construct(&$error)
{
@ -36,18 +34,6 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
$this->word_length = array('min' => $config['fulltext_mysql_min_word_len'], 'max' => $config['fulltext_mysql_max_word_len']);
// PHP may not be linked with the bundled PCRE lib and instead with an older version
if (phpbb_pcre_utf8_support())
{
$this->pcre_properties = true;
}
if (function_exists('mb_ereg'))
{
$this->mbstring_regex = true;
mb_regex_encoding('UTF-8');
}
$error = false;
}
@ -70,7 +56,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
if ($db->sql_layer != 'mysql4' && $db->sql_layer != 'mysqli')
{
return $user->lang['FULLTEXT_MYSQL_INCOMPATIBLE_VERSION'];
return $user->lang['FULLTEXT_MYSQL_INCOMPATIBLE_DATABASE'];
}
$result = $db->sql_query('SHOW TABLE STATUS LIKE \'' . POSTS_TABLE . '\'');
@ -133,40 +119,10 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
$split_keywords = preg_replace("#[\n\r\t]+#", ' ', trim(htmlspecialchars_decode($keywords)));
// Split words
if ($this->pcre_properties)
{
$split_keywords = preg_replace('#([^\p{L}\p{N}\'*"()])#u', '$1$1', str_replace('\'\'', '\' \'', trim($split_keywords)));
}
else if ($this->mbstring_regex)
{
$split_keywords = mb_ereg_replace('([^\w\'*"()])', '\\1\\1', str_replace('\'\'', '\' \'', trim($split_keywords)));
}
else
{
$split_keywords = preg_replace('#([^\w\'*"()])#u', '$1$1', str_replace('\'\'', '\' \'', trim($split_keywords)));
}
if ($this->pcre_properties)
{
$matches = array();
preg_match_all('#(?:[^\p{L}\p{N}*"()]|^)([+\-|]?(?:[\p{L}\p{N}*"()]+\'?)*[\p{L}\p{N}*"()])(?:[^\p{L}\p{N}*"()]|$)#u', $split_keywords, $matches);
$this->split_words = $matches[1];
}
else if ($this->mbstring_regex)
{
mb_ereg_search_init($split_keywords, '(?:[^\w*"()]|^)([+\-|]?(?:[\w*"()]+\'?)*[\w*"()])(?:[^\w*"()]|$)');
while (($word = mb_ereg_search_regs()))
{
$this->split_words[] = $word[1];
}
}
else
{
$matches = array();
preg_match_all('#(?:[^\w*"()]|^)([+\-|]?(?:[\w*"()]+\'?)*[\w*"()])(?:[^\w*"()]|$)#u', $split_keywords, $matches);
$this->split_words = $matches[1];
}
$split_keywords = preg_replace('#([^\p{L}\p{N}\'*"()])#u', '$1$1', str_replace('\'\'', '\' \'', trim($split_keywords)));
$matches = array();
preg_match_all('#(?:[^\p{L}\p{N}*"()]|^)([+\-|]?(?:[\p{L}\p{N}*"()]+\'?)*[\p{L}\p{N}*"()])(?:[^\p{L}\p{N}*"()]|$)#u', $split_keywords, $matches);
$this->split_words = $matches[1];
// We limit the number of allowed keywords to minimize load on the database
if ($config['max_num_search_keywords'] && sizeof($this->split_words) > $config['max_num_search_keywords'])
@ -271,41 +227,10 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
global $config;
// Split words
if ($this->pcre_properties)
{
$text = preg_replace('#([^\p{L}\p{N}\'*])#u', '$1$1', str_replace('\'\'', '\' \'', trim($text)));
}
else if ($this->mbstring_regex)
{
$text = mb_ereg_replace('([^\w\'*])', '\\1\\1', str_replace('\'\'', '\' \'', trim($text)));
}
else
{
$text = preg_replace('#([^\w\'*])#u', '$1$1', str_replace('\'\'', '\' \'', trim($text)));
}
if ($this->pcre_properties)
{
$matches = array();
preg_match_all('#(?:[^\p{L}\p{N}*]|^)([+\-|]?(?:[\p{L}\p{N}*]+\'?)*[\p{L}\p{N}*])(?:[^\p{L}\p{N}*]|$)#u', $text, $matches);
$text = $matches[1];
}
else if ($this->mbstring_regex)
{
mb_ereg_search_init($text, '(?:[^\w*]|^)([+\-|]?(?:[\w*]+\'?)*[\w*])(?:[^\w*]|$)');
$text = array();
while (($word = mb_ereg_search_regs()))
{
$text[] = $word[1];
}
}
else
{
$matches = array();
preg_match_all('#(?:[^\w*]|^)([+\-|]?(?:[\w*]+\'?)*[\w*])(?:[^\w*]|$)#u', $text, $matches);
$text = $matches[1];
}
$text = preg_replace('#([^\p{L}\p{N}\'*])#u', '$1$1', str_replace('\'\'', '\' \'', trim($text)));
$matches = array();
preg_match_all('#(?:[^\p{L}\p{N}*]|^)([+\-|]?(?:[\p{L}\p{N}*]+\'?)*[\p{L}\p{N}*])(?:[^\p{L}\p{N}*]|$)#u', $text, $matches);
$text = $matches[1];
// remove too short or too long words
$text = array_values($text);
@ -748,7 +673,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
{
if ($db->sql_layer == 'mysqli' || version_compare($db->sql_server_info(true), '4.1.3', '>='))
{
//$alter[] = 'MODIFY post_subject varchar(100) COLLATE utf8_unicode_ci DEFAULT \'\' NOT NULL';
$alter[] = 'MODIFY post_subject varchar(255) COLLATE utf8_unicode_ci DEFAULT \'\' NOT NULL';
}
else
{
@ -908,14 +833,6 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
global $user, $config;
$tpl = '
<dl>
<dt><label>' . $user->lang['FULLTEXT_MYSQL_PCRE'] . '</label><br /><span>' . $user->lang['FULLTEXT_MYSQL_PCRE_EXPLAIN'] . '</span></dt>
<dd>' . (($this->pcre_properties) ? $user->lang['YES'] : $user->lang['NO']) . ' (PHP ' . PHP_VERSION . ')</dd>
</dl>
<dl>
<dt><label>' . $user->lang['FULLTEXT_MYSQL_MBSTRING'] . '</label><br /><span>' . $user->lang['FULLTEXT_MYSQL_MBSTRING_EXPLAIN'] . '</span></dt>
<dd>' . (($this->mbstring_regex) ? $user->lang['YES'] : $user->lang['NO']). '</dd>
</dl>
<dl>
<dt><label>' . $user->lang['MIN_SEARCH_CHARS'] . ':</label><br /><span>' . $user->lang['FULLTEXT_MYSQL_MIN_SEARCH_CHARS_EXPLAIN'] . '</span></dt>
<dd>' . $config['fulltext_mysql_min_word_len'] . '</dd>

View file

@ -0,0 +1,856 @@
<?php
/**
*
* @package search
* @copyright (c) 2005 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* fulltext_postgres
* Fulltext search for PostgreSQL
* @package search
*/
class phpbb_search_fulltext_postgres extends phpbb_search_base
{
private $stats = array();
private $split_words = array();
private $tsearch_usable = false;
private $version;
private $tsearch_query;
private $phrase_search = false;
public $search_query;
public $common_words = array();
public $word_length = array();
/**
* Constructor
* Creates a new phpbb_search_fulltext_postgres, which is used as a search backend.
*
* @param string|bool $error Any error that occurs is passed on through this reference variable otherwise false
*/
public function __construct(&$error)
{
global $db, $config;
$this->word_length = array('min' => $config['fulltext_postgres_min_word_len'], 'max' => $config['fulltext_postgres_max_word_len']);
if ($db->sql_layer == 'postgres')
{
$pgsql_version = explode(',', substr($db->sql_server_info(), 10));
$this->version = trim($pgsql_version[0]);
if (version_compare($this->version, '8.3', '>='))
{
$this->tsearch_usable = true;
}
}
$error = false;
}
/**
* Returns the name of this search backend to be displayed to administrators
*
* @return string Name
*
* @access public
*/
public function get_name()
{
return 'PostgreSQL Fulltext';
}
/**
* Returns if phrase search is supported or not
*
* @return bool
*
* @access public
*/
public function supports_phrase_search()
{
return $this->phrase_search;
}
/**
* Checks for correct PostgreSQL version and stores min/max word length in the config
*
* @return string|bool Language key of the error/incompatiblity occured
*
* @access public
*/
function init()
{
global $db, $user;
if ($db->sql_layer != 'postgres')
{
return $user->lang['FULLTEXT_POSTGRES_INCOMPATIBLE_DATABASE'];
}
if (!$this->tsearch_usable)
{
return $user->lang['FULLTEXT_POSTGRES_TS_NOT_USABLE'];
}
return false;
}
/**
* Splits keywords entered by a user into an array of words stored in $this->split_words
* Stores the tidied search query in $this->search_query
*
* @param string &$keywords Contains the keyword as entered by the user
* @param string $terms is either 'all' or 'any'
* @return bool false if no valid keywords were found and otherwise true
*
* @access public
*/
function split_keywords(&$keywords, $terms)
{
global $config;
if ($terms == 'all')
{
$match = array('#\sand\s#iu', '#\sor\s#iu', '#\snot\s#iu', '#\+#', '#-#', '#\|#');
$replace = array(' +', ' |', ' -', ' +', ' -', ' |');
$keywords = preg_replace($match, $replace, $keywords);
}
// Filter out as above
$split_keywords = preg_replace("#[\"\n\r\t]+#", ' ', trim(htmlspecialchars_decode($keywords)));
// Split words
$split_keywords = preg_replace('#([^\p{L}\p{N}\'*"()])#u', '$1$1', str_replace('\'\'', '\' \'', trim($split_keywords)));
$matches = array();
preg_match_all('#(?:[^\p{L}\p{N}*"()]|^)([+\-|]?(?:[\p{L}\p{N}*"()]+\'?)*[\p{L}\p{N}*"()])(?:[^\p{L}\p{N}*"()]|$)#u', $split_keywords, $matches);
$this->split_words = $matches[1];
foreach ($this->split_words as $i => $word)
{
$clean_word = preg_replace('#^[+\-|"]#', '', $word);
// check word length
$clean_len = utf8_strlen(str_replace('*', '', $clean_word));
if (($clean_len < $config['fulltext_postgres_min_word_len']) || ($clean_len > $config['fulltext_postgres_max_word_len']))
{
$this->common_words[] = $word;
unset($this->split_words[$i]);
}
}
if ($terms == 'any')
{
$this->search_query = '';
$this->tsearch_query = '';
foreach ($this->split_words as $word)
{
if ((strpos($word, '+') === 0) || (strpos($word, '-') === 0) || (strpos($word, '|') === 0))
{
$word = substr($word, 1);
}
$this->search_query .= $word . ' ';
$this->tsearch_query .= '|' . $word . ' ';
}
}
else
{
$this->search_query = '';
$this->tsearch_query = '';
foreach ($this->split_words as $word)
{
if (strpos($word, '+') === 0)
{
$this->search_query .= $word . ' ';
$this->tsearch_query .= '&' . substr($word, 1) . ' ';
}
elseif (strpos($word, '-') === 0)
{
$this->search_query .= $word . ' ';
$this->tsearch_query .= '&!' . substr($word, 1) . ' ';
}
elseif (strpos($word, '|') === 0)
{
$this->search_query .= $word . ' ';
$this->tsearch_query .= '|' . substr($word, 1) . ' ';
}
else
{
$this->search_query .= '+' . $word . ' ';
$this->tsearch_query .= '&' . $word . ' ';
}
}
}
$this->tsearch_query = substr($this->tsearch_query, 1);
$this->search_query = utf8_htmlspecialchars($this->search_query);
if ($this->search_query)
{
$this->split_words = array_values($this->split_words);
sort($this->split_words);
return true;
}
return false;
}
/**
* Turns text into an array of words
* @param string $text contains post text/subject
*
* @access public
*/
function split_message($text)
{
global $config;
// Split words
$text = preg_replace('#([^\p{L}\p{N}\'*])#u', '$1$1', str_replace('\'\'', '\' \'', trim($text)));
$matches = array();
preg_match_all('#(?:[^\p{L}\p{N}*]|^)([+\-|]?(?:[\p{L}\p{N}*]+\'?)*[\p{L}\p{N}*])(?:[^\p{L}\p{N}*]|$)#u', $text, $matches);
$text = $matches[1];
// remove too short or too long words
$text = array_values($text);
for ($i = 0, $n = sizeof($text); $i < $n; $i++)
{
$text[$i] = trim($text[$i]);
if (utf8_strlen($text[$i]) < $config['fulltext_postgres_min_word_len'] || utf8_strlen($text[$i]) > $config['fulltext_postgres_max_word_len'])
{
unset($text[$i]);
}
}
return array_values($text);
}
/**
* Performs a search on keywords depending on display specific params. You have to run split_keywords() first.
*
* @param string $type contains either posts or topics depending on what should be searched for
* @param string $fields contains either titleonly (topic titles should be searched), msgonly (only message bodies should be searched), firstpost (only subject and body of the first post should be searched) or all (all post bodies and subjects should be searched)
* @param string $terms is either 'all' (use query as entered, words without prefix should default to "have to be in field") or 'any' (ignore search query parts and just return all posts that contain any of the specified words)
* @param array $sort_by_sql contains SQL code for the ORDER BY part of a query
* @param string $sort_key is the key of $sort_by_sql for the selected sorting
* @param string $sort_dir is either a or d representing ASC and DESC
* @param string $sort_days specifies the maximum amount of days a post may be old
* @param array $ex_fid_ary specifies an array of forum ids which should not be searched
* @param array $m_approve_fid_ary specifies an array of forum ids in which the searcher is allowed to view unapproved posts
* @param int $topic_id is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched
* @param array $author_ary an array of author ids if the author should be ignored during the search the array is empty
* @param string $author_name specifies the author match, when ANONYMOUS is also a search-match
* @param array &$id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered
* @param int $start indicates the first index of the page
* @param int $per_page number of ids each page is supposed to contain
* @return boolean|int total number of results
*
* @access public
*/
function keyword_search($type, $fields, $terms, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)
{
global $config, $db;
// No keywords? No posts.
if (!$this->search_query)
{
return false;
}
// generate a search_key from all the options to identify the results
$search_key = md5(implode('#', array(
implode(', ', $this->split_words),
$type,
$fields,
$terms,
$sort_days,
$sort_key,
$topic_id,
implode(',', $ex_fid_ary),
implode(',', $m_approve_fid_ary),
implode(',', $author_ary)
)));
// try reading the results from cache
$result_count = 0;
if ($this->obtain_ids($search_key, $result_count, $id_ary, $start, $per_page, $sort_dir) == SEARCH_RESULT_IN_CACHE)
{
return $result_count;
}
$id_ary = array();
$join_topic = ($type == 'posts') ? false : true;
// Build sql strings for sorting
$sql_sort = $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC');
$sql_sort_table = $sql_sort_join = '';
switch ($sql_sort[0])
{
case 'u':
$sql_sort_table = USERS_TABLE . ' u, ';
$sql_sort_join = ($type == 'posts') ? ' AND u.user_id = p.poster_id ' : ' AND u.user_id = t.topic_poster ';
break;
case 't':
$join_topic = true;
break;
case 'f':
$sql_sort_table = FORUMS_TABLE . ' f, ';
$sql_sort_join = ' AND f.forum_id = p.forum_id ';
break;
}
// Build some display specific sql strings
switch ($fields)
{
case 'titleonly':
$sql_match = 'p.post_subject';
$sql_match_where = ' AND p.post_id = t.topic_first_post_id';
$join_topic = true;
break;
case 'msgonly':
$sql_match = 'p.post_text';
$sql_match_where = '';
break;
case 'firstpost':
$sql_match = 'p.post_subject, p.post_text';
$sql_match_where = ' AND p.post_id = t.topic_first_post_id';
$join_topic = true;
break;
default:
$sql_match = 'p.post_subject, p.post_text';
$sql_match_where = '';
break;
}
if (!sizeof($m_approve_fid_ary))
{
$m_approve_fid_sql = ' AND p.post_approved = 1';
}
else if ($m_approve_fid_ary === array(-1))
{
$m_approve_fid_sql = '';
}
else
{
$m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')';
}
$sql_select = ($type == 'posts') ? 'p.post_id' : 'DISTINCT t.topic_id';
$sql_from = ($join_topic) ? TOPICS_TABLE . ' t, ' : '';
$field = ($type == 'posts') ? 'post_id' : 'topic_id';
$sql_author = (sizeof($author_ary) == 1) ? ' = ' . $author_ary[0] : 'IN (' . implode(', ', $author_ary) . ')';
if (sizeof($author_ary) && $author_name)
{
// first one matches post of registered users, second one guests and deleted users
$sql_author = '(' . $db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
}
else if (sizeof($author_ary))
{
$sql_author = ' AND ' . $db->sql_in_set('p.poster_id', $author_ary);
}
else
{
$sql_author = '';
}
$sql_where_options = $sql_sort_join;
$sql_where_options .= ($topic_id) ? ' AND p.topic_id = ' . $topic_id : '';
$sql_where_options .= ($join_topic) ? ' AND t.topic_id = p.topic_id' : '';
$sql_where_options .= (sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
$sql_where_options .= $m_approve_fid_sql;
$sql_where_options .= $sql_author;
$sql_where_options .= ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';
$sql_where_options .= $sql_match_where;
$tmp_sql_match = array();
foreach (explode(',', $sql_match) as $sql_match_column)
{
$tmp_sql_match[] = "to_tsvector ('" . $db->sql_escape($config['fulltext_postgres_ts_name']) . "', " . $sql_match_column . ") @@ to_tsquery ('" . $db->sql_escape($config['fulltext_postgres_ts_name']) . "', '" . $db->sql_escape($this->tsearch_query) . "')";
}
$sql = "SELECT $sql_select
FROM $sql_from$sql_sort_table" . POSTS_TABLE . " p
WHERE (" . implode(' OR ', $tmp_sql_match) . ")
$sql_where_options
ORDER BY $sql_sort";
$result = $db->sql_query_limit($sql, $config['search_block_size'], $start);
while ($row = $db->sql_fetchrow($result))
{
$id_ary[] = $row[$field];
}
$db->sql_freeresult($result);
$id_ary = array_unique($id_ary);
if (!sizeof($id_ary))
{
return false;
}
// if the total result count is not cached yet, retrieve it from the db
if (!$result_count)
{
$result_count = sizeof ($id_ary);
if (!$result_count)
{
return false;
}
}
// store the ids, from start on then delete anything that isn't on the current page because we only need ids for one page
$this->save_ids($search_key, implode(' ', $this->split_words), $author_ary, $result_count, $id_ary, $start, $sort_dir);
$id_ary = array_slice($id_ary, 0, (int) $per_page);
return $result_count;
}
/**
* Performs a search on an author's posts without caring about message contents. Depends on display specific params
*
* @param string $type contains either posts or topics depending on what should be searched for
* @param boolean $firstpost_only if true, only topic starting posts will be considered
* @param array $sort_by_sql contains SQL code for the ORDER BY part of a query
* @param string $sort_key is the key of $sort_by_sql for the selected sorting
* @param string $sort_dir is either a or d representing ASC and DESC
* @param string $sort_days specifies the maximum amount of days a post may be old
* @param array $ex_fid_ary specifies an array of forum ids which should not be searched
* @param array $m_approve_fid_ary specifies an array of forum ids in which the searcher is allowed to view unapproved posts
* @param int $topic_id is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched
* @param array $author_ary an array of author ids
* @param string $author_name specifies the author match, when ANONYMOUS is also a search-match
* @param array &$id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered
* @param int $start indicates the first index of the page
* @param int $per_page number of ids each page is supposed to contain
* @return boolean|int total number of results
*
* @access public
*/
function author_search($type, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_ary, $author_name, &$id_ary, $start, $per_page)
{
global $config, $db;
// No author? No posts.
if (!sizeof($author_ary))
{
return 0;
}
// generate a search_key from all the options to identify the results
$search_key = md5(implode('#', array(
'',
$type,
($firstpost_only) ? 'firstpost' : '',
'',
'',
$sort_days,
$sort_key,
$topic_id,
implode(',', $ex_fid_ary),
implode(',', $m_approve_fid_ary),
implode(',', $author_ary),
$author_name,
)));
// try reading the results from cache
$result_count = 0;
if ($this->obtain_ids($search_key, $result_count, $id_ary, $start, $per_page, $sort_dir) == SEARCH_RESULT_IN_CACHE)
{
return $result_count;
}
$id_ary = array();
// Create some display specific sql strings
if ($author_name)
{
// first one matches post of registered users, second one guests and deleted users
$sql_author = '(' . $db->sql_in_set('p.poster_id', array_diff($author_ary, array(ANONYMOUS)), false, true) . ' OR p.post_username ' . $author_name . ')';
}
else
{
$sql_author = $db->sql_in_set('p.poster_id', $author_ary);
}
$sql_fora = (sizeof($ex_fid_ary)) ? ' AND ' . $db->sql_in_set('p.forum_id', $ex_fid_ary, true) : '';
$sql_topic_id = ($topic_id) ? ' AND p.topic_id = ' . (int) $topic_id : '';
$sql_time = ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : '';
$sql_firstpost = ($firstpost_only) ? ' AND p.post_id = t.topic_first_post_id' : '';
// Build sql strings for sorting
$sql_sort = $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC');
$sql_sort_table = $sql_sort_join = '';
switch ($sql_sort[0])
{
case 'u':
$sql_sort_table = USERS_TABLE . ' u, ';
$sql_sort_join = ($type == 'posts') ? ' AND u.user_id = p.poster_id ' : ' AND u.user_id = t.topic_poster ';
break;
case 't':
$sql_sort_table = ($type == 'posts' && !$firstpost_only) ? TOPICS_TABLE . ' t, ' : '';
$sql_sort_join = ($type == 'posts' && !$firstpost_only) ? ' AND t.topic_id = p.topic_id ' : '';
break;
case 'f':
$sql_sort_table = FORUMS_TABLE . ' f, ';
$sql_sort_join = ' AND f.forum_id = p.forum_id ';
break;
}
if (!sizeof($m_approve_fid_ary))
{
$m_approve_fid_sql = ' AND p.post_approved = 1';
}
else if ($m_approve_fid_ary == array(-1))
{
$m_approve_fid_sql = '';
}
else
{
$m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . $db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')';
}
// Build the query for really selecting the post_ids
if ($type == 'posts')
{
$sql = "SELECT p.post_id
FROM " . $sql_sort_table . POSTS_TABLE . ' p' . (($firstpost_only) ? ', ' . TOPICS_TABLE . ' t ' : ' ') . "
WHERE $sql_author
$sql_topic_id
$sql_firstpost
$m_approve_fid_sql
$sql_fora
$sql_sort_join
$sql_time
ORDER BY $sql_sort";
$field = 'post_id';
}
else
{
$sql = "SELECT t.topic_id
FROM " . $sql_sort_table . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p
WHERE $sql_author
$sql_topic_id
$sql_firstpost
$m_approve_fid_sql
$sql_fora
AND t.topic_id = p.topic_id
$sql_sort_join
$sql_time
GROUP BY t.topic_id, $sort_by_sql[$sort_key]
ORDER BY $sql_sort";
$field = 'topic_id';
}
// Only read one block of posts from the db and then cache it
$result = $db->sql_query_limit($sql, $config['search_block_size'], $start);
while ($row = $db->sql_fetchrow($result))
{
$id_ary[] = $row[$field];
}
$db->sql_freeresult($result);
// retrieve the total result count if needed
if (!$result_count)
{
$result_count = sizeof ($id_ary);
if (!$result_count)
{
return false;
}
}
if (sizeof($id_ary))
{
$this->save_ids($search_key, '', $author_ary, $result_count, $id_ary, $start, $sort_dir);
$id_ary = array_slice($id_ary, 0, $per_page);
return $result_count;
}
return false;
}
/**
* Destroys cached search results, that contained one of the new words in a post so the results won't be outdated.
*
* @param string $mode contains the post mode: edit, post, reply, quote ...
* @param int $post_id contains the post id of the post to index
* @param string $message contains the post text of the post
* @param string $subject contains the subject of the post to index
* @param int $poster_id contains the user id of the poster
* @param int $forum_id contains the forum id of parent forum of the post
*
* @access public
*/
function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id)
{
global $db;
// Split old and new post/subject to obtain array of words
$split_text = $this->split_message($message);
$split_title = ($subject) ? $this->split_message($subject) : array();
$words = array_unique(array_merge($split_text, $split_title));
unset($split_text);
unset($split_title);
// destroy cached search results containing any of the words removed or added
$this->destroy_cache($words, array($poster_id));
unset($words);
}
/**
* Destroy cached results, that might be outdated after deleting a post
*
* @access public
*/
function index_remove($post_ids, $author_ids, $forum_ids)
{
$this->destroy_cache(array(), $author_ids);
}
/**
* Destroy old cache entries
*
* @access public
*/
function tidy()
{
global $db, $config;
// destroy too old cached search results
$this->destroy_cache(array());
set_config('search_last_gc', time(), true);
}
/**
* Create fulltext index
*
* @return string|bool error string is returned incase of errors otherwise false
*
* @access public
*/
function create_index($acp_module, $u_action)
{
global $db, $config;
// Make sure we can actually use PostgreSQL with fulltext indexes
if ($error = $this->init())
{
return $error;
}
if (empty($this->stats))
{
$this->get_stats();
}
if (!isset($this->stats['post_subject']))
{
$db->sql_query("CREATE INDEX " . POSTS_TABLE . "_" . $config['fulltext_postgres_ts_name'] . "_post_subject ON " . POSTS_TABLE . " USING gin (to_tsvector ('" . $db->sql_escape($config['fulltext_postgres_ts_name']) . "', post_subject))");
}
if (!isset($this->stats['post_text']))
{
$db->sql_query("CREATE INDEX " . POSTS_TABLE . "_" . $config['fulltext_postgres_ts_name'] . "_post_text ON " . POSTS_TABLE . " USING gin (to_tsvector ('" . $db->sql_escape($config['fulltext_postgres_ts_name']) . "', post_text))");
}
$db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
return false;
}
/**
* Drop fulltext index
*
* @return string|bool error string is returned incase of errors otherwise false
*
* @access public
*/
function delete_index($acp_module, $u_action)
{
global $db;
// Make sure we can actually use PostgreSQL with fulltext indexes
if ($error = $this->init())
{
return $error;
}
if (empty($this->stats))
{
$this->get_stats();
}
if (isset($this->stats['post_subject']))
{
$db->sql_query('DROP INDEX ' . $this->stats['post_subject']['relname']);
}
if (isset($this->stats['post_text']))
{
$db->sql_query('DROP INDEX ' . $this->stats['post_text']['relname']);
}
$db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE);
return false;
}
/**
* Returns true if both FULLTEXT indexes exist
*
* @access public
*/
function index_created()
{
if (empty($this->stats))
{
$this->get_stats();
}
return (isset($this->stats['post_text']) && isset($this->stats['post_subject'])) ? true : false;
}
/**
* Returns an associative array containing information about the indexes
*
* @access public
*/
function index_stats()
{
global $user;
if (empty($this->stats))
{
$this->get_stats();
}
return array(
$user->lang['FULLTEXT_POSTGRES_TOTAL_POSTS'] => ($this->index_created()) ? $this->stats['total_posts'] : 0,
);
}
/**
* Computes the stats and store them in the $this->stats associative array
*
* @access private
*/
function get_stats()
{
global $db, $config;
if ($db->sql_layer != 'postgres')
{
$this->stats = array();
return;
}
$sql = "SELECT c2.relname, pg_catalog.pg_get_indexdef(i.indexrelid, 0, true) AS indexdef
FROM pg_catalog.pg_class c1, pg_catalog.pg_index i, pg_catalog.pg_class c2
WHERE c1.relname = '" . POSTS_TABLE . "'
AND pg_catalog.pg_table_is_visible(c1.oid)
AND c1.oid = i.indrelid
AND i.indexrelid = c2.oid";
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
// deal with older PostgreSQL versions which didn't use Index_type
if (strpos($row['indexdef'], 'to_tsvector') !== false)
{
if ($row['relname'] == POSTS_TABLE . '_' . $config['fulltext_postgres_ts_name'] . '_post_text' || $row['relname'] == POSTS_TABLE . '_post_text')
{
$this->stats['post_text'] = $row;
}
else if ($row['relname'] == POSTS_TABLE . '_' . $config['fulltext_postgres_ts_name'] . '_post_subject' || $row['relname'] == POSTS_TABLE . '_post_subject')
{
$this->stats['post_subject'] = $row;
}
}
}
$db->sql_freeresult($result);
$this->stats['total_posts'] = $config['num_posts'];
}
/**
* Display various options that can be configured for the backend from the acp
*
* @return associative array containing template and config variables
*
* @access public
*/
function acp()
{
global $user, $config, $db;
$tpl = '
<dl>
<dt><label>' . $user->lang['FULLTEXT_POSTGRES_VERSION_CHECK'] . '</label><br /><span>' . $user->lang['FULLTEXT_POSTGRES_VERSION_CHECK_EXPLAIN'] . '</span></dt>
<dd>' . (($this->tsearch_usable) ? $user->lang['YES'] : $user->lang['NO']) . ' (PostgreSQL ' . $this->version . ')</dd>
</dl>
<dl>
<dt><label>' . $user->lang['FULLTEXT_POSTGRES_TS_NAME'] . '</label><br /><span>' . $user->lang['FULLTEXT_POSTGRES_TS_NAME_EXPLAIN'] . '</span></dt>
<dd><select name="config[fulltext_postgres_ts_name]">';
if ($db->sql_layer == 'postgres' && $this->tsearch_usable)
{
$sql = 'SELECT cfgname AS ts_name
FROM pg_ts_config';
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
$tpl .= '<option value="' . $row['ts_name'] . '"' . ($row['ts_name'] === $config['fulltext_postgres_ts_name'] ? ' selected="selected"' : '') . '>' . $row['ts_name'] . '</option>';
}
$db->sql_freeresult($result);
}
else
{
$tpl .= '<option value="' . $config['fulltext_postgres_ts_name'] . '" selected="selected">' . $config['fulltext_postgres_ts_name'] . '</option>';
}
$tpl .= '</select></dd>
</dl>
<dl>
<dt><label for="fulltext_postgres_min_word_len">' . $user->lang['FULLTEXT_POSTGRES_MIN_WORD_LEN'] . ':</label><br /><span>' . $user->lang['FULLTEXT_POSTGRES_MIN_WORD_LEN_EXPLAIN'] . '</span></dt>
<dd><input id="fulltext_postgres_min_word_len" type="text" size="3" maxlength="3" name="config[fulltext_postgres_min_word_len]" value="' . (int) $config['fulltext_postgres_min_word_len'] . '" /></dd>
</dl>
<dl>
<dt><label for="fulltext_postgres_max_word_len">' . $user->lang['FULLTEXT_POSTGRES_MAX_WORD_LEN'] . ':</label><br /><span>' . $user->lang['FULLTEXT_POSTGRES_MAX_WORD_LEN_EXPLAIN'] . '</span></dt>
<dd><input id="fulltext_postgres_max_word_len" type="text" size="3" maxlength="3" name="config[fulltext_postgres_max_word_len]" value="' . (int) $config['fulltext_postgres_max_word_len'] . '" /></dd>
</dl>
';
// These are fields required in the config table
return array(
'tpl' => $tpl,
'config' => array('fulltext_postgres_ts_name' => 'string', 'fulltext_postgres_min_word_len' => 'integer:0:255', 'fulltext_postgres_max_word_len' => 'integer:0:255')
);
}
}

View file

@ -89,9 +89,9 @@ class phpbb_style
*/
public function set_style()
{
$style_name = $this->user->theme['style_path'];
$style_dirs = ($this->user->theme['style_parent_id']) ? array_reverse(explode('/', $this->user->theme['style_parent_tree'])) : array();
$paths = array($this->get_style_path($style_name));
$style_path = $this->user->style['style_path'];
$style_dirs = ($this->user->style['style_parent_id']) ? array_reverse(explode('/', $this->user->style['style_parent_tree'])) : array();
$paths = array($this->get_style_path($style_path));
foreach ($style_dirs as $dir)
{
$paths[] = $this->get_style_path($dir);
@ -100,7 +100,7 @@ class phpbb_style
// Add 'all' path, used as last fallback path by hooks and extensions
$paths[] = $this->get_style_path('all');
return $this->set_custom_style($style_name, $paths);
return $this->set_custom_style($style_path, $paths);
}
/**

View file

@ -905,12 +905,12 @@ class phpbb_template_filter extends php_user_filter
if (substr($filename, 0, strlen($this->phpbb_root_path)) != $this->phpbb_root_path)
{
// Absolute path, include as is
return ' $_template->_js_include(\'' . addslashes($filename) . '\', false); ';
return ' $_template->_js_include(\'' . addslashes($filename) . '\', false, false); ';
}
// Relative path, remove root path from it
$filename = substr($filename, strlen($this->phpbb_root_path));
return ' global $phpbb_root_path; $_template->_js_include($phpbb_root_path . \'' . addslashes($filename) . '\', false); ';
return ' $_template->_js_include(\'' . addslashes($filename) . '\', false, true); ';
}
/**

View file

@ -496,14 +496,19 @@ class phpbb_template
*
* @param string $file file name
* @param bool $locate True if file needs to be located
* @param bool $relative True if path is relative to phpBB root directory. Ignored if $locate == true
*/
public function _js_include($file, $locate = false)
public function _js_include($file, $locate = false, $relative = false)
{
// Locate file
if ($locate)
{
$file = $this->locator->get_first_file_location(array($file), true, true);
}
else if ($relative)
{
$file = $this->phpbb_root_path . $file;
}
$file .= (strpos($file, '?') === false) ? '?' : '&';
$file .= 'assets_version=' . $this->config['assets_version'];

View file

@ -23,6 +23,7 @@ class ucp_profile_info
'signature' => array('title' => 'UCP_PROFILE_SIGNATURE', 'auth' => '', 'cat' => array('UCP_PROFILE')),
'avatar' => array('title' => 'UCP_PROFILE_AVATAR', 'auth' => 'cfg_allow_avatar && (cfg_allow_avatar_local || cfg_allow_avatar_remote || cfg_allow_avatar_upload || cfg_allow_avatar_remote_upload)', 'cat' => array('UCP_PROFILE')),
'reg_details' => array('title' => 'UCP_PROFILE_REG_DETAILS', 'auth' => '', 'cat' => array('UCP_PROFILE')),
'autologin_keys'=> array('title' => 'UCP_PROFILE_AUTOLOGIN_KEYS', 'auth' => '', 'cat' => array('UCP_PROFILE')),
),
);
}

View file

@ -327,10 +327,23 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit
trigger_error('RULE_ALREADY_DEFINED');
}
// Prevent users from flooding the rules table
$sql = 'SELECT COUNT(rule_id) AS num_rules
FROM ' . PRIVMSGS_RULES_TABLE . '
WHERE user_id = ' . (int) $user->data['user_id'];
$result = $db->sql_query($sql);
$num_rules = (int) $db->sql_fetchfield('num_rules');
$db->sql_freeresult($result);
if ($num_rules >= 5000)
{
trigger_error('RULE_LIMIT_REACHED');
}
$sql = 'INSERT INTO ' . PRIVMSGS_RULES_TABLE . ' ' . $db->sql_build_array('INSERT', $rule_ary);
$db->sql_query($sql);
// Update users message rules
// Set the user_message_rules bit
$sql = 'UPDATE ' . USERS_TABLE . '
SET user_message_rules = 1
WHERE user_id = ' . $user->data['user_id'];
@ -377,7 +390,7 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
// Update users message rules
// Unset the user_message_rules bit
if (!$row)
{
$sql = 'UPDATE ' . USERS_TABLE . '

View file

@ -618,6 +618,60 @@ class ucp_profile
}
break;
case 'autologin_keys':
add_form_key('ucp_autologin_keys');
if ($submit)
{
$keys = request_var('keys', array(''));
if (!check_form_key('ucp_autologin_keys'))
{
$error[] = 'FORM_INVALID';
}
if (!sizeof($error))
{
if (!empty($keys))
{
$sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . '
WHERE user_id = ' . (int) $user->data['user_id'] . '
AND ' . $db->sql_in_set('key_id', $keys) ;
$db->sql_query($sql);
meta_refresh(3, $this->u_action);
$message = $user->lang['AUTOLOGIN_SESSION_KEYS_DELETED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>');
trigger_error($message);
}
}
// Replace "error" strings with their real, localised form
$error = array_map(array($user, 'lang'), $error);
}
$sql = 'SELECT key_id, last_ip, last_login
FROM ' . SESSIONS_KEYS_TABLE . '
WHERE user_id = ' . (int) $user->data['user_id'];
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
$template->assign_block_vars('sessions', array(
'errors' => $error,
'KEY' => $row['key_id'],
'IP' => $row['last_ip'],
'LOGIN_TIME' => $user->format_date($row['last_login']),
));
}
$db->sql_freeresult($result);
break;
}
$template->assign_vars(array(

View file

@ -27,7 +27,7 @@ class phpbb_user extends phpbb_session
{
var $lang = array();
var $help = array();
var $theme = array();
var $style = array();
var $date_format;
/**
@ -168,11 +168,11 @@ class phpbb_user extends phpbb_session
FROM ' . STYLES_TABLE . " s
WHERE s.style_id = $style_id";
$result = $db->sql_query($sql, 3600);
$this->theme = $db->sql_fetchrow($result);
$this->style = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
// User has wrong style
if (!$this->theme && $style_id == $this->data['user_style'])
if (!$this->style && $style_id == $this->data['user_style'])
{
$style_id = $this->data['user_style'] = $config['default_style'];
@ -185,20 +185,17 @@ class phpbb_user extends phpbb_session
FROM ' . STYLES_TABLE . " s
WHERE s.style_id = $style_id";
$result = $db->sql_query($sql, 3600);
$this->theme = $db->sql_fetchrow($result);
$this->style = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
}
if (!$this->theme)
if (!$this->style)
{
trigger_error('Could not get style data', E_USER_ERROR);
}
// Now parse the cfg file and cache it
$parsed_items = $cache->obtain_cfg_items($this->theme);
// We are only interested in the theme configuration for now
$parsed_items = $parsed_items['theme'];
$parsed_items = $cache->obtain_cfg_items($this->style);
$check_for = array(
'pagination_sep' => (string) ', '
@ -206,12 +203,12 @@ class phpbb_user extends phpbb_session
foreach ($check_for as $key => $default_value)
{
$this->theme[$key] = (isset($parsed_items[$key])) ? $parsed_items[$key] : $default_value;
settype($this->theme[$key], gettype($default_value));
$this->style[$key] = (isset($parsed_items[$key])) ? $parsed_items[$key] : $default_value;
settype($this->style[$key], gettype($default_value));
if (is_string($default_value))
{
$this->theme[$key] = htmlspecialchars($this->theme[$key]);
$this->style[$key] = htmlspecialchars($this->style[$key]);
}
}

View file

@ -2248,6 +2248,21 @@ function change_database_data(&$no_updates, $version)
set_config('search_type', 'phpbb_search_' . $config['search_type']);
}
if (!isset($config['fulltext_postgres_ts_name']))
{
set_config('fulltext_postgres_ts_name', 'simple');
}
if (!isset($config['fulltext_postgres_min_word_len']))
{
set_config('fulltext_postgres_min_word_len', 4);
}
if (!isset($config['fulltext_postgres_max_word_len']))
{
set_config('fulltext_postgres_max_word_len', 254);
}
if (!isset($config['load_jquery_cdn']))
{
set_config('load_jquery_cdn', 0);
@ -2346,6 +2361,13 @@ function change_database_data(&$no_updates, $version)
'auth' => 'acl_a_styles',
'cat' => 'ACP_STYLE_MANAGEMENT',
),
'autologin_keys' => array(
'base' => 'ucp_profile',
'class' => 'ucp',
'title' => 'UCP_PROFILE_AUTOLOGIN_KEYS',
'auth' => '',
'cat' => 'UCP_PROFILE',
),
);
_add_modules($modules_to_install);

View file

@ -1178,7 +1178,7 @@ class install_install extends module
$sql_query = preg_replace('#phpbb_#i', $data['table_prefix'], $sql_query);
$sql_query = remove_comments($sql_query);
$sql_query = phpbb_remove_comments($sql_query);
$sql_query = split_sql_file($sql_query, $delimiter);
@ -1216,7 +1216,7 @@ class install_install extends module
// Change language strings...
$sql_query = preg_replace_callback('#\{L_([A-Z0-9\-_]*)\}#s', 'adjust_language_keys_callback', $sql_query);
$sql_query = remove_comments($sql_query);
$sql_query = phpbb_remove_comments($sql_query);
$sql_query = split_sql_file($sql_query, ';');
foreach ($sql_query as $sql)

View file

@ -124,6 +124,9 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_native_co
INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_native_load_upd', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_native_max_chars', '14');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_native_min_chars', '3');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_postgres_max_word_len', '254');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_postgres_min_word_len', '4');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('fulltext_postgres_ts_name', 'simple');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('gzip_compress', '0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('hot_threshold', '25');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('icons_path', 'images/icons');

View file

@ -51,16 +51,24 @@ $lang = array_merge($lang, array(
'DELETING_INDEX_IN_PROGRESS' => 'Deleting the index in progress',
'DELETING_INDEX_IN_PROGRESS_EXPLAIN' => 'The search backend is currently cleaning its index. This can take a few minutes.',
'FULLTEXT_MYSQL_INCOMPATIBLE_VERSION' => 'The MySQL fulltext backend can only be used with MySQL4 and above.',
'FULLTEXT_MYSQL_INCOMPATIBLE_DATABASE' => 'The MySQL fulltext backend can only be used with MySQL4 and above.',
'FULLTEXT_MYSQL_NOT_MYISAM' => 'MySQL fulltext indexes can only be used with MyISAM tables.',
'FULLTEXT_MYSQL_TOTAL_POSTS' => 'Total number of indexed posts',
'FULLTEXT_MYSQL_MBSTRING' => 'Support for non-latin UTF-8 characters using mbstring:',
'FULLTEXT_MYSQL_PCRE' => 'Support for non-latin UTF-8 characters using PCRE:',
'FULLTEXT_MYSQL_MBSTRING_EXPLAIN' => 'If PCRE does not have unicode character properties, the search backend will try to use mbstrings regular expression engine.',
'FULLTEXT_MYSQL_PCRE_EXPLAIN' => 'This search backend requires PCRE unicode character properties, only available in PHP 4.4, 5.1 and above, if you want to search for non-latin characters.',
'FULLTEXT_MYSQL_MIN_SEARCH_CHARS_EXPLAIN' => 'Words with at least this many characters will be indexed for searching. You or your host can only change this setting by changing the mysql configuration.',
'FULLTEXT_MYSQL_MAX_SEARCH_CHARS_EXPLAIN' => 'Words with no more than this many characters will be indexed for searching. You or your host can only change this setting by changing the mysql configuration.',
'FULLTEXT_POSTGRES_INCOMPATIBLE_DATABASE' => 'The PostgreSQL fulltext backend can only be used with PostgreSQL.',
'FULLTEXT_POSTGRES_TS_NOT_USABLE' => 'The PostgreSQL fulltext backend can only be used with PostgreSQL 8.3 and above.',
'FULLTEXT_POSTGRES_TOTAL_POSTS' => 'Total number of indexed posts',
'FULLTEXT_POSTGRES_VERSION_CHECK' => 'PostgreSQL version',
'FULLTEXT_POSTGRES_TS_NAME' => 'Text search Configuration Profile:',
'FULLTEXT_POSTGRES_MIN_WORD_LEN' => 'Minimum word length for keywords',
'FULLTEXT_POSTGRES_MAX_WORD_LEN' => 'Maximum word length for keywords',
'FULLTEXT_POSTGRES_VERSION_CHECK_EXPLAIN' => 'This search backend requires PostgreSQL version 8.3 and above.',
'FULLTEXT_POSTGRES_TS_NAME_EXPLAIN' => 'The Text search configuration profile used to determine the parser and dictionary.',
'FULLTEXT_POSTGRES_MIN_WORD_LEN_EXPLAIN' => 'Words with at least this many characters will be included in the query to the database.',
'FULLTEXT_POSTGRES_MAX_WORD_LEN_EXPLAIN' => 'Words with no more than this many characters will be included in the query to the database.',
'GENERAL_SEARCH_SETTINGS' => 'General search settings',
'GO_TO_SEARCH_INDEX' => 'Go to search index page',

View file

@ -72,6 +72,7 @@ $lang = array_merge($lang, array(
'WORDS_IN_NO_POST' => 'No posts were found because the words <strong>%s</strong> are not contained in any post.',
'POST_CHARACTERS' => 'characters of posts',
'PHRASE_SEARCH_DISABLED' => 'Searching by exact phrase is not supported on this board.',
'RECENT_SEARCHES' => 'Recent searches',
'RESULT_DAYS' => 'Limit results to previous',
@ -81,6 +82,7 @@ $lang = array_merge($lang, array(
'SEARCHED_FOR' => 'Search term used',
'SEARCHED_TOPIC' => 'Searched topic',
'SEARCHED_QUERY' => 'Searched query',
'SEARCH_ALL_TERMS' => 'Search for all terms or use query as entered',
'SEARCH_ANY_TERMS' => 'Search for any terms',
'SEARCH_AUTHOR' => 'Search for author',

View file

@ -87,6 +87,7 @@ $lang = array_merge($lang, array(
'ATTACHMENTS_EXPLAIN' => 'This is a list of attachments you have made in posts to this board.',
'ATTACHMENTS_DELETED' => 'Attachments successfully deleted.',
'ATTACHMENT_DELETED' => 'Attachment successfully deleted.',
'AUTOLOGIN_SESSION_KEYS_DELETED'=> 'The selected persistent login keys were successfully deleted.',
'AVATAR_CATEGORY' => 'Category',
'AVATAR_EXPLAIN' => 'Maximum dimensions; width: %1$s, height: %2$s, file size: %3$.2f KiB.',
'AVATAR_FEATURES_DISABLED' => 'The avatar functionality is currently disabled.',
@ -255,6 +256,8 @@ $lang = array_merge($lang, array(
'LINK_REMOTE_SIZE' => 'Avatar dimensions',
'LINK_REMOTE_SIZE_EXPLAIN' => 'Specify the width and height of the avatar, leave blank to attempt automatic verification.',
'LOGIN_EXPLAIN_UCP' => 'Please login in order to access the User Control Panel.',
'LOGIN_KEY' => 'Login Key',
'LOGIN_TIME' => 'Login Time',
'LOGIN_REDIRECT' => 'You have been successfully logged in.',
'LOGOUT_FAILED' => 'You were not logged out, as the request did not match your session. Please contact the board administrator if you continue to experience problems.',
'LOGOUT_REDIRECT' => 'You have been successfully logged out.',
@ -376,6 +379,8 @@ $lang = array_merge($lang, array(
'PREFERENCES_UPDATED' => 'Your preferences have been updated.',
'PROFILE_INFO_NOTICE' => 'Please note that this information may be viewable to other members. Be careful when including any personal details. Any fields marked with a * must be completed.',
'PROFILE_UPDATED' => 'Your profile has been updated.',
'PROFILE_AUTOLOGIN_KEYS' => 'The persistent login keys automatically log you in when you visit the board. If you logout, the persistent login key is deleted only on the computer you are using to logout. Here you can see persistent login keys created on other computers you used to access this site.',
'PROFILE_NO_AUTOLOGIN_KEYS' => 'There are no saved persistent login keys.',
'RECIPIENT' => 'Recipient',
'RECIPIENTS' => 'Recipients',
@ -398,6 +403,7 @@ $lang = array_merge($lang, array(
'RULE_ADDED' => 'Rule successfully added.',
'RULE_ALREADY_DEFINED' => 'This rule was defined previously.',
'RULE_DELETED' => 'Rule successfully removed.',
'RULE_LIMIT_REACHED' => 'You cannot add more PM rules. You have reached the maximum number of rules.',
'RULE_NOT_DEFINED' => 'Rule not correctly specified.',
'RULE_REMOVED_MESSAGES' => array(
1 => '%d private message was removed due to private message filters.',
@ -470,6 +476,7 @@ $lang = array_merge($lang, array(
'UCP_PROFILE_PROFILE_INFO' => 'Edit profile',
'UCP_PROFILE_REG_DETAILS' => 'Edit account settings',
'UCP_PROFILE_SIGNATURE' => 'Edit signature',
'UCP_PROFILE_AUTOLOGIN_KEYS'=> 'Edit persistent login keys',
'UCP_USERGROUPS' => 'Usergroups',
'UCP_USERGROUPS_MEMBER' => 'Edit memberships',

View file

@ -596,13 +596,24 @@ if ($keywords || $author || $author_id || $search_id || $submit)
$u_search .= ($search_fields != 'all') ? '&amp;sf=' . $search_fields : '';
$u_search .= ($return_chars != 300) ? '&amp;ch=' . $return_chars : '';
// Check if search backend supports phrase search or not
$phrase_search_disabled = '';
if (strpos(html_entity_decode($keywords), '"') !== false && method_exists($search, 'supports_phrase_search'))
{
$phrase_search_disabled = $search->supports_phrase_search() ? false : true;
}
$template->assign_vars(array(
'SEARCH_TITLE' => $l_search_title,
'SEARCH_MATCHES' => $l_search_matches,
'SEARCH_WORDS' => $search->search_query,
'SEARCH_WORDS' => $keywords,
'SEARCHED_QUERY' => $search->search_query,
'IGNORED_WORDS' => (sizeof($search->common_words)) ? implode(' ', $search->common_words) : '',
'PAGINATION' => generate_pagination($u_search, $total_match_count, $per_page, $start),
'PAGE_NUMBER' => on_page($total_match_count, $per_page, $start),
'PHRASE_SEARCH_DISABLED' => $phrase_search_disabled,
'TOTAL_MATCHES' => $total_match_count,
'SEARCH_IN_RESULTS' => ($search_id) ? false : true,

View file

@ -35,7 +35,12 @@
<!-- IF forumrow.MODERATORS -->
<br /><strong>{forumrow.L_MODERATOR_STR}:</strong> {forumrow.MODERATORS}
<!-- ENDIF -->
<!-- IF forumrow.SUBFORUMS and forumrow.S_LIST_SUBFORUMS --><br /><strong>{forumrow.L_SUBFORUM_STR}</strong> {forumrow.SUBFORUMS}<!-- ENDIF -->
<!-- IF .forumrow.subforum and forumrow.S_LIST_SUBFORUMS -->
<br /><strong>{forumrow.L_SUBFORUM_STR}</strong>
<!-- BEGIN subforum -->
<a href="{forumrow.subforum.U_SUBFORUM}" class="subforum<!-- IF forumrow.subforum.S_UNREAD --> unread<!-- ELSE --> read<!-- ENDIF -->" title="<!-- IF forumrow.subforum.UNREAD -->{L_UNREAD_POSTS}<!-- ELSE -->{L_NO_UNREAD_POSTS}<!-- ENDIF -->">{forumrow.subforum.SUBFORUM_NAME}</a><!-- IF not forumrow.subforum.S_LAST_ROW -->,<!-- ENDIF -->
<!-- END subforum -->
<!-- ENDIF -->
</dt>
<!-- IF forumrow.CLICKS -->
<dd class="redirect"><span>{L_REDIRECTS}: {forumrow.CLICKS}</span></dd>

View file

@ -67,7 +67,7 @@ onload_functions.push('subPanels()');
<dl>
<dt><label for="subject">{L_SPLIT_SUBJECT}:</label></dt>
<dd><input type="text" name="subject" id="subject" size="45" maxlength="64" tabindex="2" value="{SPLIT_SUBJECT}" title="{L_SPLIT_SUBJECT}" class="inputbox" /></dd>
<dd><input type="text" name="subject" id="subject" size="45" maxlength="124" tabindex="2" value="{SPLIT_SUBJECT}" title="{L_SPLIT_SUBJECT}" class="inputbox" /></dd>
</dl>
<dl>
<dt><label>{L_SPLIT_FORUM}:</label></dt>

View file

@ -8,9 +8,9 @@
<ul class="linklist">
<li class="icon-home"><a href="{U_INDEX}" accesskey="h">{L_INDEX}</a></li>
<!-- IF not S_IS_BOT -->
<!-- IF S_WATCH_FORUM_LINK --><li <!-- IF S_WATCHING_FORUM -->class="icon-unsubscribe"<!-- ELSE -->class="icon-subscribe"<!-- ENDIF -->><a href="{S_WATCH_FORUM_LINK}" title="{S_WATCH_FORUM_TITLE}" data-ajax="alt_text" data-alt-text="<!-- IF S_WATCHING_FORUM -->{L_START_WATCHING_FORUM}<!-- ELSE -->{L_STOP_WATCHING_FORUM}<!-- ENDIF -->">{S_WATCH_FORUM_TITLE}</a></li><!-- ENDIF -->
<!-- IF U_WATCH_TOPIC --><li <!-- IF S_WATCHING_TOPIC -->class="icon-unsubscribe"<!-- ELSE -->class="icon-subscribe"<!-- ENDIF -->><a href="{U_WATCH_TOPIC}" title="{L_WATCH_TOPIC}" data-ajax="alt_text" data-alt-text="<!-- IF S_WATCHING_TOPIC -->{L_START_WATCHING_TOPIC}<!-- ELSE -->{L_STOP_WATCHING_TOPIC}<!-- ENDIF -->">{L_WATCH_TOPIC}</a></li><!-- ENDIF -->
<!-- IF U_BOOKMARK_TOPIC --><li class="icon-bookmark"><a href="{U_BOOKMARK_TOPIC}" title="{L_BOOKMARK_TOPIC}" data-ajax="alt_text" data-alt-text="<!-- IF S_BOOKMARKED_TOPIC -->{L_BOOKMARK_TOPIC_REAL}<!-- ELSE -->{L_BOOKMARK_TOPIC_REMOVE}<!-- ENDIF -->">{L_BOOKMARK_TOPIC}</a></li><!-- ENDIF -->
<!-- IF U_WATCH_FORUM_LINK --><li <!-- IF S_WATCHING_FORUM -->class="icon-unsubscribe"<!-- ELSE -->class="icon-subscribe"<!-- ENDIF -->><a href="{U_WATCH_FORUM_LINK}" title="{S_WATCH_FORUM_TITLE}" data-ajax="toggle_link" data-toggle-class="icon-<!-- IF not S_WATCHING_FORUM -->unsubscribe<!-- ELSE -->subscribe<!-- ENDIF -->" data-toggle-text="{S_WATCH_FORUM_TOGGLE}" data-toggle-url="{U_WATCH_FORUM_TOGGLE}">{S_WATCH_FORUM_TITLE}</a></li><!-- ENDIF -->
<!-- IF U_WATCH_TOPIC --><li <!-- IF S_WATCHING_TOPIC -->class="icon-unsubscribe"<!-- ELSE -->class="icon-subscribe"<!-- ENDIF -->><a href="{U_WATCH_TOPIC}" title="{S_WATCH_TOPIC_TITLE}" data-ajax="toggle_link" data-toggle-class="<!-- IF not S_WATCHING_TOPIC -->icon-unsubscribe<!-- ELSE -->icon-subscribe<!-- ENDIF -->" data-toggle-text="{S_WATCH_TOPIC_TOGGLE}" data-toggle-url="{U_WATCH_TOPIC_TOGGLE}">{S_WATCH_TOPIC_TITLE}</a></li><!-- ENDIF -->
<!-- IF U_BOOKMARK_TOPIC --><li class="icon-bookmark"><a href="{U_BOOKMARK_TOPIC}" title="{L_BOOKMARK_TOPIC}" data-ajax="alt_text" data-alt-text="{S_BOOKMARK_TOGGLE}">{S_BOOKMARK_TOPIC}</a></li><!-- ENDIF -->
<!-- IF U_BUMP_TOPIC --><li class="icon-bump"><a href="{U_BUMP_TOPIC}" title="{L_BUMP_TOPIC}" data-ajax="true">{L_BUMP_TOPIC}</a></li><!-- ENDIF -->
<!-- ENDIF -->
<li class="rightside"><!-- IF U_TEAM --><a href="{U_TEAM}">{L_THE_TEAM}</a> &bull; <!-- ENDIF --><!-- IF not S_IS_BOT --><a href="{U_DELETE_COOKIES}" data-ajax="true" data-refresh="true">{L_DELETE_COOKIES}</a> &bull; <!-- ENDIF -->{S_TIMEZONE}</li>

View file

@ -103,7 +103,7 @@
<!-- IF S_POST_ACTION or S_PRIVMSGS or S_EDIT_DRAFT -->
<dl style="clear: left;">
<dt><label for="subject">{L_SUBJECT}:</label></dt>
<dd><input type="text" name="subject" id="subject" size="45" maxlength="<!-- IF S_NEW_MESSAGE -->60<!-- ELSE -->64<!-- ENDIF -->" tabindex="2" value="{SUBJECT}{DRAFT_SUBJECT}" class="inputbox autowidth" /></dd>
<dd><input type="text" name="subject" id="subject" size="45" maxlength="<!-- IF S_NEW_MESSAGE -->120<!-- ELSE -->124<!-- ENDIF -->" tabindex="2" value="{SUBJECT}{DRAFT_SUBJECT}" class="inputbox autowidth" /></dd>
</dl>
<!-- IF CAPTCHA_TEMPLATE and S_CONFIRM_CODE -->
<!-- DEFINE $CAPTCHA_TAB_INDEX = 3 -->

View file

@ -5,7 +5,7 @@
<fieldset class="fields1">
<dl style="clear: left;">
<dt><label for="subject">{L_SUBJECT}:</label></dt>
<dd><input type="text" name="subject" id="subject" size="45" maxlength="64" tabindex="2" value="{SUBJECT}" class="inputbox autowidth" /></dd>
<dd><input type="text" name="subject" id="subject" size="45" maxlength="124" tabindex="2" value="{SUBJECT}" class="inputbox autowidth" /></dd>
</dl>
<div id="message-box">
<textarea style="height: 9em;" name="message" rows="7" cols="76" tabindex="3" class="inputbox"></textarea>

View file

@ -1,7 +1,9 @@
<!-- INCLUDE overall_header.html -->
<h2><!-- IF SEARCH_TITLE -->{SEARCH_TITLE}<!-- ELSE -->{SEARCH_MATCHES}<!-- ENDIF --><!-- IF SEARCH_WORDS -->: <a href="{U_SEARCH_WORDS}">{SEARCH_WORDS}</a><!-- ENDIF --></h2>
<!-- IF SEARCHED_QUERY --> <p>{L_SEARCHED_QUERY}: <strong>{SEARCHED_QUERY}</strong></p><!-- ENDIF -->
<!-- IF IGNORED_WORDS --> <p>{L_IGNORED_TERMS}: <strong>{IGNORED_WORDS}</strong></p><!-- ENDIF -->
<!-- IF PHRASE_SEARCH_DISABLED --> <p><strong>{L_PHRASE_SEARCH_DISABLED}</strong></p><!-- ENDIF -->
<!-- IF SEARCH_TOPIC -->
<p><a class="{S_CONTENT_FLOW_BEGIN}" href="{U_SEARCH_TOPIC}">{L_RETURN_TO}: {SEARCH_TOPIC}</a></p>

View file

@ -93,7 +93,7 @@
<!-- IF pending.GROUP_DESC --><br />{pending.GROUP_DESC}<!-- ENDIF -->
<!-- IF not pending.GROUP_SPECIAL --><br /><i>{pending.GROUP_STATUS}</i><!-- ENDIF -->
</dt>
<dd class="mark"><input type="radio" name="selected" value="{pending.GROUP_ID}" <!-- IF pending.GROUP_SPECIAL -->disabled="diabled"<!-- ENDIF --> /></dd>
<dd class="mark"><input type="radio" name="selected" value="{pending.GROUP_ID}" <!-- IF pending.GROUP_SPECIAL -->disabled="disabled"<!-- ENDIF --> /></dd>
</dl>
</li>
<!-- END pending -->

View file

@ -17,10 +17,9 @@
<div id="page-header">
<h1>{SITENAME}</h1>
<p>{SITE_DESCRIPTION}<br /><a href="{U_FORUM}">{U_FORUM}</a></p>
<p>{SITE_DESCRIPTION}</p>
<h2>{TOPIC_TITLE}</h2>
<p><a href="{U_TOPIC}">{U_TOPIC}</a></p>
<h2>{L_PRIVATE_MESSAGING}</h2>
</div>
<div id="page-body">

View file

@ -0,0 +1,53 @@
<!-- INCLUDE ucp_header.html -->
<form id="ucp" method="post" action="{S_UCP_ACTION}"{S_FORM_ENCTYPE}>
<h2>{L_TITLE}</h2>
<div class="panel">
<div class="inner">
<fieldset>
<!-- IF .errors -->
<p class="error">
<!-- BEGIN errors -->
{errors} <br />
<!-- END errors -->
</p>
<!-- ENDIF -->
<p>{L_PROFILE_AUTOLOGIN_KEYS}</p><br />
<table cellspacing="1" class="table1">
<thead>
<tr>
<th>{L_MARK}</th>
<th>{L_LOGIN_KEY}</th>
<th>{L_IP}</th>
<th>{L_LOGIN_TIME}</th>
</tr>
</thead>
<tbody>
<!-- BEGIN sessions -->
<!-- IF sessions.S_ROW_COUNT is even --><tr class="bg1"><!-- ELSE --><tr class="bg2"><!-- ENDIF -->
<td style="text-align: center"><input type="checkbox" name="keys[]" value="{sessions.KEY}" id="{sessions.KEY}"/></td>
<td><label for="{sessions.KEY}">{sessions.KEY}</label></td>
<td style="text-align: center">{sessions.IP}</td>
<td style="text-align: center">{sessions.LOGIN_TIME}</td>
</tr>
<!-- BEGINELSE -->
<tr><td colspan="4" class="bg1" style="text-align: center">{L_PROFILE_NO_AUTOLOGIN_KEYS}</td></tr>
<!-- END sessions -->
</tbody>
</table>
</fieldset>
</div>
</div>
<!-- IF .sessions -->
<fieldset class="submit-buttons">
{S_HIDDEN_FIELDS}<input type="submit" name="submit" value="{L_DELETE}" class="button1" />
{S_FORM_TOKEN}
</fieldset>
<!-- ENDIF -->
</form>
<!-- INCLUDE ucp_footer.html -->

View file

@ -263,7 +263,7 @@
<!-- INCLUDE jumpbox.html -->
<!-- IF .quickmod -->
<form method="post" action="{S_MOD_ACTION}" id="quickmodform" data-ajax="true">
<form method="post" action="{S_MOD_ACTION}" id="quickmodform">
<fieldset class="quickmod">
<label for="quick-mod-select">{L_QUICK_MOD}:</label>
<select name="action" id="quick-mod-select">

View file

@ -48,8 +48,12 @@
<!-- IF forumrow.MODERATORS -->
<p class="forumdesc"><strong>{forumrow.L_MODERATOR_STR}:</strong> {forumrow.MODERATORS}</p>
<!-- ENDIF -->
<!-- IF forumrow.SUBFORUMS and forumrow.S_LIST_SUBFORUMS -->
<p class="forumdesc"><strong>{forumrow.L_SUBFORUM_STR}</strong> {forumrow.SUBFORUMS}</p>
<!-- IF .forumrow.subforum and forumrow.S_LIST_SUBFORUMS -->
<p class="forumdesc"><strong>{forumrow.L_SUBFORUM_STR}</strong>
<!-- BEGIN subforum -->
<a href="{forumrow.subforum.U_SUBFORUM}" class="subforum<!-- IF forumrow.subforum.S_UNREAD --> unread<!-- ELSE --> read<!-- ENDIF -->" title="<!-- IF forumrow.subforum.UNREAD -->{L_UNREAD_POSTS}<!-- ELSE -->{L_NO_UNREAD_POSTS}<!-- ENDIF -->">{forumrow.subforum.SUBFORUM_NAME}</a><!-- IF not forumrow.subforum.S_LAST_ROW -->,<!-- ENDIF -->
<!-- END subforum -->
</p>
<!-- ENDIF -->
</td>
<td class="row2" align="center"><p class="topicdetails">{forumrow.TOPICS}</p></td>

View file

@ -12,7 +12,7 @@
</tr>
<tr>
<td class="row1" nowrap="nowrap"><span class="gen">{L_SPLIT_SUBJECT}</span></td>
<td class="row2" colspan="2"><input class="post" style="width: 350px" type="text" size="35" maxlength="64" name="subject" value="{SPLIT_SUBJECT}" /></td>
<td class="row2" colspan="2"><input class="post" style="width: 350px" type="text" size="35" maxlength="124" name="subject" value="{SPLIT_SUBJECT}" /></td>
</tr>
<tr>
<td class="row1" nowrap="nowrap"><span class="gen">{L_SPLIT_FORUM}</span></td>

View file

@ -173,7 +173,7 @@
<tr>
<td class="row1" width="22%"><b class="genmed">{L_SUBJECT}:</b></td>
<td class="row2" width="78%"><input class="post" style="width:450px" type="text" name="subject" size="45" maxlength="<!-- IF S_NEW_MESSAGE -->60<!-- ELSE -->64<!-- ENDIF -->" tabindex="2" value="{SUBJECT}" /></td>
<td class="row2" width="78%"><input class="post" style="width:450px" type="text" name="subject" size="45" maxlength="<!-- IF S_NEW_MESSAGE -->120<!-- ELSE -->124<!-- ENDIF -->" tabindex="2" value="{SUBJECT}" /></td>
</tr>
<tr>
<td class="row1" valign="top"><b class="genmed">{L_MESSAGE_BODY}:</b><br /><span class="gensmall">{L_MESSAGE_BODY_EXPLAIN}&nbsp;</span><br /><br />

View file

@ -6,7 +6,7 @@
</tr>
<tr>
<td class="row1" width="22%"><b class="genmed">{L_SUBJECT}:</b></td>
<td class="row2" width="78%"><input class="post" style="width:450px" type="text" name="subject" size="45" maxlength="64" tabindex="2" value="{SUBJECT}" /></td>
<td class="row2" width="78%"><input class="post" style="width:450px" type="text" name="subject" size="45" maxlength="124" tabindex="2" value="{SUBJECT}" /></td>
</tr>
<tr>
<td class="row1" width="22%"><b class="genmed">{L_MESSAGE}:</b></td>

View file

@ -0,0 +1,49 @@
<!-- INCLUDE ucp_header.html -->
<table class="tablebg" width="100%" cellspacing="1">
<tr>
<th colspan="4" valign="middle">{L_TITLE}</th>
</tr>
<!-- IF .errors -->
<tr>
<td class="row3" colspan="2" align="center"><span class="gensmall error">
<!-- BEGIN errors -->
{errors} <br />
<!-- END errors -->
</td>
</tr>
<!-- ENDIF -->
<tr>
<td colspan="4" class="row1">{L_PROFILE_AUTOLOGIN_KEYS}</td>
</tr>
<tr>
<th>{L_MARK}</th>
<th>{L_LOGIN_KEY}</th>
<th>{L_IP}</th>
<th>{L_LOGIN_TIME}</th>
</tr>
<!-- BEGIN sessions -->
<!-- IF sessions.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF -->
<td class="genmed" style="text-align: center"><input type="checkbox" name="keys[]" value="{sessions.KEY}" id="{sessions.KEY}"/></td>
<td class="genmed"><label for="{sessions.KEY}">{sessions.KEY}</label></td>
<td class="genmed" style="text-align: center">{sessions.IP}</td>
<td class="genmed" style="text-align: center">{sessions.LOGIN_TIME}</td>
</tr>
<!-- BEGINELSE -->
<tr>
<td colspan="4" class="row1" style="text-align: center">{L_PROFILE_NO_AUTOLOGIN_KEYS}</td>
</tr>
<!-- END sessions -->
<!-- IF .sessions -->
<tr>
<td class="cat" colspan="4" align="center">
{S_HIDDEN_FIELDS}<input class="btnmain" type="submit" name="submit" value="{L_DELETE}" />
{S_FORM_TOKEN}
</td>
</tr>
<!-- ENDIF -->
</table>
<!-- INCLUDE ucp_footer.html -->

View file

@ -154,7 +154,7 @@
<td class="cat" colspan="<!-- IF S_TOPIC_ICONS -->7<!-- ELSE -->6<!-- ENDIF -->">
<table width="100%" cellspacing="0">
<tr class="nav">
<td valign="middle">&nbsp;<!-- IF S_WATCH_FORUM_LINK and not S_IS_BOT --><a href="{S_WATCH_FORUM_LINK}">{S_WATCH_FORUM_TITLE}</a><!-- ENDIF --></td>
<td valign="middle">&nbsp;<!-- IF U_WATCH_FORUM_LINK and not S_IS_BOT --><a href="{U_WATCH_FORUM_LINK}">{S_WATCH_FORUM_TITLE}</a><!-- ENDIF --></td>
<td align="{S_CONTENT_FLOW_END}" valign="middle"><!-- IF not S_IS_BOT and U_MARK_TOPICS --><a href="{U_MARK_TOPICS}">{L_MARK_TOPICS_READ}</a><!-- ENDIF -->&nbsp;</td>
</tr>
</table>

View file

@ -52,8 +52,8 @@
<tr>
<td class="nav" nowrap="nowrap">&nbsp;
<!-- IF not S_IS_BOT -->
<!-- IF U_WATCH_TOPIC --><a href="{U_WATCH_TOPIC}" title="{L_WATCH_TOPIC}">{L_WATCH_TOPIC}</a><!-- IF U_PRINT_TOPIC or U_EMAIL_TOPIC or U_BUMP_TOPIC or U_BOOKMARK_TOPIC --> | <!-- ENDIF --><!-- ENDIF -->
<!-- IF U_BOOKMARK_TOPIC --><a href="{U_BOOKMARK_TOPIC}" title="{L_BOOKMARK_TOPIC}">{L_BOOKMARK_TOPIC}</a><!-- IF U_PRINT_TOPIC or U_EMAIL_TOPIC or U_BUMP_TOPIC --> | <!-- ENDIF --><!-- ENDIF -->
<!-- IF U_WATCH_TOPIC --><a href="{U_WATCH_TOPIC}" title="{S_WATCH_TOPIC_TITLE}">{S_WATCH_TOPIC_TITLE}</a><!-- IF U_PRINT_TOPIC or U_EMAIL_TOPIC or U_BUMP_TOPIC or U_BOOKMARK_TOPIC --> | <!-- ENDIF --><!-- ENDIF -->
<!-- IF U_BOOKMARK_TOPIC --><a href="{U_BOOKMARK_TOPIC}" title="{S_BOOKMARK_TOPIC}">{S_BOOKMARK_TOPIC}</a><!-- IF U_PRINT_TOPIC or U_EMAIL_TOPIC or U_BUMP_TOPIC --> | <!-- ENDIF --><!-- ENDIF -->
<!-- IF U_PRINT_TOPIC --><a href="{U_PRINT_TOPIC}" title="{L_PRINT_TOPIC}">{L_PRINT_TOPIC}</a><!-- IF U_EMAIL_TOPIC or U_BUMP_TOPIC --> | <!-- ENDIF --><!-- ENDIF -->
<!-- IF U_EMAIL_TOPIC --><a href="{U_EMAIL_TOPIC}" title="{L_EMAIL_TOPIC}">{L_EMAIL_TOPIC}</a><!-- IF U_BUMP_TOPIC --> | <!-- ENDIF --><!-- ENDIF -->
<!-- IF U_BUMP_TOPIC --><a href="{U_BUMP_TOPIC}" title="{L_BUMP_TOPIC}">{L_BUMP_TOPIC}</a><!-- ENDIF -->

View file

@ -204,7 +204,9 @@ if (!$config['use_system_cron'])
// Forum rules and subscription info
$s_watching_forum = array(
'link' => '',
'link_toggle' => '',
'title' => '',
'title_toggle' => '',
'is_watching' => false,
);
@ -318,8 +320,10 @@ $template->assign_vars(array(
'S_SELECT_SORT_KEY' => $s_sort_key,
'S_SELECT_SORT_DAYS' => $s_limit_days,
'S_TOPIC_ICONS' => ($s_display_active && sizeof($active_forum_ary)) ? max($active_forum_ary['enable_icons']) : (($forum_data['enable_icons']) ? true : false),
'S_WATCH_FORUM_LINK' => $s_watching_forum['link'],
'U_WATCH_FORUM_LINK' => $s_watching_forum['link'],
'U_WATCH_FORUM_TOGGLE' => $s_watching_forum['link_toggle'],
'S_WATCH_FORUM_TITLE' => $s_watching_forum['title'],
'S_WATCH_FORUM_TOGGLE' => $s_watching_forum['title_toggle'],
'S_WATCHING_FORUM' => $s_watching_forum['is_watching'],
'S_FORUM_ACTION' => append_sid("{$phpbb_root_path}viewforum.$phpEx", "f=$forum_id" . (($start == 0) ? '' : "&amp;start=$start")),
'S_DISPLAY_SEARCHBOX' => ($auth->acl_get('u_search') && $auth->acl_get('f_search', $forum_id) && $config['load_search']) ? true : false,

View file

@ -449,7 +449,9 @@ $viewtopic_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f=$forum_id&a
// Are we watching this topic?
$s_watching_topic = array(
'link' => '',
'link_toggle' => '',
'title' => '',
'title_toggle' => '',
'is_watching' => false,
);
@ -649,13 +651,15 @@ $template->assign_vars(array(
'U_PRINT_TOPIC' => ($auth->acl_get('f_print', $forum_id)) ? $viewtopic_url . '&amp;view=print' : '',
'U_EMAIL_TOPIC' => ($auth->acl_get('f_email', $forum_id) && $config['email_enable']) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=email&amp;t=$topic_id") : '',
'U_WATCH_TOPIC' => $s_watching_topic['link'],
'L_WATCH_TOPIC' => $s_watching_topic['title'],
'U_WATCH_TOPIC' => $s_watching_topic['link'],
'U_WATCH_TOPIC_TOGGLE' => $s_watching_topic['link_toggle'],
'S_WATCH_TOPIC_TITLE' => $s_watching_topic['title'],
'S_WATCH_TOPIC_TOGGLE' => $s_watching_topic['title_toggle'],
'S_WATCHING_TOPIC' => $s_watching_topic['is_watching'],
'U_BOOKMARK_TOPIC' => ($user->data['is_registered'] && $config['allow_bookmarks']) ? $viewtopic_url . '&amp;bookmark=1&amp;hash=' . generate_link_hash("topic_$topic_id") : '',
'L_BOOKMARK_TOPIC' => ($user->data['is_registered'] && $config['allow_bookmarks'] && $topic_data['bookmarked']) ? $user->lang['BOOKMARK_TOPIC_REMOVE'] : $user->lang['BOOKMARK_TOPIC'],
'L_BOOKMARK_TOPIC_REAL' => $user->lang['BOOKMARK_TOPIC'],
'S_BOOKMARK_TOPIC' => ($user->data['is_registered'] && $config['allow_bookmarks'] && $topic_data['bookmarked']) ? $user->lang['BOOKMARK_TOPIC_REMOVE'] : $user->lang['BOOKMARK_TOPIC'],
'S_BOOKMARK_TOGGLE' => (!$user->data['is_registered'] || !$config['allow_bookmarks'] || !$topic_data['bookmarked']) ? $user->lang['BOOKMARK_TOPIC_REMOVE'] : $user->lang['BOOKMARK_TOPIC'],
'S_BOOKMARKED_TOPIC' => ($user->data['is_registered'] && $config['allow_bookmarks'] && $topic_data['bookmarked']) ? true : false,
'U_POST_NEW_TOPIC' => ($auth->acl_get('f_post', $forum_id) || $user->data['user_id'] == ANONYMOUS) ? append_sid("{$phpbb_root_path}posting.$phpEx", "mode=post&amp;f=$forum_id") : '',

View file

@ -51,6 +51,27 @@ test_config.php file:
PHPBB_TEST_DBNAME='database' PHPBB_TEST_DBUSER='user' \
PHPBB_TEST_DBPASSWD='password' phpunit
Special Database Cases
----------------------
In order to run tests on some of the databases that we support, it will be
necessary to provide a custom DSN string in test_config.php. This is only
needed for MSSQL 2000+ (PHP module), MSSQL via ODBC, and Firebird when
PDO_Firebird does not work on your system
(https://bugs.php.net/bug.php?id=61183). The variable must be named $custom_dsn.
Examples:
Firebird using http://www.firebirdsql.org/en/odbc-driver/
$custom_dsn = "Driver={Firebird/InterBase(r) driver};dbname=$dbhost:$dbname";
MSSQL
$custom_dsn = "Driver={SQL Server Native Client 10.0};Server=$dbhost;Database=$dbname";
The other fields in test_config.php should be filled out as you would normally
to connect to that database in phpBB.
Additionally, you will need to be running the DbUnit fork from
https://github.com/phpbb/dbunit/tree/phpbb.
Running
=======

View file

@ -11,8 +11,6 @@ require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/bbcode.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/message_parser.php';
require_once dirname(__FILE__) . '/../mock_user.php';
require_once dirname(__FILE__) . '/../mock/request.php';
class phpbb_url_bbcode_test extends phpbb_test_case
{

View file

@ -16,6 +16,8 @@ $table_prefix = 'phpbb_';
require_once $phpbb_root_path . 'includes/constants.php';
require_once $phpbb_root_path . 'includes/class_loader.' . $phpEx;
$phpbb_class_loader_mock = new phpbb_class_loader('phpbb_mock_', $phpbb_root_path . '../tests/mock/', ".php");
$phpbb_class_loader_mock->register();
$phpbb_class_loader_ext = new phpbb_class_loader('phpbb_ext_', $phpbb_root_path . 'ext/', ".php");
$phpbb_class_loader_ext->register();
$phpbb_class_loader = new phpbb_class_loader('phpbb_', $phpbb_root_path . 'includes/', ".php");

View file

@ -7,8 +7,6 @@
*
*/
require_once dirname(__FILE__) . '/../mock/cache.php';
class phpbb_class_loader_test extends PHPUnit_Framework_TestCase
{
public function setUp()

View file

@ -7,8 +7,6 @@
*
*/
require_once dirname(__FILE__) . '/../mock/cache.php';
class phpbb_config_db_test extends phpbb_database_test_case
{
private $cache;

View file

@ -7,7 +7,6 @@
*
*/
require_once dirname(__FILE__) . '/../mock/extension_manager.php';
require_once dirname(__FILE__) . '/includes/cron/task/core/dummy_task.php';
require_once dirname(__FILE__) . '/includes/cron/task/core/second_dummy_task.php';
require_once dirname(__FILE__) . '/ext/testext/cron/dummy_task.php';

View file

@ -7,8 +7,6 @@
*
*/
require_once dirname(__FILE__) . '/../mock/extension_manager.php';
class phpbb_cron_task_provider_test extends PHPUnit_Framework_TestCase
{
public function setUp()

69
tests/dbal/case_test.php Normal file
View file

@ -0,0 +1,69 @@
<?php
/**
*
* @package testing
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
class phpbb_dbal_case_test extends phpbb_database_test_case
{
public function getDataSet()
{
return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/config.xml');
}
public function test_case_int()
{
$db = $this->new_dbal();
$sql = 'SELECT ' . $db->sql_case('1 = 1', '1', '2') . ' AS test_num
FROM phpbb_config';
$result = $db->sql_query_limit($sql, 1);
$this->assertEquals(1, (int) $db->sql_fetchfield('test_num'));
$sql = 'SELECT ' . $db->sql_case('1 = 0', '1', '2') . ' AS test_num
FROM phpbb_config';
$result = $db->sql_query_limit($sql, 1);
$this->assertEquals(2, (int) $db->sql_fetchfield('test_num'));
}
public function test_case_string()
{
$db = $this->new_dbal();
$sql = 'SELECT ' . $db->sql_case('1 = 1', "'foo'", "'bar'") . ' AS test_string
FROM phpbb_config';
$result = $db->sql_query_limit($sql, 1);
$this->assertEquals('foo', $db->sql_fetchfield('test_string'));
$sql = 'SELECT ' . $db->sql_case('1 = 0', "'foo'", "'bar'") . ' AS test_string
FROM phpbb_config';
$result = $db->sql_query_limit($sql, 1);
$this->assertEquals('bar', $db->sql_fetchfield('test_string'));
}
public function test_case_column()
{
$db = $this->new_dbal();
$sql = 'SELECT ' . $db->sql_case("config_name = 'config1'", 'config_name', 'config_value') . " AS test_string
FROM phpbb_config
WHERE config_name = 'config1'";
$result = $db->sql_query_limit($sql, 1);
$this->assertEquals('config1', $db->sql_fetchfield('test_string'));
$sql = 'SELECT ' . $db->sql_case("config_name = 'config1'", 'config_name', 'config_value') . " AS test_string
FROM phpbb_config
WHERE config_value = 'bar'";
$result = $db->sql_query_limit($sql, 1);
$this->assertEquals('bar', $db->sql_fetchfield('test_string'));
}
}

View file

@ -0,0 +1,64 @@
<?php
/**
*
* @package testing
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
class phpbb_dbal_concatenate_test extends phpbb_database_test_case
{
public function getDataSet()
{
return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/config.xml');
}
public function test_concatenate_string()
{
$db = $this->new_dbal();
$sql = 'SELECT config_name, ' . $db->sql_concatenate('config_name', "'" . $db->sql_escape('append') . "'") . ' AS string
FROM phpbb_config';
$result = $db->sql_query($sql);
$db->sql_return_on_error(false);
$this->assertEquals(array(
array(
'config_name' => 'config1',
'string' => 'config1append',
),
array(
'config_name' => 'config2',
'string' => 'config2append',
),
),
$db->sql_fetchrowset($result)
);
}
public function test_concatenate_statement()
{
$db = $this->new_dbal();
$sql = 'SELECT config_name, ' . $db->sql_concatenate('config_name', 'config_value') . ' AS string
FROM phpbb_config';
$result = $db->sql_query($sql);
$db->sql_return_on_error(false);
$this->assertEquals(array(
array(
'config_name' => 'config1',
'string' => 'config1foo',
),
array(
'config_name' => 'config2',
'string' => 'config2bar',
),
),
$db->sql_fetchrowset($result)
);
}
}

View file

@ -14,7 +14,7 @@ class phpbb_dbal_order_lower_test extends phpbb_database_test_case
return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/styles.xml');
}
public function test_cross_join()
public function test_order_lower()
{
$db = $this->new_dbal();

View file

@ -8,7 +8,6 @@
*/
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_download.php';
require_once dirname(__FILE__) . '/../mock/request.php';
class phpbb_download_http_byte_range_test extends phpbb_test_case
{

View file

@ -7,9 +7,6 @@
*
*/
require_once dirname(__FILE__) . '/../mock/cache.php';
require_once dirname(__FILE__) . '/../mock/extension_manager.php';
class phpbb_extension_finder_test extends phpbb_test_case
{
protected $extension_manager;

View file

@ -7,7 +7,6 @@
*
*/
require_once dirname(__FILE__) . '/../mock/cache.php';
require_once dirname(__FILE__) . '/ext/bar/ext.php';
require_once dirname(__FILE__) . '/ext/foo/ext.php';
require_once dirname(__FILE__) . '/ext/vendor/moo/ext.php';

View file

@ -65,15 +65,6 @@ class phpbb_functional_extension_controller_test extends phpbb_functional_test_c
}
}
public static function tearDownAfterClass()
{
$phpbb_root_path = self::$config['phpbb_functional_path'];
// @todo delete the fixtures from the $phpbb_root_path board
// Note that it might be best to find a public domain function
// and port it into here instead of writing it from scratch
}
public function setUp()
{
parent::setUp();

View file

@ -0,0 +1,62 @@
<?php
/**
*
* @package testing
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @group functional
*/
class phpbb_functional_fileupload_form_test extends phpbb_functional_test_case
{
private $path;
public function setUp()
{
parent::setUp();
$this->path = __DIR__ . '/fixtures/files/';
$this->add_lang('posting');
$this->login();
}
public function test_empty_file()
{
$crawler = $this->request('GET', 'posting.php?mode=reply&f=2&t=1&sid=' . $this->sid);
$form = $crawler->selectButton('add_file')->form();
$form['fileupload']->upload($this->path . 'empty.png');
$crawler = $this->client->submit($form);
$this->assertEquals($this->lang('ATTACHED_IMAGE_NOT_IMAGE'), $crawler->filter('div#message p')->text());
}
public function test_invalid_extension()
{
$crawler = $this->request('GET', 'posting.php?mode=reply&f=2&t=1&sid=' . $this->sid);
$form = $crawler->selectButton('add_file')->form();
$form['fileupload']->upload($this->path . 'illegal-extension.bif');
$crawler = $this->client->submit($form);
$this->assertEquals($this->lang('DISALLOWED_EXTENSION', 'bif'), $crawler->filter('p.error')->text());
}
public function test_too_large()
{
$this->markTestIncomplete('Functional tests use an admin account which ignores maximum upload size.');
$crawler = $this->request('GET', 'posting.php?mode=reply&f=2&t=1&sid=' . $this->sid);
$form = $crawler->selectButton('add_file')->form();
$form['fileupload']->upload($this->path . 'too-large.png');
$crawler = $this->client->submit($form);
$this->assertEquals($this->lang('WRONG_FILESIZE', '256', 'KiB'), $crawler->filter('p.error')->text());
}
public function test_valid_file()
{
$crawler = $this->request('GET', 'posting.php?mode=reply&f=2&t=1&sid=' . $this->sid);
$form = $crawler->selectButton('add_file')->form();
$form['fileupload']->upload($this->path . 'valid.jpg');
$crawler = $this->client->submit($form);
$this->assertEquals(0, $crawler->filter('p.error')->count());
$this->assertContains($this->lang('POSTED_ATTACHMENTS'), $crawler->filter('#postform h3')->eq(1)->text());
}
}

View file

@ -0,0 +1,72 @@
<?php
/**
*
* @package testing
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @group functional
*/
class phpbb_functional_fileupload_remote_test extends phpbb_functional_test_case
{
public function setUp()
{
parent::setUp();
// Only doing this within the functional framework because we need a
// URL
// Global $config required by unique_id
// Global $user required by fileupload::remote_upload
global $config, $user;
if (!is_array($config))
{
$config = array();
}
$config['rand_seed'] = '';
$config['rand_seed_last_update'] = time() + 600;
$user = new phpbb_mock_user();
$user->lang = new phpbb_mock_lang();
}
public function tearDown()
{
global $config, $user;
$user = null;
$config = array();
}
public function test_invalid_extension()
{
$upload = new fileupload('', array('jpg'), 100);
$file = $upload->remote_upload('http://example.com/image.gif');
$this->assertEquals('URL_INVALID', $file->error[0]);
}
public function test_non_existant()
{
$upload = new fileupload('', array('jpg'), 100);
$file = $upload->remote_upload('http://example.com/image.jpg');
$this->assertEquals('EMPTY_REMOTE_DATA', $file->error[0]);
}
public function test_successful_upload()
{
$upload = new fileupload('', array('gif'), 1000);
$file = $upload->remote_upload($this->root_url . 'styles/prosilver/theme/images/forum_read.gif');
$this->assertEquals(0, sizeof($file->error));
$this->assertTrue(file_exists($file->filename));
}
public function test_too_large()
{
$upload = new fileupload('', array('gif'), 100);
$file = $upload->remote_upload($this->root_url . 'styles/prosilver/theme/images/forum_read.gif');
$this->assertEquals('WRONG_FILESIZE', $file->error[0]);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 519 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 B

View file

@ -7,7 +7,6 @@
*
*/
require_once dirname(__FILE__) . '/../mock/lang.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_acp.php';
class phpbb_functions_acp_build_cfg_template_test extends phpbb_test_case

View file

@ -7,7 +7,6 @@
*
*/
require_once dirname(__FILE__) . '/../mock/lang.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_acp.php';
class phpbb_functions_acp_built_select_test extends phpbb_test_case

View file

@ -7,7 +7,6 @@
*
*/
require_once dirname(__FILE__) . '/../mock/lang.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_acp.php';
class phpbb_functions_acp_h_radio_test extends phpbb_test_case

View file

@ -7,7 +7,6 @@
*
*/
require_once dirname(__FILE__) . '/../mock/lang.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_acp.php';
class phpbb_functions_acp_validate_config_vars_test extends phpbb_test_case

View file

@ -7,7 +7,6 @@
*
*/
require_once dirname(__FILE__) . '/../mock/lang.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php';
require_once dirname(__FILE__) . '/../../phpBB/includes/functions_acp.php';

32
tests/mock/filespec.php Normal file
View file

@ -0,0 +1,32 @@
<?php
/**
*
* @package testing
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* Mock filespec class with some basic values to help with testing the
* fileupload class
*/
class phpbb_mock_filespec
{
public $filesize;
public $realname;
public $extension;
public $width;
public $height;
public $error = array();
public function check_content($disallowed_content)
{
return true;
}
public function get($property)
{
return $this->$property;
}
}

52
tests/mock/fileupload.php Normal file
View file

@ -0,0 +1,52 @@
<?php
/**
*
* @package testing
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* Mock fileupload class with some basic values to help with testing the
* filespec class
*/
class phpbb_mock_fileupload
{
public $max_filesize = 100;
public $error_prefix = '';
public function valid_dimensions($filespec)
{
return true;
}
/**
* Copied verbatim from phpBB/includes/functions_upload.php's fileupload
* class to ensure the correct behaviour of filespec::move_file.
*
* Maps file extensions to the constant in second index of the array
* returned by getimagesize()
*/
public function image_types()
{
return array(
IMAGETYPE_GIF => array('gif'),
IMAGETYPE_JPEG => array('jpg', 'jpeg'),
IMAGETYPE_PNG => array('png'),
IMAGETYPE_SWF => array('swf'),
IMAGETYPE_PSD => array('psd'),
IMAGETYPE_BMP => array('bmp'),
IMAGETYPE_TIFF_II => array('tif', 'tiff'),
IMAGETYPE_TIFF_MM => array('tif', 'tiff'),
IMAGETYPE_JPC => array('jpg', 'jpeg'),
IMAGETYPE_JP2 => array('jpg', 'jpeg'),
IMAGETYPE_JPX => array('jpg', 'jpeg'),
IMAGETYPE_JB2 => array('jpg', 'jpeg'),
IMAGETYPE_SWC => array('swc'),
IMAGETYPE_IFF => array('iff'),
IMAGETYPE_WBMP => array('wbmp'),
IMAGETYPE_XBM => array('xbm'),
);
}
}

View file

@ -7,8 +7,6 @@
*
*/
require_once dirname(__FILE__) . '/../mock/request.php';
abstract class phpbb_security_test_base extends phpbb_test_case
{
/**

View file

@ -7,7 +7,6 @@
*
*/
require_once dirname(__FILE__) . '/../mock/cache.php';
require_once dirname(__FILE__) . '/testable_factory.php';
class phpbb_session_continue_test extends phpbb_database_test_case

View file

@ -7,7 +7,6 @@
*
*/
require_once dirname(__FILE__) . '/../mock/cache.php';
require_once dirname(__FILE__) . '/testable_factory.php';
class phpbb_session_init_test extends phpbb_database_test_case

View file

@ -7,9 +7,6 @@
*
*/
require_once dirname(__FILE__) . '/../mock/request.php';
require_once dirname(__FILE__) . '/../mock/session_testable.php';
/**
* This class exists to setup an instance of phpbb's session class for testing.
*

View file

@ -0,0 +1,87 @@
<?php
/**
*
* @package testing
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
require_once dirname(__FILE__) . '/template_test_case.php';
class phpbb_template_invalid_constructs_test extends phpbb_template_template_test_case
{
public function template_data()
{
return array(
array(
'Unknown tag',
'invalid/unknown_tag.html',
array(),
array(),
array(),
'invalid/output/unknown_tag.html',
),
/*
* Produces a parse error which is fatal, therefore
* destroying the test suite.
array(
'ENDIF without IF',
'invalid/endif_without_if.html',
array(),
array(),
array(),
'invalid/output/endif_without_if.html',
),
*/
);
}
public function template_data_error()
{
return array(
array(
'Include a nonexistent file',
'invalid/include_nonexistent_file.html',
array(),
array(),
array(),
E_USER_ERROR,
'invalid/output/include_nonexistent_file.html',
),
);
}
/**
* @dataProvider template_data
*/
public function test_template($description, $file, $vars, $block_vars, $destroy, $expected)
{
$cache_file = $this->template->cachepath . str_replace('/', '.', $file) . '.php';
$this->assertFileNotExists($cache_file);
$expected = file_get_contents(dirname(__FILE__) . '/templates/' . $expected);
// apparently the template engine does not put
// the trailing newline into compiled templates
$expected = trim($expected);
$this->run_template($file, $vars, $block_vars, $destroy, $expected, $cache_file);
}
/**
* @dataProvider template_data_error
*/
public function test_template_error($description, $file, $vars, $block_vars, $destroy, $error, $expected)
{
$cache_file = $this->template->cachepath . str_replace('/', '.', $file) . '.php';
$this->assertFileNotExists($cache_file);
$expected = file_get_contents(dirname(__FILE__) . '/templates/' . $expected);
// apparently the template engine does not put
// the trailing newline into compiled templates
$expected = trim($expected);
$this->setExpectedTriggerError($error, $expected);
$this->run_template($file, $vars, $block_vars, $destroy, '', $cache_file);
}
}

View file

@ -0,0 +1 @@
// JavaScript file in a parent style.

View file

@ -0,0 +1 @@
// JavaScript file only in parent style.

View file

@ -17,15 +17,14 @@ class phpbb_template_template_includejs_test extends phpbb_template_template_tes
$this->setup_engine(array('assets_version' => 1));
// Prepare correct result
$dir = dirname(__FILE__);
$scripts = array(
'<script src="' . $dir . '/templates/parent_and_child.html?assets_version=1"></script>',
'<script src="' . $dir . '/parent_templates/parent_only.html?assets_version=1"></script>',
'<script src="' . $dir . '/templates/child_only.html?assets_version=1"></script>'
'<script src="' . $this->test_path . '/templates/parent_and_child.js?assets_version=1"></script>',
'<script src="' . $this->test_path . '/parent_templates/parent_only.js?assets_version=1"></script>',
'<script src="' . $this->test_path . '/templates/child_only.js?assets_version=1"></script>'
);
// Run test
$cache_file = $this->template->cachepath . 'includejs.html.php';
$this->run_template('includejs.html', array('PARENT' => 'parent_only.html'), array(), array(), implode('', $scripts), $cache_file);
$this->run_template('includejs.html', array('PARENT' => 'parent_only.js'), array(), array(), implode('', $scripts), $cache_file);
}
}

View file

@ -17,21 +17,21 @@ class phpbb_template_template_locate_test extends phpbb_template_template_test_c
// First element of the array is test name - keep them distinct
array(
'simple inheritance - only parent template exists',
dirname(__FILE__) . '/parent_templates/parent_only.html',
$this->test_path . '/parent_templates/parent_only.html',
'parent_only.html',
false,
true,
),
array(
'simple inheritance - only child template exists',
dirname(__FILE__) . '/templates/child_only.html',
$this->test_path . '/templates/child_only.html',
'child_only.html',
false,
true,
),
array(
'simple inheritance - both parent and child templates exist',
dirname(__FILE__) . '/templates/parent_and_child.html',
$this->test_path . '/templates/parent_and_child.html',
'parent_and_child.html',
false,
true,

View file

@ -277,7 +277,7 @@ class phpbb_template_template_test extends phpbb_template_template_test_case
$this->template->set_filenames(array('test' => $filename));
$this->assertFileNotExists($this->template_path . '/' . $filename, 'Testing missing file, file cannot exist');
$expecting = sprintf('style resource locator: File for handle test does not exist. Could not find: %s', realpath($this->template_path . '/../') . '/templates/' . $filename);
$expecting = sprintf('style resource locator: File for handle test does not exist. Could not find: %s', $this->test_path . '/templates/' . $filename);
$this->setExpectedTriggerError(E_USER_ERROR, $expecting);
$this->display('test');

View file

@ -8,7 +8,6 @@
*/
require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/../mock/extension_manager.php';
class phpbb_template_template_test_case extends phpbb_test_case
{
@ -18,6 +17,8 @@ class phpbb_template_template_test_case extends phpbb_test_case
protected $style_resource_locator;
protected $style_provider;
protected $test_path = 'tests/template';
// Keep the contents of the cache for debugging?
const PRESERVE_CACHE = true;
@ -63,7 +64,7 @@ class phpbb_template_template_test_case extends phpbb_test_case
$defaults = $this->config_defaults();
$config = new phpbb_config(array_merge($defaults, $new_config));
$this->template_path = dirname(__FILE__) . '/templates';
$this->template_path = $this->test_path . '/templates';
$this->style_resource_locator = new phpbb_style_resource_locator();
$this->style_provider = new phpbb_style_path_provider();
$this->template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $this->style_resource_locator);

View file

@ -18,8 +18,8 @@ class phpbb_template_template_test_case_with_tree extends phpbb_template_templat
$defaults = $this->config_defaults();
$config = new phpbb_config(array_merge($defaults, $new_config));
$this->template_path = dirname(__FILE__) . '/templates';
$this->parent_template_path = dirname(__FILE__) . '/parent_templates';
$this->template_path = $this->test_path . '/templates';
$this->parent_template_path = $this->test_path . '/parent_templates';
$this->style_resource_locator = new phpbb_style_resource_locator();
$this->style_provider = new phpbb_style_path_provider();
$this->template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $this->style_resource_locator);

Some files were not shown because too many files have changed in this diff Show more