aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbuild/build_diff.php4
-rwxr-xr-xbuild/package.php2
-rwxr-xr-xgit-tools/hooks/pre-commit72
-rwxr-xr-xgit-tools/hooks/prepare-commit-msg34
-rwxr-xr-xphpBB/develop/fix_files.sh2
-rw-r--r--phpBB/docs/CHANGELOG.html20
-rw-r--r--phpBB/docs/INSTALL.html4
-rw-r--r--phpBB/feed.php8
-rw-r--r--phpBB/includes/acm/acm_memcache.php14
-rw-r--r--phpBB/includes/acp/acp_forums.php4
-rw-r--r--phpBB/includes/acp/acp_language.php4
-rw-r--r--phpBB/includes/acp/acp_styles.php4
-rw-r--r--phpBB/includes/constants.php2
-rw-r--r--phpBB/includes/functions.php98
-rw-r--r--phpBB/includes/functions_compress.php4
-rw-r--r--phpBB/includes/session.php10
-rw-r--r--phpBB/install/convertors/convert_phpbb20.php4
-rw-r--r--phpBB/install/database_update.php6
-rw-r--r--tests/all_tests.php56
-rw-r--r--tests/dbal/all_tests.php40
-rw-r--r--tests/dbal/dbal.php328
-rw-r--r--tests/dbal/fixtures/three_users.xml19
-rw-r--r--tests/request/all_tests.php41
-rw-r--r--tests/request/request_var.php180
-rw-r--r--tests/security/all_tests.php86
-rw-r--r--tests/security/extract_current_page.php53
-rw-r--r--tests/security/redirect.php58
-rw-r--r--tests/template/all_tests.php40
-rw-r--r--tests/template/template.php671
-rw-r--r--tests/template/templates/_dummy_include.php3
-rw-r--r--tests/template/templates/basic.html20
-rw-r--r--tests/template/templates/define.html8
-rw-r--r--tests/template/templates/expressions.html86
-rw-r--r--tests/template/templates/if.html11
-rw-r--r--tests/template/templates/include.html1
-rw-r--r--tests/template/templates/includephp.html1
-rw-r--r--tests/template/templates/lang.html3
-rw-r--r--tests/template/templates/loop.html21
-rw-r--r--tests/template/templates/loop_advanced.html19
-rw-r--r--tests/template/templates/loop_nested.html8
-rw-r--r--tests/template/templates/loop_vars.html21
-rw-r--r--tests/template/templates/php.html1
-rw-r--r--tests/template/templates/variable.html1
-rw-r--r--tests/test_framework/framework.php39
-rw-r--r--tests/test_framework/phpbb_database_test_case.php168
-rw-r--r--tests/test_framework/phpbb_test_case.php27
-rw-r--r--tests/test_framework/phpbb_test_case_helpers.php97
-rw-r--r--tests/text_processing/all_tests.php41
-rw-r--r--tests/text_processing/make_clickable.php106
-rw-r--r--tests/utf/all_tests.php43
-rw-r--r--tests/utf/utf8_clean_string_test.php32
-rw-r--r--tests/utf/utf8_wordwrap_test.php84
52 files changed, 2637 insertions, 72 deletions
diff --git a/build/build_diff.php b/build/build_diff.php
index c8a40f4f5e..ef815bc0c3 100755
--- a/build/build_diff.php
+++ b/build/build_diff.php
@@ -11,9 +11,9 @@
// CONFIG - Begin
$substitute_old = '3.0.6';
-$substitute_new = '3.0.7';
+$substitute_new = '3.0.7-PL1';
$simple_name_old = 'phpbb306';
-$simple_name_new = 'phpbb307';
+$simple_name_new = 'phpbb307-PL1';
$echo_changes = false;
// Set this to true to just compress the changes and do not build them again
// This should be used for building custom modified txt file. ;)
diff --git a/build/package.php b/build/package.php
index e04750d4be..7cb30bd493 100755
--- a/build/package.php
+++ b/build/package.php
@@ -15,7 +15,7 @@
// If RC8 drops remove the install/data directory
//$versions = array('3.0.2', '3.0.3-RC1', '3.0.3', '3.0.4-RC1', '3.0.4', '3.0.5-RC1', '3.0.5', '3.0.6-RC1', '3.0.6-RC2', '3.0.6-RC3');
//$versions = array('3.0.2', '3.0.3', '3.0.4', '3.0.5', '3.0.6', '3.0.7-RC1', '3.0.7');
-$versions = array('3.0.2', '3.0.3', '3.0.4', '3.0.5', '3.0.6', '3.0.7-RC1', '3.0.7-RC2', '3.0.7');
+$versions = array('3.0.2', '3.0.3', '3.0.4', '3.0.5', '3.0.6', '3.0.7-RC1', '3.0.7-RC2', '3.0.7', '3.0.7-PL1');
$verbose = false;
require('build_helper.php');
diff --git a/git-tools/hooks/pre-commit b/git-tools/hooks/pre-commit
new file mode 100755
index 0000000000..23ab8d6cdb
--- /dev/null
+++ b/git-tools/hooks/pre-commit
@@ -0,0 +1,72 @@
+#!/usr/bin/env bash
+#
+# A hook to disallow php syntax errors to be committed
+# by running php -l (lint) on them. It requires php-cli
+# to be installed.
+#
+# This is a pre-commit hook.
+#
+# To install this you can either copy or symlink it to
+# $GIT_DIR/hooks, example:
+#
+# ln -s ../../git-tools/hooks/pre-commit \\
+# .git/hooks/pre-commit
+
+# NOTE: this is run through /usr/bin/env
+PHP_BIN=php
+
+# necessary check for initial commit
+if git rev-parse --verify HEAD >/dev/null 2>&1
+then
+ against=HEAD
+else
+ # Initial commit: diff against an empty tree object
+ against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+fi
+
+error=0
+errors=""
+
+IFS=$'\n'
+# get a list of staged files
+for line in $(git diff-index --cached --full-index $against)
+do
+ # split needed values
+ sha=$(echo $line | cut -d' ' -f4)
+ temp=$(echo $line | cut -d' ' -f5)
+ status=$(echo $temp | cut -d' ' -f1)
+ filename=$(echo $temp | cut -d' ' -f2)
+
+ # file extension
+ ext=$(echo $filename | sed 's/^.*\.//')
+
+ # only check files with php extension
+ if [ $ext != "php" ]
+ then
+ continue
+ fi
+
+ # do not check deleted files
+ if [ $status = "D" ]
+ then
+ continue
+ fi
+
+ # check the staged file content for syntax errors
+ # using php -l (lint)
+ result=$(git cat-file -p $sha | /usr/bin/env $PHP_BIN -l 2>/dev/null)
+ if [ $? -ne 0 ]
+ then
+ error=1
+ # Swap back in correct filenames
+ errors+=${result//in - on/"$filename"}
+ fi
+done
+unset IFS
+
+if [ $error -eq 1 ]
+then
+ echo -e "PHP Syntax check failed:";
+ echo -e "$errors" | grep "^Parse error:"
+ exit 1
+fi
diff --git a/git-tools/hooks/prepare-commit-msg b/git-tools/hooks/prepare-commit-msg
new file mode 100755
index 0000000000..033cb187c7
--- /dev/null
+++ b/git-tools/hooks/prepare-commit-msg
@@ -0,0 +1,34 @@
+#!/bin/sh
+#
+# A hook to add [$branch] to the beginning of a commit message
+# if certain conditions are met.
+#
+# This is a prepare-commit-msg hook.
+#
+# To install this you can either copy or symlink it to
+# $GIT_DIR/hooks, example:
+#
+# ln -s ../../git-tools/hooks/prepare-commit-msg \\
+# .git/hooks/prepare-commit-msg
+
+# get branch name
+branch="$(git symbolic-ref HEAD)"
+
+# exit if no branch name is present
+# (eg. detached HEAD)
+if [ $? -ne 0 ]
+then
+ exit
+fi
+
+# strip off refs/heads/
+branch="$(echo "$branch" | sed "s/refs\/heads\///g")"
+
+# add [branchname] to commit message
+# * only run when normal commit is made (without -m or -F;
+# not a merge, etc.)
+# * also make sure the branch name begins with bug/ or feature/
+if [ "$2" = "" ]
+then
+ echo "[$branch] $(cat "$1")" > "$1"
+fi
diff --git a/phpBB/develop/fix_files.sh b/phpBB/develop/fix_files.sh
index d2207289dc..bf58e49e5f 100755
--- a/phpBB/develop/fix_files.sh
+++ b/phpBB/develop/fix_files.sh
@@ -14,7 +14,7 @@ find . > FILELIST.$$
grep -sv FILELIST FILELIST.$$ > FILELIST2.$$
grep -sv $(basename $0) FILELIST2.$$ > FILELIST.$$
grep -sv "^\.$" FILELIST.$$ > FILELIST2.$$
-file -f FILELIST2.$$ |grep text | sed -e 's/^\([^\:]*\)\:.*$/\1/' > FILELIST
+file -f FILELIST2.$$ |grep text | grep -v icon_textbox_search.gif | sed -e 's/^\([^\:]*\)\:.*$/\1/' > FILELIST
file -f FILELIST2.$$ |grep -sv text | sed -e 's/^\([^\:]*\)\:.*$/Not Modifying file: \1/'
rm FILELIST2.$$
rm FILELIST.$$
diff --git a/phpBB/docs/CHANGELOG.html b/phpBB/docs/CHANGELOG.html
index 5bd003eb40..4572c220a8 100644
--- a/phpBB/docs/CHANGELOG.html
+++ b/phpBB/docs/CHANGELOG.html
@@ -53,6 +53,7 @@
<ol>
<li><a href="#changelog">Changelog</a>
<ol style="list-style-type: lower-roman;">
+ <li><a href="#v307">Changes since 3.0.7-PL1</a></li>
<li><a href="#v307">Changes since 3.0.7</a></li>
<li><a href="#v306">Changes since 3.0.6</a></li>
<li><a href="#v305">Changes since 3.0.5</a></li>
@@ -88,7 +89,7 @@
<div class="content">
- <a name="v307"></a><h3>1.i. Changes since 3.0.7</h3>
+ <a name="v307-pl1"></a><h3>1.i. Changes since 3.0.7-PL1</h3>
<ul>
<li>[Fix] Correctly sort database backup file list by date on database restore page. (Bug #57385)</li>
@@ -99,8 +100,25 @@
<li>[Fix] Add terminating semicolons to JavaScript code. (Bug #58085 - Patch by nn-)</li>
<li>[Fix] Minor language fixes. (Bug #54855)</li>
<li>[Fix] Parsing urls in signatures properly uses config settings. (Bug #57105)</li>
+ <li>[Fix] Allow multibyte keys in request_var(). (Bug #51555)</li>
+ <li>[Fix] Fix inclusion check for captcha garbage collection (Bug #59425)</li>
+ <li>[Fix] Prevent wrong tar archive type detection. (Bug #12531)</li>
+ <li>[Fix] Correct redirection after login to forum not in web root (Bug #58755)</li>
+ <li>[Fix] Allow setting parent forums regardless of permission settings. (Bug #57415)</li>
+ <li>[Fix] Redirect search engines that access pages with SIDs in the URL. (Bug #58025)</li>
+ <li>[Fix] Fix incorrect ampersand encoding in redirect parameter. (Bug #58465)</li>
+ <li>[Fix] Fix open_basedir issues when accessing styles- and language-management. (Bug #59135)</li>
+ <li>[Fix] Fix table binding issues with PostgreSQL in board-wide feed. (Bug #58425)</li>
+ <li>[Fix] Only show unapproved posts in ATOM Feeds for moderators (Bug #58695)</li>
<li>[Fix] Various XHTML mistakes in ACP (Bug #58745)</li>
<li>[Feature] Support for Microsoft's Native SQL Server Driver for PHP (Bug #57055 - Patch by Chris Pucci at Microsoft)</li>
+ <li>[Feature] The memcache acm plugin now supports multiple memcache servers.</li>
+ </ul>
+
+ <a name="v307"></a><h3>1.i. Changes since 3.0.7</h3>
+
+ <ul>
+ <li>[Sec] Do not expose forum content of forums with ACL entries but no actual permission in ATOM Feeds. (Bug #58595)</li>
</ul>
<a name="v306"></a><h3>1.ii. Changes since 3.0.6</h3>
diff --git a/phpBB/docs/INSTALL.html b/phpBB/docs/INSTALL.html
index c434686357..982c28571e 100644
--- a/phpBB/docs/INSTALL.html
+++ b/phpBB/docs/INSTALL.html
@@ -273,7 +273,7 @@
<p>This package is meant for those wanting to only replace changed files from a previous version to the latest version. This package normally contains the changed files from up to five previous versions.</p>
- <p>This package contains a number of archives, each contains the files changed from a given release to the latest version. You should select the appropriate archive for your current version, e.g. if you currently have <samp>3.0.6</samp> you should select the phpBB-3.0.6_to_3.0.7.zip/tar.gz file.</p>
+ <p>This package contains a number of archives, each contains the files changed from a given release to the latest version. You should select the appropriate archive for your current version, e.g. if you currently have <samp>3.0.6</samp> you should select the phpBB-3.0.6_to_3.0.7-PL1.zip/tar.gz file.</p>
<p>The directory structure has been preserved enabling you (if you wish) to simply upload the contents of the archive to the appropriate location on your server, i.e. simply overwrite the existing files with the new versions. Do not forget that if you have installed any MODs these files will overwrite the originals possibly destroying them in the process. You will need to re-add MODs to any affected file before uploading.</p>
@@ -285,7 +285,7 @@
<p>The patch file is one solution for those with many Modifications (MODs) or other changes who do not want to re-add them back to all the changed files if they use the method explained above. To use this you will need command line access to a standard UNIX type <strong>patch</strong> application. If you do not have access to such an application but still want to use this update approach, we strongly recommend the <a href="#update_auto">Automatic update package</a> explained below. It is also the recommended update method.</p>
- <p>A number of patch files are provided to allow you to update from previous stable releases. Select the correct patch, e.g. if your current version is 3.0.6 you need the phpBB-3.0.6_to_3.0.7.patch file. Place the correct patch in the parent directory containing the phpBB3 core files (i.e. index.php, viewforum.php, etc.). With this done you should run the following command: <strong>patch -cl -d [PHPBB DIRECTORY] -p1 &lt; [PATCH NAME]</strong> (where PHPBB DIRECTORY is the directory name your phpBB Installation resides in, for example phpBB3, and where PATCH NAME is the relevant filename of the selected patch file). This should complete quickly, hopefully without any HUNK FAILED comments.</p>
+ <p>A number of patch files are provided to allow you to update from previous stable releases. Select the correct patch, e.g. if your current version is 3.0.5 you need the phpBB-3.0.6_to_3.0.7-PL1.patch file. Place the correct patch in the parent directory containing the phpBB3 core files (i.e. index.php, viewforum.php, etc.). With this done you should run the following command: <strong>patch -cl -d [PHPBB DIRECTORY] -p1 &lt; [PATCH NAME]</strong> (where PHPBB DIRECTORY is the directory name your phpBB Installation resides in, for example phpBB3, and where PATCH NAME is the relevant filename of the selected patch file). This should complete quickly, hopefully without any HUNK FAILED comments.</p>
<p>If you do get failures you should look at using the <a href="#update_files">Changed files only</a> package to replace the files which failed to patch, please note that you will need to manually re-add any Modifications (MODs) to these particular files. Alternatively if you know how you can examine the .rej files to determine what failed where and make manual adjustments to the relevant source.</p>
diff --git a/phpBB/feed.php b/phpBB/feed.php
index 1832efbc61..4e286ca9b9 100644
--- a/phpBB/feed.php
+++ b/phpBB/feed.php
@@ -522,7 +522,7 @@ class phpbb_feed_base
if (!isset($forum_ids))
{
- $forum_ids = array_keys($auth->acl_getf('f_read'));
+ $forum_ids = array_keys($auth->acl_getf('f_read', true));
}
return $forum_ids;
@@ -535,7 +535,7 @@ class phpbb_feed_base
if (!isset($forum_ids))
{
- $forum_ids = array_keys($auth->acl_getf('m_approve'));
+ $forum_ids = array_keys($auth->acl_getf('m_approve', true));
}
return $forum_ids;
@@ -783,8 +783,8 @@ class phpbb_feed_overall extends phpbb_feed_post_base
'p.post_id, p.topic_id, p.post_time, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' .
'u.username, u.user_id',
'FROM' => array(
- POSTS_TABLE => 'p',
USERS_TABLE => 'u',
+ POSTS_TABLE => 'p',
),
'LEFT_JOIN' => array(
array(
@@ -994,7 +994,7 @@ class phpbb_feed_topic extends phpbb_feed_post_base
if (!$this->topic_data['topic_approved'])
{
// Also require m_approve
- $in_fid_ary = array_intersect($in_fid_ary, array_keys($auth->acl_getf('m_approve')));
+ $in_fid_ary = array_intersect($in_fid_ary, $this->get_moderator_approve_forums());
if (empty($in_fid_ary))
{
diff --git a/phpBB/includes/acm/acm_memcache.php b/phpBB/includes/acm/acm_memcache.php
index 52b8832749..e54fa36c38 100644
--- a/phpBB/includes/acm/acm_memcache.php
+++ b/phpBB/includes/acm/acm_memcache.php
@@ -37,6 +37,12 @@ if (!defined('PHPBB_ACM_MEMCACHE_HOST'))
define('PHPBB_ACM_MEMCACHE_HOST', 'localhost');
}
+if (!defined('PHPBB_ACM_MEMCACHE'))
+{
+ //can define multiple servers with host1/port1,host2/port2 format
+ define('PHPBB_ACM_MEMCACHE', PHPBB_ACM_MEMCACHE_HOST . '/' . PHPBB_ACM_MEMCACHE_PORT);
+}
+
/**
* ACM for Memcached
* @package acm
@@ -54,7 +60,11 @@ class acm extends acm_memory
parent::acm_memory();
$this->memcache = new Memcache;
- $this->memcache->connect(PHPBB_ACM_MEMCACHE_HOST, PHPBB_ACM_MEMCACHE_PORT);
+ foreach(explode(',', PHPBB_ACM_MEMCACHE) as $u)
+ {
+ $parts = explode('/', $u);
+ $this->memcache->addServer(trim($parts[0]), trim($parts[1]));
+ }
$this->flags = (PHPBB_ACM_MEMCACHE_COMPRESS) ? MEMCACHE_COMPRESSED : 0;
}
@@ -125,4 +135,4 @@ class acm extends acm_memory
}
}
-?> \ No newline at end of file
+?>
diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php
index bde59ec870..5a5adc57ae 100644
--- a/phpBB/includes/acp/acp_forums.php
+++ b/phpBB/includes/acp/acp_forums.php
@@ -407,7 +407,7 @@ class acp_forums
$exclude_forums[] = $row['forum_id'];
}
- $parents_list = make_forum_select($forum_data['parent_id'], $exclude_forums, false, false, false);
+ $parents_list = make_forum_select($forum_data['parent_id'], $exclude_forums, true, false, false);
$forum_data['forum_password_confirm'] = $forum_data['forum_password'];
}
@@ -416,7 +416,7 @@ class acp_forums
$this->page_title = 'CREATE_FORUM';
$forum_id = $this->parent_id;
- $parents_list = make_forum_select($this->parent_id, false, false, false, false);
+ $parents_list = make_forum_select($this->parent_id, false, true, false, false);
// Fill forum data with default values
if (!$update)
diff --git a/phpBB/includes/acp/acp_language.php b/phpBB/includes/acp/acp_language.php
index fedae6fe67..c2cb2f9c11 100644
--- a/phpBB/includes/acp/acp_language.php
+++ b/phpBB/includes/acp/acp_language.php
@@ -1120,12 +1120,12 @@ class acp_language
{
while (($file = readdir($dp)) !== false)
{
- if (!is_dir($phpbb_root_path . 'language/' . $file))
+ if ($file[0] == '.' || !is_dir($phpbb_root_path . 'language/' . $file))
{
continue;
}
- if ($file[0] != '.' && file_exists("{$phpbb_root_path}language/$file/iso.txt"))
+ if (file_exists("{$phpbb_root_path}language/$file/iso.txt"))
{
if (!in_array($file, $installed))
{
diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php
index d2a0f9210f..3310560c73 100644
--- a/phpBB/includes/acp/acp_styles.php
+++ b/phpBB/includes/acp/acp_styles.php
@@ -643,13 +643,13 @@ parse_css_file = {PARSE_CSS_FILE}
{
while (($file = readdir($dp)) !== false)
{
- if (!is_dir($phpbb_root_path . 'styles/' . $file))
+ if ($file[0] == '.' || !is_dir($phpbb_root_path . 'styles/' . $file))
{
continue;
}
$subpath = ($mode != 'style') ? "$mode/" : '';
- if ($file[0] != '.' && file_exists("{$phpbb_root_path}styles/$file/$subpath$mode.cfg"))
+ if (file_exists("{$phpbb_root_path}styles/$file/$subpath$mode.cfg"))
{
if ($cfg = file("{$phpbb_root_path}styles/$file/$subpath$mode.cfg"))
{
diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php
index f58b29d232..8d31eaba7f 100644
--- a/phpBB/includes/constants.php
+++ b/phpBB/includes/constants.php
@@ -25,7 +25,7 @@ if (!defined('IN_PHPBB'))
*/
// phpBB Version
-define('PHPBB_VERSION', '3.0.7');
+define('PHPBB_VERSION', '3.0.7-PL1');
// QA-related
// define('PHPBB_QA', 1);
diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php
index 38f910974a..4f52c7c2ce 100644
--- a/phpBB/includes/functions.php
+++ b/phpBB/includes/functions.php
@@ -114,7 +114,7 @@ function request_var($var_name, $default, $multibyte = false, $cookie = false)
{
$_v = null;
}
- set_var($_k, $_k, $sub_key_type);
+ set_var($_k, $_k, $sub_key_type, $multibyte);
set_var($var[$k][$_k], $_v, $sub_type, $multibyte);
}
}
@@ -2139,8 +2139,8 @@ function append_sid($url, $params = false, $is_amp = true, $session_id = false)
{
global $_SID, $_EXTRA_URL, $phpbb_hook;
- // Developers using the hook function need to globalise the $_SID and $_EXTRA_URL on their own and also handle it appropiatly.
- // They could mimick most of what is within this function
+ // Developers using the hook function need to globalise the $_SID and $_EXTRA_URL on their own and also handle it appropriately.
+ // They could mimic most of what is within this function
if (!empty($phpbb_hook) && $phpbb_hook->call_hook(__FUNCTION__, $url, $params, $is_amp, $session_id))
{
if ($phpbb_hook->hook_return(__FUNCTION__))
@@ -2297,6 +2297,8 @@ function redirect($url, $return = false, $disable_cd_check = false)
{
global $db, $cache, $config, $user, $phpbb_root_path;
+ $failover_flag = false;
+
if (empty($user->lang))
{
$user->add_lang('common');
@@ -2344,65 +2346,69 @@ function redirect($url, $return = false, $disable_cd_check = false)
if (!file_exists($pathinfo['dirname']))
{
// fallback to "last known user page"
+ // at least this way we know the user does not leave the phpBB root
$url = generate_board_url() . '/' . $user->page['page'];
- break;
+ $failover_flag = true;
}
}
- // Is the uri pointing to the current directory?
- if ($pathinfo['dirname'] == '.')
+ if (!$failover_flag)
{
- $url = str_replace('./', '', $url);
-
- // Strip / from the beginning
- if ($url && substr($url, 0, 1) == '/')
+ // Is the uri pointing to the current directory?
+ if ($pathinfo['dirname'] == '.')
{
- $url = substr($url, 1);
- }
+ $url = str_replace('./', '', $url);
- if ($user->page['page_dir'])
- {
- $url = generate_board_url() . '/' . $user->page['page_dir'] . '/' . $url;
+ // Strip / from the beginning
+ if ($url && substr($url, 0, 1) == '/')
+ {
+ $url = substr($url, 1);
+ }
+
+ if ($user->page['page_dir'])
+ {
+ $url = generate_board_url() . '/' . $user->page['page_dir'] . '/' . $url;
+ }
+ else
+ {
+ $url = generate_board_url() . '/' . $url;
+ }
}
else
{
- $url = generate_board_url() . '/' . $url;
- }
- }
- else
- {
- // Used ./ before, but $phpbb_root_path is working better with urls within another root path
- $root_dirs = explode('/', str_replace('\\', '/', phpbb_realpath($phpbb_root_path)));
- $page_dirs = explode('/', str_replace('\\', '/', phpbb_realpath($pathinfo['dirname'])));
- $intersection = array_intersect_assoc($root_dirs, $page_dirs);
+ // Used ./ before, but $phpbb_root_path is working better with urls within another root path
+ $root_dirs = explode('/', str_replace('\\', '/', phpbb_realpath($phpbb_root_path)));
+ $page_dirs = explode('/', str_replace('\\', '/', phpbb_realpath($pathinfo['dirname'])));
+ $intersection = array_intersect_assoc($root_dirs, $page_dirs);
- $root_dirs = array_diff_assoc($root_dirs, $intersection);
- $page_dirs = array_diff_assoc($page_dirs, $intersection);
+ $root_dirs = array_diff_assoc($root_dirs, $intersection);
+ $page_dirs = array_diff_assoc($page_dirs, $intersection);
- $dir = str_repeat('../', sizeof($root_dirs)) . implode('/', $page_dirs);
+ $dir = str_repeat('../', sizeof($root_dirs)) . implode('/', $page_dirs);
- // Strip / from the end
- if ($dir && substr($dir, -1, 1) == '/')
- {
- $dir = substr($dir, 0, -1);
- }
+ // Strip / from the end
+ if ($dir && substr($dir, -1, 1) == '/')
+ {
+ $dir = substr($dir, 0, -1);
+ }
- // Strip / from the beginning
- if ($dir && substr($dir, 0, 1) == '/')
- {
- $dir = substr($dir, 1);
- }
+ // Strip / from the beginning
+ if ($dir && substr($dir, 0, 1) == '/')
+ {
+ $dir = substr($dir, 1);
+ }
- $url = str_replace($pathinfo['dirname'] . '/', '', $url);
+ $url = str_replace($pathinfo['dirname'] . '/', '', $url);
- // Strip / from the beginning
- if (substr($url, 0, 1) == '/')
- {
- $url = substr($url, 1);
- }
+ // Strip / from the beginning
+ if (substr($url, 0, 1) == '/')
+ {
+ $url = substr($url, 1);
+ }
- $url = (!empty($dir) ? $dir . '/' : '') . $url;
- $url = generate_board_url() . '/' . $url;
+ $url = (!empty($dir) ? $dir . '/' : '') . $url;
+ $url = generate_board_url() . '/' . $url;
+ }
}
}
@@ -4251,7 +4257,7 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
'S_TOPIC_ID' => $topic_id,
'S_LOGIN_ACTION' => ((!defined('ADMIN_START')) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login') : append_sid("index.$phpEx", false, true, $user->session_id)),
- 'S_LOGIN_REDIRECT' => build_hidden_fields(array('redirect' => str_replace('&amp;', '&', build_url()))),
+ 'S_LOGIN_REDIRECT' => build_hidden_fields(array('redirect' => build_url())),
'S_ENABLE_FEEDS' => ($config['feed_enable']) ? true : false,
'S_ENABLE_FEEDS_OVERALL' => ($config['feed_overall']) ? true : false,
diff --git a/phpBB/includes/functions_compress.php b/phpBB/includes/functions_compress.php
index f17c780a65..f422eaa8c1 100644
--- a/phpBB/includes/functions_compress.php
+++ b/phpBB/includes/functions_compress.php
@@ -502,8 +502,8 @@ class compress_tar extends compress
function compress_tar($mode, $file, $type = '')
{
$type = (!$type) ? $file : $type;
- $this->isgz = (strpos($type, '.tar.gz') !== false || strpos($type, '.tgz') !== false) ? true : false;
- $this->isbz = (strpos($type, '.tar.bz2') !== false) ? true : false;
+ $this->isgz = preg_match('#(\.tar\.gz|\.tgz)$#', $type);
+ $this->isbz = preg_match('#\.tar\.bz2$#', $type);
$this->mode = &$mode;
$this->file = &$file;
diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php
index 11f1896332..0a01b4e73b 100644
--- a/phpBB/includes/session.php
+++ b/phpBB/includes/session.php
@@ -83,7 +83,7 @@ class session
$query_string = trim(implode('&', $use_args));
// basenamed page name (for example: index.php)
- $page_name = basename($script_name);
+ $page_name = (substr($script_name, -1, 1) == '/') ? '' : basename($script_name);
$page_name = urlencode(htmlspecialchars($page_name));
// current directory within the phpBB root (for example: adm)
@@ -608,6 +608,12 @@ class session
}
else
{
+ // Bot user, if they have a SID in the Request URI we need to get rid of it
+ // otherwise they'll index this page with the SID, duplicate content oh my!
+ if (isset($_GET['sid']))
+ {
+ redirect(build_url(array('sid')));
+ }
$this->data['session_last_visit'] = $this->time_now;
}
@@ -977,7 +983,7 @@ class session
}
// only called from CRON; should be a safe workaround until the infrastructure gets going
- if (!class_exists('captcha_factory'))
+ if (!class_exists('phpbb_captcha_factory'))
{
include($phpbb_root_path . "includes/captcha/captcha_factory." . $phpEx);
}
diff --git a/phpBB/install/convertors/convert_phpbb20.php b/phpBB/install/convertors/convert_phpbb20.php
index 1d6b79bbec..dfade990d2 100644
--- a/phpBB/install/convertors/convert_phpbb20.php
+++ b/phpBB/install/convertors/convert_phpbb20.php
@@ -32,7 +32,7 @@ unset($dbpasswd);
$convertor_data = array(
'forum_name' => 'phpBB 2.0.x',
'version' => '1.0.3',
- 'phpbb_version' => '3.0.7',
+ 'phpbb_version' => '3.0.7-PL1',
'author' => '<a href="http://www.phpbb.com/">phpBB Group</a>',
'dbms' => $dbms,
'dbhost' => $dbhost,
@@ -83,7 +83,7 @@ $tables = array(
* 'table_format' => 'file',
* 'filename' => 'NAME OF FILE', // If the file is not in the root directory, the path needs to be added with no leading slash
* 'array_name' => 'NAME OF ARRAY', // Only used if the configuration file stores the setting in an array.
-* 'settings' => array(
+* 'settings' => array(
* 'board_email' => 'SUPPORT_EMAIL', // target config name => source target name
* )
* );
diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php
index df8aadfdb2..7af0c86314 100644
--- a/phpBB/install/database_update.php
+++ b/phpBB/install/database_update.php
@@ -911,6 +911,8 @@ function database_update_info()
'3.0.7-RC1' => array(),
// No changes from 3.0.7-RC2 to 3.0.7
'3.0.7-RC2' => array(),
+ // No changes from 3.0.7 to 3.0.7-PL1
+ '3.0.7' => array(),
);
}
@@ -1642,6 +1644,10 @@ function change_database_data(&$no_updates, $version)
// No changes from 3.0.7-RC2 to 3.0.7
case '3.0.7-RC2':
break;
+
+ // No changes from 3.0.7 to 3.0.7-PL1
+ case '3.0.7':
+ break;
}
}
diff --git a/tests/all_tests.php b/tests/all_tests.php
new file mode 100644
index 0000000000..e693427809
--- /dev/null
+++ b/tests/all_tests.php
@@ -0,0 +1,56 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+error_reporting(E_ALL);
+
+if (!defined('PHPUnit_MAIN_METHOD'))
+{
+ define('PHPUnit_MAIN_METHOD', 'phpbb_all_tests::main');
+}
+
+require_once 'test_framework/framework.php';
+require_once 'PHPUnit/TextUI/TestRunner.php';
+
+require_once 'utf/all_tests.php';
+require_once 'request/all_tests.php';
+require_once 'security/all_tests.php';
+require_once 'template/all_tests.php';
+require_once 'text_processing/all_tests.php';
+require_once 'dbal/all_tests.php';
+
+// exclude the test directory from code coverage reports
+PHPUnit_Util_Filter::addDirectoryToFilter('./');
+
+class phpbb_all_tests
+{
+ public static function main()
+ {
+ PHPUnit_TextUI_TestRunner::run(self::suite());
+ }
+
+ public static function suite()
+ {
+ $suite = new PHPUnit_Framework_TestSuite('phpBB');
+
+ $suite->addTest(phpbb_utf_all_tests::suite());
+ $suite->addTest(phpbb_request_all_tests::suite());
+ $suite->addTest(phpbb_security_all_tests::suite());
+ $suite->addTest(phpbb_template_all_tests::suite());
+ $suite->addTest(phpbb_text_processing_all_tests::suite());
+ $suite->addTest(phpbb_dbal_all_tests::suite());
+
+ return $suite;
+ }
+}
+
+if (PHPUnit_MAIN_METHOD == 'phpbb_all_tests::main')
+{
+ phpbb_all_tests::main();
+}
+
diff --git a/tests/dbal/all_tests.php b/tests/dbal/all_tests.php
new file mode 100644
index 0000000000..7aee0f6b16
--- /dev/null
+++ b/tests/dbal/all_tests.php
@@ -0,0 +1,40 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+if (!defined('PHPUnit_MAIN_METHOD'))
+{
+ define('PHPUnit_MAIN_METHOD', 'phpbb_dbal_all_tests::main');
+}
+
+require_once 'test_framework/framework.php';
+require_once 'PHPUnit/TextUI/TestRunner.php';
+
+require_once 'dbal/dbal.php';
+
+class phpbb_dbal_all_tests
+{
+ public static function main()
+ {
+ PHPUnit_TextUI_TestRunner::run(self::suite());
+ }
+
+ public static function suite()
+ {
+ $suite = new PHPUnit_Framework_TestSuite('phpBB Database Abstraction Layer');
+
+ $suite->addTestSuite('phpbb_dbal_test');
+
+ return $suite;
+ }
+}
+
+if (PHPUnit_MAIN_METHOD == 'phpbb_dbal_all_tests::main')
+{
+ phpbb_dbal_all_tests::main();
+}
diff --git a/tests/dbal/dbal.php b/tests/dbal/dbal.php
new file mode 100644
index 0000000000..f90b5efeb5
--- /dev/null
+++ b/tests/dbal/dbal.php
@@ -0,0 +1,328 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+require_once 'test_framework/framework.php';
+require_once '../phpBB/includes/functions.php';
+
+class phpbb_dbal_test extends phpbb_database_test_case
+{
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/three_users.xml');
+ }
+
+ public static function return_on_error_select_data()
+ {
+ return array(
+ array('phpbb_users', "username_clean = 'bertie'", array(array('username_clean' => 'bertie'))),
+ array('phpbb_users', "username_clean = 'phpBB'", array()),
+ array('phpbb_users', 'username_clean syntax_error', false),
+ array('phpbb_users', 'column_not_exists = 2', false),
+ array('table_not_exists', 'column_not_exists = 2', false),
+ );
+ }
+
+ /**
+ * @dataProvider return_on_error_select_data
+ */
+ public function test_return_on_error_select($table, $where, $expected)
+ {
+ $db = $this->new_dbal();
+
+ $db->sql_return_on_error(true);
+
+ $result = $db->sql_query('SELECT username_clean
+ FROM ' . $table . '
+ WHERE ' . $where . '
+ ORDER BY user_id ASC');
+
+ $db->sql_return_on_error(false);
+
+ $this->assertEquals($expected, $db->sql_fetchrowset($result));
+ }
+
+ public static function fetchrow_data()
+ {
+ return array(
+ array('', array(array('username_clean' => 'barfoo'),
+ array('username_clean' => 'foobar'),
+ array('username_clean' => 'bertie'))),
+ array('user_id = 2', array(array('username_clean' => 'foobar'))),
+ array("username_clean = 'bertie'", array(array('username_clean' => 'bertie'))),
+ array("username_clean = 'phpBB'", array()),
+ );
+ }
+
+ /**
+ * @dataProvider fetchrow_data
+ */
+ public function test_fetchrow($where, $expected)
+ {
+ $db = $this->new_dbal();
+
+ $result = $db->sql_query('SELECT username_clean
+ FROM phpbb_users
+ ' . (($where) ? ' WHERE ' . $where : '') . '
+ ORDER BY user_id ASC');
+
+ $ary = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $ary[] = $row;
+ }
+ $db->sql_freeresult($result);
+
+ $this->assertEquals($expected, $ary);
+ }
+
+ /**
+ * @dataProvider fetchrow_data
+ */
+ public function test_fetchrowset($where, $expected)
+ {
+ $db = $this->new_dbal();
+
+ $result = $db->sql_query('SELECT username_clean
+ FROM phpbb_users
+ ' . (($where) ? ' WHERE ' . $where : '') . '
+ ORDER BY user_id ASC');
+
+ $this->assertEquals($expected, $db->sql_fetchrowset($result));
+
+ $db->sql_freeresult($result);
+ }
+
+ public static function fetchfield_data()
+ {
+ return array(
+ array('', array('barfoo', 'foobar', 'bertie')),
+ array('user_id = 2', array('foobar')),
+ array("username_clean = 'bertie'", array('bertie')),
+ );
+ }
+
+ /**
+ * @dataProvider fetchfield_data
+ */
+ public function test_fetchfield($where, $expected)
+ {
+ $db = $this->new_dbal();
+
+ $result = $db->sql_query('SELECT username_clean
+ FROM phpbb_users
+ ' . (($where) ? ' WHERE ' . $where : '') . '
+ ORDER BY user_id ASC');
+
+ $ary = array();
+ while ($row = $db->sql_fetchfield('username_clean'))
+ {
+ $ary[] = $row;
+ }
+ $db->sql_freeresult($result);
+
+ $this->assertEquals($expected, $ary);
+ }
+
+ public static function query_limit_data()
+ {
+ return array(
+ array(0, 0, array(array('username_clean' => 'barfoo'),
+ array('username_clean' => 'foobar'),
+ array('username_clean' => 'bertie'))),
+ array(0, 1, array(array('username_clean' => 'foobar'),
+ array('username_clean' => 'bertie'))),
+ array(1, 0, array(array('username_clean' => 'barfoo'))),
+ array(1, 1, array(array('username_clean' => 'foobar'))),
+ array(1, 2, array(array('username_clean' => 'bertie'))),
+ array(2, 0, array(array('username_clean' => 'barfoo'),
+ array('username_clean' => 'foobar'))),
+ array(2, 2, array(array('username_clean' => 'bertie'))),
+ array(2, 5, array()),
+ array(10, 1, array(array('username_clean' => 'foobar'),
+ array('username_clean' => 'bertie'))),
+ array(10, 5, array()),
+ );
+ }
+
+ /**
+ * @dataProvider query_limit_data
+ */
+ public function test_query_limit($total, $offset, $expected)
+ {
+ $db = $this->new_dbal();
+
+ $result = $db->sql_query_limit('SELECT username_clean
+ FROM phpbb_users
+ ORDER BY user_id ASC', $total, $offset);
+
+ $ary = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $ary[] = $row;
+ }
+ $db->sql_freeresult($result);
+
+ $this->assertEquals($expected, $ary);
+ }
+
+ public static function like_expression_data()
+ {
+ // * = any_char; # = one_char
+ return array(
+ array('barfoo', array(array('username_clean' => 'barfoo'))),
+ array('bar', array()),
+ array('bar*', array(array('username_clean' => 'barfoo'))),
+ array('*bar*', array(array('username_clean' => 'barfoo'),
+ array('username_clean' => 'foobar'))),
+ array('*b*', array(array('username_clean' => 'barfoo'),
+ array('username_clean' => 'foobar'),
+ array('username_clean' => 'bertie'))),
+ array('b*r', array()),
+ array('b*e', array(array('username_clean' => 'bertie'))),
+ array('#b*e', array()),
+ array('b####e', array(array('username_clean' => 'bertie'))),
+ );
+ }
+
+ /**
+ * @dataProvider like_expression_data
+ */
+ public function test_like_expression($like_expression, $expected)
+ {
+ $db = $this->new_dbal();
+
+ $like_expression = str_replace('*', $db->any_char, $like_expression);
+ $like_expression = str_replace('#', $db->one_char, $like_expression);
+ $where = ($like_expression) ? 'username_clean ' . $db->sql_like_expression($like_expression) : '';
+
+ $result = $db->sql_query('SELECT username_clean
+ FROM phpbb_users
+ ' . (($where) ? ' WHERE ' . $where : '') . '
+ ORDER BY user_id ASC');
+
+ $this->assertEquals($expected, $db->sql_fetchrowset($result));
+
+ $db->sql_freeresult($result);
+ }
+
+ public static function in_set_data()
+ {
+ return array(
+ array('user_id', 3, false, false, array(array('username_clean' => 'bertie'))),
+ array('user_id', 3, false, true, array(array('username_clean' => 'bertie'))),
+ array('user_id', 3, true, false, array(array('username_clean' => 'barfoo'),
+ array('username_clean' => 'foobar'))),
+ array('user_id', 3, true, true, array(array('username_clean' => 'barfoo'),
+ array('username_clean' => 'foobar'))),
+ array('user_id', '3', false, false, array(array('username_clean' => 'bertie'))),
+ array('user_id', '3', false, true, array(array('username_clean' => 'bertie'))),
+ array('user_id', '3', true, false, array(array('username_clean' => 'barfoo'),
+ array('username_clean' => 'foobar'))),
+ array('user_id', '3', true, true, array(array('username_clean' => 'barfoo'),
+ array('username_clean' => 'foobar'))),
+ array('user_id', array(3), false, false, array(array('username_clean' => 'bertie'))),
+ array('user_id', array(3), false, true, array(array('username_clean' => 'bertie'))),
+ array('user_id', array(3), true, false, array(array('username_clean' => 'barfoo'),
+ array('username_clean' => 'foobar'))),
+ array('user_id', array(3), true, true, array(array('username_clean' => 'barfoo'),
+ array('username_clean' => 'foobar'))),
+ array('user_id', array(1, 3), false, false, array(array('username_clean' => 'barfoo'),
+ array('username_clean' => 'bertie'))),
+ array('user_id', array(1, 3), false, true, array(array('username_clean' => 'barfoo'),
+ array('username_clean' => 'bertie'))),
+ array('user_id', array(1, 3), true, false, array(array('username_clean' => 'foobar'))),
+ array('user_id', array(1, 3), true, true, array(array('username_clean' => 'foobar'))),
+ array('user_id', '', false, false, array()),
+ array('user_id', '', false, true, array()),
+ array('user_id', '', true, false, array(array('username_clean' => 'barfoo'),
+ array('username_clean' => 'foobar'),
+ array('username_clean' => 'bertie'))),
+ array('user_id', '', true, true, array(array('username_clean' => 'barfoo'),
+ array('username_clean' => 'foobar'),
+ array('username_clean' => 'bertie'))),
+ array('user_id', array(), false, true, array()),
+ array('user_id', array(), true, true, array(array('username_clean' => 'barfoo'),
+ array('username_clean' => 'foobar'),
+ array('username_clean' => 'bertie'))),
+
+ // These here would throw errors and therefor $result should be false.
+ array('user_id', array(), false, false, false, true),
+ array('user_id', array(), true, false, false, true),
+ );
+ }
+
+ /**
+ * @dataProvider in_set_data
+ */
+ public function test_in_set($field, $array, $negate, $allow_empty_set, $expected, $catch_error = false)
+ {
+ $db = $this->new_dbal();
+
+ if ($catch_error)
+ {
+ $db->sql_return_on_error(true);
+ }
+
+ $result = $db->sql_query('SELECT username_clean
+ FROM phpbb_users
+ WHERE ' . $db->sql_in_set($field, $array, $negate, $allow_empty_set) . '
+ ORDER BY user_id ASC');
+
+ if ($catch_error)
+ {
+ $db->sql_return_on_error(false);
+ }
+
+ $this->assertEquals($expected, $db->sql_fetchrowset($result));
+
+ $db->sql_freeresult($result);
+ }
+
+ public static function build_array_data()
+ {
+ return array(
+ array(array('username_clean' => 'barfoo'), array(array('username_clean' => 'barfoo'))),
+ array(array('username_clean' => 'barfoo', 'user_id' => 1), array(array('username_clean' => 'barfoo'))),
+ array(array('username_clean' => 'barfoo', 'user_id' => 2), array()),
+
+ // These here would throw errors and therefor $result should be false.
+ array(array(), false, true),
+ array('no_array', false, true),
+ array(0, false, true),
+ );
+ }
+
+ /**
+ * @dataProvider build_array_data
+ */
+ public function test_build_array($assoc_ary, $expected, $catch_error = false)
+ {
+ $db = $this->new_dbal();
+
+ if ($catch_error)
+ {
+ $db->sql_return_on_error(true);
+ }
+
+ $result = $db->sql_query('SELECT username_clean
+ FROM phpbb_users
+ WHERE ' . $db->sql_build_array('SELECT', $assoc_ary) . '
+ ORDER BY user_id ASC');
+
+ if ($catch_error)
+ {
+ $db->sql_return_on_error(false);
+ }
+
+ $this->assertEquals($expected, $db->sql_fetchrowset($result));
+
+ $db->sql_freeresult($result);
+ }
+}
+
diff --git a/tests/dbal/fixtures/three_users.xml b/tests/dbal/fixtures/three_users.xml
new file mode 100644
index 0000000000..a6789f4a01
--- /dev/null
+++ b/tests/dbal/fixtures/three_users.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<dataset>
+ <table name="phpbb_users">
+ <column>user_id</column>
+ <column>username_clean</column>
+ <row>
+ <value>1</value>
+ <value>barfoo</value>
+ </row>
+ <row>
+ <value>2</value>
+ <value>foobar</value>
+ </row>
+ <row>
+ <value>3</value>
+ <value>bertie</value>
+ </row>
+ </table>
+</dataset>
diff --git a/tests/request/all_tests.php b/tests/request/all_tests.php
new file mode 100644
index 0000000000..1ee3029b36
--- /dev/null
+++ b/tests/request/all_tests.php
@@ -0,0 +1,41 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+if (!defined('PHPUnit_MAIN_METHOD'))
+{
+ define('PHPUnit_MAIN_METHOD', 'phpbb_request_all_tests::main');
+}
+
+require_once 'test_framework/framework.php';
+require_once 'PHPUnit/TextUI/TestRunner.php';
+
+require_once 'request/request_var.php';
+
+class phpbb_request_all_tests
+{
+ public static function main()
+ {
+ PHPUnit_TextUI_TestRunner::run(self::suite());
+ }
+
+ public static function suite()
+ {
+ $suite = new PHPUnit_Framework_TestSuite('phpBB Request Parameter Handling');
+
+ $suite->addTestSuite('phpbb_request_request_var_test');
+
+ return $suite;
+ }
+}
+
+if (PHPUnit_MAIN_METHOD == 'phpbb_request_all_tests::main')
+{
+ phpbb_request_all_tests::main();
+}
+
diff --git a/tests/request/request_var.php b/tests/request/request_var.php
new file mode 100644
index 0000000000..b1dacef3fd
--- /dev/null
+++ b/tests/request/request_var.php
@@ -0,0 +1,180 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+require_once 'test_framework/framework.php';
+require_once '../phpBB/includes/functions.php';
+
+class phpbb_request_request_var_test extends phpbb_test_case
+{
+ /**
+ * @dataProvider request_variables
+ */
+ public function test_post($variable_value, $default, $multibyte, $expected)
+ {
+ $variable_name = 'name';
+ $this->unset_variables($variable_name);
+
+ $_POST[$variable_name] = $variable_value;
+ $_REQUEST[$variable_name] = $variable_value;
+
+ $result = request_var($variable_name, $default, $multibyte);
+
+ $label = 'Requesting POST variable, converting from ' . gettype($variable_value) . ' to ' . gettype($default) . (($multibyte) ? ' multibyte' : '');
+ $this->assertEquals($expected, $result, $label);
+ }
+
+ /**
+ * @dataProvider request_variables
+ */
+ public function test_get($variable_value, $default, $multibyte, $expected)
+ {
+ $variable_name = 'name';
+ $this->unset_variables($variable_name);
+
+ $_GET[$variable_name] = $variable_value;
+ $_REQUEST[$variable_name] = $variable_value;
+
+ $result = request_var($variable_name, $default, $multibyte);
+
+ $label = 'Requesting GET variable, converting from ' . gettype($variable_value) . ' to ' . gettype($default) . (($multibyte) ? ' multibyte' : '');
+ $this->assertEquals($expected, $result, $label);
+ }
+
+ /**
+ * @dataProvider request_variables
+ */
+ public function test_cookie($variable_value, $default, $multibyte, $expected)
+ {
+ $variable_name = 'name';
+ $this->unset_variables($variable_name);
+
+ $_GET[$variable_name] = false;
+ $_POST[$variable_name] = false;
+ $_REQUEST[$variable_name] = false;
+ $_COOKIE[$variable_name] = $variable_value;
+
+ $result = request_var($variable_name, $default, $multibyte, true);
+
+ $label = 'Requesting COOKIE variable, converting from ' . gettype($variable_value) . ' to ' . gettype($default) . (($multibyte) ? ' multibyte' : '');
+ $this->assertEquals($expected, $result, $label);
+ }
+
+ /**
+ * Helper for unsetting globals
+ */
+ private function unset_variables($var)
+ {
+ unset($_GET[$var], $_POST[$var], $_REQUEST[$var], $_COOKIE[$var]);
+ }
+
+ public static function request_variables()
+ {
+ return array(
+ // strings
+ array('abc', '', false, 'abc'),
+ array(' some spaces ', '', true, 'some spaces'),
+ array("\r\rsome\rcarriage\r\rreturns\r", '', true, "some\ncarriage\n\nreturns"),
+ array("\n\nsome\ncarriage\n\nreturns\n", '', true, "some\ncarriage\n\nreturns"),
+ array("\r\n\r\nsome\r\ncarriage\r\n\r\nreturns\r\n", '', true, "some\ncarriage\n\nreturns"),
+ array("we\xC2\xA1rd\xE1\x9A\x80ch\xCE\xB1r\xC2\xADacters", '', true, "we\xC2\xA1rd\xE1\x9A\x80ch\xCE\xB1r\xC2\xADacters"),
+ array("we\xC2\xA1rd\xE1\x9A\x80ch\xCE\xB1r\xC2\xADacters", '', false, "we??rd???ch??r??acters"),
+ array("Some <html> \"entities\" like &", '', true, "Some &lt;html&gt; &quot;entities&quot; like &amp;"),
+
+ // integers
+ array('1234', 0, false, 1234),
+ array('abc', 12, false, 0),
+ array('324abc', 0, false, 324),
+
+ // string to array
+ array('123', array(0), false, array()),
+ array('123', array(''), false, array()),
+
+ // 1 dimensional arrays
+ array(
+ // input:
+ array('123', 'abc'),
+ // default:
+ array(''),
+ false,
+ // expected:
+ array('123', 'abc')
+ ),
+ array(
+ // input:
+ array('123', 'abc'),
+ // default:
+ array(999),
+ false,
+ // expected:
+ array(123, 0)
+ ),
+ array(
+ // input:
+ array('xyz' => '123', 'abc' => 'abc'),
+ // default:
+ array('' => ''),
+ false,
+ // expected:
+ array('xyz' => '123', 'abc' => 'abc')
+ ),
+ array(
+ // input:
+ array('xyz' => '123', 'abc' => 'abc'),
+ // default:
+ array('' => 0),
+ false,
+ // expected:
+ array('xyz' => 123, 'abc' => 0)
+ ),
+
+ // 2 dimensional arrays
+ array(
+ // input:
+ '',
+ // default:
+ array(array(0)),
+ false,
+ // expected:
+ array()
+ ),
+ array(
+ // input:
+ array(
+ 'xyz' => array('123', 'def'),
+ 'abc' => 'abc'
+ ),
+ // default:
+ array('' => array('')),
+ false,
+ // expected:
+ array(
+ 'xyz' => array('123', 'def'),
+ 'abc' => array()
+ )
+ ),
+ array(
+ // input:
+ array(
+ 'xyz' => array('123', 'def'),
+ 'abc' => 'abc'
+ ),
+ // default:
+ array('' => array(0)),
+ false,
+ // expected:
+ array(
+ 'xyz' => array(123, 0),
+ 'abc' => array()
+ )
+ ),
+ );
+ }
+
+}
+
diff --git a/tests/security/all_tests.php b/tests/security/all_tests.php
new file mode 100644
index 0000000000..8e3916733f
--- /dev/null
+++ b/tests/security/all_tests.php
@@ -0,0 +1,86 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+if (!defined('PHPUnit_MAIN_METHOD'))
+{
+ define('PHPUnit_MAIN_METHOD', 'phpbb_security_all_tests::main');
+}
+
+require_once 'test_framework/framework.php';
+require_once 'PHPUnit/TextUI/TestRunner.php';
+
+require_once 'security/extract_current_page.php';
+require_once 'security/redirect.php';
+
+class phpbb_security_all_tests extends PHPUnit_Framework_TestSuite
+{
+ /**
+ * Set up the required user object and server variables for the suites
+ */
+ protected function setUp()
+ {
+ global $user, $phpbb_root_path;
+
+ // Put this into a global function being run by every test to init a proper user session
+ $_SERVER['HTTP_HOST'] = 'localhost';
+ $_SERVER['SERVER_NAME'] = 'localhost';
+ $_SERVER['SERVER_ADDR'] = '127.0.0.1';
+ $_SERVER['SERVER_PORT'] = 80;
+ $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
+ $_SERVER['QUERY_STRING'] = '';
+ $_SERVER['REQUEST_URI'] = '/tests/';
+ $_SERVER['SCRIPT_NAME'] = '/tests/index.php';
+ $_SERVER['PHP_SELF'] = '/tests/index.php';
+ $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14';
+ $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'de-de,de;q=0.8,en-us;q=0.5,en;q=0.3';
+
+/*
+ [HTTP_ACCEPT_ENCODING] => gzip,deflate
+ [HTTP_ACCEPT_CHARSET] => ISO-8859-1,utf-8;q=0.7,*;q=0.7
+ DOCUMENT_ROOT] => /var/www/
+ [SCRIPT_FILENAME] => /var/www/tests/index.php
+*/
+
+ // Set no user and trick a bit to circumvent errors
+ $user = new user();
+ $user->lang = true;
+ $user->browser = (!empty($_SERVER['HTTP_USER_AGENT'])) ? htmlspecialchars((string) $_SERVER['HTTP_USER_AGENT']) : '';
+ $user->referer = (!empty($_SERVER['HTTP_REFERER'])) ? htmlspecialchars((string) $_SERVER['HTTP_REFERER']) : '';
+ $user->forwarded_for = (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) ? (string) $_SERVER['HTTP_X_FORWARDED_FOR'] : '';
+ $user->host = (!empty($_SERVER['HTTP_HOST'])) ? (string) strtolower($_SERVER['HTTP_HOST']) : ((!empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : getenv('SERVER_NAME'));
+ $user->page = session::extract_current_page($phpbb_root_path);
+ }
+
+ protected function tearDown()
+ {
+ global $user;
+ $user = NULL;
+ }
+
+ public static function main()
+ {
+ PHPUnit_TextUI_TestRunner::run(self::suite());
+ }
+
+ public static function suite()
+ {
+ // I bet there is a better method calling this... :)
+ $suite = new phpbb_security_all_tests('phpBB Security Fixes');
+
+ $suite->addTestSuite('phpbb_security_extract_current_page_test');
+ $suite->addTestSuite('phpbb_security_redirect_test');
+
+ return $suite;
+ }
+}
+
+if (PHPUnit_MAIN_METHOD == 'phpbb_security_all_tests::main')
+{
+ phpbb_security_all_tests::main();
+}
diff --git a/tests/security/extract_current_page.php b/tests/security/extract_current_page.php
new file mode 100644
index 0000000000..8c72fe1440
--- /dev/null
+++ b/tests/security/extract_current_page.php
@@ -0,0 +1,53 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+require_once 'test_framework/framework.php';
+
+require_once '../phpBB/includes/functions.php';
+require_once '../phpBB/includes/session.php';
+
+class phpbb_security_extract_current_page_test extends phpbb_test_case
+{
+ public static function security_variables()
+ {
+ return array(
+ array('http://localhost/phpBB/index.php', 'mark=forums&x="><script>alert(/XSS/);</script>', 'mark=forums&x=%22%3E%3Cscript%3Ealert(/XSS/);%3C/script%3E'),
+ array('http://localhost/phpBB/index.php', 'mark=forums&x=%22%3E%3Cscript%3Ealert(/XSS/);%3C/script%3E', 'mark=forums&x=%22%3E%3Cscript%3Ealert(/XSS/);%3C/script%3E'),
+ );
+ }
+
+ /**
+ * @dataProvider security_variables
+ */
+ public function test_query_string_php_self($url, $query_string, $expected)
+ {
+ $_SERVER['PHP_SELF'] = $url;
+ $_SERVER['QUERY_STRING'] = $query_string;
+
+ $result = session::extract_current_page('./');
+
+ $label = 'Running extract_current_page on ' . $query_string . ' with PHP_SELF filled.';
+ $this->assertEquals($expected, $result['query_string'], $label);
+ }
+
+ /**
+ * @dataProvider security_variables
+ */
+ public function test_query_string_request_uri($url, $query_string, $expected)
+ {
+ $_SERVER['REQUEST_URI'] = $url . '?' . $query_string;
+ $_SERVER['QUERY_STRING'] = $query_string;
+
+ $result = session::extract_current_page('./');
+
+ $label = 'Running extract_current_page on ' . $query_string . ' with REQUEST_URI filled.';
+ $this->assertEquals($expected, $result['query_string'], $label);
+ }
+}
+
diff --git a/tests/security/redirect.php b/tests/security/redirect.php
new file mode 100644
index 0000000000..37b0a5bb41
--- /dev/null
+++ b/tests/security/redirect.php
@@ -0,0 +1,58 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+require_once 'test_framework/framework.php';
+
+require_once '../phpBB/includes/functions.php';
+require_once '../phpBB/includes/session.php';
+
+class phpbb_security_redirect_test extends phpbb_test_case
+{
+ public static function provider()
+ {
+ // array(Input -> redirect(), expected triggered error (else false), expected returned result url (else false))
+ return array(
+ array('data://x', false, 'http://localhost/phpBB'),
+ array('bad://localhost/phpBB/index.php', 'Tried to redirect to potentially insecure url.', false),
+ array('http://www.otherdomain.com/somescript.php', false, 'http://localhost/phpBB'),
+ array("http://localhost/phpBB/memberlist.php\n\rConnection: close", 'Tried to redirect to potentially insecure url.', false),
+ array('javascript:test', false, 'http://localhost/phpBB/../tests/javascript:test'),
+ array('http://localhost/phpBB/index.php;url=', 'Tried to redirect to potentially insecure url.', false),
+ );
+ }
+
+ protected function setUp()
+ {
+ $GLOBALS['config'] = array(
+ 'force_server_vars' => '0',
+ );
+ }
+
+ /**
+ * @dataProvider provider
+ */
+ public function test_redirect($test, $expected_error, $expected_result)
+ {
+ global $user;
+
+ if ($expected_error !== false)
+ {
+ $this->setExpectedTriggerError(E_USER_ERROR, $expected_error);
+ }
+
+ $result = redirect($test, true);
+
+ // only verify result if we did not expect an error
+ if ($expected_error === false)
+ {
+ $this->assertEquals($expected_result, $result);
+ }
+ }
+}
+
diff --git a/tests/template/all_tests.php b/tests/template/all_tests.php
new file mode 100644
index 0000000000..ea258c1680
--- /dev/null
+++ b/tests/template/all_tests.php
@@ -0,0 +1,40 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+if (!defined('PHPUnit_MAIN_METHOD'))
+{
+ define('PHPUnit_MAIN_METHOD', 'phpbb_template_all_tests::main');
+}
+
+require_once 'test_framework/framework.php';
+require_once 'PHPUnit/TextUI/TestRunner.php';
+
+require_once 'template/template.php';
+
+class phpbb_template_all_tests
+{
+ public static function main()
+ {
+ PHPUnit_TextUI_TestRunner::run(self::suite());
+ }
+
+ public static function suite()
+ {
+ $suite = new PHPUnit_Framework_TestSuite('phpBB Template Engine');
+
+ $suite->addTestSuite('phpbb_template_template_test');
+
+ return $suite;
+ }
+}
+
+if (PHPUnit_MAIN_METHOD == 'phpbb_template_all_tests::main')
+{
+ phpbb_template_all_tests::main();
+}
diff --git a/tests/template/template.php b/tests/template/template.php
new file mode 100644
index 0000000000..145fe8de61
--- /dev/null
+++ b/tests/template/template.php
@@ -0,0 +1,671 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+require_once 'test_framework/framework.php';
+
+require_once '../phpBB/includes/template.php';
+
+class phpbb_template_template_test extends phpbb_test_case
+{
+ private $template;
+ private $template_path;
+
+ // Keep the contents of the cache for debugging?
+ const PRESERVE_CACHE = true;
+
+ private function display($handle)
+ {
+ // allow the templates to throw notices
+ $error_level = error_reporting();
+ error_reporting($error_level & ~E_NOTICE);
+
+ ob_start();
+ $this->assertTrue($this->template->display($handle, false));
+
+ // reset error level
+ error_reporting($error_level);
+
+ return self::trim_template_result(ob_get_clean());
+ }
+
+ private static function trim_template_result($result)
+ {
+ return str_replace("\n\n", "\n", implode("\n", array_map('trim', explode("\n", trim($result)))));
+ }
+
+ private function setup_engine()
+ {
+ $this->template_path = dirname(__FILE__) . '/templates';
+ $this->template = new template();
+ $this->template->set_custom_template($this->template_path, 'tests');
+ }
+
+ protected function setUp()
+ {
+ // Test the engine can be used
+ $this->setup_engine();
+
+ if (!is_writable(dirname($this->template->cachepath)))
+ {
+ $this->markTestSkipped("Template cache directory is not writable.");
+ }
+
+ foreach (glob($this->template->cachepath . '*') as $file)
+ {
+ unlink($file);
+ }
+
+ $GLOBALS['config'] = array(
+ 'load_tplcompile' => true,
+ 'tpl_allow_php' => false,
+ );
+ }
+
+ protected function tearDown()
+ {
+ if (is_object($this->template))
+ {
+ foreach (glob($this->template->cachepath . '*') as $file)
+ {
+ unlink($file);
+ }
+ }
+ }
+
+ /**
+ * @todo put test data into templates/xyz.test
+ */
+ public static function template_data()
+ {
+ return array(
+ /*
+ array(
+ '', // File
+ array(), // vars
+ array(), // block vars
+ array(), // destroy
+ '', // Expected result
+ ),
+ */
+ array(
+ 'basic.html',
+ array(),
+ array(),
+ array(),
+ "pass\npass\n<!-- DUMMY var -->",
+ ),
+ array(
+ 'variable.html',
+ array('VARIABLE' => 'value'),
+ array(),
+ array(),
+ 'value',
+ ),
+ array(
+ 'if.html',
+ array(),
+ array(),
+ array(),
+ '0',
+ ),
+ array(
+ 'if.html',
+ array('S_VALUE' => true),
+ array(),
+ array(),
+ "1\n0",
+ ),
+ array(
+ 'if.html',
+ array('S_VALUE' => true, 'S_OTHER_VALUE' => true),
+ array(),
+ array(),
+ '1',
+ ),
+ array(
+ 'if.html',
+ array('S_VALUE' => false, 'S_OTHER_VALUE' => true),
+ array(),
+ array(),
+ '2',
+ ),
+ array(
+ 'loop.html',
+ array(),
+ array(),
+ array(),
+ "noloop\nnoloop",
+ ),
+ array(
+ 'loop.html',
+ array(),
+ array('loop' => array(array())),
+ array(),
+ "loop\nloop",
+ ),
+ array(
+ 'loop.html',
+ array(),
+ array('loop' => array(array(), array()), 'loop.block' => array(array())),
+ array(),
+ "loop\nloop\nloop\nloop",
+ ),
+ array(
+ 'loop.html',
+ array(),
+ array('loop' => array(array(), array()), 'loop.block' => array(array()), 'block' => array(array(), array())),
+ array(),
+ "loop\nloop\nloop\nloop\nloop#0-block#0\nloop#0-block#1\nloop#1-block#0\nloop#1-block#1",
+ ),
+ array(
+ 'loop_vars.html',
+ array(),
+ array('loop' => array(array('VARIABLE' => 'x'))),
+ array(),
+ "first\n0\nx\nset\nlast",
+ ),/* no nested top level loops
+ array(
+ 'loop_vars.html',
+ array(),
+ array('loop' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y'))),
+ array(),
+ "first\n0\n0\n2\nx\nset\n1\n1\n2\ny\nset\nlast",
+ ),
+ array(
+ 'loop_vars.html',
+ array(),
+ array('loop' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y')), 'loop.inner' => array(array(), array())),
+ array(),
+ "first\n0\n0\n2\nx\nset\n1\n1\n2\ny\nset\nlast\n0\n\n1\nlast inner\ninner loop",
+ ),*/
+ array(
+ 'loop_advanced.html',
+ array(),
+ array('loop' => array(array(), array(), array(), array(), array(), array(), array())),
+ array(),
+ "101234561\nx\n101234561\nx\n101234561\nx\n1234561\nx\n1\nx\n101\nx\n234\nx\n10\nx\n561\nx\n561",
+ ),
+ array(
+ 'define.html',
+ array(),
+ array('loop' => array(array(), array(), array(), array(), array(), array(), array()), 'test' => array(array()), 'test.deep' => array(array()), 'test.deep.defines' => array(array())),
+ array(),
+ "xyz\nabc",
+ ),
+ array(
+ 'expressions.html',
+ array(),
+ array(),
+ array(),
+ trim(str_repeat("pass", 39)),
+ ),
+ array(
+ 'php.html',
+ array(),
+ array(),
+ array(),
+ '',
+ ),
+ array(
+ 'include.html',
+ array('VARIABLE' => 'value'),
+ array(),
+ array(),
+ 'value',
+ ),
+ array(
+ 'loop_vars.html',
+ array(),
+ array('loop' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y')), 'loop.inner' => array(array(), array())),
+ array('loop'),
+ '',
+ ),/* no top level nested loops
+ array(
+ 'loop_vars.html',
+ array(),
+ array('loop' => array(array('VARIABLE' => 'x'), array('VARIABLE' => 'y')), 'loop.inner' => array(array(), array())),
+ array('loop.inner'),
+ "first\n0\n0\n2\nx\nset\n1\n1\n2\ny\nset\nlast",
+ ),*/
+ array(
+ 'lang.html',
+ array(),
+ array(),
+ array(),
+ "{ VARIABLE }\n{ VARIABLE }",
+ ),
+ array(
+ 'lang.html',
+ array('L_VARIABLE' => "Value'"),
+ array(),
+ array(),
+ "Value'\nValue\'",
+ ),
+ array(
+ 'lang.html',
+ array('LA_VARIABLE' => "Value'"),
+ array(),
+ array(),
+ "{ VARIABLE }\nValue'",
+ ),
+ );
+ }
+
+ public function test_missing_file()
+ {
+ $filename = 'file_not_found.html';
+
+ $this->template->set_filenames(array('test' => $filename));
+ $this->assertFileNotExists($this->template_path . '/' . $filename, 'Testing missing file, file cannot exist');
+
+ $expecting = sprintf('template->_tpl_load_file(): File %s does not exist or is empty', realpath($this->template_path . '/../') . '/templates/' . $filename);
+ $this->setExpectedTriggerError(E_USER_ERROR, $expecting);
+
+ $this->display('test');
+ }
+
+ public function test_empty_file()
+ {
+ $expecting = 'template->set_filenames: Empty filename specified for test';
+
+ $this->setExpectedTriggerError(E_USER_ERROR, $expecting);
+ $this->template->set_filenames(array('test' => ''));
+ }
+
+ public function test_invalid_handle()
+ {
+ $expecting = 'template->_tpl_load(): No file specified for handle test';
+ $this->setExpectedTriggerError(E_USER_ERROR, $expecting);
+
+ $this->display('test');
+ }
+
+ private function run_template($file, array $vars, array $block_vars, array $destroy, $expected, $cache_file)
+ {
+ $this->template->set_filenames(array('test' => $file));
+ $this->template->assign_vars($vars);
+
+ foreach ($block_vars as $block => $loops)
+ {
+ foreach ($loops as $_vars)
+ {
+ $this->template->assign_block_vars($block, $_vars);
+ }
+ }
+
+ foreach ($destroy as $block)
+ {
+ $this->template->destroy_block_vars($block);
+ }
+
+ try
+ {
+ $this->assertEquals($expected, $this->display('test'), "Testing $file");
+ $this->assertFileExists($cache_file);
+ }
+ catch (ErrorException $e)
+ {
+ if (file_exists($cache_file))
+ {
+ copy($cache_file, str_replace('ctpl_', 'tests_ctpl_', $cache_file));
+ }
+
+ throw $e;
+ }
+
+ // For debugging
+ if (self::PRESERVE_CACHE)
+ {
+ copy($cache_file, str_replace('ctpl_', 'tests_ctpl_', $cache_file));
+ }
+ }
+
+ /**
+ * @dataProvider template_data
+ */
+ public function test_template($file, array $vars, array $block_vars, array $destroy, $expected)
+ {
+ global $phpEx;
+ $cache_file = $this->template->cachepath . str_replace('/', '.', $file) . '.' . $phpEx;
+
+ $this->assertFileNotExists($cache_file);
+
+ $this->run_template($file, $vars, $block_vars, $destroy, $expected, $cache_file);
+
+ // Reset the engine state
+ $this->setup_engine();
+
+ $this->run_template($file, $vars, $block_vars, $destroy, $expected, $cache_file);
+ }
+
+ /**
+ * @dataProvider template_data
+ */
+ public function test_assign_display($file, array $vars, array $block_vars, array $destroy, $expected)
+ {
+ $this->template->set_filenames(array(
+ 'test' => $file,
+ 'container' => 'variable.html',
+ ));
+ $this->template->assign_vars($vars);
+
+ foreach ($block_vars as $block => $loops)
+ {
+ foreach ($loops as $_vars)
+ {
+ $this->template->assign_block_vars($block, $_vars);
+ }
+ }
+
+ foreach ($destroy as $block)
+ {
+ $this->template->destroy_block_vars($block);
+ }
+
+ $this->assertEquals($expected, self::trim_template_result($this->template->assign_display('test')), "Testing assign_display($file)");
+
+ $this->template->assign_display('test', 'VARIABLE', false);
+ $this->assertEquals($expected, $this->display('container'), "Testing assign_display($file)");
+ }
+
+ public function test_php()
+ {
+ global $phpEx;
+
+ $GLOBALS['config']['tpl_allow_php'] = true;
+
+ $cache_file = $this->template->cachepath . 'php.html.' . $phpEx;
+
+ $this->assertFileNotExists($cache_file);
+
+ $this->run_template('php.html', array(), array(), array(), 'test', $cache_file);
+
+ $GLOBALS['config']['tpl_allow_php'] = false;
+ }
+
+ public function test_includephp()
+ {
+ $this->markTestIncomplete('Include PHP test file paths are broken');
+
+ $GLOBALS['config']['tpl_allow_php'] = true;
+
+ $cache_file = $this->template->cachepath . 'includephp.html.' . PHP_EXT;
+
+ $cwd = getcwd();
+ chdir(dirname(__FILE__) . '/templates');
+
+ $this->run_template('includephp.html', array(), array(), array(), 'testing included php', $cache_file);
+
+ $this->template->set_filenames(array('test' => 'includephp.html'));
+ $this->assertEquals('testing included php', $this->display('test'), "Testing $file");
+
+ chdir($cwd);
+
+ $GLOBALS['config']['tpl_allow_php'] = false;
+ }
+
+ public static function alter_block_array_data()
+ {
+ return array(
+ array(
+ 'outer',
+ array('VARIABLE' => 'before'),
+ false,
+ 'insert',
+ <<<EOT
+outer - 0/4 - before
+outer - 1/4
+middle - 0/2
+middle - 1/2
+outer - 2/4
+middle - 0/3
+middle - 1/3
+middle - 2/3
+outer - 3/4
+middle - 0/2
+middle - 1/2
+EOT
+,
+ 'Test inserting before on top level block',
+ ),
+ array(
+ 'outer',
+ array('VARIABLE' => 'after'),
+ true,
+ 'insert',
+ <<<EOT
+outer - 0/4
+middle - 0/2
+middle - 1/2
+outer - 1/4
+middle - 0/3
+middle - 1/3
+middle - 2/3
+outer - 2/4
+middle - 0/2
+middle - 1/2
+outer - 3/4 - after
+EOT
+,
+ 'Test inserting after on top level block',
+ ),
+ array(
+ 'outer',
+ array('VARIABLE' => 'pos #1'),
+ 1,
+ 'insert',
+ <<<EOT
+outer - 0/4
+middle - 0/2
+middle - 1/2
+outer - 1/4 - pos #1
+outer - 2/4
+middle - 0/3
+middle - 1/3
+middle - 2/3
+outer - 3/4
+middle - 0/2
+middle - 1/2
+EOT
+,
+ 'Test inserting at 1 on top level block',
+ ),
+ array(
+ 'outer',
+ array('VARIABLE' => 'pos #1'),
+ 0,
+ 'change',
+ <<<EOT
+outer - 0/3 - pos #1
+middle - 0/2
+middle - 1/2
+outer - 1/3
+middle - 0/3
+middle - 1/3
+middle - 2/3
+outer - 2/3
+middle - 0/2
+middle - 1/2
+EOT
+,
+ 'Test inserting at 1 on top level block',
+ ),
+ array(
+ 'outer[0].middle',
+ array('VARIABLE' => 'before'),
+ false,
+ 'insert',
+ <<<EOT
+outer - 0/3
+middle - 0/3 - before
+middle - 1/3
+middle - 2/3
+outer - 1/3
+middle - 0/3
+middle - 1/3
+middle - 2/3
+outer - 2/3
+middle - 0/2
+middle - 1/2
+EOT
+,
+ 'Test inserting before on nested block',
+ ),
+ array(
+ 'outer[0].middle',
+ array('VARIABLE' => 'after'),
+ true,
+ 'insert',
+ <<<EOT
+outer - 0/3
+middle - 0/3
+middle - 1/3
+middle - 2/3 - after
+outer - 1/3
+middle - 0/3
+middle - 1/3
+middle - 2/3
+outer - 2/3
+middle - 0/2
+middle - 1/2
+EOT
+,
+ 'Test inserting after on nested block',
+ ),
+ array(
+ 'outer[0].middle',
+ array('VARIABLE' => 'pos #1'),
+ 1,
+ 'insert',
+ <<<EOT
+outer - 0/3
+middle - 0/3
+middle - 1/3 - pos #1
+middle - 2/3
+outer - 1/3
+middle - 0/3
+middle - 1/3
+middle - 2/3
+outer - 2/3
+middle - 0/2
+middle - 1/2
+EOT
+,
+ 'Test inserting at pos 1 on nested block',
+ ),
+ array(
+ 'outer[1].middle',
+ array('VARIABLE' => 'before'),
+ false,
+ 'insert',
+ <<<EOT
+outer - 0/3
+middle - 0/2
+middle - 1/2
+outer - 1/3
+middle - 0/4 - before
+middle - 1/4
+middle - 2/4
+middle - 3/4
+outer - 2/3
+middle - 0/2
+middle - 1/2
+EOT
+,
+ 'Test inserting before on nested block (pos 1)',
+ ),
+ array(
+ 'outer[].middle',
+ array('VARIABLE' => 'before'),
+ false,
+ 'insert',
+ <<<EOT
+outer - 0/3
+middle - 0/2
+middle - 1/2
+outer - 1/3
+middle - 0/3
+middle - 1/3
+middle - 2/3
+outer - 2/3
+middle - 0/3 - before
+middle - 1/3
+middle - 2/3
+EOT
+,
+ 'Test inserting before on nested block (end)',
+ ),
+ array(
+ 'outer.middle',
+ array('VARIABLE' => 'before'),
+ false,
+ 'insert',
+ <<<EOT
+outer - 0/3
+middle - 0/2
+middle - 1/2
+outer - 1/3
+middle - 0/3
+middle - 1/3
+middle - 2/3
+outer - 2/3
+middle - 0/3 - before
+middle - 1/3
+middle - 2/3
+EOT
+,
+ 'Test inserting before on nested block (end)',
+ ),
+ );
+ }
+
+/*
+ <<<EOT
+outer - 0/3
+middle - 0/2
+middle - 1/2
+outer - 1/3
+middle - 0/3
+middle - 1/3
+middle - 2/3
+outer - 2/3
+middle - 0/2
+middle - 1/2
+EOT
+,
+*/
+
+ /**
+ * @dataProvider alter_block_array_data
+ */
+ public function test_alter_block_array($alter_block, array $vararray, $key, $mode, $expect, $description)
+ {
+ $this->markTestIncomplete('Alter Block Test is broken');
+
+ $this->template->set_filenames(array('test' => 'loop_nested.html'));
+
+ // @todo Change this
+ $this->template->assign_block_vars('outer', array());
+ $this->template->assign_block_vars('outer.middle', array());
+ $this->template->assign_block_vars('outer.middle', array());
+ $this->template->assign_block_vars('outer', array());
+ $this->template->assign_block_vars('outer.middle', array());
+ $this->template->assign_block_vars('outer.middle', array());
+ $this->template->assign_block_vars('outer.middle', array());
+ $this->template->assign_block_vars('outer', array());
+ $this->template->assign_block_vars('outer.middle', array());
+ $this->template->assign_block_vars('outer.middle', array());
+
+ $this->assertEquals("outer - 0/3\nmiddle - 0/2\nmiddle - 1/2\nouter - 1/3\nmiddle - 0/3\nmiddle - 1/3\nmiddle - 2/3\nouter - 2/3\nmiddle - 0/2\nmiddle - 1/2", $this->display('test'), 'Ensuring template is built correctly before modification');
+
+ $this->template->alter_block_array($alter_block, $vararray, $key, $mode);
+ $this->assertEquals($expect, $this->display('test'), $description);
+ }
+}
+
diff --git a/tests/template/templates/_dummy_include.php b/tests/template/templates/_dummy_include.php
new file mode 100644
index 0000000000..1de5dddf59
--- /dev/null
+++ b/tests/template/templates/_dummy_include.php
@@ -0,0 +1,3 @@
+<?php
+
+echo "testing included php";
diff --git a/tests/template/templates/basic.html b/tests/template/templates/basic.html
new file mode 100644
index 0000000000..c1dd690260
--- /dev/null
+++ b/tests/template/templates/basic.html
@@ -0,0 +1,20 @@
+<!-- IF S_FALSE -->
+fail
+<!-- ENDIF -->
+<!-- IF S_TRUE -->
+pass
+<!-- ENDIF -->
+<!-- IF S_FALSE -->
+fail
+<!-- ELSEIF S_FALSE and not S_TRUE -->
+fail
+<!-- ELSE -->
+pass
+<!-- ENDIF -->
+<!-- BEGIN empty -->
+fail
+<!-- BEGINELSE -->
+pass
+<!-- END empty -->
+
+<!-- DUMMY var -->
diff --git a/tests/template/templates/define.html b/tests/template/templates/define.html
new file mode 100644
index 0000000000..82237d21a3
--- /dev/null
+++ b/tests/template/templates/define.html
@@ -0,0 +1,8 @@
+<!-- DEFINE $VALUE = 'xyz' -->
+{$VALUE}
+<!-- DEFINE $VALUE = 'abc' -->
+{$VALUE}
+<!-- UNDEFINE $VALUE -->
+{$VALUE}
+<!-- DEFINE $VALUE -->
+
diff --git a/tests/template/templates/expressions.html b/tests/template/templates/expressions.html
new file mode 100644
index 0000000000..c40d967dab
--- /dev/null
+++ b/tests/template/templates/expressions.html
@@ -0,0 +1,86 @@
+<!-- IF 10 is even -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF 9 is even -->fail<!-- ELSE -->pass<!-- ENDIF -->
+
+<!-- IF not 390 is even -->fail<!-- ELSE -->pass<!-- ENDIF -->
+
+<!-- IF 9 is odd -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF 32 is odd -->fail<!-- ELSE -->pass<!-- ENDIF -->
+
+<!-- IF 32 is div by 16 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF 10 is not even -->fail<!-- ELSE -->pass<!-- ENDIF -->
+
+<!-- IF 24 == 24 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF 24 eq 24 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF ((((((24 == 24)))))) -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+
+<!-- IF 24 != 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF 24 <> 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF 24 ne 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF 24 neq 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+
+<!-- IF 10 lt 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF 10 < 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+
+<!-- IF 10 le 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF 10 lte 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF 10 <= 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF 20 le 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF 20 lte 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF 20 <= 20 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+
+<!-- IF 9 gt 1 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF 9 > 1 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+
+<!-- IF 9 >= 1 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF 9 gte 1 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF 9 ge 1 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF 9 >= 9 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF 9 gte 9 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF 9 ge 9 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+
+<!-- IF true && (10 > 4) -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF true and (10 > 4) -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+
+<!-- IF false || true -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF false or true -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+
+<!-- IF !false -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF not false -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF not not not false -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+
+<!-- IF 6 % 4 == 2 -->pass<!-- ELSE -->fail<!-- ENDIF -->
+
+<!-- IF 24 mod 12 == 0 -->pass<!-- ELSE -->fail<!-- ENDIF -->
diff --git a/tests/template/templates/if.html b/tests/template/templates/if.html
new file mode 100644
index 0000000000..c502e52f51
--- /dev/null
+++ b/tests/template/templates/if.html
@@ -0,0 +1,11 @@
+<!-- IF S_VALUE -->
+1
+<!-- ELSEIF S_OTHER_VALUE -->
+2
+<!-- ELSE -->
+0
+<!-- ENDIF -->
+
+<!-- IF (S_VALUE > S_OTHER_VALUE) -->
+0
+<!-- ENDIF -->
diff --git a/tests/template/templates/include.html b/tests/template/templates/include.html
new file mode 100644
index 0000000000..730d713d65
--- /dev/null
+++ b/tests/template/templates/include.html
@@ -0,0 +1 @@
+<!-- INCLUDE variable.html -->
diff --git a/tests/template/templates/includephp.html b/tests/template/templates/includephp.html
new file mode 100644
index 0000000000..3e13fa33fa
--- /dev/null
+++ b/tests/template/templates/includephp.html
@@ -0,0 +1 @@
+<!-- INCLUDEPHP ../templates/_dummy_include.php -->
diff --git a/tests/template/templates/lang.html b/tests/template/templates/lang.html
new file mode 100644
index 0000000000..2b5ea1cafe
--- /dev/null
+++ b/tests/template/templates/lang.html
@@ -0,0 +1,3 @@
+{L_VARIABLE}
+
+{LA_VARIABLE}
diff --git a/tests/template/templates/loop.html b/tests/template/templates/loop.html
new file mode 100644
index 0000000000..de1a10004d
--- /dev/null
+++ b/tests/template/templates/loop.html
@@ -0,0 +1,21 @@
+<!-- BEGIN loop -->
+loop
+<!-- BEGINELSE -->
+noloop
+<!-- END loop -->
+
+<!-- IF .loop -->
+loop
+<!-- ELSE -->
+noloop
+<!-- ENDIF -->
+
+<!-- IF .loop == 2 -->
+loop
+<!-- ENDIF -->
+
+<!-- BEGIN loop -->
+<!-- BEGIN !block -->
+loop#{loop.S_ROW_COUNT}-block#{block.S_ROW_COUNT}
+<!-- END !block -->
+<!-- END loop -->
diff --git a/tests/template/templates/loop_advanced.html b/tests/template/templates/loop_advanced.html
new file mode 100644
index 0000000000..c75fe55f03
--- /dev/null
+++ b/tests/template/templates/loop_advanced.html
@@ -0,0 +1,19 @@
+<!-- BEGIN loop -->{loop.S_FIRST_ROW}{loop.S_ROW_COUNT}{loop.S_LAST_ROW}<!-- END loop -->
+x
+<!-- BEGIN loop(0) -->{loop.S_FIRST_ROW}{loop.S_ROW_COUNT}{loop.S_LAST_ROW}<!-- END loop -->
+x
+<!-- BEGIN loop(0,-1) -->{loop.S_FIRST_ROW}{loop.S_ROW_COUNT}{loop.S_LAST_ROW}<!-- END loop -->
+x
+<!-- BEGIN loop(1) -->{loop.S_FIRST_ROW}{loop.S_ROW_COUNT}{loop.S_LAST_ROW}<!-- END loop -->
+x
+<!-- BEGIN loop(1,1) -->{loop.S_FIRST_ROW}{loop.S_ROW_COUNT}{loop.S_LAST_ROW}<!-- END loop -->
+x
+<!-- BEGIN loop(0,1) -->{loop.S_FIRST_ROW}{loop.S_ROW_COUNT}{loop.S_LAST_ROW}<!-- END loop -->
+x
+<!-- BEGIN loop(2,4) -->{loop.S_FIRST_ROW}{loop.S_ROW_COUNT}{loop.S_LAST_ROW}<!-- END loop -->
+x
+<!-- BEGIN loop(0,-7) -->{loop.S_FIRST_ROW}{loop.S_ROW_COUNT}{loop.S_LAST_ROW}<!-- END loop -->
+x
+<!-- BEGIN loop(-2,6) -->{loop.S_FIRST_ROW}{loop.S_ROW_COUNT}{loop.S_LAST_ROW}<!-- END loop -->
+x
+<!-- BEGIN loop(-2,-1) -->{loop.S_FIRST_ROW}{loop.S_ROW_COUNT}{loop.S_LAST_ROW}<!-- END loop -->
diff --git a/tests/template/templates/loop_nested.html b/tests/template/templates/loop_nested.html
new file mode 100644
index 0000000000..571df97b4c
--- /dev/null
+++ b/tests/template/templates/loop_nested.html
@@ -0,0 +1,8 @@
+<!-- BEGIN outer -->
+ {outer.S_BLOCK_NAME} - {outer.S_ROW_NUM}/{outer.S_NUM_ROWS}<!-- IF outer.VARIABLE --> - {outer.VARIABLE}<!-- ENDIF -->
+
+ <!-- BEGIN middle -->
+ {middle.S_BLOCK_NAME} - {middle.S_ROW_NUM}/{middle.S_NUM_ROWS}<!-- IF middle.VARIABLE --> - {middle.VARIABLE}<!-- ENDIF -->
+
+ <!-- END middle -->
+<!-- END outer -->
diff --git a/tests/template/templates/loop_vars.html b/tests/template/templates/loop_vars.html
new file mode 100644
index 0000000000..4f02fd2e6c
--- /dev/null
+++ b/tests/template/templates/loop_vars.html
@@ -0,0 +1,21 @@
+<!-- BEGIN loop -->
+<!-- IF loop.S_FIRST_ROW -->first<!-- ENDIF -->
+
+{loop.S_ROW_COUNT}
+
+{loop.VARIABLE}
+
+<!-- IF loop.VARIABLE -->set<!-- ENDIF -->
+
+<!-- IF loop.S_LAST_ROW -->
+last
+<!-- ENDIF -->
+<!-- BEGIN inner -->
+
+{inner.S_ROW_COUNT}
+
+<!-- IF inner.S_LAST_ROW and inner.S_ROW_COUNT and inner.S_NUM_ROWS -->last inner<!-- ENDIF -->
+
+<!-- END inner -->
+<!-- END loop -->
+<!-- IF .loop.inner -->inner loop<!-- ENDIF -->
diff --git a/tests/template/templates/php.html b/tests/template/templates/php.html
new file mode 100644
index 0000000000..07a260cdb3
--- /dev/null
+++ b/tests/template/templates/php.html
@@ -0,0 +1 @@
+<!-- PHP -->echo "test";<!-- ENDPHP -->
diff --git a/tests/template/templates/variable.html b/tests/template/templates/variable.html
new file mode 100644
index 0000000000..f68f91597c
--- /dev/null
+++ b/tests/template/templates/variable.html
@@ -0,0 +1 @@
+{VARIABLE}
diff --git a/tests/test_framework/framework.php b/tests/test_framework/framework.php
new file mode 100644
index 0000000000..abdcd1ad79
--- /dev/null
+++ b/tests/test_framework/framework.php
@@ -0,0 +1,39 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+define('IN_PHPBB', true);
+$phpbb_root_path = '../phpBB/';
+$phpEx = 'php';
+$table_prefix = '';
+
+// If we are on PHP >= 6.0.0 we do not need some code
+if (version_compare(PHP_VERSION, '6.0.0-dev', '>='))
+{
+ define('STRIP', false);
+}
+else
+{
+ @set_magic_quotes_runtime(0);
+ define('STRIP', (get_magic_quotes_gpc()) ? true : false);
+}
+
+require_once $phpbb_root_path . 'includes/constants.php';
+
+// require at least PHPUnit 3.3.0
+require_once 'PHPUnit/Runner/Version.php';
+if (version_compare(PHPUnit_Runner_Version::id(), '3.3.0', '<'))
+{
+ trigger_error('PHPUnit >= 3.3.0 required');
+}
+
+require_once 'PHPUnit/Framework.php';
+require_once 'PHPUnit/Extensions/Database/TestCase.php';
+require_once 'test_framework/phpbb_test_case_helpers.php';
+require_once 'test_framework/phpbb_test_case.php';
+require_once 'test_framework/phpbb_database_test_case.php';
diff --git a/tests/test_framework/phpbb_database_test_case.php b/tests/test_framework/phpbb_database_test_case.php
new file mode 100644
index 0000000000..d558874c6f
--- /dev/null
+++ b/tests/test_framework/phpbb_database_test_case.php
@@ -0,0 +1,168 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_TestCase
+{
+ protected $test_case_helpers;
+
+ public function init_test_case_helpers()
+ {
+ if (!$this->test_case_helpers)
+ {
+ $this->test_case_helpers = new phpbb_test_case_helpers($this);
+ }
+ }
+
+ function get_dbms_data($dbms)
+ {
+ $available_dbms = array(
+ 'firebird' => array(
+ 'SCHEMA' => 'firebird',
+ 'DELIM' => ';;',
+ 'PDO' => 'firebird',
+ ),
+ 'mysqli' => array(
+ 'SCHEMA' => 'mysql_41',
+ 'DELIM' => ';',
+ 'PDO' => 'mysql',
+ ),
+ 'mysql' => array(
+ 'SCHEMA' => 'mysql',
+ 'DELIM' => ';',
+ 'PDO' => 'mysql',
+ ),
+ 'mssql' => array(
+ 'SCHEMA' => 'mssql',
+ 'DELIM' => 'GO',
+ 'PDO' => 'odbc',
+ ),
+ 'mssql_odbc'=> array(
+ 'SCHEMA' => 'mssql',
+ 'DELIM' => 'GO',
+ 'PDO' => 'odbc',
+ ),
+ 'mssqlnative' => array(
+ 'SCHEMA' => 'mssql',
+ 'DELIM' => 'GO',
+ 'PDO' => 'odbc',
+ ),
+ 'oracle' => array(
+ 'SCHEMA' => 'oracle',
+ 'DELIM' => '/',
+ 'PDO' => 'oci',
+ ),
+ 'postgres' => array(
+ 'SCHEMA' => 'postgres',
+ 'DELIM' => ';',
+ 'PDO' => 'pgsql',
+ ),
+ 'sqlite' => array(
+ 'SCHEMA' => 'sqlite',
+ 'DELIM' => ';',
+ 'PDO' => 'sqlite',
+ ),
+ );
+
+ if (isset($available_dbms[$dbms]))
+ {
+ return $available_dbms[$dbms];
+ }
+ else
+ {
+ trigger_error('Database unsupported', E_USER_ERROR);
+ }
+ }
+
+ function split_sql_file($sql, $delimiter)
+ {
+ $sql = str_replace("\r" , '', $sql);
+ $data = preg_split('/' . preg_quote($delimiter, '/') . '$/m', $sql);
+
+ $data = array_map('trim', $data);
+
+ // The empty case
+ $end_data = end($data);
+
+ if (empty($end_data))
+ {
+ unset($data[key($data)]);
+ }
+
+ return $data;
+ }
+
+ public function getConnection()
+ {
+ static $already_connected;
+
+ $this->init_test_case_helpers();
+ $database_config = $this->test_case_helpers->get_database_config();
+
+ $dbms_data = $this->get_dbms_data($database_config['dbms']);
+
+ if ($already_connected)
+ {
+ $pdo = new PDO($dbms_data['PDO'] . ':host=' . $database_config['dbhost'] . ';dbname=' . $database_config['dbname'], $database_config['dbuser'], $database_config['dbpasswd']);
+ }
+ else
+ {
+ $pdo = new PDO($dbms_data['PDO'] . ':host=' . $database_config['dbhost'] . ';', $database_config['dbuser'], $database_config['dbpasswd']);
+
+ try
+ {
+ $pdo->exec('DROP DATABASE ' . $database_config['dbname']);
+ }
+ catch (PDOException $e){} // ignore non existent db
+
+ $pdo->exec('CREATE DATABASE ' . $database_config['dbname']);
+
+ $pdo = new PDO($dbms_data['PDO'] . ':host=' . $database_config['dbhost'] . ';dbname=' . $database_config['dbname'], $database_config['dbuser'], $database_config['dbpasswd']);
+
+ if ($database_config['dbms'] == 'mysql')
+ {
+ $sth = $pdo->query('SELECT VERSION() AS version');
+ $row = $sth->fetch(PDO::FETCH_ASSOC);
+
+ if (version_compare($row['version'], '4.1.3', '>='))
+ {
+ $dbms_data['SCHEMA'] .= '_41';
+ }
+ else
+ {
+ $dbms_data['SCHEMA'] .= '_40';
+ }
+
+ unset($row, $sth);
+ }
+
+ $sql_query = $this->split_sql_file(file_get_contents("../phpBB/install/schemas/{$dbms_data['SCHEMA']}_schema.sql"), $dbms_data['DELIM']);
+
+ foreach ($sql_query as $sql)
+ {
+ $pdo->exec($sql);
+ }
+
+ $already_connected = true;
+ }
+
+ return $this->createDefaultDBConnection($pdo, 'testdb');
+ }
+
+ public function new_dbal()
+ {
+ $this->init_test_case_helpers();
+ return $this->test_case_helpers->new_dbal();
+ }
+
+ public function setExpectedTriggerError($errno, $message = '')
+ {
+ $this->init_test_case_helpers();
+ $this->test_case_helpers->setExpectedTriggerError($errno, $message);
+ }
+}
diff --git a/tests/test_framework/phpbb_test_case.php b/tests/test_framework/phpbb_test_case.php
new file mode 100644
index 0000000000..af867b29ff
--- /dev/null
+++ b/tests/test_framework/phpbb_test_case.php
@@ -0,0 +1,27 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+class phpbb_test_case extends PHPUnit_Framework_TestCase
+{
+ protected $test_case_helpers;
+
+ public function init_test_case_helpers()
+ {
+ if (!$this->test_case_helpers)
+ {
+ $this->test_case_helpers = new phpbb_test_case_helpers($this);
+ }
+ }
+
+ public function setExpectedTriggerError($errno, $message = '')
+ {
+ $this->init_test_case_helpers();
+ $this->test_case_helpers->setExpectedTriggerError($errno, $message);
+ }
+}
diff --git a/tests/test_framework/phpbb_test_case_helpers.php b/tests/test_framework/phpbb_test_case_helpers.php
new file mode 100644
index 0000000000..0c5932e1ad
--- /dev/null
+++ b/tests/test_framework/phpbb_test_case_helpers.php
@@ -0,0 +1,97 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+class phpbb_test_case_helpers
+{
+ protected $expectedTriggerError = false;
+
+ protected $test_case;
+
+ public function __construct($test_case)
+ {
+ $this->test_case = $test_case;
+ }
+
+ public function get_database_config()
+ {
+ static $show_error = true;
+
+ if (!file_exists('test_config.php'))
+ {
+ if ($show_error)
+ {
+ $show_error = false;
+ }
+ else
+ {
+ $this->test_case->markTestSkipped('Missing test_config.php: See first error.');
+ return;
+ }
+
+ trigger_error("You have to create a test_config.php like this:
+\"<?php
+\$dbms = 'mysqli';
+\$dbhost = 'localhost';
+\$dbport = '';
+\$dbname = 'database';
+\$dbuser = 'user';
+\$dbpasswd = 'password';
+\"
+
+NOTE: The database is dropped and recreated with the phpbb-db-schema! Do NOT specify a database with important data.", E_USER_ERROR);
+ }
+ include('test_config.php');
+
+ return array(
+ 'dbms' => $dbms,
+ 'dbhost' => $dbhost,
+ 'dbport' => $dbport,
+ 'dbname' => $dbname,
+ 'dbuser' => $dbuser,
+ 'dbpasswd' => $dbpasswd,
+ );
+ }
+
+ public function new_dbal()
+ {
+ global $phpbb_root_path, $phpEx;
+ $config = $this->get_database_config();
+
+ require_once '../phpBB/includes/db/' . $config['dbms'] . '.php';
+ $dbal = 'dbal_' . $config['dbms'];
+ $db = new $dbal();
+ $db->sql_connect($config['dbhost'], $config['dbuser'], $config['dbpasswd'], $config['dbname'], $config['dbport']);
+
+ return $db;
+ }
+
+ public function setExpectedTriggerError($errno, $message = '')
+ {
+ $exceptionName = '';
+ switch ($errno)
+ {
+ case E_NOTICE:
+ case E_STRICT:
+ PHPUnit_Framework_Error_Notice::$enabled = true;
+ $exceptionName = 'PHPUnit_Framework_Error_Notice';
+ break;
+
+ case E_WARNING:
+ PHPUnit_Framework_Error_Warning::$enabled = true;
+ $exceptionName = 'PHPUnit_Framework_Error_Warning';
+ break;
+
+ default:
+ $exceptionName = 'PHPUnit_Framework_Error';
+ break;
+ }
+ $this->expectedTriggerError = true;
+ $this->test_case->setExpectedException($exceptionName, (string) $message, $errno);
+ }
+}
diff --git a/tests/text_processing/all_tests.php b/tests/text_processing/all_tests.php
new file mode 100644
index 0000000000..5e759c72ee
--- /dev/null
+++ b/tests/text_processing/all_tests.php
@@ -0,0 +1,41 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+if (!defined('PHPUnit_MAIN_METHOD'))
+{
+ define('PHPUnit_MAIN_METHOD', 'phpbb_text_processing_all_tests::main');
+}
+
+require_once 'test_framework/framework.php';
+require_once 'PHPUnit/TextUI/TestRunner.php';
+
+require_once 'text_processing/make_clickable.php';
+
+class phpbb_text_processing_all_tests
+{
+ public static function main()
+ {
+ PHPUnit_TextUI_TestRunner::run(self::suite());
+ }
+
+ public static function suite()
+ {
+ $suite = new PHPUnit_Framework_TestSuite('phpBB Text Processing Tools');
+
+ $suite->addTestSuite('phpbb_text_processing_make_clickable_test');
+
+ return $suite;
+ }
+}
+
+if (PHPUnit_MAIN_METHOD == 'phpbb_text_processing_all_tests::main')
+{
+ phpbb_text_processing_all_tests::main();
+}
+
diff --git a/tests/text_processing/make_clickable.php b/tests/text_processing/make_clickable.php
new file mode 100644
index 0000000000..a667dd705e
--- /dev/null
+++ b/tests/text_processing/make_clickable.php
@@ -0,0 +1,106 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+require_once 'test_framework/framework.php';
+
+require_once '../phpBB/includes/functions.php';
+require_once '../phpBB/includes/functions_content.php';
+
+class phpbb_text_processing_make_clickable_test extends phpbb_test_case
+{
+ public static function make_clickable_data()
+ {
+ // value => whether it should work
+ $prefix_texts = array(
+ '' => true,
+ "np \n" => true,
+ 'bp text ' => true,
+ 'cp text>' => true,
+ 'ep text.' => array('w' => false), // doesn't work for www. type urls, but for everything else
+ );
+ $suffix_texts = array(
+ '' => true,
+ "\n ns" => true,
+ ' bs text.' => true,
+ '&gt;cs text' => true,
+ '&quot;ds text' => true,
+ '. es text.' => true,
+ ', fs text.' => true,
+ );
+
+ $urls = array(
+ 'http://example.com' => array('tag' => 'm', 'url' => false, 'text' => false), // false means same as key
+ 'http://example.com/' => array('tag' => 'm', 'url' => false, 'text' => false),
+ 'http://example.com/path?query=abc' => array('tag' => 'm', 'url' => false, 'text' => false),
+ 'http://example.com/1' => array('tag' => 'm', 'url' => false, 'text' => false),
+ 'http://example.com/some/very/long/path/with/over/55/characters?and=a&amp;long=query&amp;too=1' => array('tag' => 'm', 'url' => false, 'text' => 'http://example.com/some/very/long/path/ ... uery&amp;too=1'),
+ 'http://localhost' => array('tag' => 'm', 'url' => false, 'text' => false),
+ 'http://localhost/#abc' => array('tag' => 'm', 'url' => false, 'text' => false),
+
+ 'www.example.com/path/' => array('tag' => 'w', 'url' => 'http://www.example.com/path/', 'text' => false),
+ 'randomwww.example.com/path/' => false,
+
+ 'http://thisdomain.org' => array('tag' => 'm', 'url' => false, 'text' => false),
+ 'http://thisdomain.org/' => array('tag' => 'm', 'url' => false, 'text' => false),
+ 'http://thisdomain.org/1' => array('tag' => 'l', 'url' => false, 'text' => '1'),
+ 'http://thisdomain.org/path/some?query=abc#test' => array('tag' => 'l', 'url' => false, 'text' => 'path/some?query=abc#test'),
+
+ 'javascript:www.example.com/' => false,
+ );
+
+ $test_data = array();
+
+ // run the test for each combination
+ foreach ($prefix_texts as $prefix => $prefix_success)
+ {
+ foreach ($suffix_texts as $suffix => $suffix_success)
+ {
+ foreach ($urls as $url => $url_type)
+ {
+ $input = $prefix . $url . $suffix;
+ // no valid url => no change
+ $output = $input;
+
+ if (
+ ($prefix_success && $suffix_success && is_array($url_type)) &&
+ // handle except syntax for prefix/suffix
+ (!is_array($prefix_success) || !isset($prefix_success[$url_type['tag']]) || $prefix_success[$url_type['tag']] == true) &&
+ (!is_array($suffix_success) || !isset($suffix_success[$url_type['tag']]) || $suffix_success[$url_type['tag']] == true)
+ )
+ {
+ // false means it's the same as the url, less typing
+ $url_type['url'] = ($url_type['url']) ? $url_type['url'] : $url;
+ $url_type['text'] = ($url_type['text']) ? $url_type['text'] : $url;
+
+ $class = ($url_type['tag'] === 'l') ? 'postlink-local' : 'postlink';
+
+ // replace the url with the desired output format
+ $output = $prefix . '<!-- ' . $url_type['tag'] . ' --><a class="' . $class . '" href="' . $url_type['url'] . '">' . $url_type['text'] . '</a><!-- ' . $url_type['tag'] . ' -->' . $suffix;
+ }
+ $test_data[] = array($input, $output);
+ }
+ }
+ }
+
+ return $test_data;
+ }
+
+ /**
+ * @dataProvider make_clickable_data
+ */
+ public function test_make_clickable($input, $expected)
+ {
+ $result = make_clickable($input, 'http://thisdomain.org');
+
+ $label = 'Making text clickable: ' . $input;
+ $this->assertEquals($expected, $result, $label);
+ }
+
+}
+
diff --git a/tests/utf/all_tests.php b/tests/utf/all_tests.php
new file mode 100644
index 0000000000..0d5d44d695
--- /dev/null
+++ b/tests/utf/all_tests.php
@@ -0,0 +1,43 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+if (!defined('PHPUnit_MAIN_METHOD'))
+{
+ define('PHPUnit_MAIN_METHOD', 'phpbb_utf_all_tests::main');
+}
+
+require_once 'test_framework/framework.php';
+require_once 'PHPUnit/TextUI/TestRunner.php';
+
+require_once 'utf/utf8_wordwrap_test.php';
+require_once 'utf/utf8_clean_string_test.php';
+
+class phpbb_utf_all_tests
+{
+ public static function main()
+ {
+ PHPUnit_TextUI_TestRunner::run(self::suite());
+ }
+
+ public static function suite()
+ {
+ $suite = new PHPUnit_Framework_TestSuite('phpBB Unicode Transformation Format');
+
+ $suite->addTestSuite('phpbb_utf_utf8_wordwrap_test');
+ $suite->addTestSuite('phpbb_utf_utf8_clean_string_test');
+
+ return $suite;
+ }
+}
+
+if (PHPUnit_MAIN_METHOD == 'phpbb_utf_all_tests::main')
+{
+ phpbb_utf_all_tests::main();
+}
+
diff --git a/tests/utf/utf8_clean_string_test.php b/tests/utf/utf8_clean_string_test.php
new file mode 100644
index 0000000000..870ad76fc4
--- /dev/null
+++ b/tests/utf/utf8_clean_string_test.php
@@ -0,0 +1,32 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+require_once 'test_framework/framework.php';
+require_once '../phpBB/includes/utf/utf_tools.php';
+
+class phpbb_utf_utf8_clean_string_test extends phpbb_test_case
+{
+ public static function cleanable_strings()
+ {
+ return array(
+ array('MiXed CaSe', 'mixed case', 'Checking case folding'),
+ array(' many spaces ', 'many spaces', 'Checking whitespace reduction'),
+ array("we\xC2\xA1rd\xE1\x9A\x80ch\xCE\xB1r\xC2\xADacters", 'weird characters', 'Checking confusables replacement'),
+ );
+ }
+
+ /**
+ * @dataProvider cleanable_strings
+ */
+ public function test_utf8_clean_string($input, $output, $label)
+ {
+ $this->assertEquals($output, utf8_clean_string($input), $label);
+ }
+}
+
diff --git a/tests/utf/utf8_wordwrap_test.php b/tests/utf/utf8_wordwrap_test.php
new file mode 100644
index 0000000000..ef1165a897
--- /dev/null
+++ b/tests/utf/utf8_wordwrap_test.php
@@ -0,0 +1,84 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2008 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+require_once 'test_framework/framework.php';
+require_once '../phpBB/includes/utf/utf_tools.php';
+
+class phpbb_utf_utf8_wordwrap_test extends phpbb_test_case
+{
+ public function test_utf8_wordwrap_ascii()
+ {
+ // if the input is all ascii it should work exactly like php's wordwrap
+
+ $text = 'The quick brown fox jumped over the lazy dog.';
+
+ $php_wordwrap = wordwrap($text, 20);
+ $phpbb_utf8_wordwrap = utf8_wordwrap($text, 20);
+ $this->assertEquals($php_wordwrap, $phpbb_utf8_wordwrap, "Checking ASCII standard behaviour with length 20");
+
+ $php_wordwrap = wordwrap($text, 30, "<br />\n");
+ $phpbb_utf8_wordwrap = utf8_wordwrap($text, 30, "<br />\n");
+ $this->assertEquals($php_wordwrap, $phpbb_utf8_wordwrap, "Checking ASCII special break string with length 30");
+
+ $text = 'A very long woooooooooooord.';
+
+ $php_wordwrap = wordwrap($text, 8, "\n");
+ $phpbb_utf8_wordwrap = utf8_wordwrap($text, 8, "\n");
+ $this->assertEquals($php_wordwrap, $phpbb_utf8_wordwrap, 'Checking ASCII not cutting long words');
+
+ $php_wordwrap = wordwrap($text, 8, "\n", true);
+ $phpbb_utf8_wordwrap = utf8_wordwrap($text, 8, "\n", true);
+ $this->assertEquals($php_wordwrap, $phpbb_utf8_wordwrap, 'Checking ASCII cutting long words');
+ }
+
+ /**
+ * Helper function that generates meaningless greek text
+ */
+ private function turn_into_greek($string)
+ {
+ $greek_chars = array("\xCE\x90", "\xCE\x91", "\xCE\x92", "\xCE\x93", "\xCE\x94", "\xCE\x95", "\xCE\x96", "\xCE\x97", "\xCE\x98", "\xCE\x99");
+
+ $greek = '';
+ for ($i = 0, $n = strlen($string); $i < $n; $i++)
+ {
+ // replace each number with the character from the array
+ if (ctype_digit($string[$i]))
+ {
+ $greek .= $greek_chars[(int) $string[$i]];
+ }
+ else
+ {
+ $greek .= $string[$i];
+ }
+ }
+
+ return $greek;
+ }
+
+ public function test_utf8_wordwrap_utf8()
+ {
+ $text = "0123456 0123 012345 01234";
+ $greek = $this->turn_into_greek($text);
+
+ $expected = $this->turn_into_greek(wordwrap($text, 10));
+ $phpbb_utf8_wordwrap = utf8_wordwrap($greek, 10);
+ $this->assertEquals($expected, $phpbb_utf8_wordwrap, 'Checking UTF-8 standard behaviour with length 10');
+ }
+
+ public function test_utf8_wordwrap_utf8_cut()
+ {
+ $text = "0123456 0123 012345 01234";
+ $greek = $this->turn_into_greek($text);
+
+ $expected = $this->turn_into_greek(wordwrap($text, 5, "\n", true));
+ $phpbb_utf8_wordwrap = utf8_wordwrap($greek, 5, "\n", true);
+ $this->assertEquals($expected, $phpbb_utf8_wordwrap, 'Checking UTF-8 cutting long words');
+ }
+}
+